Version 2.9.0-0.0.dev

Merge commit '5900a0ac492b6d8ac2ca45a63f9236c61aa3f6a9' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d936ce..7bd6b44 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,15 +9,20 @@
 
 ### Language
 
-There are no new language features in this release. The only noteworthy change
-is a very minor breaking change in anticipation of the future support for null
-safety.
+There are no new language features in this release. There are only two
+minor breaking changes:
 
 *   **Breaking change** [#40675][]: Fixed an implementation bug where local
     variable inference would incorrectly use the promoted type of a type
     variable.
 
+*   **Breaking change** [#41362][]: Dart 2.0.0 made the clauses `implements
+    Function`, `extends Function`, or `with Function` have no effect (spec
+    section 19.6). We fixed an implementation bug that may be visible on some
+    rare scenarios.
+
 [#40675]: https://github.com/dart-lang/sdk/issues/40675
+[#41362]: https://github.com/dart-lang/sdk/issues/41362
 
 ### Core libraries
 
@@ -104,10 +109,18 @@
     of `Node`, even though it was not returning anything. This has been
     corrected to `void`.
 
+*   **Breaking Change**: `CssClassSet.add()` previously returned `null` if the
+    `CssClassSet` corresponded to multiple elements. In order to align with the
+    null-safe changes in the `Set` interface, it will now return `false`
+    instead. The same applies for `CssClassSet.toggle`.
+
 [#39627]: https://github.com/dart-lang/sdk/issues/39627
 
 #### `dart:io`
 
+*   Class `OSError` now implements `Exception`. This change means `OSError` will
+    now be caught in catch clauses catching `Exception`s.
+
 *   Class `HttpParser` will no longer throw an exception when a HTTP response
     status code is within [0, 999]. Customized status codes in this range are
     now valid.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5669836..101dfb2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,14 +11,14 @@
       click that icon to report a bug on the page.
     * To report an API doc bug,
       [create an SDK issue](https://github.com/dart-lang/sdk/issues/new?title=API%20doc%20issue:).
-  * Contribute to the Dart developer websites such as [www.dartlang.org](https://www.dartlang.org) (repo: [dart-lang/site-www](https://github.com/dart-lang/site-www)) and [webdev.dartlang.org](https://webdev.dartlang.org) (repo: [dart-lang/site-webdev](https://github.com/dart-lang/site-webdev)). For more information, see [Writing for Dart and Flutter websites](https://github.com/dart-lang/site-shared/wiki/Writing-for-Dart-and-Flutter-websites).
-  * Improve the API reference docs at [api.dartlang.org](https://api.dartlang.org) by editing doc comments in the [Dart SDK repo](https://github.com/dart-lang/sdk/tree/master/sdk/lib). For more information on how to write API docs, see [Effective Dart: Documentation](https://www.dartlang.org/guides/language/effective-dart/documentation).
+  * Contribute to the Dart developer websites such as [dart.dev](https://dart.dev) (repo: [dart-lang/site-www](https://github.com/dart-lang/site-www)) and [dart.dev/web](https://dart.dev/web) (repo: [dart-lang/site-webdev](https://github.com/dart-lang/site-webdev)). For more information, see [Writing for Dart and Flutter websites](https://github.com/dart-lang/site-shared/wiki/Writing-for-Dart-and-Flutter-websites).
+  * Improve the API reference docs at [api.dart.dev](https://api.dart.dev) by editing doc comments in the [Dart SDK repo](https://github.com/dart-lang/sdk/tree/master/sdk/lib). For more information on how to write API docs, see [Effective Dart: Documentation](https://dart.dev/guides/language/effective-dart/documentation).
 
 ## Before you contribute
 
 Before we can use your code, you must sign the [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual) (CLA), which you can do online.  The CLA is necessary mainly because you own the copyright to your changes, even after your contribution becomes part of our codebase, so we need your permission to use and distribute your code.  We also need to be sure of various other things—for instance that you'll tell us if you know that your code infringes on other people's patents.  You don't have to sign the CLA until after you've submitted your code for review and a member has approved it, but you must do it before we can put your code into our codebase.
 
-Before you start working on a larger contribution, you should get in touch with us first through the  [Dart Issue Tracker](http://dartbug.com) with your idea so that we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on.
+Before you start working on a larger contribution, you should get in touch with us first through the  [Dart Issue Tracker](https://dartbug.com) with your idea so that we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on.
 
 All submissions, including submissions by project members, require review.  We use the same code-review tools and process as the chromium project.  In order to submit a patch, you need to get the [depot\_tools](http://dev.chromium.org/developers/how-tos/depottools).
 
diff --git a/DEPS b/DEPS
index c8cbb91..1f170d2 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
   # 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": "9934d8540d097366287267519413e888a7f6a482",
+  "co19_rev": "929da300c553ebb8a9ff744746bcc1326613e1f9",
   "co19_2_rev": "368bfa9e877a2df003547f64bb17e30596af10c7",
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
@@ -86,7 +86,7 @@
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
   "dart_style_tag": "1.3.2",  # Please see the note above before updating.
 
-  "dartdoc_tag" : "v0.30.3",
+  "dartdoc_tag" : "v0.30.4",
   "ffi_tag": "ea88d71b043ee14b268c3aedff14e9eb32e20959",
   "fixnum_tag": "0.10.9",
   "glob_tag": "1.1.7",
@@ -97,7 +97,7 @@
   "http_retry_tag": "0.1.1",
   "http_tag" : "0.12.0+2",
   "http_throttle_tag" : "1.0.2",
-  "icu_rev" : "c56c671998902fcc4fc9ace88c83daa99f980793",
+  "icu_rev" : "5005010d694e16571b8dfbf07d70817841f80a69",
   "idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
   "intl_tag": "0.16.1",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
@@ -111,14 +111,13 @@
   "mockito_tag": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "mustache_tag" : "5e81b12215566dbe2473b2afd01a8a8aedd56ad9",
   "oauth2_tag": "1.2.1",
-  "observatory_pub_packages_rev": "0894122173b0f98eb08863a7712e78407d4477bc",
   "package_config_tag": "v1.9.2",
-  "path_tag": "1.6.2",
-  "pedantic_tag": "v1.8.0",
+  "path_tag": "1.7.0",
+  "pedantic_tag": "v1.9.0",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.6",
   "protobuf_rev": "3746c8fd3f2b0147623a8e3db89c3ff4330de760",
-  "pub_rev": "978cc9c4be7d8978348e56d4ae82be8257a59579",
+  "pub_rev": "3606265962da4248d34d352aa3d170aae4496a90",
   "pub_semver_tag": "v1.4.4",
   "quiver-dart_tag": "2.0.0+1",
   "resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
@@ -332,9 +331,6 @@
       + "@" + Var("mustache_tag"),
   Var("dart_root") + "/third_party/pkg/oauth2":
       Var("dart_git") + "oauth2.git" + "@" + Var("oauth2_tag"),
-  Var("dart_root") + "/third_party/observatory_pub_packages":
-      Var("dart_git") + "observatory_pub_packages.git"
-      + "@" + Var("observatory_pub_packages_rev"),
   Var("dart_root") + "/third_party/pkg_tested/package_config":
       Var("dart_git") + "package_config.git" +
       "@" + Var("package_config_tag"),
@@ -469,7 +465,7 @@
     "packages": [
       {
         "package": "dart/cfe/dart2js_dills",
-        "version": "binary_version:40",
+        "version": "binary_version:42",
       }
     ],
     "dep_type": "cipd",
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 99a82f2..4cbffad 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -38,6 +38,30 @@
     return []
 
 
+def _CheckSdkDdcRuntimeSync(input_api, output_api):
+    files = [git_file.LocalPath() for git_file in input_api.AffectedTextFiles()]
+    unsynchronized_files = []
+    runtime_lib = 'lib/_internal/js_dev_runtime/private/ddc_runtime/'
+    for nnbd_file in files:
+        if nnbd_file.startswith('sdk_nnbd/' + runtime_lib):
+            file = 'sdk/' + runtime_lib + nnbd_file[4:]
+            if not file in files:
+                unsynchronized_files.append(file)
+    if unsynchronized_files:
+        return [
+            output_api.PresubmitPromptWarning(
+                'Changes were made to '
+                'sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/ '
+                'that were not made to '
+                'sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/ '
+                'Please copy those changes (without Null Safety syntax) to '
+                'these files as well:\n'
+                '\n'
+                '%s' % ('\n'.join(unsynchronized_files)))
+        ]
+    return []
+
+
 def _CheckNnbdTestSync(input_api, output_api):
     """Make sure that any forked SDK tests are kept in sync. If a CL touches
     a test, the test's counterpart (if it exists at all) should be in the CL
@@ -316,6 +340,7 @@
 def _CommonChecks(input_api, output_api):
     results = []
     results.extend(_CheckNnbdSdkSync(input_api, output_api))
+    results.extend(_CheckSdkDdcRuntimeSync(input_api, output_api))
     results.extend(_CheckNnbdTestSync(input_api, output_api))
     results.extend(_CheckValidHostsInDEPS(input_api, output_api))
     results.extend(_CheckDartFormat(input_api, output_api))
diff --git a/WATCHLISTS b/WATCHLISTS
index 3e5b2ab..e587f14 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -33,7 +33,7 @@
       )
     },
     'package_vm': {
-      'filepath': '^pkg/vm',
+      'filepath': '^pkg/vm/',
     },
     'messages_review': {
       'filepath': (
diff --git a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
index 0ba9195..583344a 100644
--- a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
+++ b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
@@ -7,6 +7,7 @@
     # Allow having TODOs in the code
     todo: ignore
   exclude:
+    - test/constants/data/**
     - test/flow_analysis/assigned_variables/data/**
     - test/flow_analysis/definite_assignment/data/**
     - test/flow_analysis/definite_unassignment/data/**
diff --git a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
index feda572..02e8bdc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
@@ -62,6 +62,10 @@
    */
   ErrorSeverity get errorSeverity;
 
+  /// Whether a finding of this error is ignorable via comments such as
+  /// `// ignore:` or `// ignore_for_file:`.
+  bool get isIgnorable => errorSeverity != ErrorSeverity.ERROR;
+
   /**
    * The type of the error.
    */
@@ -225,7 +229,7 @@
     STATIC_WARNING,
     STATIC_TYPE_WARNING,
     SYNTACTIC_ERROR,
-    LINT
+    LINT,
   ];
 
   /**
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/factory_type_test_helper.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/factory_type_test_helper.dart
new file mode 100644
index 0000000..cc28dc3
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/factory_type_test_helper.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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 FactorTypeTestMixin<Type> {
+  Type futureNone(Type type);
+  Type futureOrNone(Type type);
+
+  Type get intNone;
+  Type get intQuestion;
+  Type get intStar;
+  Type get numNone;
+  Type get numQuestion;
+  Type get numStar;
+  Type get objectNone;
+  Type get objectQuestion;
+  Type get objectStar;
+  Type get stringNone;
+  Type get stringQuestion;
+  Type get stringStar;
+  Type get nullNone;
+
+  void test_futureOr() {
+    check(futureOrNone(intNone), intNone, 'Future<int>');
+    check(futureOrNone(intNone), futureNone(intNone), 'int');
+
+    check(futureOrNone(intQuestion), intNone, 'FutureOr<int?>');
+    check(futureOrNone(intQuestion), futureNone(intNone), 'FutureOr<int?>');
+    check(futureOrNone(intQuestion), intQuestion, 'Future<int?>');
+    check(futureOrNone(intQuestion), futureNone(intQuestion), 'int?');
+    check(futureOrNone(intQuestion), intStar, 'Future<int?>');
+    check(futureOrNone(intQuestion), futureNone(intStar), 'int?');
+
+    check(futureOrNone(intNone), numNone, 'Future<int>');
+    check(futureOrNone(intNone), futureNone(numNone), 'int');
+  }
+
+  void test_object() {
+    check(objectNone, objectNone, 'Never');
+    check(objectNone, objectQuestion, 'Never');
+    check(objectNone, objectStar, 'Never');
+
+    check(objectNone, intNone, 'Object');
+    check(objectNone, intQuestion, 'Object');
+    check(objectNone, intStar, 'Object');
+
+    check(objectQuestion, objectNone, 'Never?');
+    check(objectQuestion, objectQuestion, 'Never');
+    check(objectQuestion, objectStar, 'Never');
+
+    check(objectQuestion, intNone, 'Object?');
+    check(objectQuestion, intQuestion, 'Object');
+    check(objectQuestion, intStar, 'Object');
+  }
+
+  test_subtype() {
+    check(intNone, intNone, 'Never');
+    check(intNone, intQuestion, 'Never');
+    check(intNone, intStar, 'Never');
+
+    check(intQuestion, intNone, 'Never?');
+    check(intQuestion, intQuestion, 'Never');
+    check(intQuestion, intStar, 'Never');
+
+    check(intStar, intNone, 'Never');
+    check(intStar, intQuestion, 'Never');
+    check(intStar, intStar, 'Never');
+
+    check(intNone, numNone, 'Never');
+    check(intNone, numQuestion, 'Never');
+    check(intNone, numStar, 'Never');
+
+    check(intQuestion, numNone, 'Never?');
+    check(intQuestion, numQuestion, 'Never');
+    check(intQuestion, numStar, 'Never');
+
+    check(intStar, numNone, 'Never');
+    check(intStar, numQuestion, 'Never');
+    check(intStar, numStar, 'Never');
+
+    check(intNone, nullNone, 'int');
+    check(intQuestion, nullNone, 'int');
+    check(intStar, nullNone, 'int');
+
+    check(intNone, stringNone, 'int');
+    check(intQuestion, stringNone, 'int?');
+    check(intStar, stringNone, 'int*');
+
+    check(intNone, stringQuestion, 'int');
+    check(intQuestion, stringQuestion, 'int');
+    check(intStar, stringQuestion, 'int');
+
+    check(intNone, stringStar, 'int');
+    check(intQuestion, stringStar, 'int');
+    check(intStar, stringStar, 'int');
+  }
+
+  Type factor(Type T, Type S);
+
+  void expect(Type T, Type S, String actualResult, String expectedResult);
+
+  void check(Type T, Type S, String expectedStr) {
+    var result = factor(T, S);
+    var resultStr = typeString(result);
+
+    expect(T, S, resultStr, expectedStr);
+  }
+
+  String typeString(Type type);
+}
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 739dd20..2df4e4a 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
@@ -1660,7 +1660,26 @@
     List<Type> thisPromotedTypes = promotedTypes;
     List<Type> otherPromotedTypes = otherModel.promotedTypes;
     bool newAssigned = assigned || otherModel.assigned;
-    bool newUnassigned = unassigned;
+    // The variable can only be unassigned in this state if it was also
+    // unassigned in the other state or if the other state didn't complete
+    // normally. For the latter case the resulting state is unreachable but to
+    // avoid creating a variable model that is both assigned and unassigned we
+    // take the intersection below.
+    //
+    // This situation can occur in try-finally like:
+    //
+    //   method() {
+    //     var local;
+    //     try {
+    //       local = 0;
+    //       return; // assigned
+    //     } finally {
+    //       local; // unassigned
+    //     }
+    //     local; // unreachable state
+    //   }
+    //
+    bool newUnassigned = unassigned && otherModel.unassigned;
     bool newWriteCaptured = writeCaptured || otherModel.writeCaptured;
     List<Type> newPromotedTypes;
     if (unsafe) {
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 94553cd..99e57f3 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1290,6 +1290,35 @@
     message: r"""Constant evaluation error:""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String
+            string2)> templateConstEvalTruncateError = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""Binary operator '#string ~/ #string2' results is Infinity or NaN.""",
+    withArguments: _withArgumentsConstEvalTruncateError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeConstEvalTruncateError =
+    const Code<Message Function(String string, String string2)>(
+  "ConstEvalTruncateError",
+  templateConstEvalTruncateError,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalTruncateError(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeConstEvalTruncateError,
+      message:
+          """Binary operator '${string} ~/ ${string2}' results is Infinity or NaN.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstEvalUnevaluated = messageConstEvalUnevaluated;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
index 253b762..dfd9be9 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -1037,6 +1037,16 @@
   }
 
   @override
+  void beginAsOperatorType(Token operator) {
+    listener?.beginAsOperatorType(operator);
+  }
+
+  @override
+  void endAsOperatorType(Token operator) {
+    listener?.endAsOperatorType(operator);
+  }
+
+  @override
   void handleAsOperator(Token operator) {
     listener?.handleAsOperator(operator);
   }
@@ -1276,6 +1286,16 @@
   }
 
   @override
+  void beginIsOperatorType(Token operator) {
+    listener?.beginIsOperatorType(operator);
+  }
+
+  @override
+  void endIsOperatorType(Token operator) {
+    listener?.endIsOperatorType(operator);
+  }
+
+  @override
   void handleIsOperator(Token isOperator, Token not) {
     listener?.handleIsOperator(isOperator, not);
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index 112bfe6..45ed3dbd0 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -1247,6 +1247,12 @@
     logEvent("WhileStatement");
   }
 
+  void beginAsOperatorType(Token operator) {}
+
+  void endAsOperatorType(Token operator) {
+    logEvent("AsOperatorType");
+  }
+
   void handleAsOperator(Token operator) {
     logEvent("AsOperator");
   }
@@ -1358,6 +1364,12 @@
     logEvent("IndexedExpression");
   }
 
+  void beginIsOperatorType(Token operator) {}
+
+  void endIsOperatorType(Token operator) {
+    logEvent("IsOperatorType");
+  }
+
   void handleIsOperator(Token isOperator, Token not) {
     logEvent("IsOperator");
   }
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 8a75f87..b3ad6f5 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -1151,6 +1151,7 @@
   }
 
   Token parseWithClauseOpt(Token token) {
+    // <mixins> ::= with <typeNotVoidList>
     Token withKeyword = token.next;
     if (optional('with', withKeyword)) {
       token = parseTypeList(withKeyword);
@@ -1936,6 +1937,7 @@
   }
 
   Token parseClassExtendsOpt(Token token) {
+    // extends <typeNotVoid>
     Token next = token.next;
     if (optional('extends', next)) {
       Token extendsKeyword = next;
@@ -5468,8 +5470,10 @@
     if (optional('!', token.next)) {
       not = token = token.next;
     }
+    listener.beginIsOperatorType(operator);
     TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
     token = typeInfo.ensureTypeNotVoid(token, this);
+    listener.endIsOperatorType(operator);
     listener.handleIsOperator(operator, not);
     return skipChainedAsIsOperators(token);
   }
@@ -5497,8 +5501,10 @@
   Token parseAsOperatorRest(Token token) {
     Token operator = token = token.next;
     assert(optional('as', operator));
+    listener.beginAsOperatorType(operator);
     TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
     token = typeInfo.ensureTypeNotVoid(token, this);
+    listener.endAsOperatorType(operator);
     listener.handleAsOperator(operator);
     return skipChainedAsIsOperators(token);
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/features.dart b/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
index 36e32d7..f42cd25 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
@@ -59,31 +59,74 @@
 
   /// Returns a string containing all features in a comma-separated list sorted
   /// by feature names.
-  String getText() {
-    StringBuffer sb = new StringBuffer();
-    bool needsComma = false;
-    for (String name in _features.keys.toList()..sort()) {
-      dynamic value = _features[name];
-      if (value != null) {
-        if (needsComma) {
-          sb.write(',');
+  String getText([String indent]) {
+    if (indent == null) {
+      StringBuffer sb = new StringBuffer();
+      bool needsComma = false;
+      for (String name in _features.keys.toList()..sort()) {
+        dynamic value = _features[name];
+        if (value != null) {
+          if (needsComma) {
+            sb.write(',');
+          }
+          sb.write(name);
+          if (value is List<String>) {
+            if (_unsorted.contains(name)) {
+              value = '[${value.join(',')}]';
+            } else {
+              value = '[${(value..sort()).join(',')}]';
+            }
+          }
+          if (value != '') {
+            sb.write('=');
+            sb.write(value);
+          }
+          needsComma = true;
         }
+      }
+      return sb.toString();
+    } else {
+      StringBuffer sb = new StringBuffer();
+      Map<String, dynamic> values = {};
+      for (String name in _features.keys.toList()..sort()) {
+        dynamic value = _features[name];
+        if (value != null) {
+          values[name] = value;
+        }
+      }
+      String comma = '';
+      if (values.length > 1) {
+        comma = '\n$indent ';
+      }
+      values.forEach((String name, dynamic value) {
+        sb.write(comma);
         sb.write(name);
         if (value is List<String>) {
-          if (_unsorted.contains(name)) {
-            value = '[${value.join(',')}]';
+          if (value.length > 1) {
+            if (_unsorted.contains(name)) {
+              value = '[\n$indent  ${value.join(',\n$indent  ')}]';
+            } else {
+              value = '[\n$indent  ${(value..sort()).join(',\n$indent  ')}]';
+            }
           } else {
-            value = '[${(value..sort()).join(',')}]';
+            if (_unsorted.contains(name)) {
+              value = '[${value.join(',')}]';
+            } else {
+              value = '[${(value..sort()).join(',')}]';
+            }
           }
         }
         if (value != '') {
           sb.write('=');
           sb.write(value);
         }
-        needsComma = true;
+        comma = ',\n$indent ';
+      });
+      if (values.length > 1) {
+        sb.write('\n$indent');
       }
+      return sb.toString();
     }
-    return sb.toString();
   }
 
   @override
@@ -274,8 +317,8 @@
   }
 
   @override
-  String getText(Features actualData) {
-    return actualData.getText();
+  String getText(Features actualData, [String indentation]) {
+    return actualData.getText(indentation);
   }
 
   @override
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
index 6800762..dd3fdb7e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
@@ -12,7 +12,8 @@
     Uri mainUri,
     Map<String, Map<Uri, Map<Id, ActualData<T>>>> actualData,
     DataInterpreter<T> dataInterpreter,
-    {Annotation Function(Annotation expected, Annotation actual) createDiff}) {
+    {Annotation Function(Annotation expected, Annotation actual) createDiff,
+    bool forceUpdate: false}) {
   Set<Uri> uriSet = {};
   Set<String> actualMarkers = actualData.keys.toSet();
   Map<Uri, Map<Id, Map<String, IdValue>>> idValuePerUri = {};
@@ -68,7 +69,7 @@
         code != null, "No annotated code for ${uri} in ${annotatedCode.keys}");
     result[uri] = _computeAnnotations(code, expectedMaps.keys, actualMarkers,
         idValuePerId, actualDataPerId, dataInterpreter,
-        sortMarkers: false, createDiff: createDiff);
+        sortMarkers: false, createDiff: createDiff, forceUpdate: forceUpdate);
   }
   return result;
 }
@@ -83,31 +84,42 @@
     {String defaultPrefix: '/*',
     String defaultSuffix: '*/',
     bool sortMarkers: true,
-    Annotation Function(Annotation expected, Annotation actual) createDiff}) {
+    Annotation Function(Annotation expected, Annotation actual) createDiff,
+    bool forceUpdate: false}) {
   assert(annotatedCode != null);
 
   Annotation createAnnotationFromData(
       ActualData<T> actualData, Annotation annotation) {
+    String getIndentationFromOffset(int offset) {
+      int lineIndex = annotatedCode.getLineIndex(offset);
+      String line = annotatedCode.getLine(lineIndex);
+      String trimmed = line.trimLeft();
+      return line.substring(0, line.length - trimmed.length);
+    }
+
     int offset;
     String prefix;
     String suffix;
+    String indentation;
     if (annotation != null) {
       offset = annotation.offset;
       prefix = annotation.prefix;
       suffix = annotation.suffix;
+      indentation = getIndentationFromOffset(offset);
     } else {
       Id id = actualData.id;
       if (id is NodeId) {
         offset = id.value;
         prefix = defaultPrefix;
         suffix = defaultSuffix;
+        indentation = getIndentationFromOffset(offset);
       } else if (id is ClassId || id is MemberId) {
         // Place the annotation at the line above at the indentation level of
         // the class/member.
         int lineIndex = annotatedCode.getLineIndex(actualData.offset);
         String line = annotatedCode.getLine(lineIndex);
         String trimmed = line.trimLeft();
-        String indentation = line.substring(0, line.length - trimmed.length);
+        indentation = line.substring(0, line.length - trimmed.length);
         offset = annotatedCode.getLineStart(lineIndex);
         prefix = '$indentation$defaultPrefix';
         suffix = '$defaultSuffix\n';
@@ -124,6 +136,7 @@
         offset = annotatedCode.getLineStart(lineIndex);
         prefix = '\n$defaultPrefix';
         suffix = '$defaultSuffix\n';
+        indentation = '';
       } else {
         throw 'Unexpected id $id (${id.runtimeType})';
       }
@@ -135,8 +148,8 @@
         annotation?.columnNo ?? -1,
         offset,
         prefix,
-        IdValue.idToString(
-            actualData.id, dataInterpreter.getText(actualData.value)),
+        IdValue.idToString(actualData.id,
+            dataInterpreter.getText(actualData.value, indentation)),
         suffix);
   }
 
@@ -154,7 +167,8 @@
       Annotation actualAnnotation;
       if (idValue != null && actualData != null) {
         if (dataInterpreter.isAsExpected(actualData.value, idValue.value) ==
-            null) {
+                null &&
+            !forceUpdate) {
           // Use existing annotation.
           expectedAnnotation = actualAnnotation = idValue.annotation;
         } else {
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
index 7b64c73..14ab354 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
@@ -434,7 +434,10 @@
   bool isEmpty(T actualData);
 
   /// Returns a textual representation of [actualData].
-  String getText(T actualData);
+  ///
+  /// If [indentation] is provided a multiline pretty printing can be returned
+  /// using [indentation] for additional lines.
+  String getText(T actualData, [String indentation]);
 }
 
 /// Default data interpreter for string data.
@@ -457,7 +460,7 @@
   }
 
   @override
-  String getText(String actualData) {
+  String getText(String actualData, [String indentation]) {
     return actualData;
   }
 }
@@ -725,6 +728,7 @@
   bool continued = false;
   bool hasFailures = false;
   bool generateAnnotations = args.remove('-g');
+  bool forceUpdate = args.remove('-f');
 
   String relativeDir = dataDir.uri.path.replaceAll(Uri.base.path, '');
   print('Data dir: ${relativeDir}');
@@ -791,7 +795,7 @@
     if (hasErrors) {
       // Cannot generate annotations for erroneous tests.
       hasFailures = true;
-    } else if (hasMismatches) {
+    } else if (hasMismatches || (forceUpdate && generateAnnotations)) {
       if (generateAnnotations) {
         DataInterpreter dataInterpreter;
         Map<String, Map<Uri, Map<Id, ActualData<T>>>> actualData = {};
@@ -823,7 +827,8 @@
             testData.expectedMaps,
             testData.entryPoint,
             actualData,
-            dataInterpreter);
+            dataInterpreter,
+            forceUpdate: forceUpdate);
         annotations.forEach((Uri uri, List<Annotation> annotations) {
           assert(uri != null, "Annotations without uri: $annotations");
           AnnotatedCode code = testData.code[uri];
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index 2efa38e..cb6e229 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
 name: _fe_analyzer_shared
-version: 1.0.3
+version: 2.2.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/constants/data/errors.dart b/pkg/_fe_analyzer_shared/test/constants/data/errors.dart
index c25cead..b2026dc 100644
--- a/pkg/_fe_analyzer_shared/test/constants/data/errors.dart
+++ b/pkg/_fe_analyzer_shared/test/constants/data/errors.dart
@@ -2,10 +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.
 
-// ignore_for_file: const_initialized_with_non_constant_value
-
-// TODO(paulberry): Support testing errors in analyzer id testing.
-
 String method() => 'foo';
 
 const String string0 =
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
index f4f7394..2d2050f 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
@@ -41,6 +41,6 @@
 questionEq_rhs_not_guaranteed_to_execute() {
   late int v;
   int? i;
-  /*cfe.unassigned*/ i ??= (v = 0);
+  /*unassigned*/ i ??= (v = 0);
   /*unassigned*/ v;
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/issue41284.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/issue41284.dart
new file mode 100644
index 0000000..95c0e7d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/issue41284.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.
+
+void method1() {
+  var local;
+  try {
+    local = 0;
+    return;
+  } finally {
+    print(/*unassigned*/ local);
+  }
+  local;
+}
+
+void method2() {
+  var local;
+  try {
+    local = 0;
+    return;
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    print(/*unassigned*/ local);
+  }
+  local;
+}
+
+void method3() {
+  var local;
+  try {
+    local = 0;
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    print(/*unassigned*/ local);
+  }
+  local;
+}
+
+void method4() {
+  var local;
+  try {
+    print(/*unassigned*/ local);
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    local = 0;
+  }
+  local;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/issue41284.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/issue41284.dart
new file mode 100644
index 0000000..59f4591
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/issue41284.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.
+
+void method1() {
+  var local;
+  try {
+    local = 0;
+    return;
+  } finally {
+    print(/*unassigned*/ local);
+  }
+  local;
+}
+
+void method2() {
+  var local;
+  try {
+    local = 0;
+    return;
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    print(/*unassigned*/ local);
+  }
+  local;
+}
+
+void method3() {
+  var local;
+  try {
+    local = 0;
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    print(local);
+  }
+  local;
+}
+
+void method4() {
+  var local;
+  try {
+    print(/*unassigned*/ local);
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    local = 0;
+  }
+  local;
+}
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 f28c2e9..9b759b1 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
@@ -1799,9 +1799,7 @@
 
       test('unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h);
+        var s1 = FlowModel<_Var, _Type>(true).declare(objectQVar, true);
         var s2 = s1.write(objectQVar, _Type('Object?'), h);
         expect(s2, same(s1));
       });
@@ -1823,8 +1821,7 @@
       test('un-promotes fully', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('int'))
             .ifTrue;
         expect(s1.variableInfo, contains(objectQVar));
@@ -1842,8 +1839,7 @@
       test('un-promotes partially, when no exact match', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifTrue
             .tryPromote(h, objectQVar, _Type('int'))
@@ -1869,8 +1865,7 @@
       test('un-promotes partially, when exact match', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifTrue
             .tryPromote(h, objectQVar, _Type('num'))
@@ -1898,8 +1893,7 @@
       test('leaves promoted, when exact match', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifTrue
             .tryPromote(h, objectQVar, _Type('num'))
@@ -1919,8 +1913,7 @@
       test('leaves promoted, when writing a subtype', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifTrue
             .tryPromote(h, objectQVar, _Type('num'))
@@ -1940,8 +1933,7 @@
       test('Promotes to type of interest when not previously promoted', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifFalse;
         expect(s1.variableInfo, {
@@ -1956,8 +1948,7 @@
       test('Promotes to type of interest when previously promoted', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifTrue
             .tryPromote(h, objectQVar, _Type('int?'))
@@ -1977,8 +1968,7 @@
           () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('int?'))
             .ifFalse
             .tryPromote(h, objectQVar, _Type('num?'))
@@ -1999,8 +1989,7 @@
           () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifFalse
             .tryPromote(h, objectQVar, _Type('int?'))
@@ -2019,8 +2008,7 @@
       test('Multiple candidate types of interest; ambiguous', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifFalse
             .tryPromote(h, objectQVar, _Type('num*'))
@@ -2039,8 +2027,7 @@
           () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .declare(objectQVar, false)
-            .write(objectQVar, _Type('Object?'), h)
+            .declare(objectQVar, true)
             .tryPromote(h, objectQVar, _Type('num?'))
             .ifFalse
             .tryPromote(h, objectQVar, _Type('num*'))
@@ -2337,9 +2324,7 @@
             List<String> expectedChain) {
           var h = _Harness();
           var x = _Var('x', _Type('Object?'));
-          var s0 = FlowModel<_Var, _Type>(true)
-              .declare(x, false)
-              .write(x, _Type('Object?'), h);
+          var s0 = FlowModel<_Var, _Type>(true).declare(x, true);
           var s1 = thisType == null
               ? s0
               : s0.tryPromote(h, x, _Type(thisType)).ifTrue;
@@ -2391,9 +2376,7 @@
             List<String> inFinally, List<String> expectedResult) {
           var h = _Harness();
           var x = _Var('x', _Type('Object?'));
-          var initialModel = FlowModel<_Var, _Type>(true)
-              .declare(x, false)
-              .write(x, _Type('Object?'), h);
+          var initialModel = FlowModel<_Var, _Type>(true).declare(x, true);
           for (var t in before) {
             initialModel = initialModel.tryPromote(h, x, _Type(t)).ifTrue;
           }
@@ -2445,7 +2428,7 @@
         var h = _Harness();
         var x = _Var('x', _Type('Object?'));
         var s0 = FlowModel<_Var, _Type>(true);
-        var s1 = s0.declare(x, false).write(x, _Type('Object?'), h);
+        var s1 = s0.declare(x, true);
         expect(s0.restrict(h, s1, {}), same(s0));
         expect(s0.restrict(h, s1, {x}), same(s0));
         expect(s1.restrict(h, s0, {}), same(s0));
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/issue41284.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/issue41284.dart
new file mode 100644
index 0000000..1a13beb
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/issue41284.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.
+
+/*member: method1:doesNotComplete*/
+void method1() {
+  var local;
+  try {
+    local = 0;
+    return;
+  } finally {
+    print(local);
+  }
+  /*stmt: unreachable*/ local;
+}
+
+/*member: method2:doesNotComplete*/
+void method2() {
+  var local;
+  try {
+    local = 0;
+    return;
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    print(local);
+  }
+  /*stmt: unreachable*/ local;
+}
+
+void method3() {
+  var local;
+  try {
+    local = 0;
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    print(local);
+  }
+  local;
+}
+
+void method4() {
+  var local;
+  try {
+    print(local);
+  } catch (e) {
+    local = 42;
+    rethrow;
+  } finally {
+    local = 0;
+  }
+  local;
+}
diff --git a/pkg/_fe_analyzer_shared/test/id_generation_test.dart b/pkg/_fe_analyzer_shared/test/id_generation_test.dart
index 6010ed5..0f19b23 100644
--- a/pkg/_fe_analyzer_shared/test/id_generation_test.dart
+++ b/pkg/_fe_analyzer_shared/test/id_generation_test.dart
@@ -339,7 +339,13 @@
     }
   }, expectedResult: '''
 some code
-/*a.member: memberName:test1=b,test2=[c,d],test3=e*/
+/*a.member: memberName:
+ test1=b,
+ test2=[
+  c,
+  d],
+ test3=e
+*/
 /*b|c.member: memberName:
  test1=a,
  test2=[
@@ -349,6 +355,8 @@
 */
 some more code
 ''');
+  // TODO(johnniwinther): Should new data reuse an existing encoding when that
+  // differs from the pretty printed encoding?
   testFeatures('''
 some code
 /*a.member: memberName:test1=b,test2=[c,d],test3=e*/
@@ -366,7 +374,14 @@
     }
   }, expectedResult: '''
 some code
-/*a|b.member: memberName:test1=b,test2=[c,d],test3=e*/
+/*a.member: memberName:test1=b,test2=[c,d],test3=e*/
+/*b.member: memberName:
+ test1=b,
+ test2=[
+  c,
+  d],
+ test3=e
+*/
 /*c.member: memberName:
  test1=a,
  test2=[
@@ -378,7 +393,52 @@
 ''');
   testFeatures('''
 some code
-/*a|b.member: memberName:test1=b,test2=[c,d],test3=e*/
+/*a.member: memberName:
+ test1=b,
+ test2=[
+  c,
+  d],
+ test3=e
+*/
+/*b|c.member: memberName:
+ test1=a,
+ test2=[
+  b,
+  c],
+ test3=d
+*/
+some more code
+''', actualData: {
+    'b': {
+      new MemberId('memberName'): 'test1=b,test2=[c,d],test3=e',
+    }
+  }, expectedResult: '''
+some code
+/*a|b.member: memberName:
+ test1=b,
+ test2=[
+  c,
+  d],
+ test3=e
+*/
+/*c.member: memberName:
+ test1=a,
+ test2=[
+  b,
+  c],
+ test3=d
+*/
+some more code
+''');
+  testFeatures('''
+some code
+/*a|b.member: memberName:
+ test1=b,
+ test2=[
+  c,
+  d],
+ test3=e
+*/
 /*c.member: memberName:
  test1=a,
  test2=[
@@ -393,7 +453,13 @@
     }
   }, expectedResult: '''
 some code
-/*member: memberName:test1=b,test2=[c,d],test3=e*/
+/*member: memberName:
+ test1=b,
+ test2=[
+  c,
+  d],
+ test3=e
+*/
 some more code
 ''');
 }
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart
index aae2ae8..cdf272f 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart
@@ -17,32 +17,26 @@
   /*member: SubClass2.method:int? Function(int)*/
 }
 
-// TODO: Solve CFE / analyzer difference.
-// This an following examples end up with implementing `GenericInterface`
-// with `int` and `int?` type arguments, and their NNBD_TOP_MERGE does not
-// exist. it does not matter that some of these interfaces come through a
-// legacy library.
-
 /*class: GenericSubClass1a:GenericClass1,GenericInterface<int?>,GenericLegacyClass1a,GenericSubClass1a,Object*/
-/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass1a
-    extends GenericLegacyClass1a implements GenericInterface<int?> {
+abstract class GenericSubClass1a extends GenericLegacyClass1a
+    implements GenericInterface<int?> {
   /*member: GenericSubClass1a.method:int? Function(int?)*/
 }
 
 /*class: GenericSubClass1b:GenericClass1,GenericInterface<int?>,GenericLegacyClass1b,GenericSubClass1b,Object*/
-/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass1b
-    extends GenericLegacyClass1b implements GenericInterface<int?> {
+abstract class GenericSubClass1b extends GenericLegacyClass1b
+    implements GenericInterface<int?> {
   /*member: GenericSubClass1b.method:int? Function(int?)*/
 }
 
 /*class: GenericSubClass2a:GenericClass2,GenericInterface<int>,GenericLegacyClass2a,GenericSubClass2a,Object*/
-/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass2a
-    extends GenericLegacyClass2a implements GenericInterface<int> {
+abstract class GenericSubClass2a extends GenericLegacyClass2a
+    implements GenericInterface<int> {
   /*member: GenericSubClass2a.method:int Function(int)*/
 }
 
 /*class: GenericSubClass2b:GenericClass2,GenericInterface<int>,GenericLegacyClass2b,GenericSubClass2b,Object*/
-/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass2b
-    extends GenericLegacyClass2b implements GenericInterface<int> {
+abstract class GenericSubClass2b extends GenericLegacyClass2b
+    implements GenericInterface<int> {
   /*member: GenericSubClass2b.method:int Function(int)*/
 }
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/opt_out.dart
index 1766444..09cfea2 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/opt_out.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/opt_out.dart
@@ -18,30 +18,24 @@
   /*member: LegacyClass2.method:int* Function(int*)**/
 }
 
-/// TODO: Solve CFE / analyzer difference.
-/// Classes in legacy libraries can only have members with legacy signatures.
 /*class: GenericLegacyClass1a:GenericClass1,GenericInterface<int*>,GenericLegacyClass1a,Object*/
 abstract class GenericLegacyClass1a extends GenericClass1 {
-  /*cfe|cfe:builder.member: GenericLegacyClass1a.method:int* Function(int*)*/
-  /*analyzer.member: GenericLegacyClass1a.method:int* Function(int*)**/
+  /*member: GenericLegacyClass1a.method:int* Function(int*)**/
 }
 
 /*class: GenericLegacyClass1b:GenericClass1,GenericInterface<int*>,GenericLegacyClass1b,Object*/
 abstract class GenericLegacyClass1b extends GenericClass1
     implements GenericInterface<int> {
-  /*cfe|cfe:builder.member: GenericLegacyClass1b.method:int* Function(int*)*/
-  /*analyzer.member: GenericLegacyClass1b.method:int* Function(int*)**/
+  /*member: GenericLegacyClass1b.method:int* Function(int*)**/
 }
 
 /*class: GenericLegacyClass2a:GenericClass2,GenericInterface<int*>,GenericLegacyClass2a,Object*/
 abstract class GenericLegacyClass2a extends GenericClass2 {
-  /*cfe|cfe:builder.member: GenericLegacyClass2a.method:int* Function(int*)*/
-  /*analyzer.member: GenericLegacyClass2a.method:int* Function(int*)**/
+  /*member: GenericLegacyClass2a.method:int* Function(int*)**/
 }
 
 /*class: GenericLegacyClass2b:GenericClass2,GenericInterface<int*>,GenericLegacyClass2b,Object*/
 abstract class GenericLegacyClass2b extends GenericClass2
     implements GenericInterface<int> {
-  /*cfe|cfe:builder.member: GenericLegacyClass2b.method:int* Function(int*)*/
-  /*analyzer.member: GenericLegacyClass2b.method:int* Function(int*)**/
+  /*member: GenericLegacyClass2b.method:int* Function(int*)**/
 }
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart
index 8b854b8..ce65245 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart
@@ -56,49 +56,57 @@
 
 /*class: F1:A,C,F1,Object*/
 class F1 extends A implements C {
-  /*member: F1.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: F1.method:void Function(void, {void named})*/
+  /*analyzer.member: F1.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: F2:A,C,F2,Object*/
 class F2 extends C implements A {
-  /*member: F2.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: F2.method:void Function(void, {void named})*/
+  /*analyzer.member: F2.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: F3:A,C,F3,Object*/
 class F3 implements A, C {
-  /*member: F3.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: F3.method:void Function(void, {void named})*/
+  /*analyzer.member: F3.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: F4:A,C,F4,Object*/
 class F4 implements C, A {
-  /*member: F4.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: F4.method:void Function(void, {void named})*/
+  /*analyzer.member: F4.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G1:A,B,C,G1,Object*/
 class G1 extends B implements C {
-  /*member: G1.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: G1.method:void Function(void, {void named})*/
+  /*analyzer.member: G1.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G2:A,B,C,G2,Object*/
 class G2 extends C implements B {
-  /*member: G2.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: G2.method:void Function(void, {void named})*/
+  /*analyzer.member: G2.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G3:A,B,C,G3,Object*/
 class G3 implements B, C {
-  /*member: G3.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: G3.method:void Function(void, {void named})*/
+  /*analyzer.member: G3.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G4:A,B,C,G4,Object*/
 class G4 implements C, B {
-  /*member: G4.method:void Function(void, {void named})*/
+  /*cfe|cfe:builder.member: G4.method:void Function(void, {void named})*/
+  /*analyzer.member: G4.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart
index 9ef0a47..a388a8d 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart
@@ -19,7 +19,8 @@
 /*class: B1:A<Object?>,A_Object,A_dynamic,B1,Object*/
 class B1 extends A_Object implements A_dynamic {}
 
-/*class: B2:A<void>,A_Object,A_void,B2,Object*/
+/*cfe|cfe:builder.class: B2:A<void>,A_Object,A_void,B2,Object*/
+/*analyzer.class: B2:A<Object?>,A_Object,A_void,B2,Object*/
 class B2 extends A_Object implements A_void {}
 
 main() {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart
index 4a6f1ad..a84f5d1 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart
@@ -15,7 +15,8 @@
 /*class: B1:A<Object?>,A_Object,A_dynamic,B1,Object*/
 class B1 extends A_Object implements A_dynamic {}
 
-/*class: B2:A<void>,A_Object,A_void,B2,Object*/
+/*cfe|cfe:builder.class: B2:A<void>,A_Object,A_void,B2,Object*/
+/*analyzer.class: B2:A<Object?>,A_Object,A_void,B2,Object*/
 class B2 extends A_Object implements A_void {}
 
 main() {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/main.dart
index ff14c36..f05435c 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/main.dart
@@ -1,4 +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.
+
 /*library: nnbd=true*/
+
 import "opt_out.dart";
 import "dart:async";
 
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/opt_out.dart
index 787499e..8647b27 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/opt_out.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40553/opt_out.dart
@@ -1,3 +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.6
 
 /*library: nnbd=false*/
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/norm_supertypes.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/norm_supertypes.dart
index fb47fcd..12f8c82 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/norm_supertypes.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/norm_supertypes.dart
@@ -12,18 +12,19 @@
 /*class: Foo:A<FutureOr<T?>>,Foo<T, S>,Object*/
 class Foo<T extends S, S extends Never> implements A<FutureOr<T?>> {}
 
-/// TODO: Solve CFE / analyzer difference.
-/// It looks to me that is should be `A<FutureOr<Never?>>`, because this is
-/// what is written in the code. We don't do normalization because there is
-/// only one implementation of `A` in `Bar`.
-/*cfe|cfe:builder.class: Bar:A<FutureOr<Never>>,Bar,Object*/
-/*analyzer.class: Bar:A<FutureOr<Never?>>,Bar,Object*/
+/*class: Bar:A<FutureOr<Never?>>,Bar,Object*/
 class Bar implements A<FutureOr<Never?>> {}
 
 /*class: Baz:A<Future<Null>?>,Baz,Object*/
 class Baz implements A<Future<Null>?> {}
 
-/*class: Hest:A<Future<Null>?>,Bar,Foo<Never, Never>,Hest,Object*/
+/// TODO: Solve CFE / analyzer difference.
+/// Instantiation of [Foo] is `Foo<Never, Never>`, so it implements
+/// `A<FutureOr<Never?>>`, and `Bar` implements the same `A<FutureOr<Never?>>`.
+/// So, these two are syntactically equal, so NORM and TOP_MERGE should not
+/// be applied.
+/*cfe|cfe:builder.class: Hest:A<Future<Null>?>,Bar,Foo<Never, Never>,Hest,Object*/
+/*analyzer.class: Hest:A<FutureOr<Never?>>,Bar,Foo<Never, Never>,Hest,Object*/
 class Hest extends Foo implements Bar {}
 
 /*class: Fisk:A<Future<Null>?>,Bar,Baz,Fisk,Object*/
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart
index d0865e2..bd4dc1f 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart
@@ -32,7 +32,8 @@
 
 /*class: E1:A,B,C,D,E1,Object*/
 abstract class E1 implements A, B, C, D {
-  /*member: E1.method:void Function(void)*/
+  /*cfe|cfe:builder.member: E1.method:void Function(void)*/
+  /*analyzer.member: E1.method:Object? Function(Object?)*/
 }
 
 /*class: E2:A,B,E2,Object*/
@@ -42,12 +43,14 @@
 
 /*class: E3:B,C,E3,Object*/
 abstract class E3 implements B, C {
-  /*member: E3.method:void Function(void)*/
+  /*cfe|cfe:builder.member: E3.method:void Function(void)*/
+  /*analyzer.member: E3.method:Object? Function(Object?)*/
 }
 
 /*class: E4:A,C,E4,Object*/
 abstract class E4 implements A, C {
-  /*member: E4.method:void Function(void)*/
+  /*cfe|cfe:builder.member: E4.method:void Function(void)*/
+  /*analyzer.member: E4.method:Object? Function(Object?)*/
 }
 
 /*class: E5:A,D,E5,Object*/
@@ -68,20 +71,24 @@
 
 /*class: G1:A,C,F,G1,Object*/
 abstract class G1 implements A, C, F {
-  /*member: G1.method:void Function(void)*/
+  /*cfe|cfe:builder.member: G1.method:void Function(void)*/
+  /*analyzer.member: G1.method:Object? Function(Object?)*/
 }
 
 /*class: G2:A,C,F,G2,Object*/
 abstract class G2 implements A, F, C {
-  /*member: G2.method:void Function(void)*/
+  /*cfe|cfe:builder.member: G2.method:void Function(void)*/
+  /*analyzer.member: G2.method:Object? Function(Object?)*/
 }
 
 /*class: G3:A,C,F,G3,Object*/
 abstract class G3 implements C, A, F {
-  /*member: G3.method:void Function(void)*/
+  /*cfe|cfe:builder.member: G3.method:void Function(void)*/
+  /*analyzer.member: G3.method:Object? Function(Object?)*/
 }
 
 /*class: G4:A,C,F,G4,Object*/
 abstract class G4 implements C, F, A {
-  /*member: G4.method:void Function(void)*/
+  /*cfe|cfe:builder.member: G4.method:void Function(void)*/
+  /*analyzer.member: G4.method:Object? Function(Object?)*/
 }
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 75045dd..616ebe9 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -1101,6 +1101,41 @@
         <p>
           A list of the paths of the files that are being analyzed.
         </p>
+      </dd></dl></dd><dt class="notification"><a name="notification_analysis.closingLabels">analysis.closingLabels</a></dt><dd><div class="box"><pre>notification: {
+  "event": "analysis.closingLabels"
+  "params": {
+    "<b>file</b>": <a href="#type_FilePath">FilePath</a>
+    "<b>labels</b>": List&lt;<a href="#type_ClosingLabel">ClosingLabel</a>&gt;
+  }
+}</pre></div>
+    <p>
+      Reports closing labels relevant to a given file.
+    </p>
+    <p>
+      This notification is not subscribed to by default. Clients
+      can subscribe by including the value <tt>"CLOSING_LABELS"</tt>
+      in the list of services passed in an
+      analysis.setSubscriptions request.
+    </p>
+    
+  <h4>parameters:</h4><dl><dt class="field"><b>file: <a href="#type_FilePath">FilePath</a></b></dt><dd>
+        
+        <p>
+          The file the closing labels relate to.
+        </p>
+      </dd><dt class="field"><b>labels: List&lt;<a href="#type_ClosingLabel">ClosingLabel</a>&gt;</b></dt><dd>
+        
+        <p>
+          Closing labels relevant to the file. Each item
+          represents a useful label associated with some range
+          with may be useful to display to the user within the editor
+          at the end of the range to indicate what construct is closed
+          at that location. Closing labels include constructor/method
+          calls and List arguments that span multiple lines.
+          Note that the ranges that are returned can overlap
+          each other because they may be associated with
+          constructs that can be nested.
+        </p>
       </dd></dl></dd><dt class="notification"><a name="notification_analysis.errors">analysis.errors</a></dt><dd><div class="box"><pre>notification: {
   "event": "analysis.errors"
   "params": {
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 6cddd5e..141ef76 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -76,7 +76,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is AnalyzerStatusParams) {
+    if (other is AnalyzerStatusParams &&
+        other.runtimeType == AnalyzerStatusParams) {
       return isAnalyzing == other.isAnalyzing && true;
     }
     return false;
@@ -166,7 +167,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ClosingLabel) {
+    if (other is ClosingLabel && other.runtimeType == ClosingLabel) {
       return range == other.range && label == other.label && true;
     }
     return false;
@@ -355,7 +356,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CompletionItemResolutionInfo) {
+    if (other is CompletionItemResolutionInfo &&
+        other.runtimeType == CompletionItemResolutionInfo) {
       return file == other.file &&
           offset == other.offset &&
           libId == other.libId &&
@@ -433,7 +435,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DartDiagnosticServer) {
+    if (other is DartDiagnosticServer &&
+        other.runtimeType == DartDiagnosticServer) {
       return port == other.port && true;
     }
     return false;
@@ -580,7 +583,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Element) {
+    if (other is Element && other.runtimeType == Element) {
       return range == other.range &&
           name == other.name &&
           kind == other.kind &&
@@ -816,7 +819,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FlutterOutline) {
+    if (other is FlutterOutline && other.runtimeType == FlutterOutline) {
       return kind == other.kind &&
           label == other.label &&
           className == other.className &&
@@ -944,7 +947,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FlutterOutlineAttribute) {
+    if (other is FlutterOutlineAttribute &&
+        other.runtimeType == FlutterOutlineAttribute) {
       return name == other.name &&
           label == other.label &&
           valueRange == other.valueRange &&
@@ -1085,7 +1089,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Outline) {
+    if (other is Outline && other.runtimeType == Outline) {
       return element == other.element &&
           range == other.range &&
           codeRange == other.codeRange &&
@@ -1188,7 +1192,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is PublishClosingLabelsParams) {
+    if (other is PublishClosingLabelsParams &&
+        other.runtimeType == PublishClosingLabelsParams) {
       return uri == other.uri &&
           listEqual(labels, other.labels,
               (ClosingLabel a, ClosingLabel b) => a == b) &&
@@ -1286,7 +1291,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is PublishFlutterOutlineParams) {
+    if (other is PublishFlutterOutlineParams &&
+        other.runtimeType == PublishFlutterOutlineParams) {
       return uri == other.uri && outline == other.outline && true;
     }
     return false;
@@ -1379,7 +1385,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is PublishOutlineParams) {
+    if (other is PublishOutlineParams &&
+        other.runtimeType == PublishOutlineParams) {
       return uri == other.uri && outline == other.outline && true;
     }
     return false;
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index e4c0e70..fdafe89 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -94,7 +94,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ApplyWorkspaceEditParams) {
+    if (other is ApplyWorkspaceEditParams &&
+        other.runtimeType == ApplyWorkspaceEditParams) {
       return label == other.label && edit == other.edit && true;
     }
     return false;
@@ -182,7 +183,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ApplyWorkspaceEditResponse) {
+    if (other is ApplyWorkspaceEditResponse &&
+        other.runtimeType == ApplyWorkspaceEditResponse) {
       return applied == other.applied &&
           failureReason == other.failureReason &&
           true;
@@ -257,7 +259,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CancelParams) {
+    if (other is CancelParams && other.runtimeType == CancelParams) {
       return id == other.id && true;
     }
     return false;
@@ -356,7 +358,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ClientCapabilities) {
+    if (other is ClientCapabilities &&
+        other.runtimeType == ClientCapabilities) {
       return workspace == other.workspace &&
           textDocument == other.textDocument &&
           experimental == other.experimental &&
@@ -513,7 +516,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeAction) {
+    if (other is CodeAction && other.runtimeType == CodeAction) {
       return title == other.title &&
           kind == other.kind &&
           listEqual(diagnostics, other.diagnostics,
@@ -624,7 +627,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeActionContext) {
+    if (other is CodeActionContext && other.runtimeType == CodeActionContext) {
       return listEqual(diagnostics, other.diagnostics,
               (Diagnostic a, Diagnostic b) => a == b) &&
           listEqual(only, other.only,
@@ -772,7 +775,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeActionOptions) {
+    if (other is CodeActionOptions && other.runtimeType == CodeActionOptions) {
       return listEqual(codeActionKinds, other.codeActionKinds,
               (CodeActionKind a, CodeActionKind b) => a == b) &&
           true;
@@ -899,7 +902,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeActionParams) {
+    if (other is CodeActionParams && other.runtimeType == CodeActionParams) {
       return textDocument == other.textDocument &&
           range == other.range &&
           context == other.context &&
@@ -998,8 +1001,10 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeActionRegistrationOptions) {
-      return documentSelector == other.documentSelector &&
+    if (other is CodeActionRegistrationOptions &&
+        other.runtimeType == CodeActionRegistrationOptions) {
+      return listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           listEqual(codeActionKinds, other.codeActionKinds,
               (CodeActionKind a, CodeActionKind b) => a == b) &&
           true;
@@ -1112,7 +1117,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeLens) {
+    if (other is CodeLens && other.runtimeType == CodeLens) {
       return range == other.range &&
           command == other.command &&
           data == other.data &&
@@ -1177,7 +1182,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeLensOptions) {
+    if (other is CodeLensOptions && other.runtimeType == CodeLensOptions) {
       return resolveProvider == other.resolveProvider && true;
     }
     return false;
@@ -1248,7 +1253,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeLensParams) {
+    if (other is CodeLensParams && other.runtimeType == CodeLensParams) {
       return textDocument == other.textDocument && true;
     }
     return false;
@@ -1334,9 +1339,11 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CodeLensRegistrationOptions) {
+    if (other is CodeLensRegistrationOptions &&
+        other.runtimeType == CodeLensRegistrationOptions) {
       return resolveProvider == other.resolveProvider &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -1480,7 +1487,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Color) {
+    if (other is Color && other.runtimeType == Color) {
       return red == other.red &&
           green == other.green &&
           blue == other.blue &&
@@ -1580,7 +1587,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ColorInformation) {
+    if (other is ColorInformation && other.runtimeType == ColorInformation) {
       return range == other.range && color == other.color && true;
     }
     return false;
@@ -1695,7 +1702,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ColorPresentation) {
+    if (other is ColorPresentation && other.runtimeType == ColorPresentation) {
       return label == other.label &&
           textEdit == other.textEdit &&
           listEqual(additionalTextEdits, other.additionalTextEdits,
@@ -1822,7 +1829,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ColorPresentationParams) {
+    if (other is ColorPresentationParams &&
+        other.runtimeType == ColorPresentationParams) {
       return textDocument == other.textDocument &&
           color == other.color &&
           range == other.range &&
@@ -1869,7 +1877,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ColorProviderOptions) {
+    if (other is ColorProviderOptions &&
+        other.runtimeType == ColorProviderOptions) {
       return true;
     }
     return false;
@@ -1980,7 +1989,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Command) {
+    if (other is Command && other.runtimeType == Command) {
       return title == other.title &&
           command == other.command &&
           listEqual(
@@ -2077,7 +2086,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CompletionContext) {
+    if (other is CompletionContext && other.runtimeType == CompletionContext) {
       return triggerKind == other.triggerKind &&
           triggerCharacter == other.triggerCharacter &&
           true;
@@ -2470,7 +2479,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CompletionItem) {
+    if (other is CompletionItem && other.runtimeType == CompletionItem) {
       return label == other.label &&
           kind == other.kind &&
           detail == other.detail &&
@@ -2651,7 +2660,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CompletionList) {
+    if (other is CompletionList && other.runtimeType == CompletionList) {
       return isIncomplete == other.isIncomplete &&
           listEqual(items, other.items,
               (CompletionItem a, CompletionItem b) => a == b) &&
@@ -2737,7 +2746,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CompletionOptions) {
+    if (other is CompletionOptions && other.runtimeType == CompletionOptions) {
       return resolveProvider == other.resolveProvider &&
           listEqual(triggerCharacters, other.triggerCharacters,
               (String a, String b) => a == b) &&
@@ -2860,7 +2869,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CompletionParams) {
+    if (other is CompletionParams && other.runtimeType == CompletionParams) {
       return context == other.context &&
           textDocument == other.textDocument &&
           position == other.position &&
@@ -3014,13 +3023,15 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CompletionRegistrationOptions) {
+    if (other is CompletionRegistrationOptions &&
+        other.runtimeType == CompletionRegistrationOptions) {
       return listEqual(triggerCharacters, other.triggerCharacters,
               (String a, String b) => a == b) &&
           listEqual(allCommitCharacters, other.allCommitCharacters,
               (String a, String b) => a == b) &&
           resolveProvider == other.resolveProvider &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -3137,7 +3148,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ConfigurationItem) {
+    if (other is ConfigurationItem && other.runtimeType == ConfigurationItem) {
       return scopeUri == other.scopeUri && section == other.section && true;
     }
     return false;
@@ -3210,7 +3221,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ConfigurationParams) {
+    if (other is ConfigurationParams &&
+        other.runtimeType == ConfigurationParams) {
       return listEqual(items, other.items,
               (ConfigurationItem a, ConfigurationItem b) => a == b) &&
           true;
@@ -3325,7 +3337,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CreateFile) {
+    if (other is CreateFile && other.runtimeType == CreateFile) {
       return kind == other.kind &&
           uri == other.uri &&
           options == other.options &&
@@ -3405,7 +3417,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is CreateFileOptions) {
+    if (other is CreateFileOptions && other.runtimeType == CreateFileOptions) {
       return overwrite == other.overwrite &&
           ignoreIfExists == other.ignoreIfExists &&
           true;
@@ -3521,7 +3533,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DeleteFile) {
+    if (other is DeleteFile && other.runtimeType == DeleteFile) {
       return kind == other.kind &&
           uri == other.uri &&
           options == other.options &&
@@ -3602,7 +3614,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DeleteFileOptions) {
+    if (other is DeleteFileOptions && other.runtimeType == DeleteFileOptions) {
       return recursive == other.recursive &&
           ignoreIfNotExists == other.ignoreIfNotExists &&
           true;
@@ -3779,7 +3791,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Diagnostic) {
+    if (other is Diagnostic && other.runtimeType == Diagnostic) {
       return range == other.range &&
           severity == other.severity &&
           code == other.code &&
@@ -3895,7 +3907,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DiagnosticRelatedInformation) {
+    if (other is DiagnosticRelatedInformation &&
+        other.runtimeType == DiagnosticRelatedInformation) {
       return location == other.location && message == other.message && true;
     }
     return false;
@@ -3990,7 +4003,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidChangeConfigurationParams) {
+    if (other is DidChangeConfigurationParams &&
+        other.runtimeType == DidChangeConfigurationParams) {
       return settings == other.settings && true;
     }
     return false;
@@ -4100,7 +4114,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidChangeTextDocumentParams) {
+    if (other is DidChangeTextDocumentParams &&
+        other.runtimeType == DidChangeTextDocumentParams) {
       return textDocument == other.textDocument &&
           listEqual(
               contentChanges,
@@ -4183,7 +4198,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidChangeWatchedFilesParams) {
+    if (other is DidChangeWatchedFilesParams &&
+        other.runtimeType == DidChangeWatchedFilesParams) {
       return listEqual(
               changes, other.changes, (FileEvent a, FileEvent b) => a == b) &&
           true;
@@ -4263,7 +4279,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidChangeWatchedFilesRegistrationOptions) {
+    if (other is DidChangeWatchedFilesRegistrationOptions &&
+        other.runtimeType == DidChangeWatchedFilesRegistrationOptions) {
       return listEqual(watchers, other.watchers,
               (FileSystemWatcher a, FileSystemWatcher b) => a == b) &&
           true;
@@ -4336,7 +4353,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidChangeWorkspaceFoldersParams) {
+    if (other is DidChangeWorkspaceFoldersParams &&
+        other.runtimeType == DidChangeWorkspaceFoldersParams) {
       return event == other.event && true;
     }
     return false;
@@ -4407,7 +4425,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidCloseTextDocumentParams) {
+    if (other is DidCloseTextDocumentParams &&
+        other.runtimeType == DidCloseTextDocumentParams) {
       return textDocument == other.textDocument && true;
     }
     return false;
@@ -4478,7 +4497,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidOpenTextDocumentParams) {
+    if (other is DidOpenTextDocumentParams &&
+        other.runtimeType == DidOpenTextDocumentParams) {
       return textDocument == other.textDocument && true;
     }
     return false;
@@ -4566,7 +4586,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DidSaveTextDocumentParams) {
+    if (other is DidSaveTextDocumentParams &&
+        other.runtimeType == DidSaveTextDocumentParams) {
       return textDocument == other.textDocument && text == other.text && true;
     }
     return false;
@@ -4669,7 +4690,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentFilter) {
+    if (other is DocumentFilter && other.runtimeType == DocumentFilter) {
       return language == other.language &&
           scheme == other.scheme &&
           pattern == other.pattern &&
@@ -4773,7 +4794,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentFormattingParams) {
+    if (other is DocumentFormattingParams &&
+        other.runtimeType == DocumentFormattingParams) {
       return textDocument == other.textDocument &&
           options == other.options &&
           true;
@@ -4866,7 +4888,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentHighlight) {
+    if (other is DocumentHighlight && other.runtimeType == DocumentHighlight) {
       return range == other.range && kind == other.kind && true;
     }
     return false;
@@ -5002,7 +5024,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentLink) {
+    if (other is DocumentLink && other.runtimeType == DocumentLink) {
       return range == other.range &&
           target == other.target &&
           data == other.data &&
@@ -5067,7 +5089,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentLinkOptions) {
+    if (other is DocumentLinkOptions &&
+        other.runtimeType == DocumentLinkOptions) {
       return resolveProvider == other.resolveProvider && true;
     }
     return false;
@@ -5138,7 +5161,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentLinkParams) {
+    if (other is DocumentLinkParams &&
+        other.runtimeType == DocumentLinkParams) {
       return textDocument == other.textDocument && true;
     }
     return false;
@@ -5224,9 +5248,11 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentLinkRegistrationOptions) {
+    if (other is DocumentLinkRegistrationOptions &&
+        other.runtimeType == DocumentLinkRegistrationOptions) {
       return resolveProvider == other.resolveProvider &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -5322,7 +5348,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentOnTypeFormattingOptions) {
+    if (other is DocumentOnTypeFormattingOptions &&
+        other.runtimeType == DocumentOnTypeFormattingOptions) {
       return firstTriggerCharacter == other.firstTriggerCharacter &&
           listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
               (String a, String b) => a == b) &&
@@ -5479,7 +5506,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentOnTypeFormattingParams) {
+    if (other is DocumentOnTypeFormattingParams &&
+        other.runtimeType == DocumentOnTypeFormattingParams) {
       return textDocument == other.textDocument &&
           position == other.position &&
           ch == other.ch &&
@@ -5608,11 +5636,13 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentOnTypeFormattingRegistrationOptions) {
+    if (other is DocumentOnTypeFormattingRegistrationOptions &&
+        other.runtimeType == DocumentOnTypeFormattingRegistrationOptions) {
       return firstTriggerCharacter == other.firstTriggerCharacter &&
           listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
               (String a, String b) => a == b) &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -5739,7 +5769,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentRangeFormattingParams) {
+    if (other is DocumentRangeFormattingParams &&
+        other.runtimeType == DocumentRangeFormattingParams) {
       return textDocument == other.textDocument &&
           range == other.range &&
           options == other.options &&
@@ -5957,7 +5988,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentSymbol) {
+    if (other is DocumentSymbol && other.runtimeType == DocumentSymbol) {
       return name == other.name &&
           detail == other.detail &&
           kind == other.kind &&
@@ -6042,7 +6073,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is DocumentSymbolParams) {
+    if (other is DocumentSymbolParams &&
+        other.runtimeType == DocumentSymbolParams) {
       return textDocument == other.textDocument && true;
     }
     return false;
@@ -6150,7 +6182,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ExecuteCommandOptions) {
+    if (other is ExecuteCommandOptions &&
+        other.runtimeType == ExecuteCommandOptions) {
       return listEqual(
               commands, other.commands, (String a, String b) => a == b) &&
           true;
@@ -6240,7 +6273,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ExecuteCommandParams) {
+    if (other is ExecuteCommandParams &&
+        other.runtimeType == ExecuteCommandParams) {
       return command == other.command &&
           listEqual(
               arguments, other.arguments, (dynamic a, dynamic b) => a == b) &&
@@ -6317,7 +6351,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ExecuteCommandRegistrationOptions) {
+    if (other is ExecuteCommandRegistrationOptions &&
+        other.runtimeType == ExecuteCommandRegistrationOptions) {
       return listEqual(
               commands, other.commands, (String a, String b) => a == b) &&
           true;
@@ -6491,7 +6526,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FileEvent) {
+    if (other is FileEvent && other.runtimeType == FileEvent) {
       return uri == other.uri && type == other.type && true;
     }
     return false;
@@ -6591,7 +6626,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FileSystemWatcher) {
+    if (other is FileSystemWatcher && other.runtimeType == FileSystemWatcher) {
       return globPattern == other.globPattern && kind == other.kind && true;
     }
     return false;
@@ -6744,7 +6779,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FoldingRange) {
+    if (other is FoldingRange && other.runtimeType == FoldingRange) {
       return startLine == other.startLine &&
           startCharacter == other.startCharacter &&
           endLine == other.endLine &&
@@ -6855,7 +6890,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FoldingRangeParams) {
+    if (other is FoldingRangeParams &&
+        other.runtimeType == FoldingRangeParams) {
       return textDocument == other.textDocument && true;
     }
     return false;
@@ -6898,7 +6934,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FoldingRangeProviderOptions) {
+    if (other is FoldingRangeProviderOptions &&
+        other.runtimeType == FoldingRangeProviderOptions) {
       return true;
     }
     return false;
@@ -6993,7 +7030,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is FormattingOptions) {
+    if (other is FormattingOptions && other.runtimeType == FormattingOptions) {
       return tabSize == other.tabSize &&
           insertSpaces == other.insertSpaces &&
           true;
@@ -7090,7 +7127,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Hover) {
+    if (other is Hover && other.runtimeType == Hover) {
       return contents == other.contents && range == other.range && true;
     }
     return false;
@@ -7287,7 +7324,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is InitializeParams) {
+    if (other is InitializeParams && other.runtimeType == InitializeParams) {
       return processId == other.processId &&
           rootPath == other.rootPath &&
           rootUri == other.rootUri &&
@@ -7372,7 +7409,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is InitializeResult) {
+    if (other is InitializeResult && other.runtimeType == InitializeResult) {
       return capabilities == other.capabilities && true;
     }
     return false;
@@ -7413,7 +7450,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is InitializedParams) {
+    if (other is InitializedParams && other.runtimeType == InitializedParams) {
       return true;
     }
     return false;
@@ -7541,7 +7578,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Location) {
+    if (other is Location && other.runtimeType == Location) {
       return uri == other.uri && range == other.range && true;
     }
     return false;
@@ -7696,7 +7733,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is LocationLink) {
+    if (other is LocationLink && other.runtimeType == LocationLink) {
       return originSelectionRange == other.originSelectionRange &&
           targetUri == other.targetUri &&
           targetRange == other.targetRange &&
@@ -7798,7 +7835,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is LogMessageParams) {
+    if (other is LogMessageParams && other.runtimeType == LogMessageParams) {
       return type == other.type && message == other.message && true;
     }
     return false;
@@ -7915,7 +7952,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is MarkupContent) {
+    if (other is MarkupContent && other.runtimeType == MarkupContent) {
       return kind == other.kind && value == other.value && true;
     }
     return false;
@@ -8029,7 +8066,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Message) {
+    if (other is Message && other.runtimeType == Message) {
       return jsonrpc == other.jsonrpc && true;
     }
     return false;
@@ -8097,7 +8134,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is MessageActionItem) {
+    if (other is MessageActionItem && other.runtimeType == MessageActionItem) {
       return title == other.title && true;
     }
     return false;
@@ -8418,7 +8455,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is NotificationMessage) {
+    if (other is NotificationMessage &&
+        other.runtimeType == NotificationMessage) {
       return method == other.method &&
           params == other.params &&
           jsonrpc == other.jsonrpc &&
@@ -8530,7 +8568,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ParameterInformation) {
+    if (other is ParameterInformation &&
+        other.runtimeType == ParameterInformation) {
       return label == other.label &&
           documentation == other.documentation &&
           true;
@@ -8632,7 +8671,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Position) {
+    if (other is Position && other.runtimeType == Position) {
       return line == other.line && character == other.character && true;
     }
     return false;
@@ -8732,7 +8771,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is PublishDiagnosticsParams) {
+    if (other is PublishDiagnosticsParams &&
+        other.runtimeType == PublishDiagnosticsParams) {
       return uri == other.uri &&
           listEqual(diagnostics, other.diagnostics,
               (Diagnostic a, Diagnostic b) => a == b) &&
@@ -8829,7 +8869,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Range) {
+    if (other is Range && other.runtimeType == Range) {
       return start == other.start && end == other.end && true;
     }
     return false;
@@ -8921,7 +8961,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RangeAndPlaceholder) {
+    if (other is RangeAndPlaceholder &&
+        other.runtimeType == RangeAndPlaceholder) {
       return range == other.range && placeholder == other.placeholder && true;
     }
     return false;
@@ -8991,7 +9032,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ReferenceContext) {
+    if (other is ReferenceContext && other.runtimeType == ReferenceContext) {
       return includeDeclaration == other.includeDeclaration && true;
     }
     return false;
@@ -9116,7 +9157,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ReferenceParams) {
+    if (other is ReferenceParams && other.runtimeType == ReferenceParams) {
       return context == other.context &&
           textDocument == other.textDocument &&
           position == other.position &&
@@ -9232,7 +9273,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Registration) {
+    if (other is Registration && other.runtimeType == Registration) {
       return id == other.id &&
           method == other.method &&
           registerOptions == other.registerOptions &&
@@ -9310,7 +9351,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RegistrationParams) {
+    if (other is RegistrationParams &&
+        other.runtimeType == RegistrationParams) {
       return listEqual(registrations, other.registrations,
               (Registration a, Registration b) => a == b) &&
           true;
@@ -9450,7 +9492,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RenameFile) {
+    if (other is RenameFile && other.runtimeType == RenameFile) {
       return kind == other.kind &&
           oldUri == other.oldUri &&
           newUri == other.newUri &&
@@ -9532,7 +9574,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RenameFileOptions) {
+    if (other is RenameFileOptions && other.runtimeType == RenameFileOptions) {
       return overwrite == other.overwrite &&
           ignoreIfExists == other.ignoreIfExists &&
           true;
@@ -9595,7 +9637,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RenameOptions) {
+    if (other is RenameOptions && other.runtimeType == RenameOptions) {
       return prepareProvider == other.prepareProvider && true;
     }
     return false;
@@ -9720,7 +9762,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RenameParams) {
+    if (other is RenameParams && other.runtimeType == RenameParams) {
       return textDocument == other.textDocument &&
           position == other.position &&
           newName == other.newName &&
@@ -9810,9 +9852,11 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RenameRegistrationOptions) {
+    if (other is RenameRegistrationOptions &&
+        other.runtimeType == RenameRegistrationOptions) {
       return prepareProvider == other.prepareProvider &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -9951,7 +9995,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is RequestMessage) {
+    if (other is RequestMessage && other.runtimeType == RequestMessage) {
       return id == other.id &&
           method == other.method &&
           params == other.params &&
@@ -10107,7 +10151,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ResponseError) {
+    if (other is ResponseError && other.runtimeType == ResponseError) {
       return code == other.code &&
           message == other.message &&
           data == other.data &&
@@ -10240,7 +10284,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ResponseMessage) {
+    if (other is ResponseMessage && other.runtimeType == ResponseMessage) {
       return id == other.id &&
           result == other.result &&
           error == other.error &&
@@ -10306,7 +10350,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is SaveOptions) {
+    if (other is SaveOptions && other.runtimeType == SaveOptions) {
       return includeText == other.includeText && true;
     }
     return false;
@@ -10875,7 +10919,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ServerCapabilities) {
+    if (other is ServerCapabilities &&
+        other.runtimeType == ServerCapabilities) {
       return textDocumentSync == other.textDocumentSync &&
           hoverProvider == other.hoverProvider &&
           completionProvider == other.completionProvider &&
@@ -10992,7 +11037,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ServerCapabilitiesWorkspace) {
+    if (other is ServerCapabilitiesWorkspace &&
+        other.runtimeType == ServerCapabilitiesWorkspace) {
       return workspaceFolders == other.workspaceFolders && true;
     }
     return false;
@@ -11075,7 +11121,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ServerCapabilitiesWorkspaceFolders) {
+    if (other is ServerCapabilitiesWorkspaceFolders &&
+        other.runtimeType == ServerCapabilitiesWorkspaceFolders) {
       return supported == other.supported &&
           changeNotifications == other.changeNotifications &&
           true;
@@ -11173,7 +11220,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ShowMessageParams) {
+    if (other is ShowMessageParams && other.runtimeType == ShowMessageParams) {
       return type == other.type && message == other.message && true;
     }
     return false;
@@ -11291,7 +11338,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is ShowMessageRequestParams) {
+    if (other is ShowMessageRequestParams &&
+        other.runtimeType == ShowMessageRequestParams) {
       return type == other.type &&
           message == other.message &&
           listEqual(actions, other.actions,
@@ -11418,7 +11466,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is SignatureHelp) {
+    if (other is SignatureHelp && other.runtimeType == SignatureHelp) {
       return listEqual(signatures, other.signatures,
               (SignatureInformation a, SignatureInformation b) => a == b) &&
           activeSignature == other.activeSignature &&
@@ -11488,7 +11536,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is SignatureHelpOptions) {
+    if (other is SignatureHelpOptions &&
+        other.runtimeType == SignatureHelpOptions) {
       return listEqual(triggerCharacters, other.triggerCharacters,
               (String a, String b) => a == b) &&
           true;
@@ -11582,10 +11631,12 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is SignatureHelpRegistrationOptions) {
+    if (other is SignatureHelpRegistrationOptions &&
+        other.runtimeType == SignatureHelpRegistrationOptions) {
       return listEqual(triggerCharacters, other.triggerCharacters,
               (String a, String b) => a == b) &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -11707,7 +11758,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is SignatureInformation) {
+    if (other is SignatureInformation &&
+        other.runtimeType == SignatureInformation) {
       return label == other.label &&
           documentation == other.documentation &&
           listEqual(parameters, other.parameters,
@@ -11773,7 +11825,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is StaticRegistrationOptions) {
+    if (other is StaticRegistrationOptions &&
+        other.runtimeType == StaticRegistrationOptions) {
       return id == other.id && true;
     }
     return false;
@@ -11940,7 +11993,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is SymbolInformation) {
+    if (other is SymbolInformation && other.runtimeType == SymbolInformation) {
       return name == other.name &&
           kind == other.kind &&
           deprecated == other.deprecated &&
@@ -12101,9 +12154,11 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentChangeRegistrationOptions) {
+    if (other is TextDocumentChangeRegistrationOptions &&
+        other.runtimeType == TextDocumentChangeRegistrationOptions) {
       return syncKind == other.syncKind &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -12653,7 +12708,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilities) {
+    if (other is TextDocumentClientCapabilities &&
+        other.runtimeType == TextDocumentClientCapabilities) {
       return synchronization == other.synchronization &&
           completion == other.completion &&
           hover == other.hover &&
@@ -12784,7 +12840,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesCodeAction) {
+    if (other is TextDocumentClientCapabilitiesCodeAction &&
+        other.runtimeType == TextDocumentClientCapabilitiesCodeAction) {
       return dynamicRegistration == other.dynamicRegistration &&
           codeActionLiteralSupport == other.codeActionLiteralSupport &&
           true;
@@ -12866,7 +12923,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesCodeActionKind) {
+    if (other is TextDocumentClientCapabilitiesCodeActionKind &&
+        other.runtimeType == TextDocumentClientCapabilitiesCodeActionKind) {
       return listEqual(valueSet, other.valueSet,
               (CodeActionKind a, CodeActionKind b) => a == b) &&
           true;
@@ -12947,7 +13005,9 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesCodeActionLiteralSupport) {
+    if (other is TextDocumentClientCapabilitiesCodeActionLiteralSupport &&
+        other.runtimeType ==
+            TextDocumentClientCapabilitiesCodeActionLiteralSupport) {
       return codeActionKind == other.codeActionKind && true;
     }
     return false;
@@ -13009,7 +13069,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesCodeLens) {
+    if (other is TextDocumentClientCapabilitiesCodeLens &&
+        other.runtimeType == TextDocumentClientCapabilitiesCodeLens) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -13074,7 +13135,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesColorProvider) {
+    if (other is TextDocumentClientCapabilitiesColorProvider &&
+        other.runtimeType == TextDocumentClientCapabilitiesColorProvider) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -13197,7 +13259,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesCompletion) {
+    if (other is TextDocumentClientCapabilitiesCompletion &&
+        other.runtimeType == TextDocumentClientCapabilitiesCompletion) {
       return dynamicRegistration == other.dynamicRegistration &&
           completionItem == other.completionItem &&
           completionItemKind == other.completionItemKind &&
@@ -13354,7 +13417,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesCompletionItem) {
+    if (other is TextDocumentClientCapabilitiesCompletionItem &&
+        other.runtimeType == TextDocumentClientCapabilitiesCompletionItem) {
       return snippetSupport == other.snippetSupport &&
           commitCharactersSupport == other.commitCharactersSupport &&
           listEqual(documentationFormat, other.documentationFormat,
@@ -13437,7 +13501,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesCompletionItemKind) {
+    if (other is TextDocumentClientCapabilitiesCompletionItemKind &&
+        other.runtimeType == TextDocumentClientCapabilitiesCompletionItemKind) {
       return listEqual(valueSet, other.valueSet,
               (CompletionItemKind a, CompletionItemKind b) => a == b) &&
           true;
@@ -13524,7 +13589,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesDeclaration) {
+    if (other is TextDocumentClientCapabilitiesDeclaration &&
+        other.runtimeType == TextDocumentClientCapabilitiesDeclaration) {
       return dynamicRegistration == other.dynamicRegistration &&
           linkSupport == other.linkSupport &&
           true;
@@ -13607,7 +13673,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesDefinition) {
+    if (other is TextDocumentClientCapabilitiesDefinition &&
+        other.runtimeType == TextDocumentClientCapabilitiesDefinition) {
       return dynamicRegistration == other.dynamicRegistration &&
           linkSupport == other.linkSupport &&
           true;
@@ -13672,7 +13739,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesDocumentHighlight) {
+    if (other is TextDocumentClientCapabilitiesDocumentHighlight &&
+        other.runtimeType == TextDocumentClientCapabilitiesDocumentHighlight) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -13734,7 +13802,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesDocumentLink) {
+    if (other is TextDocumentClientCapabilitiesDocumentLink &&
+        other.runtimeType == TextDocumentClientCapabilitiesDocumentLink) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -13838,7 +13907,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesDocumentSymbol) {
+    if (other is TextDocumentClientCapabilitiesDocumentSymbol &&
+        other.runtimeType == TextDocumentClientCapabilitiesDocumentSymbol) {
       return dynamicRegistration == other.dynamicRegistration &&
           symbolKind == other.symbolKind &&
           hierarchicalDocumentSymbolSupport ==
@@ -13950,7 +14020,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesFoldingRange) {
+    if (other is TextDocumentClientCapabilitiesFoldingRange &&
+        other.runtimeType == TextDocumentClientCapabilitiesFoldingRange) {
       return dynamicRegistration == other.dynamicRegistration &&
           rangeLimit == other.rangeLimit &&
           lineFoldingOnly == other.lineFoldingOnly &&
@@ -14017,7 +14088,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesFormatting) {
+    if (other is TextDocumentClientCapabilitiesFormatting &&
+        other.runtimeType == TextDocumentClientCapabilitiesFormatting) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -14104,7 +14176,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesHover) {
+    if (other is TextDocumentClientCapabilitiesHover &&
+        other.runtimeType == TextDocumentClientCapabilitiesHover) {
       return dynamicRegistration == other.dynamicRegistration &&
           listEqual(contentFormat, other.contentFormat,
               (MarkupKind a, MarkupKind b) => a == b) &&
@@ -14193,7 +14266,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesImplementation) {
+    if (other is TextDocumentClientCapabilitiesImplementation &&
+        other.runtimeType == TextDocumentClientCapabilitiesImplementation) {
       return dynamicRegistration == other.dynamicRegistration &&
           linkSupport == other.linkSupport &&
           true;
@@ -14258,7 +14332,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesOnTypeFormatting) {
+    if (other is TextDocumentClientCapabilitiesOnTypeFormatting &&
+        other.runtimeType == TextDocumentClientCapabilitiesOnTypeFormatting) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -14324,7 +14399,9 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesParameterInformation) {
+    if (other is TextDocumentClientCapabilitiesParameterInformation &&
+        other.runtimeType ==
+            TextDocumentClientCapabilitiesParameterInformation) {
       return labelOffsetSupport == other.labelOffsetSupport && true;
     }
     return false;
@@ -14386,7 +14463,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesPublishDiagnostics) {
+    if (other is TextDocumentClientCapabilitiesPublishDiagnostics &&
+        other.runtimeType == TextDocumentClientCapabilitiesPublishDiagnostics) {
       return relatedInformation == other.relatedInformation && true;
     }
     return false;
@@ -14448,7 +14526,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesRangeFormatting) {
+    if (other is TextDocumentClientCapabilitiesRangeFormatting &&
+        other.runtimeType == TextDocumentClientCapabilitiesRangeFormatting) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -14510,7 +14589,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesReferences) {
+    if (other is TextDocumentClientCapabilitiesReferences &&
+        other.runtimeType == TextDocumentClientCapabilitiesReferences) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -14591,7 +14671,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesRename) {
+    if (other is TextDocumentClientCapabilitiesRename &&
+        other.runtimeType == TextDocumentClientCapabilitiesRename) {
       return dynamicRegistration == other.dynamicRegistration &&
           prepareSupport == other.prepareSupport &&
           true;
@@ -14681,7 +14762,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesSignatureHelp) {
+    if (other is TextDocumentClientCapabilitiesSignatureHelp &&
+        other.runtimeType == TextDocumentClientCapabilitiesSignatureHelp) {
       return dynamicRegistration == other.dynamicRegistration &&
           signatureInformation == other.signatureInformation &&
           true;
@@ -14776,7 +14858,9 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesSignatureInformation) {
+    if (other is TextDocumentClientCapabilitiesSignatureInformation &&
+        other.runtimeType ==
+            TextDocumentClientCapabilitiesSignatureInformation) {
       return listEqual(documentationFormat, other.documentationFormat,
               (MarkupKind a, MarkupKind b) => a == b) &&
           parameterInformation == other.parameterInformation &&
@@ -14852,7 +14936,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesSymbolKind) {
+    if (other is TextDocumentClientCapabilitiesSymbolKind &&
+        other.runtimeType == TextDocumentClientCapabilitiesSymbolKind) {
       return listEqual(valueSet, other.valueSet,
               (SymbolKind a, SymbolKind b) => a == b) &&
           true;
@@ -14969,7 +15054,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesSynchronization) {
+    if (other is TextDocumentClientCapabilitiesSynchronization &&
+        other.runtimeType == TextDocumentClientCapabilitiesSynchronization) {
       return dynamicRegistration == other.dynamicRegistration &&
           willSave == other.willSave &&
           willSaveWaitUntil == other.willSaveWaitUntil &&
@@ -15061,7 +15147,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentClientCapabilitiesTypeDefinition) {
+    if (other is TextDocumentClientCapabilitiesTypeDefinition &&
+        other.runtimeType == TextDocumentClientCapabilitiesTypeDefinition) {
       return dynamicRegistration == other.dynamicRegistration &&
           linkSupport == other.linkSupport &&
           true;
@@ -15168,7 +15255,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentContentChangeEvent) {
+    if (other is TextDocumentContentChangeEvent &&
+        other.runtimeType == TextDocumentContentChangeEvent) {
       return range == other.range &&
           rangeLength == other.rangeLength &&
           text == other.text &&
@@ -15276,7 +15364,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentEdit) {
+    if (other is TextDocumentEdit && other.runtimeType == TextDocumentEdit) {
       return textDocument == other.textDocument &&
           listEqual(edits, other.edits, (TextEdit a, TextEdit b) => a == b) &&
           true;
@@ -15350,7 +15438,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentIdentifier) {
+    if (other is TextDocumentIdentifier &&
+        other.runtimeType == TextDocumentIdentifier) {
       return uri == other.uri && true;
     }
     return false;
@@ -15496,7 +15585,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentItem) {
+    if (other is TextDocumentItem && other.runtimeType == TextDocumentItem) {
       return uri == other.uri &&
           languageId == other.languageId &&
           version == other.version &&
@@ -15607,7 +15696,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentPositionParams) {
+    if (other is TextDocumentPositionParams &&
+        other.runtimeType == TextDocumentPositionParams) {
       return textDocument == other.textDocument &&
           position == other.position &&
           true;
@@ -15708,8 +15798,11 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentRegistrationOptions) {
-      return documentSelector == other.documentSelector && true;
+    if (other is TextDocumentRegistrationOptions &&
+        other.runtimeType == TextDocumentRegistrationOptions) {
+      return listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
+          true;
     }
     return false;
   }
@@ -15828,9 +15921,11 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentSaveRegistrationOptions) {
+    if (other is TextDocumentSaveRegistrationOptions &&
+        other.runtimeType == TextDocumentSaveRegistrationOptions) {
       return includeText == other.includeText &&
-          documentSelector == other.documentSelector &&
+          listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
           true;
     }
     return false;
@@ -16001,7 +16096,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextDocumentSyncOptions) {
+    if (other is TextDocumentSyncOptions &&
+        other.runtimeType == TextDocumentSyncOptions) {
       return openClose == other.openClose &&
           change == other.change &&
           willSave == other.willSave &&
@@ -16105,7 +16201,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is TextEdit) {
+    if (other is TextEdit && other.runtimeType == TextEdit) {
       return range == other.range && newText == other.newText && true;
     }
     return false;
@@ -16201,7 +16297,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is Unregistration) {
+    if (other is Unregistration && other.runtimeType == Unregistration) {
       return id == other.id && method == other.method && true;
     }
     return false;
@@ -16275,7 +16371,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is UnregistrationParams) {
+    if (other is UnregistrationParams &&
+        other.runtimeType == UnregistrationParams) {
       return listEqual(unregisterations, other.unregisterations,
               (Unregistration a, Unregistration b) => a == b) &&
           true;
@@ -16372,7 +16469,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is VersionedTextDocumentIdentifier) {
+    if (other is VersionedTextDocumentIdentifier &&
+        other.runtimeType == VersionedTextDocumentIdentifier) {
       return version == other.version && uri == other.uri && true;
     }
     return false;
@@ -16500,7 +16598,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WillSaveTextDocumentParams) {
+    if (other is WillSaveTextDocumentParams &&
+        other.runtimeType == WillSaveTextDocumentParams) {
       return textDocument == other.textDocument &&
           reason == other.reason &&
           true;
@@ -16729,7 +16828,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceClientCapabilities) {
+    if (other is WorkspaceClientCapabilities &&
+        other.runtimeType == WorkspaceClientCapabilities) {
       return applyEdit == other.applyEdit &&
           workspaceEdit == other.workspaceEdit &&
           didChangeConfiguration == other.didChangeConfiguration &&
@@ -16807,7 +16907,9 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceClientCapabilitiesDidChangeConfiguration) {
+    if (other is WorkspaceClientCapabilitiesDidChangeConfiguration &&
+        other.runtimeType ==
+            WorkspaceClientCapabilitiesDidChangeConfiguration) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -16872,7 +16974,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceClientCapabilitiesDidChangeWatchedFiles) {
+    if (other is WorkspaceClientCapabilitiesDidChangeWatchedFiles &&
+        other.runtimeType == WorkspaceClientCapabilitiesDidChangeWatchedFiles) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -16934,7 +17037,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceClientCapabilitiesExecuteCommand) {
+    if (other is WorkspaceClientCapabilitiesExecuteCommand &&
+        other.runtimeType == WorkspaceClientCapabilitiesExecuteCommand) {
       return dynamicRegistration == other.dynamicRegistration && true;
     }
     return false;
@@ -17016,7 +17120,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceClientCapabilitiesSymbol) {
+    if (other is WorkspaceClientCapabilitiesSymbol &&
+        other.runtimeType == WorkspaceClientCapabilitiesSymbol) {
       return dynamicRegistration == other.dynamicRegistration &&
           symbolKind == other.symbolKind &&
           true;
@@ -17091,7 +17196,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceClientCapabilitiesSymbolKind) {
+    if (other is WorkspaceClientCapabilitiesSymbolKind &&
+        other.runtimeType == WorkspaceClientCapabilitiesSymbolKind) {
       return listEqual(valueSet, other.valueSet,
               (SymbolKind a, SymbolKind b) => a == b) &&
           true;
@@ -17201,7 +17307,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceClientCapabilitiesWorkspaceEdit) {
+    if (other is WorkspaceClientCapabilitiesWorkspaceEdit &&
+        other.runtimeType == WorkspaceClientCapabilitiesWorkspaceEdit) {
       return documentChanges == other.documentChanges &&
           listEqual(resourceOperations, other.resourceOperations,
               (ResourceOperationKind a, ResourceOperationKind b) => a == b) &&
@@ -17335,9 +17442,12 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceEdit) {
-      return mapEqual(changes, other.changes,
-              (List<TextEdit> a, List<TextEdit> b) => a == b) &&
+    if (other is WorkspaceEdit && other.runtimeType == WorkspaceEdit) {
+      return mapEqual(
+              changes,
+              other.changes,
+              (List<TextEdit> a, List<TextEdit> b) =>
+                  listEqual(a, b, (TextEdit a, TextEdit b) => a == b)) &&
           documentChanges == other.documentChanges &&
           true;
     }
@@ -17433,7 +17543,7 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceFolder) {
+    if (other is WorkspaceFolder && other.runtimeType == WorkspaceFolder) {
       return uri == other.uri && name == other.name && true;
     }
     return false;
@@ -17540,7 +17650,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceFoldersChangeEvent) {
+    if (other is WorkspaceFoldersChangeEvent &&
+        other.runtimeType == WorkspaceFoldersChangeEvent) {
       return listEqual(added, other.added,
               (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
           listEqual(removed, other.removed,
@@ -17614,7 +17725,8 @@
 
   @override
   bool operator ==(Object other) {
-    if (other is WorkspaceSymbolParams) {
+    if (other is WorkspaceSymbolParams &&
+        other.runtimeType == WorkspaceSymbolParams) {
       return query == other.query && true;
     }
     return false;
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ffb863f7..f712b61 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -29,14 +29,11 @@
 import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
 import 'package:analysis_server/src/domains/analysis/occurrences.dart';
 import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
-import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
 import 'package:analysis_server/src/edit/edit_domain.dart';
 import 'package:analysis_server/src/flutter/flutter_domain.dart';
 import 'package:analysis_server/src/flutter/flutter_notifications.dart';
 import 'package:analysis_server/src/operation/operation_analysis.dart';
 import 'package:analysis_server/src/plugin/notification_manager.dart';
-import 'package:analysis_server/src/plugin/plugin_manager.dart';
-import 'package:analysis_server/src/plugin/plugin_watcher.dart';
 import 'package:analysis_server/src/protocol_server.dart' as server;
 import 'package:analysis_server/src/search/search_domain.dart';
 import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
@@ -46,30 +43,20 @@
 import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/server/sdk_configuration.dart';
 import 'package:analysis_server/src/services/flutter/widget_descriptions.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analysis_server/src/services/search/search_engine_internal.dart';
-import 'package:analysis_server/src/utilities/file_string_sink.dart';
-import 'package:analysis_server/src/utilities/null_string_sink.dart';
 import 'package:analysis_server/src/utilities/request_statistics.dart';
-import 'package:analysis_server/src/utilities/tee_string_sink.dart';
-import 'package:analyzer/dart/analysis/features.dart' as analyzer_features;
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/overlay_file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/status.dart' as nd;
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
 import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
 import 'package:telemetry/crash_reporting.dart';
@@ -85,17 +72,6 @@
   /// be sent.
   final ServerCommunicationChannel channel;
 
-  /// The object used to manage sending a subset of notifications to the client.
-  /// The subset of notifications are those to which plugins may contribute.
-  /// This field is `null` when the new plugin support is disabled.
-  NotificationManager notificationManager;
-
-  /// The object used to manage the execution of plugins.
-  PluginManager pluginManager;
-
-  /// The [SearchEngine] for this server, may be `null` if indexing is disabled.
-  SearchEngine searchEngine;
-
   /// A flag indicating the value of the 'analyzing' parameter sent in the last
   /// status message to the client.
   bool statusAnalyzing = false;
@@ -104,15 +80,6 @@
   /// server.
   List<RequestHandler> handlers;
 
-  /// The object used to manage the SDK's known to this server.
-  final DartSdkManager sdkManager;
-
-  /// The instrumentation service that is to be used by this analysis server.
-  final InstrumentationService instrumentationService;
-
-  /// The helper for tracking request / response statistics.
-  final RequestStatisticsHelper requestStatistics;
-
   /// A set of the [ServerService]s to send notifications for.
   Set<ServerService> serverServices = HashSet<ServerService>();
 
@@ -145,12 +112,6 @@
   /// `null`.
   Set<String> prevAnalyzedFiles;
 
-  /// The default options used to create new analysis contexts. This object is
-  /// also referenced by the ContextManager.
-  final AnalysisOptionsImpl defaultContextOptions = AnalysisOptionsImpl();
-
-  PerformanceLog _analysisPerformanceLogger;
-
   /// The controller for [onAnalysisSetChanged].
   final StreamController _onAnalysisSetChangedController =
       StreamController.broadcast(sync: true);
@@ -168,67 +129,29 @@
     this.channel,
     ResourceProvider baseResourceProvider,
     AnalysisServerOptions options,
-    this.sdkManager,
+    DartSdkManager sdkManager,
     CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
-    this.instrumentationService, {
-    this.requestStatistics,
+    InstrumentationService instrumentationService, {
+    RequestStatisticsHelper requestStatistics,
     DiagnosticServer diagnosticServer,
     this.detachableFileSystemManager,
-  }) : super(options, diagnosticServer, crashReportingAttachmentsBuilder,
-            baseResourceProvider) {
-    notificationManager = NotificationManager(channel, resourceProvider);
-
-    pluginManager = PluginManager(
-        resourceProvider,
-        _getByteStorePath(),
-        sdkManager.defaultSdkDirectory,
-        notificationManager,
-        instrumentationService);
-    var pluginWatcher = PluginWatcher(resourceProvider, pluginManager);
-
-    defaultContextOptions.contextFeatures =
-        analyzer_features.FeatureSet.fromEnableFlags(
-            options.enabledExperiments);
-    defaultContextOptions.generateImplicitErrors = false;
-    defaultContextOptions.useFastaParser = options.useFastaParser;
-
-    {
-      var name = options.newAnalysisDriverLog;
-      StringSink sink = NullStringSink();
-      if (name != null) {
-        if (name == 'stdout') {
-          sink = io.stdout;
-        } else if (name.startsWith('file:')) {
-          var path = name.substring('file:'.length);
-          sink = FileStringSink(path);
-        }
-      }
-      if (requestStatistics != null) {
-        sink = TeeStringSink(sink, requestStatistics.perfLoggerStringSink);
-      }
-      _analysisPerformanceLogger = PerformanceLog(sink);
-    }
-
-    byteStore = createByteStore(resourceProvider);
-
-    analysisDriverScheduler = nd.AnalysisDriverScheduler(
-        _analysisPerformanceLogger,
-        driverWatcher: pluginWatcher);
-    analysisDriverScheduler.status.listen(sendStatusNotificationNew);
-    analysisDriverScheduler.start();
-
-    if (options.featureSet.completion) {
-      declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
-      declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
-      analysisDriverScheduler.outOfBandWorker =
-          CompletionLibrariesWorker(declarationsTracker);
-    }
-
-    contextManager = ContextManagerImpl(resourceProvider, sdkManager,
-        analyzedFilesGlobs, instrumentationService, defaultContextOptions);
+  }) : super(
+          options,
+          sdkManager,
+          diagnosticServer,
+          crashReportingAttachmentsBuilder,
+          baseResourceProvider,
+          instrumentationService,
+          NotificationManager(channel, baseResourceProvider.pathContext),
+          requestStatistics: requestStatistics,
+        ) {
     var contextManagerCallbacks =
         ServerContextManagerCallbacks(this, resourceProvider);
     contextManager.callbacks = contextManagerCallbacks;
+
+    analysisDriverScheduler.status.listen(sendStatusNotificationNew);
+    analysisDriverScheduler.start();
+
     _onAnalysisStartedController = StreamController.broadcast();
     onAnalysisStarted.first.then((_) {
       onAnalysisComplete.then((_) {
@@ -236,7 +159,6 @@
         performance = performanceAfterStartup;
       });
     });
-    searchEngine = SearchEngineImpl(driverMap.values);
     var notification =
         ServerConnectedParams(PROTOCOL_VERSION, io.pid).toNotification();
     channel.sendNotification(notification);
@@ -664,22 +586,6 @@
 //    });
   }
 
-  /// Return the path to the location of the byte store on disk, or `null` if
-  /// there is no on-disk byte store.
-  String _getByteStorePath() {
-    ResourceProvider provider = resourceProvider;
-    if (provider is OverlayResourceProvider) {
-      provider = (provider as OverlayResourceProvider).baseProvider;
-    }
-    if (provider is PhysicalResourceProvider) {
-      var stateLocation = provider.getStateLocation('.analysis-driver');
-      if (stateLocation != null) {
-        return stateLocation.path;
-      }
-    }
-    return null;
-  }
-
   /// Returns `true` if there is a subscription for the given [service] and
   /// [file].
   bool _hasAnalysisServiceSubscription(AnalysisService service, String file) {
@@ -941,7 +847,7 @@
         resourceProvider, analysisServer.sdkManager, null,
         options: builderOptions);
     builder.analysisDriverScheduler = analysisServer.analysisDriverScheduler;
-    builder.performanceLog = analysisServer._analysisPerformanceLogger;
+    builder.performanceLog = analysisServer.analysisPerformanceLogger;
     builder.byteStore = analysisServer.byteStore;
     builder.enableIndex = true;
     return builder;
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 93975bf..98f4efe 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -4,15 +4,26 @@
 
 import 'dart:async';
 import 'dart:core';
+import 'dart:io' as io;
 
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/collections.dart';
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
+import 'package:analysis_server/src/plugin/notification_manager.dart';
+import 'package:analysis_server/src/plugin/plugin_manager.dart';
+import 'package:analysis_server/src/plugin/plugin_watcher.dart';
 import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
 import 'package:analysis_server/src/server/diagnostic_server.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/search/element_visitors.dart';
+import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/services/search/search_engine_internal.dart';
+import 'package:analysis_server/src/utilities/file_string_sink.dart';
+import 'package:analysis_server/src/utilities/null_string_sink.dart';
+import 'package:analysis_server/src/utilities/request_statistics.dart';
+import 'package:analysis_server/src/utilities/tee_string_sink.dart';
+import 'package:analyzer/dart/analysis/features.dart' as analyzer_features;
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -21,16 +32,19 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/overlay_file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
 import 'package:analyzer/src/dart/analysis/file_byte_store.dart'
     show EvictingFileByteStore;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
+import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/status.dart' as nd;
 import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer/src/util/glob.dart';
 
@@ -47,6 +61,24 @@
   /// context directories.
   ContextManager contextManager;
 
+  /// The default options used to create new analysis contexts. This object is
+  /// also referenced by the ContextManager.
+  final AnalysisOptionsImpl defaultContextOptions = AnalysisOptionsImpl();
+
+  /// The object used to manage sending a subset of notifications to the client.
+  /// The subset of notifications are those to which plugins may contribute.
+  /// This field is `null` when the new plugin support is disabled.
+  NotificationManager notificationManager;
+
+  /// The object used to manage the execution of plugins.
+  PluginManager pluginManager;
+
+  /// The object used to manage the SDK's known to this server.
+  final DartSdkManager sdkManager;
+
+  /// The [SearchEngine] for this server, may be `null` if indexing is disabled.
+  SearchEngine searchEngine;
+
   ByteStore byteStore;
 
   nd.AnalysisDriverScheduler analysisDriverScheduler;
@@ -63,6 +95,9 @@
   /// server.
   final RecentBuffer<ServerException> exceptions = RecentBuffer(10);
 
+  /// The instrumentation service that is to be used by this analysis server.
+  InstrumentationService instrumentationService;
+
   /// Performance information after initial analysis is complete
   /// or `null` if the initial analysis is not yet complete
   ServerPerformance performanceAfterStartup;
@@ -75,6 +110,10 @@
   /// Performance information before initial analysis is complete.
   final ServerPerformance performanceDuringStartup = ServerPerformance();
 
+  RequestStatisticsHelper requestStatistics;
+
+  PerformanceLog analysisPerformanceLogger;
+
   /// The set of the files that are currently priority.
   final Set<String> priorityFiles = <String>{};
 
@@ -98,12 +137,63 @@
   List<Glob> _analyzedFilesGlobs;
 
   AbstractAnalysisServer(
-      this.options,
-      this.diagnosticServer,
-      this.crashReportingAttachmentsBuilder,
-      ResourceProvider baseResourceProvider)
-      : resourceProvider = OverlayResourceProvider(baseResourceProvider) {
+    this.options,
+    this.sdkManager,
+    this.diagnosticServer,
+    this.crashReportingAttachmentsBuilder,
+    ResourceProvider baseResourceProvider,
+    this.instrumentationService,
+    this.notificationManager, {
+    this.requestStatistics,
+  }) : resourceProvider = OverlayResourceProvider(baseResourceProvider) {
     performance = performanceDuringStartup;
+
+    pluginManager = PluginManager(
+        resourceProvider,
+        _getByteStorePath(),
+        sdkManager.defaultSdkDirectory,
+        notificationManager,
+        instrumentationService);
+    var pluginWatcher = PluginWatcher(resourceProvider, pluginManager);
+
+    defaultContextOptions.contextFeatures =
+        analyzer_features.FeatureSet.fromEnableFlags(
+            options.enabledExperiments);
+    defaultContextOptions.useFastaParser = options.useFastaParser;
+
+    {
+      var name = options.newAnalysisDriverLog;
+      StringSink sink = NullStringSink();
+      if (name != null) {
+        if (name == 'stdout') {
+          sink = io.stdout;
+        } else if (name.startsWith('file:')) {
+          var path = name.substring('file:'.length);
+          sink = FileStringSink(path);
+        }
+      }
+      if (requestStatistics != null) {
+        sink = TeeStringSink(sink, requestStatistics.perfLoggerStringSink);
+      }
+      analysisPerformanceLogger = PerformanceLog(sink);
+    }
+
+    byteStore = createByteStore(resourceProvider);
+
+    analysisDriverScheduler = nd.AnalysisDriverScheduler(
+        analysisPerformanceLogger,
+        driverWatcher: pluginWatcher);
+
+    if (options.featureSet.completion) {
+      declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+      declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+      analysisDriverScheduler.outOfBandWorker =
+          CompletionLibrariesWorker(declarationsTracker);
+    }
+
+    contextManager = ContextManagerImpl(resourceProvider, sdkManager,
+        analyzedFilesGlobs, instrumentationService, defaultContextOptions);
+    searchEngine = SearchEngineImpl(driverMap.values);
   }
 
   /// Return a list of the globs used to determine which files should be
@@ -333,4 +423,20 @@
     declarationsTracker?.discardContext(driver.analysisContext);
     declarationsTracker?.addContext(driver.analysisContext);
   }
+
+  /// Return the path to the location of the byte store on disk, or `null` if
+  /// there is no on-disk byte store.
+  String _getByteStorePath() {
+    ResourceProvider provider = resourceProvider;
+    if (provider is OverlayResourceProvider) {
+      provider = (provider as OverlayResourceProvider).baseProvider;
+    }
+    if (provider is PhysicalResourceProvider) {
+      var stateLocation = provider.getStateLocation('.analysis-driver');
+      if (stateLocation != null) {
+        return stateLocation.path;
+      }
+    }
+    return null;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/domain_abstract.dart b/pkg/analysis_server/lib/src/domain_abstract.dart
index 1bf5c678..fc0b989 100644
--- a/pkg/analysis_server/lib/src/domain_abstract.dart
+++ b/pkg/analysis_server/lib/src/domain_abstract.dart
@@ -7,6 +7,7 @@
 import 'dart:math' as math;
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/analysis_server_abstract.dart';
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/protocol_server.dart' hide Element;
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
@@ -15,13 +16,21 @@
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
 
 /// An abstract implementation of a request handler.
-abstract class AbstractRequestHandler implements RequestHandler {
+abstract class AbstractRequestHandler
+    with RequestHandlerMixin<AnalysisServer>
+    implements RequestHandler {
   /// The analysis server that is using this handler to process requests.
+  @override
   final AnalysisServer server;
 
   /// Initialize a newly created request handler to be associated with the given
   /// analysis [server].
   AbstractRequestHandler(this.server);
+}
+
+mixin RequestHandlerMixin<T extends AbstractAnalysisServer> {
+  /// The analysis server that is using this handler to process requests.
+  T get server;
 
   /// Given a mapping from plugins to futures that will complete when the plugin
   /// has responded to a request, wait for a finite amount of time for each of
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 5eff309..1527b5b 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -93,6 +93,7 @@
       performance.logStartTime(COMPUTE_SUGGESTIONS_TAG);
 
       var manager = DartCompletionManager(
+        dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(request.result),
         includedElementKinds: includedElementKinds,
         includedElementNames: includedElementNames,
         includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index d063871..82bb849 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -251,6 +251,7 @@
   }
 
   Future<bool> rerunTasks([List<String> changedPaths]) async {
+    listener.reset();
     if (changedPaths == null) {
       final drivers = <AnalysisDriver>{};
       for (var path in getPathsToProcess()) {
diff --git a/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart b/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
index aad1d10..a711888 100644
--- a/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
@@ -88,4 +88,15 @@
         result.path, offset, length, locInfo.lineNumber, locInfo.columnNumber);
     return location;
   }
+
+  /// Reset this listener so that it can accrue a new set of changes.
+  void reset() {
+    suggestions.clear();
+    otherSuggestions.clear();
+    sourceChange
+      ..edits.clear()
+      ..linkedEditGroups.clear()
+      ..selection = null
+      ..id = null;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index 4d3b523..35c6e54 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -28,6 +28,8 @@
   /// mature enough.
   static const bool _usePermissiveMode = true;
 
+  final int preferredPort;
+
   final DartFixListener listener;
 
   /// The root of the included paths.
@@ -59,7 +61,8 @@
 
   Future<void> Function([List<String>]) rerunFunction;
 
-  NonNullableFix(this.listener, {List<String> included = const []})
+  NonNullableFix(this.listener,
+      {List<String> included = const [], this.preferredPort})
       : includedRoot =
             _getIncludedRoot(included, listener.server.resourceProvider) {
     reset();
@@ -70,6 +73,7 @@
 
   /// Return a list of the URLs corresponding to the included roots.
   List<String> get previewUrls => [
+        // TODO(jcollins-g): Change protocol to only return a single string.
         Uri(
             scheme: 'http',
             host: 'localhost',
@@ -85,7 +89,7 @@
     await state.refresh();
 
     if (server == null) {
-      server = HttpPreviewServer(state, rerun);
+      server = HttpPreviewServer(state, rerun, preferredPort);
       server.serveHttp();
       port = await server.boundPort;
       authToken = await server.authToken;
@@ -243,8 +247,8 @@
 
   static void task(DartFixRegistrar registrar, DartFixListener listener,
       EditDartfixParams params) {
-    registrar
-        .registerCodeTask(NonNullableFix(listener, included: params.included));
+    registrar.registerCodeTask(NonNullableFix(listener,
+        included: params.included, preferredPort: params.port));
   }
 
   /// Get the "root" of all [included] paths. See [includedRoot] for its
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
index a4a89b4..4c1bbe1 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
@@ -11,16 +11,15 @@
 import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
-import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     show SourceFileEdit;
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
 import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
@@ -125,324 +124,6 @@
         'Reason', [_makeTraceEntry(info.description, info.codeReference)]));
   }
 
-  /// Return detail text for a fix built from an edge with origin info [origin]
-  /// and [fixKind].
-  ///
-  /// Text is meant to be used as the beginning of a sentence. It is written in
-  /// present tense, beginning with a capital letter, not ending in a period.
-  String _baseDescriptionForOrigin(
-      EdgeOriginInfo origin, NullabilityFixKind fixKind) {
-    var node = origin.node;
-    var parent = node.parent;
-
-    String aNullableDefault(DefaultFormalParameter node) {
-      var defaultValue = node.defaultValue;
-      if (defaultValue == null) {
-        return "an implicit default value of 'null'";
-      } else if (defaultValue is NullLiteral) {
-        return "an explicit default value of 'null'";
-      }
-      return 'a nullable default value';
-    }
-
-    if (node is DefaultFormalParameter) {
-      if (fixKind == NullabilityFixKind.addRequired) {
-        return 'This parameter is non-nullable, so cannot have '
-            '${aNullableDefault(node)}';
-      } else {
-        return 'This parameter has ${aNullableDefault(node)}';
-      }
-    } else if (node is FieldFormalParameter) {
-      if (parent is DefaultFormalParameter) {
-        return 'This field is initialized by an optional field formal '
-            'parameter that has ${aNullableDefault(parent)}';
-      }
-      return 'This field is initialized by a field formal parameter and a '
-          'nullable value is passed as an argument';
-    } else if (parent is DefaultFormalParameter) {
-      return 'This parameter has ${aNullableDefault(parent)}';
-    } else if (parent is AsExpression) {
-      return 'The value of the expression is nullable';
-    }
-
-    if (origin.kind == EdgeOriginKind.listLengthConstructor) {
-      return 'A length is specified in the "List()" constructor and the list '
-          'items are initialized to null';
-    }
-    if (origin.kind == EdgeOriginKind.typeParameterInstantiation) {
-      return 'This type parameter is instantiated with a nullable type';
-    }
-    if (origin.kind == EdgeOriginKind.inferredTypeParameterInstantiation) {
-      return 'This type parameter is instantiated with an inferred nullable '
-          'type';
-    }
-
-    var unit = node.thisOrAncestorOfType<CompilationUnit>();
-    var lineNumber = unit.lineInfo.getLocation(node.offset).lineNumber;
-
-    if (origin.kind == EdgeOriginKind.uninitializedRead) {
-      return 'Used on line $lineNumber, when it is possibly uninitialized';
-    } else if (origin.kind == EdgeOriginKind.implicitNullReturn) {
-      return 'This function contains a return statement with no value on line '
-          '$lineNumber, which implicitly returns null.';
-    }
-
-    // Text indicating the type of nullable value found.
-    String nullableValue;
-    if (node is NullLiteral) {
-      nullableValue = "an explicit 'null'";
-    } else if (origin.kind == EdgeOriginKind.dynamicAssignment) {
-      nullableValue = 'a dynamic value, which is nullable';
-    } else {
-      nullableValue = 'a nullable value';
-    }
-
-    /// If the [node] is inside the return expression for a function body,
-    /// return the function body. Otherwise return `null`.
-    FunctionBody findFunctionBody() {
-      if (parent is ExpressionFunctionBody) {
-        return parent;
-      } else {
-        var returnNode = parent.thisOrAncestorOfType<ReturnStatement>();
-        var bodyNode = returnNode?.thisOrAncestorOfType<BlockFunctionBody>();
-        return bodyNode;
-      }
-    }
-
-    /// If the [node] is inside a collection literal, return it. Otherwise
-    /// return `null`.
-    TypedLiteral findCollectionLiteral() {
-      var ancestor = parent;
-      // Walk up collection elements, except for collection literals.
-      while (ancestor is CollectionElement && ancestor is! TypedLiteral) {
-        ancestor = ancestor.parent;
-      }
-      return (ancestor is TypedLiteral) ? ancestor : null;
-    }
-
-    var functionBody = findFunctionBody();
-    if (functionBody != null) {
-      var function = functionBody.parent;
-      if (function is MethodDeclaration) {
-        if (function.isGetter) {
-          return 'This getter returns $nullableValue on line $lineNumber';
-        }
-        return 'This method returns $nullableValue on line $lineNumber';
-      }
-      return 'This function returns $nullableValue on line $lineNumber';
-    }
-
-    var collectionLiteral = findCollectionLiteral();
-    if (collectionLiteral != null) {
-      if (collectionLiteral is ListLiteral) {
-        return 'This list is initialized with $nullableValue on line '
-            '$lineNumber';
-      } else if (collectionLiteral is SetOrMapLiteral) {
-        var mapOrSet = collectionLiteral.isMap ? 'map' : 'set';
-        return 'This $mapOrSet is initialized with $nullableValue on line '
-            '$lineNumber';
-      }
-    } else if (node is InvocationExpression &&
-        origin.kind == EdgeOriginKind.namedParameterNotSupplied) {
-      return 'This named parameter is omitted in a call to this function';
-    } else if (parent is ArgumentList) {
-      return capitalize('$nullableValue is passed as an argument');
-    } else if (parent is VariableDeclaration) {
-      var grandparent = parent.parent?.parent;
-      if (grandparent is FieldDeclaration) {
-        return 'This field is initialized to $nullableValue';
-      }
-      return 'This variable is initialized to $nullableValue';
-    } else if (origin.kind == EdgeOriginKind.fieldNotInitialized) {
-      if (node is ConstructorDeclaration) {
-        var constructorName = node.declaredElement.enclosingElement.displayName;
-        if (node.declaredElement.displayName.isNotEmpty) {
-          constructorName =
-              '$constructorName.${node.declaredElement.displayName}';
-        }
-        return "The constructor '$constructorName' does not initialize this "
-            'field in its initializer list';
-      } else {
-        return 'This field is not initialized';
-      }
-    }
-
-    var enclosingMemberDescription = buildEnclosingMemberDescription(node);
-    if (enclosingMemberDescription != null) {
-      return capitalize(
-          '$nullableValue is assigned in $enclosingMemberDescription');
-    } else {
-      assert(false, 'no enclosing member description');
-      return capitalize('$nullableValue is assigned');
-    }
-  }
-
-  /// Return a description of the given [origin].
-  String _buildDescriptionForOrigin(
-      EdgeOriginInfo origin, NullabilityFixKind fixKind) {
-    var description = _baseDescriptionForOrigin(origin, fixKind);
-    if (_inTestCode(origin.node)) {
-      // TODO(brianwilkerson) Don't add this if the graph node with which the
-      //  origin is associated is also in test code.
-      description += ' in test code';
-    }
-    return description;
-  }
-
-  /// Return a description of the given [origin] associated with the [edge].
-  RegionDetail _buildDetailForOrigin(
-      EdgeOriginInfo origin, EdgeInfo edge, NullabilityFixKind fixKind) {
-    var node = origin.node;
-    NavigationTarget target;
-    var type = info.typeAnnotationForNode(edge.sourceNode);
-    var typeParent = type?.parent;
-
-    if (typeParent is GenericFunctionType && type == typeParent.returnType) {
-      var description =
-          'A function-typed value with a nullable return type is assigned';
-      target = _proximateTargetForNode(origin.source.fullName, node);
-      return RegionDetail(description, target);
-    }
-    if (typeParent is FormalParameter) {
-      FormalParameterList parameterList =
-          typeParent.parent is DefaultFormalParameter
-              ? typeParent.parent.parent
-              : typeParent.parent;
-      if (parameterList.parent is GenericFunctionType) {
-        var description =
-            'The function-typed element in which this parameter is declared is '
-            'assigned to a function whose matching parameter is nullable';
-        target = _proximateTargetForNode(origin.source.fullName, node);
-        return RegionDetail(description, target);
-      }
-    }
-
-    // Some nodes don't need a target; default formal parameters
-    // without explicit default values, for example.
-    if (node is DefaultFormalParameter && node.defaultValue == null) {
-      target = null;
-    } else {
-      if (origin.kind == EdgeOriginKind.parameterInheritance ||
-          origin.kind == EdgeOriginKind.returnTypeInheritance) {
-        // The node is the method declaration in the subclass and we want to
-        // link to the either the corresponding parameter in the declaration in
-        // the superclass, or the return type in the declaration in that
-        // subclass.
-        if (type != null) {
-          var unit = type.thisOrAncestorOfType<CompilationUnit>();
-          target = _proximateTargetForNode(
-              unit.declaredElement.source.fullName, type);
-        }
-        var description = _buildInheritanceDescriptionForOrigin(origin, type);
-        return RegionDetail(description, target);
-      } else {
-        target = _proximateTargetForNode(origin.source.fullName, node);
-      }
-    }
-    return RegionDetail(_buildDescriptionForOrigin(origin, fixKind), target);
-  }
-
-  String _buildInheritanceDescriptionForOrigin(
-      EdgeOriginInfo origin, TypeAnnotation type) {
-    if (origin.kind == EdgeOriginKind.parameterInheritance) {
-      var overriddenName = 'the overridden method';
-      if (type != null && type.parent is FormalParameter) {
-        FormalParameter parameter = type.parent;
-        if (parameter.parent is DefaultFormalParameter) {
-          parameter = parameter.parent;
-        }
-        if (parameter.parent is FormalParameterList &&
-            parameter.parent.parent is MethodDeclaration) {
-          MethodDeclaration method = parameter.parent.parent;
-          var methodName = method.name.name;
-          ClassOrMixinDeclaration cls = method.parent;
-          var className = cls.name.name;
-          overriddenName += ', $className.$methodName,';
-        }
-      }
-      return 'The corresponding parameter in $overriddenName is nullable';
-    } else {
-      return 'An overridding method has a nullable return value';
-    }
-  }
-
-  /// Compute the details for the fix with the given [edit].
-  List<RegionDetail> _computeDetails(AtomicEdit edit) {
-    var details = <RegionDetail>[];
-    var fixInfo = edit.info;
-    for (var reason in fixInfo?.fixReasons ?? []) {
-      if (reason == null) {
-        // Sometimes reasons are null, so just ignore them (see for example the
-        // test case InfoBuilderTest.test_discardCondition.  If only we had
-        // NNBD, we could have prevented this!
-        // TODO(paulberry): fix this so that it will never happen.
-      } else if (reason is NullabilityNodeInfo) {
-        if (reason.isExactNullable) {
-          // When the node is exact nullable, that nullability propagated from
-          // downstream.
-          for (var edge in reason.downstreamEdges) {
-            final exactNullableDownstream = edge.destinationNode;
-            if (!exactNullableDownstream.isExactNullable) {
-              // This wasn't the source of the nullability.
-              continue;
-            }
-
-            var nodeInfo = info.nodeInfoFor(exactNullableDownstream);
-            if (nodeInfo != null) {
-              // TODO(mfairhurst): Give a better text description.
-              details.add(RegionDetail(
-                  'This is later required to accept null.',
-                  _proximateTargetForNode(
-                      nodeInfo.filePath, nodeInfo.astNode)));
-            } else {
-              final description =
-                  'exact nullable node with no info ($exactNullableDownstream)';
-              assert(false, description);
-              details.add(RegionDetail(description, null));
-            }
-          }
-        }
-
-        for (var edge in upstreamTriggeredEdges(reason)) {
-          var origin = info.edgeOrigin[edge];
-          if (origin != null) {
-            details.add(
-                _buildDetailForOrigin(origin, edge, fixInfo.description.kind));
-          } else {
-            final description = 'upstream edge with no origin ($edge)';
-            assert(false, description);
-            details.add(RegionDetail(description, null));
-          }
-        }
-      } else if (reason is EdgeInfo) {
-        var destination = reason.destinationNode;
-        var nodeInfo = info.nodeInfoFor(destination);
-        var edge = info.edgeOrigin[reason];
-        if (destination == info.never) {
-          details.add(RegionDetail(_describeNonNullEdge(edge), null));
-        } else if (nodeInfo != null && nodeInfo.astNode != null) {
-          NavigationTarget target;
-          if (destination != info.always) {
-            target =
-                _proximateTargetForNode(nodeInfo.filePath, nodeInfo.astNode);
-          }
-          details.add(RegionDetail(_describeNonNullEdge(edge), target));
-        } else {
-          // Likely an assignment to a migrated type.
-          final description = 'node with no info ($destination)';
-          assert(false, description);
-          details.add(RegionDetail(description, null));
-        }
-      } else if (reason is SimpleFixReasonInfo) {
-        details.add(RegionDetail(reason.description, null));
-      } else {
-        throw UnimplementedError(
-            'Unexpected class of reason: ${reason.runtimeType}');
-      }
-    }
-    return details;
-  }
-
   /// Return an edit that can be applied.
   List<EditDetail> _computeEdits(AtomicEditInfo fixInfo, int offset) {
     var edits = <EditDetail>[];
@@ -457,22 +138,36 @@
       case NullabilityFixKind.checkExpression:
         // TODO(brianwilkerson) Determine whether we can know that the fix is
         //  associated with a parameter and insert an assert if it is.
-        edits.add(EditDetail('Force null check.', offset, 0, '/*!*/'));
+        edits.add(EditDetail('Add /*!*/ hint', offset, 0, '/*!*/'));
         break;
-      case NullabilityFixKind.discardCondition:
-      case NullabilityFixKind.discardElse:
-      case NullabilityFixKind.discardIf:
-      case NullabilityFixKind.discardThen:
+      case NullabilityFixKind.checkExpressionDueToHint:
+        edits.add(EditDetail('Remove /*!*/ hint', offset, 5, ''));
+        break;
+      case NullabilityFixKind.downcastExpression:
+      case NullabilityFixKind.otherCastExpression:
+        // There's no useful hint to apply to casts.
+        break;
       case NullabilityFixKind.removeAs:
-      case NullabilityFixKind.removeNullAwareness:
+      case NullabilityFixKind.removeDeadCode:
       case NullabilityFixKind.removeLanguageVersionComment:
         // There's no need for hints around code that is being removed.
         break;
+      case NullabilityFixKind.addType:
+      case NullabilityFixKind.replaceVar:
+        // There's no need for hints around inserted types.
+        break;
       case NullabilityFixKind.makeTypeNullable:
       case NullabilityFixKind.typeNotMadeNullable:
-        edits.add(
-            EditDetail('Force type to be non-nullable.', offset, 0, '/*!*/'));
-        edits.add(EditDetail('Force type to be nullable.', offset, 0, '/*?*/'));
+        edits.add(EditDetail('Add /*!*/ hint', offset, 0, '/*!*/'));
+        edits.add(EditDetail('Add /*?*/ hint', offset, 0, '/*?*/'));
+        break;
+      case NullabilityFixKind.makeTypeNullableDueToHint:
+        edits.add(EditDetail('Add /*!*/ hint', offset, 5, '/*!*/'));
+        edits.add(EditDetail('Remove /*?*/ hint', offset, 5, ''));
+        break;
+      case NullabilityFixKind.typeNotMadeNullableDueToHint:
+        edits.add(EditDetail('Remove /*!*/ hint', offset, 5, ''));
+        edits.add(EditDetail('Add /*?*/ hint', offset, 5, '/*?*/'));
         break;
     }
     return edits;
@@ -504,8 +199,8 @@
     }).toList();
   }
 
-  void _computeTraceNonNullableInfo(
-      NullabilityNodeInfo node, List<TraceInfo> traces) {
+  void _computeTraceNonNullableInfo(NullabilityNodeInfo node,
+      List<TraceInfo> traces, FixReasonTarget target) {
     var entries = <TraceEntryInfo>[];
     var step = node.whyNotNullable;
     if (step == null) {
@@ -519,12 +214,12 @@
       }
       step = step.principalCause;
     }
-    var description = 'Non-nullability reason';
+    var description = 'Non-nullability reason${target.suffix}';
     traces.add(TraceInfo(description, entries));
   }
 
-  void _computeTraceNullableInfo(
-      NullabilityNodeInfo node, List<TraceInfo> traces) {
+  void _computeTraceNullableInfo(NullabilityNodeInfo node,
+      List<TraceInfo> traces, FixReasonTarget target) {
     var entries = <TraceEntryInfo>[];
     var step = node.whyNullable;
     if (step == null) {
@@ -538,24 +233,28 @@
       }
       step = step.principalCause;
     }
-    var description = 'Nullability reason';
+    var description = 'Nullability reason${target.suffix}';
     traces.add(TraceInfo(description, entries));
   }
 
-  List<TraceInfo> _computeTraces(List<FixReasonInfo> fixReasons) {
+  List<TraceInfo> _computeTraces(
+      Map<FixReasonTarget, FixReasonInfo> fixReasons) {
     var traces = <TraceInfo>[];
-    for (var reason in fixReasons) {
+    for (var entry in fixReasons.entries) {
+      var reason = entry.value;
       if (reason is NullabilityNodeInfo) {
         if (reason.isNullable) {
-          _computeTraceNullableInfo(reason, traces);
+          _computeTraceNullableInfo(reason, traces, FixReasonTarget.root);
         } else {
-          _computeTraceNonNullableInfo(reason, traces);
+          _computeTraceNonNullableInfo(reason, traces, FixReasonTarget.root);
         }
       } else if (reason is EdgeInfo) {
-        assert(reason.sourceNode.isNullable);
-        assert(!reason.destinationNode.isNullable);
-        _computeTraceNullableInfo(reason.sourceNode, traces);
-        _computeTraceNonNullableInfo(reason.destinationNode, traces);
+        if (reason.sourceNode.isNullable &&
+            !reason.destinationNode.isNullable) {
+          var target = entry.key;
+          _computeTraceNullableInfo(reason.sourceNode, traces, target);
+          _computeTraceNonNullableInfo(reason.destinationNode, traces, target);
+        }
       } else if (reason is SimpleFixReasonInfo) {
         _addSimpleTrace(reason, traces);
       } else {
@@ -565,23 +264,6 @@
     return traces;
   }
 
-  /// Describe why an edge may have gotten a '!'.
-  String _describeNonNullEdge(EdgeOriginInfo edge) {
-    // TODO(mfairhurst/paulberry): Do NOT use astNode/parent to create this
-    // description, as we are just duplicating work if we do so.
-    final astNode = edge.node;
-    final parent = astNode.parent;
-    if (parent is PropertyAccess && parent.target == astNode ||
-        parent is PrefixedIdentifier && parent.prefix == astNode) {
-      return 'This value must be null-checked before accessing its properties.';
-    }
-    if (parent is MethodInvocation && parent.target == astNode) {
-      return 'This value must be null-checked before calling its methods.';
-    }
-
-    return 'This value must be null-checked before use here.';
-  }
-
   /// Return the migration information for the unit associated with the
   /// [result].
   UnitInfo _explainUnit(SourceInformation sourceInfo, ResolvedUnitResult result,
@@ -589,6 +271,7 @@
     var unitInfo = _unitForPath(result.path);
     unitInfo.sources ??= _computeNavigationSources(result);
     var content = result.content;
+    unitInfo.diskContent = content;
     var regions = unitInfo.regions;
     var lineInfo = result.unit.lineInfo;
     var insertions = <int, List<AtomicEdit>>{};
@@ -613,37 +296,36 @@
           (insertions[sourceOffset] ??= []).add(AtomicEdit.insert(replacement));
         }
         var info = edit.info;
-        var explanation = info?.description?.appliedMessage;
         var edits = info != null ? _computeEdits(info, sourceOffset) : [];
-        List<RegionDetail> details;
-        try {
-          details = _computeDetails(edit);
-        } catch (e, st) {
-          // TODO(mfairhurst): get the correct Source, and an AstNode.
-          if (migration.isPermissive) {
-            adapter.reportException(result.libraryElement.source, null, e, st);
-            details = [];
-          } else {
-            rethrow;
-          }
-        }
         var lineNumber = lineInfo.getLocation(sourceOffset).lineNumber;
         var traces = info == null ? const [] : _computeTraces(info.fixReasons);
-        if (explanation != null) {
-          if (length > 0) {
+        var description = info?.description;
+        if (description != null) {
+          var explanation = description.appliedMessage;
+          var kind = description.kind;
+          if (edit.isInformative) {
+            regions.add(RegionInfo(RegionType.informative, offset,
+                replacement.length, lineNumber, explanation, kind,
+                edits: edits, traces: traces));
+          } else if (edit.isInsertion) {
+            regions.add(RegionInfo(RegionType.add, offset, replacement.length,
+                lineNumber, explanation, kind,
+                edits: edits, traces: traces));
+          } else if (edit.isDeletion) {
             regions.add(RegionInfo(RegionType.remove, offset, length,
-                lineNumber, explanation, details,
+                lineNumber, explanation, kind,
+                edits: edits, traces: traces));
+          } else if (edit.isReplacement) {
+            regions.add(RegionInfo(RegionType.remove, offset, length,
+                lineNumber, explanation, kind,
+                edits: edits, traces: traces));
+            regions.add(RegionInfo(RegionType.add, end, replacement.length,
+                lineNumber, explanation, kind,
                 edits: edits, traces: traces));
           } else {
-            if (edit.isInformative) {
-              regions.add(RegionInfo(RegionType.informative, offset,
-                  replacement.length, lineNumber, explanation, const [],
-                  edits: edits, traces: traces));
-            } else {
-              regions.add(RegionInfo(RegionType.add, offset, replacement.length,
-                  lineNumber, explanation, details,
-                  edits: edits, traces: traces));
-            }
+            throw StateError(
+                'Edit is not an insertion, deletion, replacement, nor '
+                'informative: $edit');
           }
         }
         offset += replacement.length;
@@ -657,25 +339,11 @@
     edits.sort((first, second) => first.offset.compareTo(second.offset));
     var mapper = OffsetMapper.forEdits(edits);
     regions.sort((first, second) => first.offset.compareTo(second.offset));
-    unitInfo.offsetMapper = mapper;
+    unitInfo.migrationOffsetMapper = mapper;
     unitInfo.content = content;
     return unitInfo;
   }
 
-  /// Return `true` if the given [node] is from a compilation unit within the
-  /// 'test' directory of the package.
-  bool _inTestCode(AstNode node) {
-    // TODO(brianwilkerson) Generalize this.
-    var unit = node.thisOrAncestorOfType<CompilationUnit>();
-    var unitElement = unit?.declaredElement;
-    if (unitElement == null) {
-      return false;
-    }
-    var filePath = unitElement.source.fullName;
-    var resourceProvider = unitElement.session.resourceProvider;
-    return resourceProvider.pathContext.split(filePath).contains('test');
-  }
-
   TraceEntryInfo _makeTraceEntry(
       String description, CodeReference codeReference) {
     var length = 1; // TODO(paulberry): figure out the correct value.
@@ -693,42 +361,6 @@
     return _makeTraceEntry(description, node.codeReference);
   }
 
-  /// Return the navigation target corresponding to the given [node] in the file
-  /// with the given [filePath].
-  ///
-  /// Rather than a NavigationTarget targeting exactly [node], heuristics are
-  /// made to point to a narrower target, for example the name of a
-  /// method declaration, rather the the entire declaration.
-  NavigationTarget _proximateTargetForNode(String filePath, AstNode node) {
-    if (node == null) {
-      return null;
-    }
-    var parent = node.parent;
-    var unit = node.thisOrAncestorOfType<CompilationUnit>();
-    if (node is ConstructorDeclaration) {
-      if (node.name != null) {
-        return _targetForNode(filePath, node.name, unit);
-      } else {
-        return _targetForNode(filePath, node.returnType, unit);
-      }
-    } else if (node is MethodDeclaration) {
-      // Rather than create a NavigationTarget for an entire method declaration
-      // (starting at its doc comment, ending at `}`, return a target pointing
-      // to the method's name.
-      return _targetForNode(filePath, node.name, unit);
-    } else if (parent is ReturnStatement) {
-      // Rather than create a NavigationTarget for an entire expression, return
-      // a target pointing to the `return` token.
-      return _targetForNode(filePath, parent.returnKeyword, unit);
-    } else if (parent is ExpressionFunctionBody) {
-      // Rather than create a NavigationTarget for an entire expression function
-      // body, return a target pointing to the `=>` token.
-      return _targetForNode(filePath, parent.functionDefinition, unit);
-    } else {
-      return _targetForNode(filePath, node, unit);
-    }
-  }
-
   TraceEntryInfo _stepToTraceEntry(PropagationStepInfo step) {
     var description = step.edge?.description;
     description ??= step.toString(); // TODO(paulberry): improve this message.
@@ -737,20 +369,6 @@
 
   /// Return the navigation target in the file with the given [filePath] at the
   /// given [offset] ans with the given [length].
-  NavigationTarget _targetForNode(
-      String filePath, SyntacticEntity node, CompilationUnit unit) {
-    var unitInfo = _unitForPath(filePath);
-    var offset = node.offset;
-    var length = node.length;
-
-    var line = unit.lineInfo.getLocation(node.offset).lineNumber;
-    var target = NavigationTarget(filePath, offset, line, length);
-    unitInfo.targets.add(target);
-    return target;
-  }
-
-  /// Return the navigation target in the file with the given [filePath] at the
-  /// given [offset] ans with the given [length].
   NavigationTarget _targetForRawTarget(
       String filePath, protocol.NavigationTarget rawTarget) {
     var unitInfo = _unitForPath(filePath);
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
index 272b98e..6eb9fd4 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -49,13 +49,16 @@
   /// Whether the migration has been applied already or not.
   final bool hasBeenApplied;
 
+  /// Whether the migration needs to be rerun due to disk changes.
+  final bool needsRerun;
+
   /// An object used to map the file paths of analyzed files to the file paths
   /// of the HTML files used to view the content of those files.
   final PathMapper pathMapper;
 
   /// Creates an output object for the given library info.
-  InstrumentationRenderer(
-      this.migrationInfo, this.pathMapper, this.hasBeenApplied);
+  InstrumentationRenderer(this.migrationInfo, this.pathMapper,
+      this.hasBeenApplied, this.needsRerun);
 
   /// Returns the path context used to manipulate paths.
   path.Context get pathContext => migrationInfo.pathContext;
@@ -70,6 +73,7 @@
       'highlightStylePath': migrationInfo.highlightStylePath,
       'sdkVersion': _dartSdkVersion,
       'migrationAppliedStyle': hasBeenApplied ? 'applied' : 'proposed',
+      'needsRerunStyle': needsRerun ? 'needs-rerun' : '',
     };
 
     return substituteVariables(resources.index_html, variables);
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
index f190d0d..bde42b0 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
@@ -6,7 +6,10 @@
 import 'package:analysis_server/src/edit/nnbd_migration/unit_link.dart';
 import 'package:analysis_server/src/edit/preview/preview_site.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:collection/collection.dart';
+import 'package:crypto/crypto.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:path/path.dart' as path;
 
 /// A description of an edit that can be applied before rerunning the migration
@@ -126,19 +129,6 @@
   String toString() => 'NavigationTarget["$filePath", $line, $offset, $length]';
 }
 
-/// An additional detail related to a region.
-class RegionDetail {
-  /// A textual description of the detail.
-  final String description;
-
-  /// The location associated with the detail, such as the location of an
-  /// argument that's assigned to a parameter.
-  final NavigationTarget target;
-
-  /// Initialize a newly created detail.
-  RegionDetail(this.description, this.target);
-}
-
 /// A description of an explanation associated with a region of code that was
 /// modified.
 class RegionInfo {
@@ -157,8 +147,8 @@
   /// The explanation to be displayed for the region.
   final String explanation;
 
-  /// Details that further explain why a change was made.
-  final List<RegionDetail> details;
+  /// The kind of fix that was applied.
+  final NullabilityFixKind kind;
 
   /// A list of the edits that are related to this range.
   List<EditDetail> edits;
@@ -169,7 +159,7 @@
 
   /// Initialize a newly created region.
   RegionInfo(this.regionType, this.offset, this.length, this.lineNumber,
-      this.explanation, this.details,
+      this.explanation, this.kind,
       {this.edits = const [], this.traces = const []});
 }
 
@@ -217,7 +207,10 @@
   /// The absolute and normalized path of the unit.
   final String path;
 
-  /// The content of unit.
+  /// Hash of the original contents of the unit.
+  List<int> _diskContentHash;
+
+  /// The preview content of unit.
   String content;
 
   /// The information about the regions that have an explanation associated with
@@ -232,13 +225,23 @@
   /// targets are offsets into the pre-edit content.
   final Set<NavigationTarget> targets = {};
 
-  /// The object used to map the pre-edit offsets in the navigation targets to
-  /// the post-edit offsets in the [content].
-  OffsetMapper offsetMapper = OffsetMapper.identity;
+  /// An offset mapper reflecting changes made by the migration edits.
+  OffsetMapper migrationOffsetMapper = OffsetMapper.identity;
+
+  /// An offset mapper reflecting changes made to disk since the migration was
+  /// run, which can be rebased on [migrationOffsetMapper] to create and
+  /// maintain an offset mapper from current disk state to migration result.
+  OffsetMapper diskChangesOffsetMapper = OffsetMapper.identity;
 
   /// Initialize a newly created unit.
   UnitInfo(this.path);
 
+  /// Set the original/disk content of this file to later use [hadDiskContent].
+  /// This does not have a getter because it is backed by a private hash.
+  set diskContent(String originalContent) {
+    _diskContentHash = md5.convert((originalContent ?? '').codeUnits).bytes;
+  }
+
   /// Returns the [regions] that represent a fixed (changed) region of code.
   List<RegionInfo> get fixRegions => regions
       .where((region) => region.regionType != RegionType.informative)
@@ -249,6 +252,46 @@
       .where((region) => region.regionType == RegionType.informative)
       .toList();
 
+  /// The object used to map the pre-edit offsets in the navigation targets to
+  /// the post-edit offsets in the [content].
+  OffsetMapper get offsetMapper =>
+      OffsetMapper.rebase(diskChangesOffsetMapper, migrationOffsetMapper);
+
+  /// Check if this unit's file had expected disk contents [checkContent].
+  bool hadDiskContent(String checkContent) {
+    assert(_diskContentHash != null);
+    return const ListEquality().equals(
+        _diskContentHash, md5.convert((checkContent ?? '').codeUnits).bytes);
+  }
+
+  void handleInsertion(int offset, String replacement) {
+    final contentCopy = content;
+    final regionsCopy = List<RegionInfo>.from(regions);
+    final length = replacement.length;
+    offset = offsetMapper.map(offset);
+    try {
+      content = content.replaceRange(offset, offset, replacement);
+      regions.clear();
+      regions.addAll(regionsCopy.map((region) {
+        if (region.offset < offset) {
+          return region;
+        }
+        // TODO: adjust traces
+        return RegionInfo(region.regionType, region.offset + length,
+            region.length, region.lineNumber, region.explanation, region.kind,
+            edits: region.edits, traces: region.traces);
+      }));
+
+      diskChangesOffsetMapper = OffsetMapper.sequence(
+          diskChangesOffsetMapper, OffsetMapper.forInsertion(offset, length));
+    } catch (e) {
+      regions.clear();
+      regions.addAll(regionsCopy);
+      content = contentCopy;
+      rethrow;
+    }
+  }
+
   /// Returns the [RegionInfo] at offset [offset].
   // TODO(srawlins): This is O(n), used each time the user clicks on a region.
   //  Consider changing the type of [regions] to facilitate O(1) searching.
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart
index 41ab440..53b0a73 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart
@@ -35,6 +35,9 @@
   /// The object used to map paths.
   PathMapper pathMapper;
 
+  /// If there have been changes to disk so the migration needs to be rerun.
+  bool needsRerun = false;
+
   /// Initialize a newly created migration state with the given values.
   MigrationState(this.migration, this.includedRoot, this.listener,
       this.instrumentationListener, this.adapter);
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/offset_mapper.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/offset_mapper.dart
index 45218d8..f53fd79 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/offset_mapper.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/offset_mapper.dart
@@ -13,6 +13,22 @@
   /// Return a mapper representing the file modified by the given [edits].
   factory OffsetMapper.forEdits(List<SourceEdit> edits) => _EditMapper(edits);
 
+  /// Return a mapper representing the file modified by an insertion at [offset]
+  /// the given with [length].
+  factory OffsetMapper.forInsertion(int offset, int length) =>
+      _SimpleInsertionMapper(offset, length);
+
+  /// Return a mapper representing [rebased] rebased by [rebaser].
+  factory OffsetMapper.rebase(OffsetMapper rebaser, OffsetMapper rebased) {
+    return _RebasedOffsetMapper(rebaser, rebased);
+  }
+
+  /// Return a mapper representing a sequence of edits made in order, with the
+  /// offsets coming out of [first] being the offsets passed into [second].
+  factory OffsetMapper.sequence(OffsetMapper first, OffsetMapper second) {
+    return _OffsetMapperChain([first, second]);
+  }
+
   /// Return the post-edit offset that corresponds to the given pre-edit
   /// [offset].
   int map(int offset);
@@ -71,3 +87,40 @@
   @override
   int map(int offset) => offset;
 }
+
+class _OffsetMapperChain implements OffsetMapper {
+  final List<OffsetMapper> innerMappers;
+
+  _OffsetMapperChain(this.innerMappers);
+
+  @override
+  int map(int offset) {
+    for (final mapper in innerMappers) {
+      offset = mapper.map(offset);
+    }
+    return offset;
+  }
+}
+
+class _RebasedOffsetMapper implements OffsetMapper {
+  final OffsetMapper rebaser;
+  final OffsetMapper rebased;
+
+  _RebasedOffsetMapper(this.rebaser, this.rebased);
+
+  @override
+  int map(int offset) {
+    final delta = rebased.map(offset) - offset;
+    return rebaser.map(offset) + delta;
+  }
+}
+
+class _SimpleInsertionMapper implements OffsetMapper {
+  final int offset;
+  final int length;
+
+  _SimpleInsertionMapper(this.offset, this.length);
+
+  @override
+  int map(int offset) => offset < this.offset ? offset : offset + length;
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart
index f1aea6c..6ac067c3 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart
@@ -60,13 +60,6 @@
       path: unitInfo.path,
       line: region.lineNumber,
       explanation: region.explanation,
-      details: [
-        for (var detail in region.details)
-          EditRationale(
-              description: detail.description,
-              link:
-                  detail.target == null ? null : linkForTarget(detail.target)),
-      ],
       edits: supportsIncrementalWorkflow
           ? [
               for (var edit in region.edits) linkForEdit(edit),
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
index 96f80c9..335e0c9 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
@@ -7,7 +7,7 @@
     <link rel="stylesheet" href="{{ highlightStylePath }}">
     <style>{{ dartPageStyle }}</style>
 </head>
-<body class="{{ migrationAppliedStyle }}">
+<body class="{{ migrationAppliedStyle }} {{ needsRerunStyle }}">
 <div class="rerunning-pane">
   <h1>Rerunning...</h1>
 </div>
@@ -16,9 +16,16 @@
     <h1 class="before-apply">Proposed null safety changes</h1>
     <h1 class="after-apply">&#10003; Null safety migration applied</h1>
     <h2 id="unit-name">&nbsp;</h2>
-    <button class="apply-migration before-apply">&#9998; Apply Migration</button>
-    <button class="apply-migration after-apply" disabled>&#9998; Apply Migration</button>
-    <button class="rerun-migration before-apply">&#8635; Rerun From Sources</button>
+    <button class="apply-migration">&#9998; Apply Migration</button>
+    <button class="apply-migration" disabled>&#9998; Apply Migration</button>
+    <button class="rerun-migration before-apply">
+      <span class="optional">&#8635; Rerun From Sources</span>
+      <span class="required">
+        <span class="icon" 
+          title="Disk contents have changed. Rerun to get an up-to-date migration.">!</span>
+        Rerun With Changes
+      </span>
+    </button>
 </header>
 <div class="panels horizontal">
     <div class="nav-panel">
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css
index 76ae137..c857fab 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css
@@ -27,6 +27,14 @@
   display: none;
 }
 
+.applied .apply-migration:not([disabled]), .needs-rerun .apply-migration:not([disabled]) {
+  display: none;
+}
+
+.proposed:not(.needs-rerun) .apply-migration[disabled] {
+  display: none;
+}
+
 header {
   background-color: #1c2834;
   height: 48px;
@@ -57,6 +65,48 @@
   margin: 10px;
 }
 
+.rerun-migration .required {
+  display: none;
+}
+
+.needs-rerun .rerun-migration .required {
+  display: initial;
+}
+
+.needs-rerun .rerun-migration .optional {
+  display:none;
+}
+
+/* Red triangle */
+.rerun-migration .required .icon::before {
+  transform: translate(-8px, -11px);
+  content: '\25B3';
+  font-size: 25px;
+  position: fixed;
+  color: #e82c2c;
+  text-shadow: 0px 0px 5px white;
+  z-index: -3;
+}
+
+/* Red triangle fill */
+.rerun-migration .required .icon::after {
+  transform: translate(-9px, -10px);
+  content: '\25B4';
+  font-size: 25px;
+  position: fixed;
+  color: #b3ecff;
+  z-index: -1;
+}
+
+/* Red triangle exclamation */
+.rerun-migration .required .icon {
+  display: inline-block;
+  margin-right: 8px;
+  transform: translate(0px, 2px);
+  margin-left: 2px;
+  color: #2b2b2b;
+}
+
 footer {
   color: #ccc;
   background-color: #27323a;
@@ -416,7 +466,12 @@
   fill: #fff;
 }
 
-button {
+a.post-link {
+  display: inline-block;
+  margin: 3px;
+}
+
+button, a.post-link {
   background-color: #33ccff;
   border: 2px solid #37aedc;
   border-radius: 3px;
@@ -425,7 +480,7 @@
   color: #282828;
 }
 
-button:hover {
+button:hover, a.post-link:hover {
   background-color: #80dfff;
   border: 2px solid #52b8e0;
   cursor: pointer;
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
index a1b30c5..821e26a 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
@@ -270,7 +270,7 @@
 ''';
 
 String _index_html;
-// index_html md5 is '41fa7069b77fe104e2d78f9fd1d8d99b'
+// index_html md5 is 'b80e110b4fee8e204eeefbfcffeeff7c'
 String _index_html_base64 = '''
 PGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPk51bGwgU2FmZXR5IFByZXZpZXc8L3RpdGxlPgogICAgPHNj
 cmlwdCBzcmM9Int7IGhpZ2hsaWdodEpzUGF0aCB9fSI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0Pnt7IGRh
@@ -278,46 +278,50 @@
 dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzP2ZhbWlseT1PcGVuK1NhbnM6NDAwLDYwMCZkaXNw
 bGF5PXN3YXAiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJ7eyBoaWdobGlnaHRTdHls
 ZVBhdGggfX0iPgogICAgPHN0eWxlPnt7IGRhcnRQYWdlU3R5bGUgfX08L3N0eWxlPgo8L2hlYWQ+Cjxi
-b2R5IGNsYXNzPSJ7eyBtaWdyYXRpb25BcHBsaWVkU3R5bGUgfX0iPgo8ZGl2IGNsYXNzPSJyZXJ1bm5p
-bmctcGFuZSI+CiAgPGgxPlJlcnVubmluZy4uLjwvaDE+CjwvZGl2Pgo8cCBjbGFzcz0icm9vdCI+e3sg
-cm9vdCB9fTwvcD4KPGhlYWRlciBjbGFzcz0iZWxldmF0aW9uLXo0Ij4KICAgIDxoMSBjbGFzcz0iYmVm
-b3JlLWFwcGx5Ij5Qcm9wb3NlZCBudWxsIHNhZmV0eSBjaGFuZ2VzPC9oMT4KICAgIDxoMSBjbGFzcz0i
-YWZ0ZXItYXBwbHkiPiYjMTAwMDM7IE51bGwgc2FmZXR5IG1pZ3JhdGlvbiBhcHBsaWVkPC9oMT4KICAg
-IDxoMiBpZD0idW5pdC1uYW1lIj4mbmJzcDs8L2gyPgogICAgPGJ1dHRvbiBjbGFzcz0iYXBwbHktbWln
-cmF0aW9uIGJlZm9yZS1hcHBseSI+JiM5OTk4OyBBcHBseSBNaWdyYXRpb248L2J1dHRvbj4KICAgIDxi
-dXR0b24gY2xhc3M9ImFwcGx5LW1pZ3JhdGlvbiBhZnRlci1hcHBseSIgZGlzYWJsZWQ+JiM5OTk4OyBB
-cHBseSBNaWdyYXRpb248L2J1dHRvbj4KICAgIDxidXR0b24gY2xhc3M9InJlcnVuLW1pZ3JhdGlvbiBi
-ZWZvcmUtYXBwbHkiPiYjODYzNTsgUmVydW4gRnJvbSBTb3VyY2VzPC9idXR0b24+CjwvaGVhZGVyPgo8
-ZGl2IGNsYXNzPSJwYW5lbHMgaG9yaXpvbnRhbCI+CiAgICA8ZGl2IGNsYXNzPSJuYXYtcGFuZWwiPgog
-ICAgICAgIDxkaXYgY2xhc3M9Im5hdi1pbm5lciI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVs
-LWhlYWRpbmciPlByb2plY3QgRmlsZXM8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibmF2LXRy
-ZWUiPjwvZGl2PgogICAgICAgIDwvZGl2PjwhLS0gL25hdi1pbm5lciAtLT4KICAgIDwvZGl2PjwhLS0g
-L25hdiAtLT4KICAgIDxkaXYgY2xhc3M9ImNvbnRlbnQiPgogICAgICAgIDxkaXYgY2xhc3M9InJlZ2lv
-bnMiPgogICAgICAgICAgICA8IS0tIFRoZSByZWdpb25zIG92ZXJsYXkgY29kZSBjb3B5IG9mIHRoZSBj
-b250ZW50IHRvIHByb3ZpZGUgLS0+CiAgICAgICAgICAgIDwhLS0gdG9vbHRpcHMgZm9yIG1vZGlmaWVk
-IHJlZ2lvbnMuIC0tPgogICAgICAgIDwvZGl2PjwhLS0gL3JlZ2lvbnMgLS0+CiAgICAgICAgPGRpdiBj
-bGFzcz0iY29kZSI+CiAgICAgICAgICAgIDwhLS0gQ29tcGlsYXRpb24gdW5pdCBjb250ZW50IGlzIHdy
-aXR0ZW4gaGVyZS4gLS0+CiAgICAgICAgICAgIDxwIGNsYXNzPSJ3ZWxjb21lIj4KICAgICAgICAgICAg
-ICAgIFNlbGVjdCBhIHNvdXJjZSBmaWxlIG9uIHRoZSBsZWZ0IHRvIHByZXZpZXcgdGhlIHByb3Bvc2Vk
-IGVkaXRzLgogICAgICAgICAgICA8L3A+CiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj48IS0tIC9jb250
-ZW50IC0tPgogICAgPGRpdiBjbGFzcz0iaW5mby1wYW5lbCI+CiAgICAgICAgPGRpdiBjbGFzcz0iZWRp
-dC1saXN0Ij4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+UHJvcG9zZWQgRWRp
-dHM8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+PC9kaXY+CiAgICAg
-ICAgPC9kaXY+PCEtLSAvZWRpdC1saXN0IC0tPgogICAgICAgIDxkaXYgY2xhc3M9ImVkaXQtcGFuZWwi
-PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj5FZGl0IERldGFpbHM8L2Rpdj4K
-ICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+CiAgICAgICAgICAgICAgICA8cCBj
-bGFzcz0icGxhY2Vob2xkZXIiPlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQgZWRpdC48L3A+CiAg
-ICAgICAgICAgIDwvZGl2PjwhLS0gL3BhbmVsLWNvbnRlbnQgLS0+CiAgICAgICAgPC9kaXY+PCEtLSAv
-ZWRpdC1wYW5lbCAtLT4KICAgIDwvZGl2PjwhLS0gL2luZm8tcGFuZWwgLS0+CjwvZGl2PjwhLS0gL3Bh
-bmVscyAtLT4KPGZvb3Rlcj4KICAgIDxhIHRhcmdldD0iX2JsYW5rIgogICAgICAgaHJlZj0iaHR0cHM6
-Ly9naXRodWIuY29tL2RhcnQtbGFuZy9zZGsvYmxvYi9tYXN0ZXIvcGtnL25uYmRfbWlncmF0aW9uL1JF
-QURNRS5tZCI+TnVsbAogICAgICAgIHNhZmV0eSBtaWdyYXRpb24gaGVscDwvYT4KICAgIDxzcGFuIGNs
-YXNzPSJ3aWRlIj4gPC9zcGFuPgogICAgPGRpdj5CYXNlZCBvbiB7eyBzZGtWZXJzaW9uIH19PC9kaXY+
-CjwvZm9vdGVyPgo8L2JvZHk+CjwvaHRtbD4K
+b2R5IGNsYXNzPSJ7eyBtaWdyYXRpb25BcHBsaWVkU3R5bGUgfX0ge3sgbmVlZHNSZXJ1blN0eWxlIH19
+Ij4KPGRpdiBjbGFzcz0icmVydW5uaW5nLXBhbmUiPgogIDxoMT5SZXJ1bm5pbmcuLi48L2gxPgo8L2Rp
+dj4KPHAgY2xhc3M9InJvb3QiPnt7IHJvb3QgfX08L3A+CjxoZWFkZXIgY2xhc3M9ImVsZXZhdGlvbi16
+NCI+CiAgICA8aDEgY2xhc3M9ImJlZm9yZS1hcHBseSI+UHJvcG9zZWQgbnVsbCBzYWZldHkgY2hhbmdl
+czwvaDE+CiAgICA8aDEgY2xhc3M9ImFmdGVyLWFwcGx5Ij4mIzEwMDAzOyBOdWxsIHNhZmV0eSBtaWdy
+YXRpb24gYXBwbGllZDwvaDE+CiAgICA8aDIgaWQ9InVuaXQtbmFtZSI+Jm5ic3A7PC9oMj4KICAgIDxi
+dXR0b24gY2xhc3M9ImFwcGx5LW1pZ3JhdGlvbiI+JiM5OTk4OyBBcHBseSBNaWdyYXRpb248L2J1dHRv
+bj4KICAgIDxidXR0b24gY2xhc3M9ImFwcGx5LW1pZ3JhdGlvbiIgZGlzYWJsZWQ+JiM5OTk4OyBBcHBs
+eSBNaWdyYXRpb248L2J1dHRvbj4KICAgIDxidXR0b24gY2xhc3M9InJlcnVuLW1pZ3JhdGlvbiBiZWZv
+cmUtYXBwbHkiPgogICAgICA8c3BhbiBjbGFzcz0ib3B0aW9uYWwiPiYjODYzNTsgUmVydW4gRnJvbSBT
+b3VyY2VzPC9zcGFuPgogICAgICA8c3BhbiBjbGFzcz0icmVxdWlyZWQiPgogICAgICAgIDxzcGFuIGNs
+YXNzPSJpY29uIiAKICAgICAgICAgIHRpdGxlPSJEaXNrIGNvbnRlbnRzIGhhdmUgY2hhbmdlZC4gUmVy
+dW4gdG8gZ2V0IGFuIHVwLXRvLWRhdGUgbWlncmF0aW9uLiI+ITwvc3Bhbj4KICAgICAgICBSZXJ1biBX
+aXRoIENoYW5nZXMKICAgICAgPC9zcGFuPgogICAgPC9idXR0b24+CjwvaGVhZGVyPgo8ZGl2IGNsYXNz
+PSJwYW5lbHMgaG9yaXpvbnRhbCI+CiAgICA8ZGl2IGNsYXNzPSJuYXYtcGFuZWwiPgogICAgICAgIDxk
+aXYgY2xhc3M9Im5hdi1pbm5lciI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmci
+PlByb2plY3QgRmlsZXM8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ibmF2LXRyZWUiPjwvZGl2
+PgogICAgICAgIDwvZGl2PjwhLS0gL25hdi1pbm5lciAtLT4KICAgIDwvZGl2PjwhLS0gL25hdiAtLT4K
+ICAgIDxkaXYgY2xhc3M9ImNvbnRlbnQiPgogICAgICAgIDxkaXYgY2xhc3M9InJlZ2lvbnMiPgogICAg
+ICAgICAgICA8IS0tIFRoZSByZWdpb25zIG92ZXJsYXkgY29kZSBjb3B5IG9mIHRoZSBjb250ZW50IHRv
+IHByb3ZpZGUgLS0+CiAgICAgICAgICAgIDwhLS0gdG9vbHRpcHMgZm9yIG1vZGlmaWVkIHJlZ2lvbnMu
+IC0tPgogICAgICAgIDwvZGl2PjwhLS0gL3JlZ2lvbnMgLS0+CiAgICAgICAgPGRpdiBjbGFzcz0iY29k
+ZSI+CiAgICAgICAgICAgIDwhLS0gQ29tcGlsYXRpb24gdW5pdCBjb250ZW50IGlzIHdyaXR0ZW4gaGVy
+ZS4gLS0+CiAgICAgICAgICAgIDxwIGNsYXNzPSJ3ZWxjb21lIj4KICAgICAgICAgICAgICAgIFNlbGVj
+dCBhIHNvdXJjZSBmaWxlIG9uIHRoZSBsZWZ0IHRvIHByZXZpZXcgdGhlIHByb3Bvc2VkIGVkaXRzLgog
+ICAgICAgICAgICA8L3A+CiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj48IS0tIC9jb250ZW50IC0tPgog
+ICAgPGRpdiBjbGFzcz0iaW5mby1wYW5lbCI+CiAgICAgICAgPGRpdiBjbGFzcz0iZWRpdC1saXN0Ij4K
+ICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+UHJvcG9zZWQgRWRpdHM8L2Rpdj4K
+ICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+PC9kaXY+CiAgICAgICAgPC9kaXY+
+PCEtLSAvZWRpdC1saXN0IC0tPgogICAgICAgIDxkaXYgY2xhc3M9ImVkaXQtcGFuZWwiPgogICAgICAg
+ICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj5FZGl0IERldGFpbHM8L2Rpdj4KICAgICAgICAg
+ICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+CiAgICAgICAgICAgICAgICA8cCBjbGFzcz0icGxh
+Y2Vob2xkZXIiPlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQgZWRpdC48L3A+CiAgICAgICAgICAg
+IDwvZGl2PjwhLS0gL3BhbmVsLWNvbnRlbnQgLS0+CiAgICAgICAgPC9kaXY+PCEtLSAvZWRpdC1wYW5l
+bCAtLT4KICAgIDwvZGl2PjwhLS0gL2luZm8tcGFuZWwgLS0+CjwvZGl2PjwhLS0gL3BhbmVscyAtLT4K
+PGZvb3Rlcj4KICAgIDxhIHRhcmdldD0iX2JsYW5rIgogICAgICAgaHJlZj0iaHR0cHM6Ly9naXRodWIu
+Y29tL2RhcnQtbGFuZy9zZGsvYmxvYi9tYXN0ZXIvcGtnL25uYmRfbWlncmF0aW9uL1JFQURNRS5tZCI+
+TnVsbAogICAgICAgIHNhZmV0eSBtaWdyYXRpb24gaGVscDwvYT4KICAgIDxzcGFuIGNsYXNzPSJ3aWRl
+Ij4gPC9zcGFuPgogICAgPGRpdj5CYXNlZCBvbiB7eyBzZGtWZXJzaW9uIH19PC9kaXY+CjwvZm9vdGVy
+Pgo8L2JvZHk+CjwvaHRtbD4K
 ''';
 
 String _migration_css;
-// migration_css md5 is 'eab70bd06e8c1bfe25644337e63495b9'
+// migration_css md5 is '0063c2f22a79d4534f0b3e9d3a805e2d'
 String _migration_css_base64 = '''
 LyogQ29weXJpZ2h0IChjKSAyMDE5LCB0aGUgRGFydCBwcm9qZWN0IGF1dGhvcnMuIFBsZWFzZSBzZWUg
 dGhlIEFVVEhPUlMgZmlsZSAgKi8KLyogZm9yIGRldGFpbHMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFVz
@@ -329,114 +333,131 @@
 cDogMDsKICByaWdodDogMDsKICBib3R0b206IDA7CiAgbGVmdDogMDsKICBtYXJnaW46IDA7CiAgcGFk
 ZGluZzogMDsKICBvdmVyZmxvdzogaGlkZGVuOwp9CgoucHJvcG9zZWQgLmFmdGVyLWFwcGx5IHsKICBk
 aXNwbGF5OiBub25lOwp9CgouYXBwbGllZCAuYmVmb3JlLWFwcGx5IHsKICBkaXNwbGF5OiBub25lOwp9
-CgpoZWFkZXIgewogIGJhY2tncm91bmQtY29sb3I6ICMxYzI4MzQ7CiAgaGVpZ2h0OiA0OHB4OwogIHBh
-ZGRpbmctbGVmdDogMjRweDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIHotaW5kZXg6IDQ7Cn0KCmhl
-YWRlciBoMSwKaGVhZGVyIGgyIHsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9udC1mYW1pbHk6
-ICJHb29nbGUgU2FucyIsIlJvYm90byIsc2Fucy1zZXJpZjsKICBmb250LXdlaWdodDogNDAwOwogIG1h
-cmdpbi1yaWdodDogMjRweDsKfQoKaDEgewogIGZvbnQtc2l6ZTogMS41ZW07Cn0KCmhlYWRlciBoMiB7
-CiAgZm9udC1zaXplOiAxLjJlbTsKfQoKaGVhZGVyIC5hcHBseS1taWdyYXRpb24sIC5yZXJ1bi1taWdy
-YXRpb24gewogIHJpZ2h0OiAwcHg7CiAgZmxvYXQ6IHJpZ2h0OwogIG1hcmdpbjogMTBweDsKfQoKZm9v
-dGVyIHsKICBjb2xvcjogI2NjYzsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjczMjNhOwogIGRpc3BsYXk6
-IGZsZXg7CiAgZmxleC1kaXJlY3Rpb246IHJvdzsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIHBhZGRp
-bmc6IDhweCAyNHB4Owp9Cgpmb290ZXIgLndpZGUgewogIGZsZXg6IDE7Cn0KCi5ob3Jpem9udGFsIHsK
-ICBkaXNwbGF5OiBmbGV4Owp9CgoucGFuZWxzIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTIxYTI1Owog
-IGZsZXg6IDE7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKfQoKLnBhbmVsLWhlYWRpbmcgewogIGNvbG9yOiBn
-cmF5OwogIG1hcmdpbjogOHB4Owp9CgoubmF2LWxpbmssCi5yZWdpb24gewogIGN1cnNvcjogcG9pbnRl
-cjsKfQoKLm5hdi1wYW5lbCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBmbGV4OiAxIDIw
-MHB4OwogIG1hcmdpbjogMDsKICBvdmVyZmxvdzogc2Nyb2xsOwp9CgoubmF2LWlubmVyIHsKICBwYWRk
-aW5nOiAwIDAgN3B4IDdweDsKfQoKLmZpeGVkIHsKICBwb3NpdGlvbjogZml4ZWQ7CiAgdG9wOiAwOwp9
-Cgoucm9vdCB7CiAgbWFyZ2luOiAwOwogIGRpc3BsYXk6IG5vbmU7Cn0KCi5uYXYtdHJlZSA+IHVsIHsK
-ICBwYWRkaW5nLWxlZnQ6IDZweDsKfQoKLm5hdi1pbm5lciB1bCB7CiAgcGFkZGluZy1sZWZ0OiAxMnB4
-OwogIG1hcmdpbjogMDsKfQoKLm5hdi1pbm5lciBsaSB7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwp9
-CgoubmF2LWlubmVyIGxpOm5vdCguZGlyKSB7CiAgbWFyZ2luLWxlZnQ6IDIwcHg7CiAgbWFyZ2luLWJv
-dHRvbTogM3B4Owp9CgoubmF2LWlubmVyIGxpLmRpciAuYXJyb3cgewogIGN1cnNvcjogcG9pbnRlcjsK
-ICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9udC1zaXplOiAxMHB4OwogIG1hcmdpbi1yaWdodDog
-NHB4OwogIHRyYW5zaXRpb246IHRyYW5zZm9ybSAwLjVzIGVhc2Utb3V0Owp9CgoubmF2LWlubmVyIGxp
-LmRpciAuYXJyb3cuY29sbGFwc2VkIHsKICB0cmFuc2Zvcm06IHJvdGF0ZSgtOTBkZWcpOwp9CgoubmF2
-LWlubmVyIHVsIHsKICBtYXgtaGVpZ2h0OiAyMDAwcHg7CiAgdHJhbnNpdGlvbjogbWF4LWhlaWdodCAw
-LjVzIGVhc2Utb3V0Owp9CgoubmF2LWlubmVyIHVsLmNvbGxhcHNlZCB7CiAgbWF4LWhlaWdodDogMCAh
-aW1wb3J0YW50OwogIG92ZXJmbG93OiBoaWRkZW47Cn0KCi5uYXYtaW5uZXIgLnNlbGVjdGVkLWZpbGUg
-ewogIGNvbG9yOiB3aGl0ZTsKICBjdXJzb3I6IGluaGVyaXQ7CiAgZm9udC13ZWlnaHQ6IDYwMDsKICB0
-ZXh0LWRlY29yYXRpb246IG5vbmU7Cn0KCi5lZGl0LWNvdW50IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAj
-MzdhZWRjOwogIGJvcmRlci1yYWRpdXM6IDEwcHg7CiAgY29sb3I6ICMwMDAwMDA7CiAgZGlzcGxheTog
-aW5saW5lLWJsb2NrOwogIGZvbnQtc2l6ZTogMTFweDsKICBmb250LXdlaWdodDogNjAwOwogIG1hcmdp
-bi1sZWZ0OiA1cHg7CiAgbWluLXdpZHRoOiAyNXB4OwogIHBhZGRpbmc6IDRweCAwIDJweCAwOwogIHRl
-eHQtYWxpZ246IGNlbnRlcjsKICBsaW5lLWhlaWdodDogMWVtOwp9CgouY29udGVudCB7CiAgZmxleDog
-NCAzMDBweDsKICBiYWNrZ3JvdW5kOiAjMjgyYjJlOwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7CiAg
-bWFyZ2luOiAwIDZweDsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgd2hpdGUtc3BhY2U6IHByZTsKICBv
-dmVyZmxvdzogc2Nyb2xsOwp9CgouY29kZSB7CiAgcGFkZGluZzogMC41ZW07CiAgcG9zaXRpb246IGFi
-c29sdXRlOwogIGxlZnQ6IDA7CiAgdG9wOiAwOwogIG1hcmdpbi1sZWZ0OiA1NnB4Owp9CgouaGxqcyB7
-CiAgYmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBkaXNwbGF5OiBibG9jazsKICBvdmVyZmxvdy14
-OiBhdXRvOwogIHBhZGRpbmc6IDAuNWVtOwp9CgouY29kZSAud2VsY29tZSB7CiAgZm9udC1mYW1pbHk6
-ICJHb29nbGUgU2FucyIsIlJvYm90byIsc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDE4cHg7CiAgbWFy
-Z2luLXJpZ2h0OiA2MnB4OwogIGNvbG9yOiAjNzc3Owp9CgouY29kZSAubmF2LWxpbmsgewogIGNvbG9y
-OiBpbmhlcml0OwogIHRleHQtZGVjb3JhdGlvbi1saW5lOiBub25lOwp9CgouY29kZSAubmF2LWxpbms6
-dmlzaXRlZCB7CiAgY29sb3I6IGluaGVyaXQ7CiAgdGV4dC1kZWNvcmF0aW9uLWxpbmU6IG5vbmU7Cn0K
-Ci5jb2RlIC5uYXYtbGluazpob3ZlciB7CiAgdGV4dC1kZWNvcmF0aW9uLWxpbmU6IHVuZGVybGluZTsK
-ICBmb250LXdlaWdodDogNjAwOwp9CgoucmVnaW9ucyB7CiAgcGFkZGluZzogMC41ZW07CiAgcG9zaXRp
-b246IGFic29sdXRlOwogIGxlZnQ6IDA7CiAgdG9wOiAwOwp9CgoucmVnaW9ucyB0YWJsZSB7CiAgYm9y
-ZGVyLXNwYWNpbmc6IDA7CiAgZm9udC1zaXplOiBpbmhlcml0Owp9CgoucmVnaW9ucyB0ZCB7CiAgYm9y
-ZGVyOiBub25lOwogIC8qIFRoZSBjb250ZW50IG9mIHRoZSByZWdpb25zIGlzIG5vdCB2aXNpYmxlOyB0
-aGUgdXNlciBpbnN0ZWFkIHdpbGwgc2VlIHRoZQogICAqIGhpZ2hsaWdodGVkIGNvcHkgb2YgdGhlIGNv
-bnRlbnQuICovCiAgY29sb3I6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMCk7CiAgcGFkZGluZzogMDsKICB3
-aGl0ZS1zcGFjZTogcHJlOwp9CgoucmVnaW9ucyB0ZDplbXB0eTphZnRlciB7CiAgY29udGVudDogIlww
-MGEwIjsKfQoKLnJlZ2lvbnMgdHIuaGlnaGxpZ2h0IHRkOmxhc3QtY2hpbGQgewogIGJhY2tncm91bmQt
-Y29sb3I6ICM0NDQ0NDQ7CiAgY29sb3I6IHdoaXRlOwp9CgoucmVnaW9ucyB0ZC5saW5lLW5vIHsKICBi
-b3JkZXItcmlnaHQ6IHNvbGlkICMyODJiMmUgMnB4OwogIGNvbG9yOiAjOTk5OTk5OwogIHBhZGRpbmct
-cmlnaHQ6IDRweDsKICB0ZXh0LWFsaWduOiByaWdodDsKICB2aXNpYmlsaXR5OiB2aXNpYmxlOwogIHdp
-ZHRoOiA1MHB4OwogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKfQoKLnJlZ2lvbnMgdHIuaGlnaGxpZ2h0
-IHRkLmxpbmUtbm8gewogIGJvcmRlci1yaWdodDogc29saWQgI2NjYyAycHg7Cn0KCi5yZWdpb24gewog
-IGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdmlzaWJpbGl0eTog
-dmlzaWJsZTsKICB6LWluZGV4OiAyMDA7Cn0KCi5yZWdpb24uYWRkZWQtcmVnaW9uIHsKICBiYWNrZ3Jv
-dW5kLWNvbG9yOiAjY2NmZmNjOwogIGNvbG9yOiAjMDAzMzAwOwp9CgoucmVnaW9uLnJlbW92ZWQtcmVn
-aW9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2NjY2OwogIGNvbG9yOiAjMDAxMTAwOwp9CgoucmVn
-aW9uLmluZm9ybWF0aXZlLXJlZ2lvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzg4ODg4ODsKICBjb2xv
-cjogIzAwMDAwMDsKfQoKLnRhcmdldCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzQ0NDsKICBwb3NpdGlv
-bjogcmVsYXRpdmU7CiAgdmlzaWJpbGl0eTogdmlzaWJsZTsKICBmb250LXdlaWdodDogNjAwOwp9Cgou
-aW5mby1wYW5lbCB7CiAgZmxleDogMSAyMDBweDsKICBtYXJnaW46IDA7CiAgaGVpZ2h0OiAxMDAlOwog
-IGRpc3BsYXk6IGZsZXg7CiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKfQoKLmluZm8tcGFuZWwgLmVk
-aXQtcGFuZWwgewogIGJhY2tncm91bmQtY29sb3I6ICMyODJiMmU7CiAgb3ZlcmZsb3c6IGF1dG87Cn0K
-Ci5pbmZvLXBhbmVsIC5wYW5lbC1jb250ZW50IHsKICBwYWRkaW5nOiA3cHg7Cn0KCi5pbmZvLXBhbmVs
-IC5wYW5lbC1jb250ZW50PiA6Zmlyc3QtY2hpbGQgewogIG1hcmdpbi10b3A6IDA7Cn0KCi5pbmZvLXBh
-bmVsIC5ub3dyYXAgewogIHdoaXRlLXNwYWNlOiBub3dyYXA7Cn0KCi5pbmZvLXBhbmVsIHVsLAouaW5m
-by1wYW5lbCBvbCB7CiAgcGFkZGluZy1sZWZ0OiAyMHB4Owp9CgouaW5mby1wYW5lbCBsaSB7CiAgbWFy
-Z2luOiAwIDAgNXB4IDA7Cn0KCi5pbmZvLXBhbmVsIGEgewogIGNvbG9yOiAjMzNjY2ZmOwp9CgouaW5m
-by1wYW5lbCAuZWRpdC1saXN0IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjgyYjJlOwogIG92ZXJmbG93
-OiBhdXRvOwp9CgouZWRpdC1wYW5lbCB7CiAgbWFyZ2luLXRvcDogNnB4OwogIGZsZXg6IDEgMTAwcHg7
-Cn0KCi5lZGl0LWxpc3QgewogIGZsZXg6IDIgMTAwcHg7Cn0KCi5lZGl0LWxpc3QgLmVkaXQgewogIG1h
-cmdpbjogM3B4IDA7Cn0KCi5lZGl0LWxpc3QgLmVkaXQtbGluayB7CiAgY3Vyc29yOiBwb2ludGVyOwp9
-CgoucmVydW5uaW5nLXBhbmUgewogIGRpc3BsYXk6IG5vbmU7Cn0KCmJvZHkucmVydW5uaW5nIC5yZXJ1
-bm5pbmctcGFuZSB7CiAgZGlzcGxheTogYmxvY2s7CiAgcG9zaXRpb246IGZpeGVkOwogIHRvcDogMHB4
-OwogIGJvdHRvbTogMHB4OwogIGxlZnQ6IDBweDsKICByaWdodDogMHB4OwogIGJhY2tncm91bmQtY29s
-b3I6ICMwMDAwMDBBQTsgLyogdHJhbnNsdWNlbnQgYmxhY2sgKi8KICB6LWluZGV4OiA0MDA7Cn0KCi5y
-ZXJ1bm5pbmctcGFuZSBoMSB7CiAgcG9zaXRpb246IGFic29sdXRlOwogIHRvcDogNTAlOwogIGxlZnQ6
-IDUwJTsKICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTsKfQoKcC50cmFjZSAudHlwZS1k
-ZXNjcmlwdGlvbiB7CiAgLyogRnJvbSBITEpTJ3MgLmhsanMta2V5d29yZCwgLmhsanMtc2VsZWN0b3It
-dGFnLCAuaGxqcy1kZWxldGlvbiAqLwogIGNvbG9yOiAjY2M3ODMyOwogIGZvbnQtZmFtaWx5OiBtb25v
-c3BhY2U7Cn0KCnVsLnRyYWNlIHsKICBmb250LXNpemU6IDEzcHg7CiAgbGlzdC1zdHlsZS10eXBlOiBu
-b25lOwogIHBhZGRpbmctbGVmdDogMHB4Owp9Cgp1bC50cmFjZSBsaSB7CiAgY29sb3I6IHdoaXRlOwog
-IG1hcmdpbi1sZWZ0OiAxNHB4OwogIHRleHQtaW5kZW50OiAtMTRweDsKfQoKdWwudHJhY2UgbGkgLmZ1
-bmN0aW9uIHsKICAvKiBGcm9tIEhMSlMncyAuaGxqcy1zZWN0aW9uLCAuaGxqcy10aXRsZSwgLmhsanMt
-dHlwZSAqLwogIGNvbG9yOiAjZmZjNjZkOwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7CiAgZm9udC13
-ZWlnaHQ6IDYwMDsKfQoKLmVsZXZhdGlvbi16NCB7CiAgYm94LXNoYWRvdzogMHB4IDJweCA0cHggLTFw
-eCByZ2JhKDAsIDAsIDAsIDAuMiksCiAgICAgIDBweCA0cHggNXB4IDBweCByZ2JhKDAsIDAsIDAsIDAu
-MTQpLAogICAgICAwcHggMXB4IDEwcHggMHB4IHJnYmEoMCwgMCwgMCwgLjEyKTsKfQoKYSB7CiAgY29s
-b3I6ICNjY2M7CiAgZmlsbDogI2NjYzsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7Cn0KCmE6aG92ZXIg
-ewogIGNvbG9yOiAjZmZmOwogIGZpbGw6ICNmZmY7Cn0KCmJ1dHRvbiB7CiAgYmFja2dyb3VuZC1jb2xv
-cjogIzMzY2NmZjsKICBib3JkZXI6IDJweCBzb2xpZCAjMzdhZWRjOwogIGJvcmRlci1yYWRpdXM6IDNw
-eDsKICBwYWRkaW5nOiA2cHggMTBweDsKICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogIzI4Mjgy
-ODsKfQoKYnV0dG9uOmhvdmVyIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjODBkZmZmOwogIGJvcmRlcjog
-MnB4IHNvbGlkICM1MmI4ZTA7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgpidXR0b25bZGlzYWJsZWRdIHsK
-ICBiYWNrZ3JvdW5kLWNvbG9yOiAjN2FhOGI4OwogIGNvbG9yOiAjNTA3MTc3OwogIGJvcmRlcjogMnB4
-IHNvbGlkICM1MDcxNzc7CiAgY3Vyc29yOiBub3QtYWxsb3dlZDsKfQoKLnBsYWNlaG9sZGVyIHsKICBj
-b2xvcjogIzc3NzsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgbWFyZ2luLXRvcDogM2VtICFpbXBvcnRh
-bnQ7Cn0KCi8qKgogKiBITEpTIE92ZXJyaWRlcwogKi8KLmhsanMgewogIC8qKgogICAqIFRoaXMgYWxs
-b3dzIHRoZSBwZXItbGluZSBoaWdobGlnaHRzIHRvIHNob3cuCiAgICovCiAgYmFja2dyb3VuZDogbm9u
-ZTsKfQo=
+CgouYXBwbGllZCAuYXBwbHktbWlncmF0aW9uOm5vdChbZGlzYWJsZWRdKSwgLm5lZWRzLXJlcnVuIC5h
+cHBseS1taWdyYXRpb246bm90KFtkaXNhYmxlZF0pIHsKICBkaXNwbGF5OiBub25lOwp9CgoucHJvcG9z
+ZWQ6bm90KC5uZWVkcy1yZXJ1bikgLmFwcGx5LW1pZ3JhdGlvbltkaXNhYmxlZF0gewogIGRpc3BsYXk6
+IG5vbmU7Cn0KCmhlYWRlciB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzFjMjgzNDsKICBoZWlnaHQ6IDQ4
+cHg7CiAgcGFkZGluZy1sZWZ0OiAyNHB4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgei1pbmRleDog
+NDsKfQoKaGVhZGVyIGgxLApoZWFkZXIgaDIgewogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBmb250
+LWZhbWlseTogIkdvb2dsZSBTYW5zIiwiUm9ib3RvIixzYW5zLXNlcmlmOwogIGZvbnQtd2VpZ2h0OiA0
+MDA7CiAgbWFyZ2luLXJpZ2h0OiAyNHB4Owp9CgpoMSB7CiAgZm9udC1zaXplOiAxLjVlbTsKfQoKaGVh
+ZGVyIGgyIHsKICBmb250LXNpemU6IDEuMmVtOwp9CgpoZWFkZXIgLmFwcGx5LW1pZ3JhdGlvbiwgLnJl
+cnVuLW1pZ3JhdGlvbiB7CiAgcmlnaHQ6IDBweDsKICBmbG9hdDogcmlnaHQ7CiAgbWFyZ2luOiAxMHB4
+Owp9CgoucmVydW4tbWlncmF0aW9uIC5yZXF1aXJlZCB7CiAgZGlzcGxheTogbm9uZTsKfQoKLm5lZWRz
+LXJlcnVuIC5yZXJ1bi1taWdyYXRpb24gLnJlcXVpcmVkIHsKICBkaXNwbGF5OiBpbml0aWFsOwp9Cgou
+bmVlZHMtcmVydW4gLnJlcnVuLW1pZ3JhdGlvbiAub3B0aW9uYWwgewogIGRpc3BsYXk6bm9uZTsKfQoK
+LyogUmVkIHRyaWFuZ2xlICovCi5yZXJ1bi1taWdyYXRpb24gLnJlcXVpcmVkIC5pY29uOjpiZWZvcmUg
+ewogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC04cHgsIC0xMXB4KTsKICBjb250ZW50OiAnXDI1QjMnOwog
+IGZvbnQtc2l6ZTogMjVweDsKICBwb3NpdGlvbjogZml4ZWQ7CiAgY29sb3I6ICNlODJjMmM7CiAgdGV4
+dC1zaGFkb3c6IDBweCAwcHggNXB4IHdoaXRlOwogIHotaW5kZXg6IC0zOwp9CgovKiBSZWQgdHJpYW5n
+bGUgZmlsbCAqLwoucmVydW4tbWlncmF0aW9uIC5yZXF1aXJlZCAuaWNvbjo6YWZ0ZXIgewogIHRyYW5z
+Zm9ybTogdHJhbnNsYXRlKC05cHgsIC0xMHB4KTsKICBjb250ZW50OiAnXDI1QjQnOwogIGZvbnQtc2l6
+ZTogMjVweDsKICBwb3NpdGlvbjogZml4ZWQ7CiAgY29sb3I6ICNiM2VjZmY7CiAgei1pbmRleDogLTE7
+Cn0KCi8qIFJlZCB0cmlhbmdsZSBleGNsYW1hdGlvbiAqLwoucmVydW4tbWlncmF0aW9uIC5yZXF1aXJl
+ZCAuaWNvbiB7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIG1hcmdpbi1yaWdodDogOHB4OwogIHRy
+YW5zZm9ybTogdHJhbnNsYXRlKDBweCwgMnB4KTsKICBtYXJnaW4tbGVmdDogMnB4OwogIGNvbG9yOiAj
+MmIyYjJiOwp9Cgpmb290ZXIgewogIGNvbG9yOiAjY2NjOwogIGJhY2tncm91bmQtY29sb3I6ICMyNzMy
+M2E7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogcm93OwogIGFsaWduLWl0ZW1zOiBj
+ZW50ZXI7CiAgcGFkZGluZzogOHB4IDI0cHg7Cn0KCmZvb3RlciAud2lkZSB7CiAgZmxleDogMTsKfQoK
+Lmhvcml6b250YWwgewogIGRpc3BsYXk6IGZsZXg7Cn0KCi5wYW5lbHMgewogIGJhY2tncm91bmQtY29s
+b3I6ICMxMjFhMjU7CiAgZmxleDogMTsKICBvdmVyZmxvdzogaGlkZGVuOwp9CgoucGFuZWwtaGVhZGlu
+ZyB7CiAgY29sb3I6IGdyYXk7CiAgbWFyZ2luOiA4cHg7Cn0KCi5uYXYtbGluaywKLnJlZ2lvbiB7CiAg
+Y3Vyc29yOiBwb2ludGVyOwp9CgoubmF2LXBhbmVsIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjgyYjJl
+OwogIGZsZXg6IDEgMjAwcHg7CiAgbWFyZ2luOiAwOwogIG92ZXJmbG93OiBzY3JvbGw7Cn0KCi5uYXYt
+aW5uZXIgewogIHBhZGRpbmc6IDAgMCA3cHggN3B4Owp9CgouZml4ZWQgewogIHBvc2l0aW9uOiBmaXhl
+ZDsKICB0b3A6IDA7Cn0KCi5yb290IHsKICBtYXJnaW46IDA7CiAgZGlzcGxheTogbm9uZTsKfQoKLm5h
+di10cmVlID4gdWwgewogIHBhZGRpbmctbGVmdDogNnB4Owp9CgoubmF2LWlubmVyIHVsIHsKICBwYWRk
+aW5nLWxlZnQ6IDEycHg7CiAgbWFyZ2luOiAwOwp9CgoubmF2LWlubmVyIGxpIHsKICBsaXN0LXN0eWxl
+LXR5cGU6IG5vbmU7Cn0KCi5uYXYtaW5uZXIgbGk6bm90KC5kaXIpIHsKICBtYXJnaW4tbGVmdDogMjBw
+eDsKICBtYXJnaW4tYm90dG9tOiAzcHg7Cn0KCi5uYXYtaW5uZXIgbGkuZGlyIC5hcnJvdyB7CiAgY3Vy
+c29yOiBwb2ludGVyOwogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBmb250LXNpemU6IDEwcHg7CiAg
+bWFyZ2luLXJpZ2h0OiA0cHg7CiAgdHJhbnNpdGlvbjogdHJhbnNmb3JtIDAuNXMgZWFzZS1vdXQ7Cn0K
+Ci5uYXYtaW5uZXIgbGkuZGlyIC5hcnJvdy5jb2xsYXBzZWQgewogIHRyYW5zZm9ybTogcm90YXRlKC05
+MGRlZyk7Cn0KCi5uYXYtaW5uZXIgdWwgewogIG1heC1oZWlnaHQ6IDIwMDBweDsKICB0cmFuc2l0aW9u
+OiBtYXgtaGVpZ2h0IDAuNXMgZWFzZS1vdXQ7Cn0KCi5uYXYtaW5uZXIgdWwuY29sbGFwc2VkIHsKICBt
+YXgtaGVpZ2h0OiAwICFpbXBvcnRhbnQ7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKfQoKLm5hdi1pbm5lciAu
+c2VsZWN0ZWQtZmlsZSB7CiAgY29sb3I6IHdoaXRlOwogIGN1cnNvcjogaW5oZXJpdDsKICBmb250LXdl
+aWdodDogNjAwOwogIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKfQoKLmVkaXQtY291bnQgewogIGJhY2tn
+cm91bmQtY29sb3I6ICMzN2FlZGM7CiAgYm9yZGVyLXJhZGl1czogMTBweDsKICBjb2xvcjogIzAwMDAw
+MDsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9udC1zaXplOiAxMXB4OwogIGZvbnQtd2VpZ2h0
+OiA2MDA7CiAgbWFyZ2luLWxlZnQ6IDVweDsKICBtaW4td2lkdGg6IDI1cHg7CiAgcGFkZGluZzogNHB4
+IDAgMnB4IDA7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIGxpbmUtaGVpZ2h0OiAxZW07Cn0KCi5jb250
+ZW50IHsKICBmbGV4OiA0IDMwMHB4OwogIGJhY2tncm91bmQ6ICMyODJiMmU7CiAgZm9udC1mYW1pbHk6
+IG1vbm9zcGFjZTsKICBtYXJnaW46IDAgNnB4OwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB3aGl0ZS1z
+cGFjZTogcHJlOwogIG92ZXJmbG93OiBzY3JvbGw7Cn0KCi5jb2RlIHsKICBwYWRkaW5nOiAwLjVlbTsK
+ICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgbGVmdDogMDsKICB0b3A6IDA7CiAgbWFyZ2luLWxlZnQ6IDU2
+cHg7Cn0KCi5obGpzIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjgyYjJlOwogIGRpc3BsYXk6IGJsb2Nr
+OwogIG92ZXJmbG93LXg6IGF1dG87CiAgcGFkZGluZzogMC41ZW07Cn0KCi5jb2RlIC53ZWxjb21lIHsK
+ICBmb250LWZhbWlseTogIkdvb2dsZSBTYW5zIiwiUm9ib3RvIixzYW5zLXNlcmlmOwogIGZvbnQtc2l6
+ZTogMThweDsKICBtYXJnaW4tcmlnaHQ6IDYycHg7CiAgY29sb3I6ICM3Nzc7Cn0KCi5jb2RlIC5uYXYt
+bGluayB7CiAgY29sb3I6IGluaGVyaXQ7CiAgdGV4dC1kZWNvcmF0aW9uLWxpbmU6IG5vbmU7Cn0KCi5j
+b2RlIC5uYXYtbGluazp2aXNpdGVkIHsKICBjb2xvcjogaW5oZXJpdDsKICB0ZXh0LWRlY29yYXRpb24t
+bGluZTogbm9uZTsKfQoKLmNvZGUgLm5hdi1saW5rOmhvdmVyIHsKICB0ZXh0LWRlY29yYXRpb24tbGlu
+ZTogdW5kZXJsaW5lOwogIGZvbnQtd2VpZ2h0OiA2MDA7Cn0KCi5yZWdpb25zIHsKICBwYWRkaW5nOiAw
+LjVlbTsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgbGVmdDogMDsKICB0b3A6IDA7Cn0KCi5yZWdpb25z
+IHRhYmxlIHsKICBib3JkZXItc3BhY2luZzogMDsKICBmb250LXNpemU6IGluaGVyaXQ7Cn0KCi5yZWdp
+b25zIHRkIHsKICBib3JkZXI6IG5vbmU7CiAgLyogVGhlIGNvbnRlbnQgb2YgdGhlIHJlZ2lvbnMgaXMg
+bm90IHZpc2libGU7IHRoZSB1c2VyIGluc3RlYWQgd2lsbCBzZWUgdGhlCiAgICogaGlnaGxpZ2h0ZWQg
+Y29weSBvZiB0aGUgY29udGVudC4gKi8KICBjb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwKTsKICBw
+YWRkaW5nOiAwOwogIHdoaXRlLXNwYWNlOiBwcmU7Cn0KCi5yZWdpb25zIHRkOmVtcHR5OmFmdGVyIHsK
+ICBjb250ZW50OiAiXDAwYTAiOwp9CgoucmVnaW9ucyB0ci5oaWdobGlnaHQgdGQ6bGFzdC1jaGlsZCB7
+CiAgYmFja2dyb3VuZC1jb2xvcjogIzQ0NDQ0NDsKICBjb2xvcjogd2hpdGU7Cn0KCi5yZWdpb25zIHRk
+LmxpbmUtbm8gewogIGJvcmRlci1yaWdodDogc29saWQgIzI4MmIyZSAycHg7CiAgY29sb3I6ICM5OTk5
+OTk7CiAgcGFkZGluZy1yaWdodDogNHB4OwogIHRleHQtYWxpZ246IHJpZ2h0OwogIHZpc2liaWxpdHk6
+IHZpc2libGU7CiAgd2lkdGg6IDUwcHg7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwp9CgoucmVnaW9u
+cyB0ci5oaWdobGlnaHQgdGQubGluZS1ubyB7CiAgYm9yZGVyLXJpZ2h0OiBzb2xpZCAjY2NjIDJweDsK
+fQoKLnJlZ2lvbiB7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIHBvc2l0aW9uOiByZWxhdGl2ZTsK
+ICB2aXNpYmlsaXR5OiB2aXNpYmxlOwogIHotaW5kZXg6IDIwMDsKfQoKLnJlZ2lvbi5hZGRlZC1yZWdp
+b24gewogIGJhY2tncm91bmQtY29sb3I6ICNjY2ZmY2M7CiAgY29sb3I6ICMwMDMzMDA7Cn0KCi5yZWdp
+b24ucmVtb3ZlZC1yZWdpb24gewogIGJhY2tncm91bmQtY29sb3I6ICNmZjY2NjY7CiAgY29sb3I6ICMw
+MDExMDA7Cn0KCi5yZWdpb24uaW5mb3JtYXRpdmUtcmVnaW9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAj
+ODg4ODg4OwogIGNvbG9yOiAjMDAwMDAwOwp9CgoudGFyZ2V0IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAj
+NDQ0OwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB2aXNpYmlsaXR5OiB2aXNpYmxlOwogIGZvbnQtd2Vp
+Z2h0OiA2MDA7Cn0KCi5pbmZvLXBhbmVsIHsKICBmbGV4OiAxIDIwMHB4OwogIG1hcmdpbjogMDsKICBo
+ZWlnaHQ6IDEwMCU7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwp9Cgou
+aW5mby1wYW5lbCAuZWRpdC1wYW5lbCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBvdmVy
+ZmxvdzogYXV0bzsKfQoKLmluZm8tcGFuZWwgLnBhbmVsLWNvbnRlbnQgewogIHBhZGRpbmc6IDdweDsK
+fQoKLmluZm8tcGFuZWwgLnBhbmVsLWNvbnRlbnQ+IDpmaXJzdC1jaGlsZCB7CiAgbWFyZ2luLXRvcDog
+MDsKfQoKLmluZm8tcGFuZWwgLm5vd3JhcCB7CiAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKfQoKLmluZm8t
+cGFuZWwgdWwsCi5pbmZvLXBhbmVsIG9sIHsKICBwYWRkaW5nLWxlZnQ6IDIwcHg7Cn0KCi5pbmZvLXBh
+bmVsIGxpIHsKICBtYXJnaW46IDAgMCA1cHggMDsKfQoKLmluZm8tcGFuZWwgYSB7CiAgY29sb3I6ICMz
+M2NjZmY7Cn0KCi5pbmZvLXBhbmVsIC5lZGl0LWxpc3QgewogIGJhY2tncm91bmQtY29sb3I6ICMyODJi
+MmU7CiAgb3ZlcmZsb3c6IGF1dG87Cn0KCi5lZGl0LXBhbmVsIHsKICBtYXJnaW4tdG9wOiA2cHg7CiAg
+ZmxleDogMSAxMDBweDsKfQoKLmVkaXQtbGlzdCB7CiAgZmxleDogMiAxMDBweDsKfQoKLmVkaXQtbGlz
+dCAuZWRpdCB7CiAgbWFyZ2luOiAzcHggMDsKfQoKLmVkaXQtbGlzdCAuZWRpdC1saW5rIHsKICBjdXJz
+b3I6IHBvaW50ZXI7Cn0KCi5yZXJ1bm5pbmctcGFuZSB7CiAgZGlzcGxheTogbm9uZTsKfQoKYm9keS5y
+ZXJ1bm5pbmcgLnJlcnVubmluZy1wYW5lIHsKICBkaXNwbGF5OiBibG9jazsKICBwb3NpdGlvbjogZml4
+ZWQ7CiAgdG9wOiAwcHg7CiAgYm90dG9tOiAwcHg7CiAgbGVmdDogMHB4OwogIHJpZ2h0OiAwcHg7CiAg
+YmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMEFBOyAvKiB0cmFuc2x1Y2VudCBibGFjayAqLwogIHotaW5k
+ZXg6IDQwMDsKfQoKLnJlcnVubmluZy1wYW5lIGgxIHsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgdG9w
+OiA1MCU7CiAgbGVmdDogNTAlOwogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpOwp9Cgpw
+LnRyYWNlIC50eXBlLWRlc2NyaXB0aW9uIHsKICAvKiBGcm9tIEhMSlMncyAuaGxqcy1rZXl3b3JkLCAu
+aGxqcy1zZWxlY3Rvci10YWcsIC5obGpzLWRlbGV0aW9uICovCiAgY29sb3I6ICNjYzc4MzI7CiAgZm9u
+dC1mYW1pbHk6IG1vbm9zcGFjZTsKfQoKdWwudHJhY2UgewogIGZvbnQtc2l6ZTogMTNweDsKICBsaXN0
+LXN0eWxlLXR5cGU6IG5vbmU7CiAgcGFkZGluZy1sZWZ0OiAwcHg7Cn0KCnVsLnRyYWNlIGxpIHsKICBj
+b2xvcjogd2hpdGU7CiAgbWFyZ2luLWxlZnQ6IDE0cHg7CiAgdGV4dC1pbmRlbnQ6IC0xNHB4Owp9Cgp1
+bC50cmFjZSBsaSAuZnVuY3Rpb24gewogIC8qIEZyb20gSExKUydzIC5obGpzLXNlY3Rpb24sIC5obGpz
+LXRpdGxlLCAuaGxqcy10eXBlICovCiAgY29sb3I6ICNmZmM2NmQ7CiAgZm9udC1mYW1pbHk6IG1vbm9z
+cGFjZTsKICBmb250LXdlaWdodDogNjAwOwp9CgouZWxldmF0aW9uLXo0IHsKICBib3gtc2hhZG93OiAw
+cHggMnB4IDRweCAtMXB4IHJnYmEoMCwgMCwgMCwgMC4yKSwKICAgICAgMHB4IDRweCA1cHggMHB4IHJn
+YmEoMCwgMCwgMCwgMC4xNCksCiAgICAgIDBweCAxcHggMTBweCAwcHggcmdiYSgwLCAwLCAwLCAuMTIp
+Owp9CgphIHsKICBjb2xvcjogI2NjYzsKICBmaWxsOiAjY2NjOwogIHRleHQtZGVjb3JhdGlvbjogbm9u
+ZTsKfQoKYTpob3ZlciB7CiAgY29sb3I6ICNmZmY7CiAgZmlsbDogI2ZmZjsKfQoKYS5wb3N0LWxpbmsg
+ewogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBtYXJnaW46IDNweDsKfQoKYnV0dG9uLCBhLnBvc3Qt
+bGluayB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzY2NmZjsKICBib3JkZXI6IDJweCBzb2xpZCAjMzdh
+ZWRjOwogIGJvcmRlci1yYWRpdXM6IDNweDsKICBwYWRkaW5nOiA2cHggMTBweDsKICBmb250LXdlaWdo
+dDogYm9sZDsKICBjb2xvcjogIzI4MjgyODsKfQoKYnV0dG9uOmhvdmVyLCBhLnBvc3QtbGluazpob3Zl
+ciB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzgwZGZmZjsKICBib3JkZXI6IDJweCBzb2xpZCAjNTJiOGUw
+OwogIGN1cnNvcjogcG9pbnRlcjsKfQoKYnV0dG9uW2Rpc2FibGVkXSB7CiAgYmFja2dyb3VuZC1jb2xv
+cjogIzdhYThiODsKICBjb2xvcjogIzUwNzE3NzsKICBib3JkZXI6IDJweCBzb2xpZCAjNTA3MTc3Owog
+IGN1cnNvcjogbm90LWFsbG93ZWQ7Cn0KCi5wbGFjZWhvbGRlciB7CiAgY29sb3I6ICM3Nzc7CiAgdGV4
+dC1hbGlnbjogY2VudGVyOwogIG1hcmdpbi10b3A6IDNlbSAhaW1wb3J0YW50Owp9CgovKioKICogSExK
+UyBPdmVycmlkZXMKICovCi5obGpzIHsKICAvKioKICAgKiBUaGlzIGFsbG93cyB0aGUgcGVyLWxpbmUg
+aGlnaGxpZ2h0cyB0byBzaG93LgogICAqLwogIGJhY2tncm91bmQ6IG5vbmU7Cn0K
 ''';
 
 String _migration_js;
-// migration_dart md5 is '46d77ad01f8c88bd4174b5dfbb872e82'
+// migration_dart md5 is '8114403a4ae0e1440ba0cea2923c01da'
 String _migration_js_base64 = '''
 KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgdD1P
 YmplY3Qua2V5cyhhKQpmb3IodmFyIHM9MDtzPHQubGVuZ3RoO3MrKyl7dmFyIHI9dFtzXQpiW3JdPWFb
@@ -467,16 +488,16 @@
 dFRvRmFzdE9iamVjdChhW3RdKX12YXIgeT0wCmZ1bmN0aW9uIHRlYXJPZmZHZXR0ZXIoYSxiLGMsZCxl
 KXtyZXR1cm4gZT9uZXcgRnVuY3Rpb24oImZ1bmNzIiwiYXBwbHlUcmFtcG9saW5lSW5kZXgiLCJyZWZs
 ZWN0aW9uSW5mbyIsIm5hbWUiLCJIIiwiYyIsInJldHVybiBmdW5jdGlvbiB0ZWFyT2ZmXyIrZCt5Kysr
-IihyZWNlaXZlcikgeyIrImlmIChjID09PSBudWxsKSBjID0gIisiSC5LcSIrIigiKyJ0aGlzLCBmdW5j
+IihyZWNlaXZlcikgeyIrImlmIChjID09PSBudWxsKSBjID0gIisiSC51YyIrIigiKyJ0aGlzLCBmdW5j
 cywgYXBwbHlUcmFtcG9saW5lSW5kZXgsIHJlZmxlY3Rpb25JbmZvLCBmYWxzZSwgdHJ1ZSwgbmFtZSk7
 IisicmV0dXJuIG5ldyBjKHRoaXMsIGZ1bmNzWzBdLCByZWNlaXZlciwgbmFtZSk7IisifSIpKGEsYixj
 LGQsSCxudWxsKTpuZXcgRnVuY3Rpb24oImZ1bmNzIiwiYXBwbHlUcmFtcG9saW5lSW5kZXgiLCJyZWZs
 ZWN0aW9uSW5mbyIsIm5hbWUiLCJIIiwiYyIsInJldHVybiBmdW5jdGlvbiB0ZWFyT2ZmXyIrZCt5Kysr
-IigpIHsiKyJpZiAoYyA9PT0gbnVsbCkgYyA9ICIrIkguS3EiKyIoIisidGhpcywgZnVuY3MsIGFwcGx5
+IigpIHsiKyJpZiAoYyA9PT0gbnVsbCkgYyA9ICIrIkgudWMiKyIoIisidGhpcywgZnVuY3MsIGFwcGx5
 VHJhbXBvbGluZUluZGV4LCByZWZsZWN0aW9uSW5mbywgZmFsc2UsIGZhbHNlLCBuYW1lKTsiKyJyZXR1
 cm4gbmV3IGModGhpcywgZnVuY3NbMF0sIG51bGwsIG5hbWUpOyIrIn0iKShhLGIsYyxkLEgsbnVsbCl9
 ZnVuY3Rpb24gdGVhck9mZihhLGIsYyxkLGUsZil7dmFyIHQ9bnVsbApyZXR1cm4gZD9mdW5jdGlvbigp
-e2lmKHQ9PT1udWxsKXQ9SC5LcSh0aGlzLGEsYixjLHRydWUsZmFsc2UsZSkucHJvdG90eXBlCnJldHVy
+e2lmKHQ9PT1udWxsKXQ9SC51Yyh0aGlzLGEsYixjLHRydWUsZmFsc2UsZSkucHJvdG90eXBlCnJldHVy
 biB0fTp0ZWFyT2ZmR2V0dGVyKGEsYixjLGUsZil9dmFyIHg9MApmdW5jdGlvbiBpbnN0YWxsVGVhck9m
 ZihhLGIsYyxkLGUsZixnLGgsaSxqKXt2YXIgdD1bXQpmb3IodmFyIHM9MDtzPGgubGVuZ3RoO3MrKyl7
 dmFyIHI9aFtzXQppZih0eXBlb2Ygcj09J3N0cmluZycpcj1hW3JdCnIuJGNhbGxOYW1lPWdbc10KdC5w
@@ -513,1877 +534,1927 @@
 d1t0XVthXSlyZXR1cm4gd1t0XVthXX19dmFyIEM9e30sSD17Rks6ZnVuY3Rpb24gRksoKXt9LApvbzpm
 dW5jdGlvbihhKXt2YXIgdCxzPWFeNDgKaWYoczw9OSlyZXR1cm4gcwp0PWF8MzIKaWYoOTc8PXQmJnQ8
 PTEwMilyZXR1cm4gdC04NwpyZXR1cm4tMX0sCnFDOmZ1bmN0aW9uKGEsYixjLGQpe1AuazEoYiwic3Rh
-cnQiKQppZihjIT1udWxsKXtQLmsxKGMsImVuZCIpCmlmKGI+YylILnZoKFAuVEUoYiwwLGMsInN0YXJ0
+cnQiKQppZihjIT1udWxsKXtQLmsxKGMsImVuZCIpCmlmKGI+YylILlZqKFAuVEUoYiwwLGMsInN0YXJ0
 IixudWxsKSl9cmV0dXJuIG5ldyBILm5IKGEsYixjLGQuQygibkg8MD4iKSl9LApLMTpmdW5jdGlvbihh
-LGIsYyxkKXtpZih1Lmd3LmIoYSkpcmV0dXJuIG5ldyBILnh5KGEsYixjLkMoIkA8MD4iKS5LcShkKS5D
-KCJ4eTwxLDI+IikpCnJldHVybiBuZXcgSC5pMShhLGIsYy5DKCJAPDA+IikuS3EoZCkuQygiaTE8MSwy
-PiIpKX0sCldwOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBQLmxqKCJObyBlbGVtZW50Iil9LApkVTpmdW5j
-dGlvbigpe3JldHVybiBuZXcgUC5saigiVG9vIG1hbnkgZWxlbWVudHMiKX0sCmFyOmZ1bmN0aW9uKCl7
-cmV0dXJuIG5ldyBQLmxqKCJUb28gZmV3IGVsZW1lbnRzIil9LApxajpmdW5jdGlvbiBxaihhKXt0aGlz
-LmE9YX0sCmJROmZ1bmN0aW9uIGJRKCl7fSwKYUw6ZnVuY3Rpb24gYUwoKXt9LApuSDpmdW5jdGlvbiBu
-SChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LAphNzpmdW5jdGlv
-biBhNyhhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9MApfLmQ9bnVsbApfLiR0aT1jfSwK
-aTE6ZnVuY3Rpb24gaTEoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LAp4eTpmdW5j
-dGlvbiB4eShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCk1IOmZ1bmN0aW9uIE1I
-KGEsYixjKXt2YXIgXz10aGlzCl8uYT1udWxsCl8uYj1hCl8uYz1iCl8uJHRpPWN9LApsSjpmdW5jdGlv
-biBsSihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sClU1OmZ1bmN0aW9uIFU1KGEs
-YixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKdkc6ZnVuY3Rpb24gdkcoYSxiLGMpe3Ro
-aXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApTVTpmdW5jdGlvbiBTVSgpe30sClJlOmZ1bmN0aW9u
-IFJlKCl7fSwKdzI6ZnVuY3Rpb24gdzIoKXt9LAp3djpmdW5jdGlvbiB3dihhKXt0aGlzLmE9YX0sCmRj
-OmZ1bmN0aW9uKCl7dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIE1hcCIp
-KX0sCk5ROmZ1bmN0aW9uKGEpe3ZhciB0LHM9SC5KZyhhKQppZih0eXBlb2Ygcz09InN0cmluZyIpcmV0
-dXJuIHMKdD0ibWluaWZpZWQ6IithCnJldHVybiB0fSwKd1Y6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihi
-IT1udWxsKXt0PWIueAppZih0IT1udWxsKXJldHVybiB0fXJldHVybiB1LmFVLmIoYSl9LApkOmZ1bmN0
-aW9uKGEpe3ZhciB0CmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gYQppZih0eXBlb2YgYT09Im51
-bWJlciIpe2lmKGEhPT0wKXJldHVybiIiK2F9ZWxzZSBpZighMD09PWEpcmV0dXJuInRydWUiCmVsc2Ug
-aWYoITE9PT1hKXJldHVybiJmYWxzZSIKZWxzZSBpZihhPT1udWxsKXJldHVybiJudWxsIgp0PUouQWMo
-YSkKaWYodHlwZW9mIHQhPSJzdHJpbmciKXRocm93IEguYihILkkoYSkpCnJldHVybiB0fSwKZVE6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9YS4kaWRlbnRpdHlIYXNoCmlmKHQ9PW51bGwpe3Q9TWF0aC5yYW5kb20oKSow
-eDNmZmZmZmZmfDAKYS4kaWRlbnRpdHlIYXNoPXR9cmV0dXJuIHR9LApIcDpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMscixxLHAsbyxuPW51bGwKaWYodHlwZW9mIGEhPSJzdHJpbmciKUgudmgoSC5JKGEpKQp0PS9e
+LGIsYyxkKXtpZih1Lmd3LmIoYSkpcmV0dXJuIG5ldyBILnh5KGEsYixjLkMoIkA8MD4iKS5LKGQpLkMo
+Inh5PDEsMj4iKSkKcmV0dXJuIG5ldyBILmkxKGEsYixjLkMoIkA8MD4iKS5LKGQpLkMoImkxPDEsMj4i
+KSl9LApXcDpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5saigiTm8gZWxlbWVudCIpfSwKZFU6ZnVuY3Rp
+b24oKXtyZXR1cm4gbmV3IFAubGooIlRvbyBtYW55IGVsZW1lbnRzIil9LAphcjpmdW5jdGlvbigpe3Jl
+dHVybiBuZXcgUC5saigiVG9vIGZldyBlbGVtZW50cyIpfSwKcWo6ZnVuY3Rpb24gcWooYSl7dGhpcy5h
+PWF9LApiUTpmdW5jdGlvbiBiUSgpe30sCmFMOmZ1bmN0aW9uIGFMKCl7fSwKbkg6ZnVuY3Rpb24gbkgo
+YSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKYTc6ZnVuY3Rpb24g
+YTcoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCmkx
+OmZ1bmN0aW9uIGkxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKeHk6ZnVuY3Rp
+b24geHkoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApNSDpmdW5jdGlvbiBNSChh
+LGIsYyl7dmFyIF89dGhpcwpfLmE9bnVsbApfLmI9YQpfLmM9YgpfLiR0aT1jfSwKbEo6ZnVuY3Rpb24g
+bEooYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApVNTpmdW5jdGlvbiBVNShhLGIs
+Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCnZHOmZ1bmN0aW9uIHZHKGEsYixjKXt0aGlz
+LmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKU1U6ZnVuY3Rpb24gU1UoKXt9LApSZTpmdW5jdGlvbiBS
+ZSgpe30sCncyOmZ1bmN0aW9uIHcyKCl7fSwKd3Y6ZnVuY3Rpb24gd3YoYSl7dGhpcy5hPWF9LApkYzpm
+dW5jdGlvbigpe3Rocm93IEguYihQLkw0KCJDYW5ub3QgbW9kaWZ5IHVubW9kaWZpYWJsZSBNYXAiKSl9
+LApOUTpmdW5jdGlvbihhKXt2YXIgdCxzPUguSmcoYSkKaWYodHlwZW9mIHM9PSJzdHJpbmciKXJldHVy
+biBzCnQ9Im1pbmlmaWVkOiIrYQpyZXR1cm4gdH0sClh0OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYiE9
+bnVsbCl7dD1iLngKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gdS5hVS5iKGEpfSwKZDpmdW5jdGlv
+bihhKXt2YXIgdAppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJudW1i
+ZXIiKXtpZihhIT09MClyZXR1cm4iIithfWVsc2UgaWYoITA9PT1hKXJldHVybiJ0cnVlIgplbHNlIGlm
+KCExPT09YSlyZXR1cm4iZmFsc2UiCmVsc2UgaWYoYT09bnVsbClyZXR1cm4ibnVsbCIKdD1KLkFjKGEp
+CmlmKHR5cGVvZiB0IT0ic3RyaW5nIil0aHJvdyBILmIoSC50TChhKSkKcmV0dXJuIHR9LAplUTpmdW5j
+dGlvbihhKXt2YXIgdD1hLiRpZGVudGl0eUhhc2gKaWYodD09bnVsbCl7dD1NYXRoLnJhbmRvbSgpKjB4
+M2ZmZmZmZmZ8MAphLiRpZGVudGl0eUhhc2g9dH1yZXR1cm4gdH0sCkhwOmZ1bmN0aW9uKGEsYil7dmFy
+IHQscyxyLHEscCxvLG49bnVsbAppZih0eXBlb2YgYSE9InN0cmluZyIpSC5WaihILnRMKGEpKQp0PS9e
 XHMqWystXT8oKDB4W2EtZjAtOV0rKXwoXGQrKXwoW2EtejAtOV0rKSlccyokL2kuZXhlYyhhKQppZih0
 PT1udWxsKXJldHVybiBuCmlmKDM+PXQubGVuZ3RoKXJldHVybiBILmsodCwzKQpzPUguYyh0WzNdKQpp
 ZihiPT1udWxsKXtpZihzIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZih0WzJdIT1udWxsKXJl
 dHVybiBwYXJzZUludChhLDE2KQpyZXR1cm4gbn1pZihiPDJ8fGI+MzYpdGhyb3cgSC5iKFAuVEUoYiwy
 LDM2LCJyYWRpeCIsbikpCmlmKGI9PT0xMCYmcyE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYo
 YjwxMHx8cz09bnVsbCl7cj1iPD0xMD80NytiOjg2K2IKcT10WzFdCmZvcihwPXEubGVuZ3RoLG89MDtv
-PHA7KytvKWlmKChDLnhCLlcocSxvKXwzMik+cilyZXR1cm4gbn1yZXR1cm4gcGFyc2VJbnQoYSxiKX0s
-CmxoOmZ1bmN0aW9uKGEpe3ZhciB0PUguSDUoYSkKcmV0dXJuIHR9LApINTpmdW5jdGlvbihhKXt2YXIg
-dCxzLHIKaWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIEguSihILnEoYSksbnVsbCkKaWYoSi5pYShh
-KT09PUMuT2t8fHUuYWsuYihhKSl7dD1DLndiKGEpCmlmKEguQmUodCkpcmV0dXJuIHQKcz1hLmNvbnN0
-cnVjdG9yCmlmKHR5cGVvZiBzPT0iZnVuY3Rpb24iKXtyPXMubmFtZQppZih0eXBlb2Ygcj09InN0cmlu
-ZyImJkguQmUocikpcmV0dXJuIHJ9fXJldHVybiBILkooSC5xKGEpLG51bGwpfSwKQmU6ZnVuY3Rpb24o
-YSl7dmFyIHQ9YSE9PSJPYmplY3QiJiZhIT09IiIKcmV0dXJuIHR9LApNMDpmdW5jdGlvbigpe2lmKCEh
-c2VsZi5sb2NhdGlvbilyZXR1cm4gc2VsZi5sb2NhdGlvbi5ocmVmCnJldHVybiBudWxsfSwKVks6ZnVu
-Y3Rpb24oYSl7dmFyIHQscyxyLHEscD1hLmxlbmd0aAppZihwPD01MDApcmV0dXJuIFN0cmluZy5mcm9t
-Q2hhckNvZGUuYXBwbHkobnVsbCxhKQpmb3IodD0iIixzPTA7czxwO3M9cil7cj1zKzUwMApxPXI8cD9y
-OnAKdCs9U3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLGEuc2xpY2UocyxxKSl9cmV0dXJuIHR9
-LApDcTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1ILlZNKFtdLHUudCkKZm9yKHQ9YS5sZW5ndGgscz0w
-O3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpe3I9YVtzXQppZighSC5vayhy
-KSl0aHJvdyBILmIoSC5JKHIpKQppZihyPD02NTUzNSlDLk5tLmkocSxyKQplbHNlIGlmKHI8PTExMTQx
-MTEpe0MuTm0uaShxLDU1Mjk2KyhDLmpuLndHKHItNjU1MzYsMTApJjEwMjMpKQpDLk5tLmkocSw1NjMy
-MCsociYxMDIzKSl9ZWxzZSB0aHJvdyBILmIoSC5JKHIpKX1yZXR1cm4gSC5WSyhxKX0sCmVUOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTA7czx0Oysrcyl7cj1hW3NdCmlmKCFILm9r
-KHIpKXRocm93IEguYihILkkocikpCmlmKHI8MCl0aHJvdyBILmIoSC5JKHIpKQppZihyPjY1NTM1KXJl
-dHVybiBILkNxKGEpfXJldHVybiBILlZLKGEpfSwKZnc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixx
-CmlmKGM8PTUwMCYmYj09PTAmJmM9PT1hLmxlbmd0aClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5h
-cHBseShudWxsLGEpCmZvcih0PWIscz0iIjt0PGM7dD1yKXtyPXQrNTAwCnE9cjxjP3I6YwpzKz1TdHJp
-bmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zdWJhcnJheSh0LHEpKX1yZXR1cm4gc30sCkx3OmZ1
-bmN0aW9uKGEpe3ZhciB0CmlmKDA8PWEpe2lmKGE8PTY1NTM1KXJldHVybiBTdHJpbmcuZnJvbUNoYXJD
-b2RlKGEpCmlmKGE8PTExMTQxMTEpe3Q9YS02NTUzNgpyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgo
-NTUyOTZ8Qy5qbi53Ryh0LDEwKSk+Pj4wLDU2MzIwfHQmMTAyMyl9fXRocm93IEguYihQLlRFKGEsMCwx
-MTE0MTExLG51bGwsbnVsbCkpfSwKbzI6ZnVuY3Rpb24oYSl7aWYoYS5kYXRlPT09dm9pZCAwKWEuZGF0
-ZT1uZXcgRGF0ZShhLmEpCnJldHVybiBhLmRhdGV9LAp0SjpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEp
-LmdldEZ1bGxZZWFyKCkrMApyZXR1cm4gdH0sCk5TOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0
-TW9udGgoKSsxCnJldHVybiB0fSwKakE6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXREYXRlKCkr
-MApyZXR1cm4gdH0sCktMOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0SG91cnMoKSswCnJldHVy
-biB0fSwKY2g6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXRNaW51dGVzKCkrMApyZXR1cm4gdH0s
-CkpkOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0U2Vjb25kcygpKzAKcmV0dXJuIHR9LApWYTpm
-dW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldE1pbGxpc2Vjb25kcygpKzAKcmV0dXJuIHR9LAp6bzpm
-dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPXt9CnIuYT0wCnQ9W10Kcz1bXQpyLmE9Yi5sZW5ndGgKQy5O
-bS5GVih0LGIpCnIuYj0iIgppZihjIT1udWxsJiZjLmEhPT0wKWMuSygwLG5ldyBILkNqKHIscyx0KSkK
-IiIrci5hCnJldHVybiBKLkp5KGEsbmV3IEguTEkoQy5UZSwwLHQscywwKSl9LApFazpmdW5jdGlvbihh
-LGIsYyl7dmFyIHQscyxyLHEKaWYoYiBpbnN0YW5jZW9mIEFycmF5KXQ9Yz09bnVsbHx8Yy5hPT09MApl
-bHNlIHQ9ITEKaWYodCl7cz1iCnI9cy5sZW5ndGgKaWYocj09PTApe2lmKCEhYS4kMClyZXR1cm4gYS4k
-MCgpfWVsc2UgaWYocj09PTEpe2lmKCEhYS4kMSlyZXR1cm4gYS4kMShzWzBdKX1lbHNlIGlmKHI9PT0y
-KXtpZighIWEuJDIpcmV0dXJuIGEuJDIoc1swXSxzWzFdKX1lbHNlIGlmKHI9PT0zKXtpZighIWEuJDMp
-cmV0dXJuIGEuJDMoc1swXSxzWzFdLHNbMl0pfWVsc2UgaWYocj09PTQpe2lmKCEhYS4kNClyZXR1cm4g
-YS4kNChzWzBdLHNbMV0sc1syXSxzWzNdKX1lbHNlIGlmKHI9PT01KWlmKCEhYS4kNSlyZXR1cm4gYS4k
-NShzWzBdLHNbMV0sc1syXSxzWzNdLHNbNF0pCnE9YVsiIisiJCIrcl0KaWYocSE9bnVsbClyZXR1cm4g
-cS5hcHBseShhLHMpfXJldHVybiBILkV3KGEsYixjKX0sCkV3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
-LHIscSxwLG8sbixtLGwsaz1iIGluc3RhbmNlb2YgQXJyYXk/YjpQLkNIKGIsITAsdS56KSxqPWsubGVu
-Z3RoLGk9YS4kUgppZihqPGkpcmV0dXJuIEguem8oYSxrLGMpCnQ9YS4kRApzPXQ9PW51bGwKcj0hcz90
-KCk6bnVsbApxPUouaWEoYSkKcD1xLiRDCmlmKHR5cGVvZiBwPT0ic3RyaW5nIilwPXFbcF0KaWYocyl7
-aWYoYyE9bnVsbCYmYy5hIT09MClyZXR1cm4gSC56byhhLGssYykKaWYoaj09PWkpcmV0dXJuIHAuYXBw
-bHkoYSxrKQpyZXR1cm4gSC56byhhLGssYyl9aWYociBpbnN0YW5jZW9mIEFycmF5KXtpZihjIT1udWxs
-JiZjLmEhPT0wKXJldHVybiBILnpvKGEsayxjKQppZihqPmkrci5sZW5ndGgpcmV0dXJuIEguem8oYSxr
-LG51bGwpCkMuTm0uRlYoayxyLnNsaWNlKGotaSkpCnJldHVybiBwLmFwcGx5KGEsayl9ZWxzZXtpZihq
-PmkpcmV0dXJuIEguem8oYSxrLGMpCm89T2JqZWN0LmtleXMocikKaWYoYz09bnVsbClmb3Iocz1vLmxl
-bmd0aCxuPTA7bjxvLmxlbmd0aDtvLmxlbmd0aD09PXN8fCgwLEgubGspKG8pLCsrbilDLk5tLmkoayxy
-W0guYyhvW25dKV0pCmVsc2V7Zm9yKHM9by5sZW5ndGgsbT0wLG49MDtuPG8ubGVuZ3RoO28ubGVuZ3Ro
-PT09c3x8KDAsSC5saykobyksKytuKXtsPUguYyhvW25dKQppZihjLng0KGwpKXsrK20KQy5ObS5pKGss
-Yy5xKDAsbCkpfWVsc2UgQy5ObS5pKGsscltsXSl9aWYobSE9PWMuYSlyZXR1cm4gSC56byhhLGssYyl9
-cmV0dXJuIHAuYXBwbHkoYSxrKX19LApwWTpmdW5jdGlvbihhKXt0aHJvdyBILmIoSC5JKGEpKX0sCms6
-ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKUouSChhKQp0aHJvdyBILmIoSC5IWShhLGIpKX0sCkhZOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscyxyPSJpbmRleCIKaWYoIUgub2soYikpcmV0dXJuIG5ldyBQLkFUKCEw
-LGIscixudWxsKQp0PUguV1koSi5IKGEpKQppZighKGI8MCkpe2lmKHR5cGVvZiB0IT09Im51bWJlciIp
-cmV0dXJuIEgucFkodCkKcz1iPj10fWVsc2Ugcz0hMAppZihzKXJldHVybiBQLnQoYixhLHIsbnVsbCx0
-KQpyZXR1cm4gUC5PNyhiLHIpfSwKYXU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PSJJbnZhbGlkIHZhbHVl
-IgppZihhPmMpcmV0dXJuIG5ldyBQLmJKKDAsYywhMCxhLCJzdGFydCIsdCkKaWYoYiE9bnVsbCl7aWYo
-IUgub2soYikpcmV0dXJuIG5ldyBQLkFUKCEwLGIsImVuZCIsbnVsbCkKaWYoYjxhfHxiPmMpcmV0dXJu
-IG5ldyBQLmJKKGEsYywhMCxiLCJlbmQiLHQpfXJldHVybiBuZXcgUC5BVCghMCxiLCJlbmQiLG51bGwp
-fSwKSTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQVQoITAsYSxudWxsLG51bGwpfSwKYjpmdW5jdGlv
-bihhKXt2YXIgdAppZihhPT1udWxsKWE9bmV3IFAuTEsoKQp0PW5ldyBFcnJvcigpCnQuZGFydEV4Y2Vw
-dGlvbj1hCmlmKCJkZWZpbmVQcm9wZXJ0eSIgaW4gT2JqZWN0KXtPYmplY3QuZGVmaW5lUHJvcGVydHko
-dCwibWVzc2FnZSIse2dldDpILkp1fSkKdC5uYW1lPSIifWVsc2UgdC50b1N0cmluZz1ILkp1CnJldHVy
-biB0fSwKSnU6ZnVuY3Rpb24oKXtyZXR1cm4gSi5BYyh0aGlzLmRhcnRFeGNlcHRpb24pfSwKdmg6ZnVu
-Y3Rpb24oYSl7dGhyb3cgSC5iKGEpfSwKbGs6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAuYTQoYSkpfSwK
-Y006ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvCmE9SC5lQShhLnJlcGxhY2UoU3RyaW5nKHt9KSwn
-JHJlY2VpdmVyJCcpKQp0PWEubWF0Y2goL1xcXCRbYS16QS1aXStcXFwkL2cpCmlmKHQ9PW51bGwpdD1I
-LlZNKFtdLHUucykKcz10LmluZGV4T2YoIlxcJGFyZ3VtZW50c1xcJCIpCnI9dC5pbmRleE9mKCJcXCRh
-cmd1bWVudHNFeHByXFwkIikKcT10LmluZGV4T2YoIlxcJGV4cHJcXCQiKQpwPXQuaW5kZXhPZigiXFwk
-bWV0aG9kXFwkIikKbz10LmluZGV4T2YoIlxcJHJlY2VpdmVyXFwkIikKcmV0dXJuIG5ldyBILmY5KGEu
-cmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkYXJndW1lbnRzXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154
-XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJGFyZ3VtZW50c0V4cHJcXFxcXFwkJywnZycp
-LCcoKD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkZXhwclxcXFxcXCQnLCdn
-JyksJygoPzp4fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRtZXRob2RcXFxcXFwk
-JywnZycpLCcoKD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkcmVjZWl2ZXJc
-XFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJykscyxyLHEscCxvKX0sClM3OmZ1bmN0aW9uKGEpe3Jl
-dHVybiBmdW5jdGlvbigkZXhwciQpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7
-JGV4cHIkLiRtZXRob2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2godCl7cmV0dXJuIHQubWVzc2FnZX19
-KGEpfSwKTWo6ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCRleHByJCl7dHJ5eyRleHByJC4kbWV0
-aG9kJH1jYXRjaCh0KXtyZXR1cm4gdC5tZXNzYWdlfX0oYSl9LApJajpmdW5jdGlvbihhLGIpe3JldHVy
-biBuZXcgSC5XMChhLGI9PW51bGw/bnVsbDpiLm1ldGhvZCl9LApUMzpmdW5jdGlvbihhLGIpe3ZhciB0
-PWI9PW51bGwscz10P251bGw6Yi5tZXRob2QKcmV0dXJuIG5ldyBILmF6KGEscyx0P251bGw6Yi5yZWNl
-aXZlcil9LApSdTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGY9bnVs
-bCxlPW5ldyBILkFtKGEpCmlmKGE9PW51bGwpcmV0dXJuIGYKaWYoYSBpbnN0YW5jZW9mIEguYnEpcmV0
-dXJuIGUuJDEoYS5hKQppZih0eXBlb2YgYSE9PSJvYmplY3QiKXJldHVybiBhCmlmKCJkYXJ0RXhjZXB0
-aW9uIiBpbiBhKXJldHVybiBlLiQxKGEuZGFydEV4Y2VwdGlvbikKZWxzZSBpZighKCJtZXNzYWdlIiBp
-biBhKSlyZXR1cm4gYQp0PWEubWVzc2FnZQppZigibnVtYmVyIiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9
-PSJudW1iZXIiKXtzPWEubnVtYmVyCnI9cyY2NTUzNQppZigoQy5qbi53RyhzLDE2KSY4MTkxKT09PTEw
-KXN3aXRjaChyKXtjYXNlIDQzODpyZXR1cm4gZS4kMShILlQzKEguZCh0KSsiIChFcnJvciAiK3IrIiki
-LGYpKQpjYXNlIDQ0NTpjYXNlIDUwMDc6cmV0dXJuIGUuJDEoSC5JaihILmQodCkrIiAoRXJyb3IgIity
-KyIpIixmKSl9fWlmKGEgaW5zdGFuY2VvZiBUeXBlRXJyb3Ipe3E9JC5TbigpCnA9JC5scSgpCm89JC5O
-OSgpCm49JC5pSSgpCm09JC5VTigpCmw9JC5aaCgpCms9JC5yTigpCiQuYzMoKQpqPSQuSEsoKQppPSQu
-cjEoKQpoPXEucVModCkKaWYoaCE9bnVsbClyZXR1cm4gZS4kMShILlQzKEguYyh0KSxoKSkKZWxzZXto
-PXAucVModCkKaWYoaCE9bnVsbCl7aC5tZXRob2Q9ImNhbGwiCnJldHVybiBlLiQxKEguVDMoSC5jKHQp
-LGgpKX1lbHNle2g9by5xUyh0KQppZihoPT1udWxsKXtoPW4ucVModCkKaWYoaD09bnVsbCl7aD1tLnFT
-KHQpCmlmKGg9PW51bGwpe2g9bC5xUyh0KQppZihoPT1udWxsKXtoPWsucVModCkKaWYoaD09bnVsbCl7
-aD1uLnFTKHQpCmlmKGg9PW51bGwpe2g9ai5xUyh0KQppZihoPT1udWxsKXtoPWkucVModCkKZz1oIT1u
-dWxsfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBn
-PSEwfWVsc2UgZz0hMAppZihnKXJldHVybiBlLiQxKEguSWooSC5jKHQpLGgpKX19cmV0dXJuIGUuJDEo
-bmV3IEgudlYodHlwZW9mIHQ9PSJzdHJpbmciP3Q6IiIpKX1pZihhIGluc3RhbmNlb2YgUmFuZ2VFcnJv
-cil7aWYodHlwZW9mIHQ9PSJzdHJpbmciJiZ0LmluZGV4T2YoImNhbGwgc3RhY2siKSE9PS0xKXJldHVy
-biBuZXcgUC5LWSgpCnQ9ZnVuY3Rpb24oYil7dHJ5e3JldHVybiBTdHJpbmcoYil9Y2F0Y2goZCl7fXJl
-dHVybiBudWxsfShhKQpyZXR1cm4gZS4kMShuZXcgUC5BVCghMSxmLGYsdHlwZW9mIHQ9PSJzdHJpbmci
-P3QucmVwbGFjZSgvXlJhbmdlRXJyb3I6XHMqLywiIik6dCkpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9y
-PT0iZnVuY3Rpb24iJiZhIGluc3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2YgdD09InN0cmlu
-ZyImJnQ9PT0idG9vIG11Y2ggcmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRz
-OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVs
-bClyZXR1cm4gbmV3IEguWE8oYSkKdD1hLiRjYWNoZWRUcmFjZQppZih0IT1udWxsKXJldHVybiB0CnJl
-dHVybiBhLiRjYWNoZWRUcmFjZT1uZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
-LHE9YS5sZW5ndGgKZm9yKHQ9MDt0PHE7dD1yKXtzPXQrMQpyPXMrMQpiLlkoMCxhW3RdLGFbc10pfXJl
-dHVybiBifSwKZnQ6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3UuWi5hKGEpCnN3aXRjaChILldZKGIpKXtj
-YXNlIDA6cmV0dXJuIGEuJDAoKQpjYXNlIDE6cmV0dXJuIGEuJDEoYykKY2FzZSAyOnJldHVybiBhLiQy
-KGMsZCkKY2FzZSAzOnJldHVybiBhLiQzKGMsZCxlKQpjYXNlIDQ6cmV0dXJuIGEuJDQoYyxkLGUsZil9
-dGhyb3cgSC5iKG5ldyBQLkNEKCJVbnN1cHBvcnRlZCBudW1iZXIgb2YgYXJndW1lbnRzIGZvciB3cmFw
-cGVkIGNsb3N1cmUiKSl9LAp0UjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG51
-bGwKdD1hLiRpZGVudGl0eQppZighIXQpcmV0dXJuIHQKdD1mdW5jdGlvbihjLGQsZSl7cmV0dXJuIGZ1
-bmN0aW9uKGYsZyxoLGkpe3JldHVybiBlKGMsZCxmLGcsaCxpKX19KGEsYixILmZ0KQphLiRpZGVudGl0
-eT10CnJldHVybiB0fSwKaUE6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG4s
-bSxsPW51bGwsaz1iWzBdLGo9ay4kY2FsbE5hbWUsaT1lP09iamVjdC5jcmVhdGUobmV3IEguengoKS5j
-b25zdHJ1Y3Rvci5wcm90b3R5cGUpOk9iamVjdC5jcmVhdGUobmV3IEguankobCxsLGwsbCkuY29uc3Ry
-dWN0b3IucHJvdG90eXBlKQppLiRpbml0aWFsaXplPWkuY29uc3RydWN0b3IKaWYoZSl0PWZ1bmN0aW9u
-IHN0YXRpY190ZWFyX29mZigpe3RoaXMuJGluaXRpYWxpemUoKX0KZWxzZXtzPSQueWoKaWYodHlwZW9m
-IHMhPT0ibnVtYmVyIilyZXR1cm4gcy5oKCkKJC55aj1zKzEKcz1uZXcgRnVuY3Rpb24oImEsYixjLGQi
-K3MsInRoaXMuJGluaXRpYWxpemUoYSxiLGMsZCIrcysiKSIpCnQ9c31pLmNvbnN0cnVjdG9yPXQKdC5w
-cm90b3R5cGU9aQppZighZSl7cj1ILmJ4KGEsayxmKQpyLiRyZWZsZWN0aW9uSW5mbz1kfWVsc2V7aS4k
-c3RhdGljX25hbWU9ZwpyPWt9cT1ILmltKGQsZSxmKQppLiRTPXEKaVtqXT1yCmZvcihwPXIsbz0xO288
-Yi5sZW5ndGg7KytvKXtuPWJbb10KbT1uLiRjYWxsTmFtZQppZihtIT1udWxsKXtuPWU/bjpILmJ4KGEs
-bixmKQppW21dPW59aWYobz09PWMpe24uJHJlZmxlY3Rpb25JbmZvPWQKcD1ufX1pLiRDPXAKaS4kUj1r
-LiRSCmkuJEQ9ay4kRApyZXR1cm4gdH0sCmltOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZih0eXBlb2Yg
-YT09Im51bWJlciIpcmV0dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGQo
-ZSl9fShILkJwLGEpCmlmKHR5cGVvZiBhPT0ic3RyaW5nIil7aWYoYil0aHJvdyBILmIoIkNhbm5vdCBj
-b21wdXRlIHNpZ25hdHVyZSBmb3Igc3RhdGljIHRlYXJvZmYuIikKdD1jP0guUFc6SC5UbgpyZXR1cm4g
-ZnVuY3Rpb24oZCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZSh0aGlzLGQpfX0oYSx0KX10aHJv
-dyBILmIoIkVycm9yIGluIGZ1bmN0aW9uVHlwZSBvZiB0ZWFyb2ZmIil9LAp2cTpmdW5jdGlvbihhLGIs
-YyxkKXt2YXIgdD1ILkRWCnN3aXRjaChiPy0xOmEpe2Nhc2UgMDpyZXR1cm4gZnVuY3Rpb24oZSxmKXty
-ZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZih0aGlzKVtlXSgpfX0oYyx0KQpjYXNlIDE6cmV0dXJuIGZ1
-bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcpe3JldHVybiBmKHRoaXMpW2VdKGcpfX0oYyx0KQpj
-YXNlIDI6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCl7cmV0dXJuIGYodGhp
-cylbZV0oZyxoKX19KGMsdCkKY2FzZSAzOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlv
-bihnLGgsaSl7cmV0dXJuIGYodGhpcylbZV0oZyxoLGkpfX0oYyx0KQpjYXNlIDQ6cmV0dXJuIGZ1bmN0
-aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGop
-fX0oYyx0KQpjYXNlIDU6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGos
-ayl7cmV0dXJuIGYodGhpcylbZV0oZyxoLGksaixrKX19KGMsdCkKZGVmYXVsdDpyZXR1cm4gZnVuY3Rp
-b24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZS5hcHBseShmKHRoaXMpLGFyZ3VtZW50cyl9
-fShkLHQpfX0sCmJ4OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbgppZihjKXJldHVybiBI
-LkhmKGEsYikKdD1iLiRzdHViTmFtZQpzPWIubGVuZ3RoCnI9YVt0XQpxPWI9PW51bGw/cj09bnVsbDpi
-PT09cgpwPSFxfHxzPj0yNwppZihwKXJldHVybiBILnZxKHMsIXEsdCxiKQppZihzPT09MCl7cT0kLnlq
-CmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuaCgpCiQueWo9cSsxCm89InNlbGYiK3EKcT0i
-cmV0dXJuIGZ1bmN0aW9uKCl7dmFyICIrbysiID0gdGhpcy4iCnA9JC5tSgpyZXR1cm4gbmV3IEZ1bmN0
-aW9uKHErSC5kKHA9PW51bGw/JC5tSj1ILkUyKCJzZWxmIik6cCkrIjtyZXR1cm4gIitvKyIuIitILmQo
-dCkrIigpO30iKSgpfW49ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Ii5zcGxpdCgiIikuc3BsaWNl
-KDAscykuam9pbigiLCIpCnE9JC55agppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLmgoKQok
-LnlqPXErMQpuKz1xCnE9InJldHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRoaXMuIgpwPSQubUoK
-cmV0dXJuIG5ldyBGdW5jdGlvbihxK0guZChwPT1udWxsPyQubUo9SC5FMigic2VsZiIpOnApKyIuIitI
-LmQodCkrIigiK24rIik7fSIpKCl9LApaNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILkRWLHM9SC55
-Uwpzd2l0Y2goYj8tMTphKXtjYXNlIDA6dGhyb3cgSC5iKEguRWYoIkludGVyY2VwdGVkIGZ1bmN0aW9u
-IHdpdGggbm8gYXJndW1lbnRzLiIpKQpjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4g
-ZnVuY3Rpb24oKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpKX19KGMsdCxzKQpjYXNlIDI6cmV0dXJu
-IGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlz
-KSxoKX19KGMsdCxzKQpjYXNlIDM6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24o
-aCxpKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSl9fShjLHQscykKY2FzZSA0OnJldHVybiBm
-dW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnKHRo
-aXMpLGgsaSxqKX19KGMsdCxzKQpjYXNlIDU6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVu
-Y3Rpb24oaCxpLGosayl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksaixrKX19KGMsdCxzKQpj
-YXNlIDY6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGosayxsKXtyZXR1
-cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqLGssbCl9fShjLHQscykKZGVmYXVsdDpyZXR1cm4gZnVu
-Y3Rpb24oZSxmLGcsaCl7cmV0dXJuIGZ1bmN0aW9uKCl7aD1bZyh0aGlzKV0KQXJyYXkucHJvdG90eXBl
-LnB1c2guYXBwbHkoaCxhcmd1bWVudHMpCnJldHVybiBlLmFwcGx5KGYodGhpcyksaCl9fShkLHQscyl9
-fSwKSGY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtPSQubUoKaWYobT09bnVsbCltPSQu
-bUo9SC5FMigic2VsZiIpCnQ9JC5QNAppZih0PT1udWxsKXQ9JC5QND1ILkUyKCJyZWNlaXZlciIpCnM9
-Yi4kc3R1Yk5hbWUKcj1iLmxlbmd0aApxPWFbc10KcD1iPT1udWxsP3E9PW51bGw6Yj09PXEKbz0hcHx8
-cj49MjgKaWYobylyZXR1cm4gSC5aNChyLCFwLHMsYikKaWYocj09PTEpe209InJldHVybiBmdW5jdGlv
-bigpe3JldHVybiB0aGlzLiIrSC5kKG0pKyIuIitILmQocykrIih0aGlzLiIrSC5kKHQpKyIpOyIKdD0k
-LnlqCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcg
-RnVuY3Rpb24obSt0KyJ9IikoKX1uPSJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIp
-LnNwbGljZSgwLHItMSkuam9pbigiLCIpCm09InJldHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRo
-aXMuIitILmQobSkrIi4iK0guZChzKSsiKHRoaXMuIitILmQodCkrIiwgIituKyIpOyIKdD0kLnlqCmlm
-KHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcgRnVuY3Rp
-b24obSt0KyJ9IikoKX0sCktxOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3JldHVybiBILmlBKGEsYixj
-LGQsISFlLCEhZixnKX0sClRuOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguY0Uodi50eXBlVW5pdmVyc2Us
-SC5xKGEuYSksYil9LApQVzpmdW5jdGlvbihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgu
-cShhLmMpLGIpfSwKRFY6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVy
-biBhLmN9LApFMjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1uZXcgSC5qeSgic2VsZiIsInRhcmdldCIs
-InJlY2VpdmVyIiwibmFtZSIpLHA9Si5FcChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhxKSkKZm9y
-KHQ9cC5sZW5ndGgscz0wO3M8dDsrK3Mpe3I9cFtzXQppZihxW3JdPT09YSlyZXR1cm4gcn19LApvVDpm
-dW5jdGlvbihhKXtpZihhPT1udWxsKUguZk8oImJvb2xlYW4gZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBu
-dWxsIikKcmV0dXJuIGF9LApmTzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IEgua1koYSkpfSwKYWc6
-ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKG5ldyBQLnQ3KGEpKX0sCkVmOmZ1bmN0aW9uKGEpe3JldHVybiBu
-ZXcgSC5FcShhKX0sCllnOmZ1bmN0aW9uKGEpe3JldHVybiB2LmdldElzb2xhdGVUYWcoYSl9LApWTTpm
-dW5jdGlvbihhLGIpe2Fbdi5hcnJheVJ0aV09YgpyZXR1cm4gYX0sCm9YOmZ1bmN0aW9uKGEpe2lmKGE9
-PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIGEuJHRpfSwKSU06ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBI
-Llk5KGFbIiRhIitILmQoYyldLEgub1goYikpfSwKWTk6ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJl
-dHVybiBiCmE9YS5hcHBseShudWxsLGIpCmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoQXJyYXkuaXNB
-cnJheShhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gYS5hcHBseShudWxs
-LGIpCnJldHVybiBifSwKSUc6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBhLmFwcGx5KGIsSC5ZOShKLmlh
-KGIpWyIkYSIrSC5kKGMpXSxILm9YKGIpKSl9LAppdzpmdW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmlu
-ZVByb3BlcnR5KGEsYix7dmFsdWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmln
-dXJhYmxlOnRydWV9KX0sCkc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1ILmMoJC55LiQxKGEpKSxv
-PSQualtwXQppZihvIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVy
-dHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6
-dHJ1ZX0pCnJldHVybiBvLml9dD0kLnZbcF0KaWYodCE9bnVsbClyZXR1cm4gdApzPXYuaW50ZXJjZXB0
-b3JzQnlUYWdbcF0KaWYocz09bnVsbCl7cD1ILmMoJC51LiQyKGEscCkpCmlmKHAhPW51bGwpe289JC5q
-W3BdCmlmKG8hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5h
-bWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVl
-fSkKcmV0dXJuIG8uaX10PSQudltwXQppZih0IT1udWxsKXJldHVybiB0CnM9di5pbnRlcmNlcHRvcnNC
-eVRhZ1twXX19aWYocz09bnVsbClyZXR1cm4gbnVsbAp0PXMucHJvdG90eXBlCnI9cFswXQppZihyPT09
-IiEiKXtvPUgubCh0KQokLmpbcF09bwpPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJv
-cGVydHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFi
-bGU6dHJ1ZX0pCnJldHVybiBvLml9aWYocj09PSJ+Iil7JC52W3BdPXQKcmV0dXJuIHR9aWYocj09PSIt
-Iil7cT1ILmwodCkKT2JqZWN0LmRlZmluZVByb3BlcnR5KE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSx2
-LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpxLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1
-ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBxLml9aWYocj09PSIrIilyZXR1cm4gSC5MYyhhLHQp
-CmlmKHI9PT0iKiIpdGhyb3cgSC5iKFAubihwKSkKaWYodi5sZWFmVGFnc1twXT09PXRydWUpe3E9SC5s
-KHQpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSksdi5kaXNwYXRj
-aFByb3BlcnR5TmFtZSx7dmFsdWU6cSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmln
-dXJhYmxlOnRydWV9KQpyZXR1cm4gcS5pfWVsc2UgcmV0dXJuIEguTGMoYSx0KX0sCkxjOmZ1bmN0aW9u
-KGEsYil7dmFyIHQ9T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0
-LHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOkouUXUoYix0LG51bGwsbnVsbCksZW51bWVyYWJs
-ZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIGJ9LApsOmZ1bmN0
-aW9uKGEpe3JldHVybiBKLlF1KGEsITEsbnVsbCwhIWEuJGlYail9LApWRjpmdW5jdGlvbihhLGIsYyl7
-dmFyIHQ9Yi5wcm90b3R5cGUKaWYodi5sZWFmVGFnc1thXT09PXRydWUpcmV0dXJuIEgubCh0KQplbHNl
-IHJldHVybiBKLlF1KHQsYyxudWxsLG51bGwpfSwKTTpmdW5jdGlvbigpe2lmKCEwPT09JC5LKXJldHVy
-bgokLks9ITAKSC5EKCl9LApEOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbQokLmo9T2JqZWN0
-LmNyZWF0ZShudWxsKQokLnY9T2JqZWN0LmNyZWF0ZShudWxsKQpILmEoKQp0PXYuaW50ZXJjZXB0b3Jz
-QnlUYWcKcz1PYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0KQppZih0eXBlb2Ygd2luZG93IT0idW5k
-ZWZpbmVkIil7d2luZG93CnI9ZnVuY3Rpb24oKXt9CmZvcihxPTA7cTxzLmxlbmd0aDsrK3Epe3A9c1tx
-XQpvPSQueDcuJDEocCkKaWYobyE9bnVsbCl7bj1ILlZGKHAsdFtwXSxvKQppZihuIT1udWxsKXtPYmpl
-Y3QuZGVmaW5lUHJvcGVydHkobyx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpuLGVudW1lcmFi
-bGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnIucHJvdG90eXBlPW99fX19
-Zm9yKHE9MDtxPHMubGVuZ3RoOysrcSl7cD1zW3FdCmlmKC9eW0EtWmEtel9dLy50ZXN0KHApKXttPXRb
-cF0KdFsiISIrcF09bQp0WyJ+IitwXT1tCnRbIi0iK3BdPW0KdFsiKyIrcF09bQp0WyIqIitwXT1tfX19
-LAphOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49Qy5PNCgpCm49SC5GKEMuWXEsSC5GKEMuS1Us
-SC5GKEMuZlEsSC5GKEMuZlEsSC5GKEMuaTcsSC5GKEMueGksSC5GKEMuZGsoQy53YiksbikpKSkpKSkK
-aWYodHlwZW9mIGRhcnROYXRpdmVEaXNwYXRjaEhvb2tzVHJhbnNmb3JtZXIhPSJ1bmRlZmluZWQiKXt0
-PWRhcnROYXRpdmVEaXNwYXRjaEhvb2tzVHJhbnNmb3JtZXIKaWYodHlwZW9mIHQ9PSJmdW5jdGlvbiIp
-dD1bdF0KaWYodC5jb25zdHJ1Y3Rvcj09QXJyYXkpZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3Nd
-CmlmKHR5cGVvZiByPT0iZnVuY3Rpb24iKW49cihuKXx8bn19cT1uLmdldFRhZwpwPW4uZ2V0VW5rbm93
-blRhZwpvPW4ucHJvdG90eXBlRm9yVGFnCiQueT1uZXcgSC5yKHEpCiQudT1uZXcgSC5kQyhwKQokLng3
-PW5ldyBILndOKG8pfSwKRjpmdW5jdGlvbihhLGIpe3JldHVybiBhKGIpfHxifSwKdjQ6ZnVuY3Rpb24o
-YSxiLGMsZCxlLGYpe3ZhciB0PWI/Im0iOiIiLHM9Yz8iIjoiaSIscj1kPyJ1IjoiIixxPWU/InMiOiIi
-LHA9Zj8iZyI6IiIsbz1mdW5jdGlvbihnLGgpe3RyeXtyZXR1cm4gbmV3IFJlZ0V4cChnLGgpfWNhdGNo
-KG4pe3JldHVybiBufX0oYSx0K3MrcitxK3ApCmlmKG8gaW5zdGFuY2VvZiBSZWdFeHApcmV0dXJuIG8K
-dGhyb3cgSC5iKFAucnIoIklsbGVnYWwgUmVnRXhwIHBhdHRlcm4gKCIrU3RyaW5nKG8pKyIpIixhLG51
-bGwpKX0sCm0yOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZih0eXBlb2YgYj09InN0cmluZyIpcmV0dXJu
-IGEuaW5kZXhPZihiLGMpPj0wCmVsc2UgaWYoYiBpbnN0YW5jZW9mIEguVlIpe3Q9Qy54Qi5HKGEsYykK
-cmV0dXJuIGIuYi50ZXN0KHQpfWVsc2V7dD1KLkZMKGIsQy54Qi5HKGEsYykpCnJldHVybiF0LmdsMCh0
-KX19LApBNDpmdW5jdGlvbihhKXtpZihhLmluZGV4T2YoIiQiLDApPj0wKXJldHVybiBhLnJlcGxhY2Uo
-L1wkL2csIiQkJCQiKQpyZXR1cm4gYX0sCmVBOmZ1bmN0aW9uKGEpe2lmKC9bW1xde30oKSorPy5cXF4k
-fF0vLnRlc3QoYSkpcmV0dXJuIGEucmVwbGFjZSgvW1tcXXt9KCkqKz8uXFxeJHxdL2csIlxcJCYiKQpy
-ZXR1cm4gYX0sCnlzOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILm5NKGEsYixjKQpyZXR1cm4gdH0sCm5N
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihiPT09IiIpe2lmKGE9PT0iIilyZXR1cm4gYwp0
-PWEubGVuZ3RoCmZvcihzPWMscj0wO3I8dDsrK3Ipcz1zK2Fbcl0rYwpyZXR1cm4gcy5jaGFyQ29kZUF0
-KDApPT0wP3M6c31xPWEuaW5kZXhPZihiLDApCmlmKHE8MClyZXR1cm4gYQppZihhLmxlbmd0aDw1MDB8
-fGMuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEuc3BsaXQoYikuam9pbihjKQpyZXR1cm4gYS5yZXBs
-YWNlKG5ldyBSZWdFeHAoSC5lQShiKSwnZycpLEguQTQoYykpfSwKUEQ6ZnVuY3Rpb24gUEQoYSxiKXt0
-aGlzLmE9YQp0aGlzLiR0aT1ifSwKV1U6ZnVuY3Rpb24gV1UoKXt9LApMUDpmdW5jdGlvbiBMUChhLGIs
-YyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LApYUjpmdW5jdGlvbiBYUihh
-LGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApMSTpmdW5jdGlvbiBMSShhLGIsYyxkLGUpe3ZhciBfPXRo
-aXMKXy5hPWEKXy5jPWIKXy5kPWMKXy5lPWQKXy5mPWV9LApDajpmdW5jdGlvbiBDaihhLGIsYyl7dGhp
-cy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApmOTpmdW5jdGlvbiBmOShhLGIsYyxkLGUsZil7dmFyIF89
-dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sClcwOmZ1bmN0aW9uIFcwKGEs
-Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LAphejpmdW5jdGlvbiBheihhLGIsYyl7dGhpcy5hPWEKdGhpcy5i
-PWIKdGhpcy5jPWN9LAp2VjpmdW5jdGlvbiB2VihhKXt0aGlzLmE9YX0sCmJxOmZ1bmN0aW9uIGJxKGEs
-Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBbTpmdW5jdGlvbiBBbShhKXt0aGlzLmE9YX0sClhPOmZ1bmN0
-aW9uIFhPKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKVHA6ZnVuY3Rpb24gVHAoKXt9LApsYzpmdW5j
-dGlvbiBsYygpe30sCnp4OmZ1bmN0aW9uIHp4KCl7fSwKank6ZnVuY3Rpb24gankoYSxiLGMsZCl7dmFy
-IF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCkVxOmZ1bmN0aW9uIEVxKGEpe3RoaXMuYT1h
-fSwKa1k6ZnVuY3Rpb24ga1koYSl7dGhpcy5hPWF9LApONTpmdW5jdGlvbiBONShhKXt2YXIgXz10aGlz
-Cl8uYT0wCl8uZj1fLmU9Xy5kPV8uYz1fLmI9bnVsbApfLnI9MApfLiR0aT1hfSwKZGI6ZnVuY3Rpb24g
-ZGIoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbH0sCmk1OmZ1bmN0aW9uIGk1
-KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCk42OmZ1bmN0aW9uIE42KGEsYixjKXt2YXIgXz10aGlz
-Cl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbApfLiR0aT1jfSwKcjpmdW5jdGlvbiByKGEpe3RoaXMuYT1h
-fSwKZEM6ZnVuY3Rpb24gZEMoYSl7dGhpcy5hPWF9LAp3TjpmdW5jdGlvbiB3TihhKXt0aGlzLmE9YX0s
-ClZSOmZ1bmN0aW9uIFZSKGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGx9LApF
-SzpmdW5jdGlvbiBFSyhhKXt0aGlzLmI9YX0sCktXOmZ1bmN0aW9uIEtXKGEsYixjKXt0aGlzLmE9YQp0
-aGlzLmI9Ygp0aGlzLmM9Y30sClBiOmZ1bmN0aW9uIFBiKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8u
-Yj1iCl8uYz1jCl8uZD1udWxsfSwKdFE6ZnVuY3Rpb24gdFEoYSxiKXt0aGlzLmE9YQp0aGlzLmM9Yn0s
-Ck5GOmZ1bmN0aW9uIE5GKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClNkOmZ1bmN0
-aW9uIFNkKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1udWxsfSwKWEY6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGF9LApEUTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEludDhBcnJheShhKX0s
-Cm9kOmZ1bmN0aW9uKGEsYixjKXtpZihhPj4+MCE9PWF8fGE+PWMpdGhyb3cgSC5iKEguSFkoYixhKSl9
-LApyTTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYoIShhPj4+MCE9PWEpKXQ9Yj4+PjAhPT1ifHxhPmJ8
-fGI+YwplbHNlIHQ9ITAKaWYodCl0aHJvdyBILmIoSC5hdShhLGIsYykpCnJldHVybiBifSwKcEY6ZnVu
-Y3Rpb24gcEYoKXt9LApiMDpmdW5jdGlvbiBiMCgpe30sCkRnOmZ1bmN0aW9uIERnKCl7fSwKUGc6ZnVu
-Y3Rpb24gUGcoKXt9LAp4ajpmdW5jdGlvbiB4aigpe30sCmRFOmZ1bmN0aW9uIGRFKCl7fSwKWkE6ZnVu
-Y3Rpb24gWkEoKXt9LAp3ZjpmdW5jdGlvbiB3Zigpe30sClBxOmZ1bmN0aW9uIFBxKCl7fSwKZUU6ZnVu
-Y3Rpb24gZUUoKXt9LApWNjpmdW5jdGlvbiBWNigpe30sClJHOmZ1bmN0aW9uIFJHKCl7fSwKVlA6ZnVu
-Y3Rpb24gVlAoKXt9LApXQjpmdW5jdGlvbiBXQigpe30sClpHOmZ1bmN0aW9uIFpHKCl7fSwKY3o6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdD1iLmMKcmV0dXJuIHQ9PW51bGw/Yi5jPUguQmMoYSxiLnosITApOnR9LAp4
-WjpmdW5jdGlvbihhLGIpe3ZhciB0PWIuYwpyZXR1cm4gdD09bnVsbD9iLmM9SC5RMihhLCJiOCIsW2Iu
-el0pOnR9LApRMTpmdW5jdGlvbihhKXt2YXIgdD1hLnkKaWYodD09PTZ8fHQ9PT03fHx0PT09OClyZXR1
-cm4gSC5RMShhLnopCnJldHVybiB0PT09MTF8fHQ9PT0xMn0sCm1EOmZ1bmN0aW9uKGEpe3JldHVybiBh
-LmN5fSwKTjA6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRSh2LnR5cGVVbml2ZXJzZSxhLCExKX0sClBMOmZ1
-bmN0aW9uKGEsYixjLGEwKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkPWIueQpz
-d2l0Y2goZCl7Y2FzZSA1OmNhc2UgMTpjYXNlIDI6Y2FzZSAzOmNhc2UgNDpyZXR1cm4gYgpjYXNlIDY6
-dD1iLnoKcz1ILlBMKGEsdCxjLGEwKQppZihzPT09dClyZXR1cm4gYgpyZXR1cm4gSC5TTyhhLHMsITAp
-CmNhc2UgNzp0PWIuegpzPUguUEwoYSx0LGMsYTApCmlmKHM9PT10KXJldHVybiBiCnJldHVybiBILkJj
-KGEscywhMCkKY2FzZSA4OnQ9Yi56CnM9SC5QTChhLHQsYyxhMCkKaWYocz09PXQpcmV0dXJuIGIKcmV0
-dXJuIEguTE4oYSxzLCEwKQpjYXNlIDk6cj1iLlEKcT1ILmJaKGEscixjLGEwKQppZihxPT09cilyZXR1
-cm4gYgpyZXR1cm4gSC5RMihhLGIueixxKQpjYXNlIDEwOnA9Yi56Cm89SC5QTChhLHAsYyxhMCkKbj1i
-LlEKbT1ILmJaKGEsbixjLGEwKQppZihvPT09cCYmbT09PW4pcmV0dXJuIGIKcmV0dXJuIEguYXAoYSxv
-LG0pCmNhc2UgMTE6bD1iLnoKaz1ILlBMKGEsbCxjLGEwKQpqPWIuUQppPUgucVQoYSxqLGMsYTApCmlm
-KGs9PT1sJiZpPT09ailyZXR1cm4gYgpyZXR1cm4gSC5OZihhLGssaSkKY2FzZSAxMjpoPWIuUQphMCs9
-aC5sZW5ndGgKZz1ILmJaKGEsaCxjLGEwKQpwPWIuegpvPUguUEwoYSxwLGMsYTApCmlmKGc9PT1oJiZv
-PT09cClyZXR1cm4gYgpyZXR1cm4gSC5EUyhhLG8sZywhMCkKY2FzZSAxMzpmPWIuegppZihmPGEwKXJl
-dHVybiBiCmU9Y1tmLWEwXQppZihlPT1udWxsKXJldHVybiBiCnJldHVybiBlCmRlZmF1bHQ6dGhyb3cg
-SC5iKFAuaFYoIkF0dGVtcHRlZCB0byBzdWJzdGl0dXRlIHVuZXhwZWN0ZWQgUlRJIGtpbmQgIitkKSl9
-fSwKYlo6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscD1iLmxlbmd0aCxvPVtdCmZvcih0PSEx
-LHM9MDtzPHA7KytzKXtyPWJbc10KcT1ILlBMKGEscixjLGQpCmlmKHEhPT1yKXQ9ITAKby5wdXNoKHEp
-fXJldHVybiB0P286Yn0sCnZPOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbz1iLmxlbmd0
-aCxuPVtdCmZvcih0PSExLHM9MDtzPG87cys9Mil7cj1iW3NdCnE9YltzKzFdCnA9SC5QTChhLHEsYyxk
-KQppZihwIT09cSl0PSEwCm4ucHVzaChyKQpuLnB1c2gocCl9cmV0dXJuIHQ/bjpifSwKcVQ6ZnVuY3Rp
-b24oYSxiLGMsZCl7dmFyIHQscz1iLmEscj1ILmJaKGEscyxjLGQpLHE9Yi5iLHA9SC5iWihhLHEsYyxk
-KSxvPWIuYyxuPUgudk8oYSxvLGMsZCkKaWYocj09PXMmJnA9PT1xJiZuPT09bylyZXR1cm4gYgp0PW5l
-dyBILkVUKCkKdC5hPXIKdC5iPXAKdC5jPW4KcmV0dXJuIHR9LApKUzpmdW5jdGlvbihhKXt2YXIgdD1h
-LiRTCmlmKHQhPW51bGwpe2lmKHR5cGVvZiB0PT0ibnVtYmVyIilyZXR1cm4gSC5CcCh0KQpyZXR1cm4g
-YS4kUygpfXJldHVybiBudWxsfSwKVWU6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihILlExKGIpKWlmKGEg
-aW5zdGFuY2VvZiBILlRwKXt0PUguSlMoYSkKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gSC5xKGEp
-fSwKcTpmdW5jdGlvbihhKXt2YXIgdAppZihhIGluc3RhbmNlb2YgUC5NaCl7dD1hLiR0aQpyZXR1cm4g
-dCE9bnVsbD90OkguVlUoYSl9aWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gSC50NihhKQpyZXR1cm4g
-SC5WVShKLmlhKGEpKX0sCnQ2OmZ1bmN0aW9uKGEpe3ZhciB0PWFbdi5hcnJheVJ0aV0scz11Lm0KaWYo
-dD09bnVsbClyZXR1cm4gcwppZih0LmNvbnN0cnVjdG9yIT09cy5jb25zdHJ1Y3RvcilyZXR1cm4gcwpy
-ZXR1cm4gdH0sCkxoOmZ1bmN0aW9uKGEpe3ZhciB0PWEuJHRpCnJldHVybiB0IT1udWxsP3Q6SC5WVShh
-KX0sClZVOmZ1bmN0aW9uKGEpe3ZhciB0PWEuY29uc3RydWN0b3Iscz10LiRjY2FjaGUKaWYocyE9bnVs
-bClyZXR1cm4gcwpyZXR1cm4gSC5yOShhLHQpfSwKcjk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hIGluc3Rh
-bmNlb2YgSC5UcD9hLl9fcHJvdG9fXy5fX3Byb3RvX18uY29uc3RydWN0b3I6YixzPUguYWkodi50eXBl
-VW5pdmVyc2UsdC5uYW1lKQpiLiRjY2FjaGU9cwpyZXR1cm4gc30sCkJwOmZ1bmN0aW9uKGEpe3ZhciB0
-LHM9YSxyPXYudHlwZXMscT1yW3NdCmlmKHR5cGVvZiBxPT0ic3RyaW5nIil7dD1ILkUodi50eXBlVW5p
-dmVyc2UscSwhMSkKcltzXT10CnJldHVybiB0fXJldHVybiBxfSwKSko6ZnVuY3Rpb24oYSl7dmFyIHQ9
-dGhpcyxzPUguWU8scj11LksKaWYodD09PXIpe3M9SC5rZQp0LmE9SC5UaX1lbHNlIGlmKEguQTgodCl8
-fHQ9PT1yKXtzPUguSXcKdC5hPUguaG59ZWxzZSBpZih0PT09dS5TKXM9SC5vawplbHNlIGlmKHQ9PT11
-LmdSKXM9SC5LSAplbHNlIGlmKHQ9PT11LmRpKXM9SC5LSAplbHNlIGlmKHQ9PT11Lk4pcz1ILk1NCmVs
-c2UgaWYodD09PXUueSlzPUguclEKZWxzZSBpZih0Lnk9PT05KXtyPXQuegppZih0LlEuZXZlcnkoSC5j
-Yykpe3Qucj0iJGkiK3IKcz1ILnQ0fX10LmI9cwpyZXR1cm4gdC5iKGEpfSwKWU86ZnVuY3Rpb24oYSl7
-dmFyIHQ9dGhpcwpyZXR1cm4gSC5XZSh2LnR5cGVVbml2ZXJzZSxILlVlKGEsdCksbnVsbCx0LG51bGwp
-fSwKdDQ6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPXQucgppZihhIGluc3RhbmNlb2YgUC5NaClyZXR1
-cm4hIWFbc10KcmV0dXJuISFKLmlhKGEpW3NdfSwKT3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwppZihh
-PT1udWxsKXJldHVybiBhCmVsc2UgaWYodC5iKGEpKXJldHVybiBhCnRocm93IEguYihILlpjKEgucChh
-LEguVWUoYSx0KSxILkoodCxudWxsKSkpKX0sCkRoOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PW51bGwK
-aWYoSC5XZSh2LnR5cGVVbml2ZXJzZSxhLHQsYix0KSlyZXR1cm4gYQp0aHJvdyBILmIoSC5aYygiVGhl
-IHR5cGUgYXJndW1lbnQgJyIrSC5kKEguSihhLHQpKSsiJyBpcyBub3QgYSBzdWJ0eXBlIG9mIHRoZSB0
-eXBlIHZhcmlhYmxlIGJvdW5kICciK0guZChILkooYix0KSkrIicgb2YgdHlwZSB2YXJpYWJsZSAnIitj
-KyInIGluICciK0guZChkKSsiJy4iKSl9LApwOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1QLmgoYSkscz1I
-LkooYj09bnVsbD9ILnEoYSk6YixudWxsKQpyZXR1cm4gdCsiOiB0eXBlICciK0guZChzKSsiJyBpcyBu
-b3QgYSBzdWJ0eXBlIG9mIHR5cGUgJyIrSC5kKGMpKyInIn0sClpjOmZ1bmN0aW9uKGEpe3JldHVybiBu
-ZXcgSC54KCJUeXBlRXJyb3I6ICIrYSl9LApCOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILngoIlR5
-cGVFcnJvcjogIitILnAoYSxudWxsLGIpKX0sCmtlOmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKVGk6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGF9LApJdzpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCmhuOmZ1bmN0aW9uKGEp
-e3JldHVybiBhfSwKclE6ZnVuY3Rpb24oYSl7cmV0dXJuITA9PT1hfHwhMT09PWF9LApFOTpmdW5jdGlv
-bihhKXtpZighMD09PWF8fCExPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEgu
-YihILkIoYSwiYm9vbCIpKX0sCmRqOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1
-cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILkIoYSwiZG91YmxlIikpfSwKb2s6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09PWF9LApXWTpm
-dW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hKXJldHVybiBh
-CmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEguQihhLCJpbnQiKSl9LApLSDpmdW5jdGlvbihh
-KXtyZXR1cm4gdHlwZW9mIGE9PSJudW1iZXIifSwKdVU6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJu
-dW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEguQihhLCJudW0iKSl9
-LApNTTpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJzdHJpbmcifSwKYzpmdW5jdGlvbihhKXtp
-Zih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIo
-SC5CKGEsIlN0cmluZyIpKX0sCnc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKZm9yKHQ9IiIscz0iIixy
-PTA7cjxhLmxlbmd0aDsrK3Iscz0iLCAiKXQrPUMueEIuaChzLEguSihhW3JdLGIpKQpyZXR1cm4gdH0s
-CmY6ZnVuY3Rpb24oYTEsYTIsYTMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQs
-YyxiLGEsYTA9IiwgIgppZihhMyE9bnVsbCl7dD1hMy5sZW5ndGgKaWYoYTI9PW51bGwpe2EyPUguVk0o
-W10sdS5zKQpzPW51bGx9ZWxzZSBzPWEyLmxlbmd0aApyPWEyLmxlbmd0aApmb3IocT10O3E+MDstLXEp
-Qy5ObS5pKGEyLCJUIisocitxKSkKZm9yKHA9dS5LLG89IjwiLG49IiIscT0wO3E8dDsrK3Esbj1hMCl7
-bys9bgptPWEyLmxlbmd0aApsPW0tMS1xCmlmKGw8MClyZXR1cm4gSC5rKGEyLGwpCm89Qy54Qi5oKG8s
-YTJbbF0pCms9YTNbcV0KaWYoIShILkE4KGspfHxrPT09cCkpbT0hKGs9PT1wKQplbHNlIG09ITEKaWYo
-bSlvKz1DLnhCLmgoIiBleHRlbmRzICIsSC5KKGssYTIpKX1vKz0iPiJ9ZWxzZXtvPSIiCnM9bnVsbH1w
-PWExLnoKaj1hMS5RCmk9ai5hCmg9aS5sZW5ndGgKZz1qLmIKZj1nLmxlbmd0aAplPWouYwpkPWUubGVu
-Z3RoCmM9SC5KKHAsYTIpCmZvcihiPSIiLGE9IiIscT0wO3E8aDsrK3EsYT1hMCliKz1DLnhCLmgoYSxI
-LkooaVtxXSxhMikpCmlmKGY+MCl7Yis9YSsiWyIKZm9yKGE9IiIscT0wO3E8ZjsrK3EsYT1hMCliKz1D
-LnhCLmgoYSxILkooZ1txXSxhMikpCmIrPSJdIn1pZihkPjApe2IrPWErInsiCmZvcihhPSIiLHE9MDtx
-PGQ7cSs9MixhPWEwKWIrPUMueEIuaChhLEguSihlW3ErMV0sYTIpKSsiICIrZVtxXQpiKz0ifSJ9aWYo
-cyE9bnVsbClhMi5sZW5ndGg9cwpyZXR1cm4gbysiKCIrYisiKSA9PiAiK0guZChjKX0sCko6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtPWEueQppZihtPT09NSlyZXR1cm4iZXJhc2VkIgppZiht
-PT09MilyZXR1cm4iZHluYW1pYyIKaWYobT09PTMpcmV0dXJuInZvaWQiCmlmKG09PT0xKXJldHVybiJO
-ZXZlciIKaWYobT09PTQpcmV0dXJuImFueSIKaWYobT09PTYpe3Q9SC5KKGEueixiKQpyZXR1cm4gdH1p
-ZihtPT09Nyl7cz1hLnoKdD1ILkoocyxiKQpyPXMueQpyZXR1cm4gSi5tKHI9PT0xMXx8cj09PTEyP0Mu
-eEIuaCgiKCIsdCkrIikiOnQsIj8iKX1pZihtPT09OClyZXR1cm4iRnV0dXJlT3I8IitILmQoSC5KKGEu
-eixiKSkrIj4iCmlmKG09PT05KXtxPUguQyhhLnopCnA9YS5RCnJldHVybiBwLmxlbmd0aCE9PTA/cSso
-IjwiK0gudyhwLGIpKyI+Iik6cX1pZihtPT09MTEpcmV0dXJuIEguZihhLGIsbnVsbCkKaWYobT09PTEy
-KXJldHVybiBILmYoYS56LGIsYS5RKQppZihtPT09MTMpe289YS56Cm49Yi5sZW5ndGgKbz1uLTEtbwpp
-ZihvPDB8fG8+PW4pcmV0dXJuIEguayhiLG8pCnJldHVybiBiW29dfXJldHVybiI/In0sCkM6ZnVuY3Rp
-b24oYSl7dmFyIHQscz1ILkpnKGEpCmlmKHMhPW51bGwpcmV0dXJuIHMKdD0ibWluaWZpZWQ6IithCnJl
-dHVybiB0fSwKUW86ZnVuY3Rpb24oYSxiKXt2YXIgdD1hLnRSW2JdCmZvcig7dHlwZW9mIHQ9PSJzdHJp
-bmciOyl0PWEudFJbdF0KcmV0dXJuIHR9LAphaTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz1h
-LmVULG49b1tiXQppZihuPT1udWxsKXJldHVybiBILkUoYSxiLCExKQplbHNlIGlmKHR5cGVvZiBuPT0i
-bnVtYmVyIil7dD1uCnM9SC5tWihhLDUsIiMiKQpyPVtdCmZvcihxPTA7cTx0OysrcSlyLnB1c2gocykK
-cD1ILlEyKGEsYixyKQpvW2JdPXAKcmV0dXJuIHB9ZWxzZSByZXR1cm4gbn0sCnhiOmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIEguSXgoYS50UixiKX0sCkZGOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguSXgoYS5lVCxi
-KX0sCkU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9YS5lQyxyPXMuZ2V0KGIpCmlmKHIhPW51bGwpcmV0
-dXJuIHIKdD1ILnooYSxudWxsLGIsYykKcy5zZXQoYix0KQpyZXR1cm4gdH0sCmNFOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdCxzLHI9Yi5jaAppZihyPT1udWxsKXI9Yi5jaD1uZXcgTWFwKCkKdD1yLmdldChjKQpp
-Zih0IT1udWxsKXJldHVybiB0CnM9SC56KGEsYixjLCEwKQpyLnNldChjLHMpCnJldHVybiBzfSwKdjU6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPWIuY3gKaWYocT09bnVsbClxPWIuY3g9bmV3IE1hcCgp
-CnQ9Yy5jeQpzPXEuZ2V0KHQpCmlmKHMhPW51bGwpcmV0dXJuIHMKcj1ILmFwKGEsYixjLnk9PT0xMD9j
-LlE6W2NdKQpxLnNldCh0LHIpCnJldHVybiByfSwKejpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILmko
-SC5vKGEsYixjLGQpKQppZih0IT1udWxsKXJldHVybiB0CnRocm93IEguYihQLm4oJ19Vbml2ZXJzZS5f
-cGFyc2VSZWNpcGUoIicrSC5kKGMpKyciKScpKX0sCkJEOmZ1bmN0aW9uKGEsYil7Yi5hPUguT3oKYi5i
-PUguSkoKcmV0dXJuIGJ9LAptWjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPWEuZUMuZ2V0KGMpCmlm
-KHIhPW51bGwpcmV0dXJuIHIKdD1uZXcgSC5KYyhudWxsLG51bGwpCnQueT1iCnQuY3k9YwpzPUguQkQo
-YSx0KQphLmVDLnNldChjLHMpCnJldHVybiBzfSwKU086ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Yi5j
-eSsiKiIscj1hLmVDLmdldChzKQppZihyIT1udWxsKXJldHVybiByCnQ9SC5aNyhhLGIscyxjKQphLmVD
-LnNldChzLHQpCnJldHVybiB0fSwKWjc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwppZihkKXt0PWIu
-eQppZihILkE4KGIpfHxiPT09dS5LfHxiPT09dS5QfHx0PT09N3x8dD09PTYpcmV0dXJuIGJ9cz1uZXcg
-SC5KYyhudWxsLG51bGwpCnMueT02CnMuej1iCnMuY3k9YwpyZXR1cm4gSC5CRChhLHMpfSwKQmM6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciB0LHM9Yi5jeSsiPyIscj1hLmVDLmdldChzKQppZihyIT1udWxsKXJldHVy
-biByCnQ9SC5sbChhLGIscyxjKQphLmVDLnNldChzLHQpCnJldHVybiB0fSwKbGw6ZnVuY3Rpb24oYSxi
-LGMsZCl7dmFyIHQscyxyLHEscAppZihkKXt0PWIueQppZighSC5BOChiKSlpZighKGI9PT11LlApKWlm
-KHQhPT03KXM9dD09PTgmJkgubFIoYi56KQplbHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMAppZihz
-KXJldHVybiBiCmVsc2UgaWYodD09PTEpcmV0dXJuIHUuUAplbHNlIGlmKHQ9PT02KXtyPWIuegpxPXIu
-eQppZihxPT09MSlyZXR1cm4gdS5QCmVsc2UgaWYocT09PTgmJkgubFIoci56KSlyZXR1cm4gcgplbHNl
-IHJldHVybiBILmN6KGEsYil9fXA9bmV3IEguSmMobnVsbCxudWxsKQpwLnk9NwpwLno9YgpwLmN5PWMK
-cmV0dXJuIEguQkQoYSxwKX0sCkxOOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuY3krIi8iLHI9YS5l
-Qy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PUguZVYoYSxiLHMsYykKYS5lQy5zZXQocyx0KQpy
-ZXR1cm4gdH0sCmVWOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMKaWYoZCl7dD1iLnkKaWYoSC5BOChi
-KXx8Yj09PXUuS3x8Yj09PXUuSylyZXR1cm4gYgplbHNlIGlmKHQ9PT0xKXJldHVybiBILlEyKGEsImI4
-IixbYl0pCmVsc2UgaWYoYj09PXUuUClyZXR1cm4gdS5hUX1zPW5ldyBILkpjKG51bGwsbnVsbCkKcy55
-PTgKcy56PWIKcy5jeT1jCnJldHVybiBILkJEKGEscyl9LApIYzpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
-cj0iIitiKyJeIixxPWEuZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0dXJuIHEKdD1uZXcgSC5KYyhudWxs
-LG51bGwpCnQueT0xMwp0Lno9Ygp0LmN5PXIKcz1ILkJEKGEsdCkKYS5lQy5zZXQocixzKQpyZXR1cm4g
-c30sClV4OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPWEubGVuZ3RoCmZvcih0PSIiLHM9IiIscj0wO3I8
-cTsrK3Iscz0iLCIpdCs9cythW3JdLmN5CnJldHVybiB0fSwKUzQ6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
-LHEscCxvPWEubGVuZ3RoCmZvcih0PSIiLHM9IiIscj0wO3I8bztyKz0yLHM9IiwiKXtxPWFbcl0KcD1h
-W3IrMV0uY3kKdCs9cytxKyI6IitwfXJldHVybiB0fSwKUTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
-cixxPWIKaWYoYy5sZW5ndGghPT0wKXErPSI8IitILlV4KGMpKyI+Igp0PWEuZUMuZ2V0KHEpCmlmKHQh
-PW51bGwpcmV0dXJuIHQKcz1uZXcgSC5KYyhudWxsLG51bGwpCnMueT05CnMuej1iCnMuUT1jCmlmKGMu
-bGVuZ3RoPjApcy5jPWNbMF0Kcy5jeT1xCnI9SC5CRChhLHMpCmEuZUMuc2V0KHEscikKcmV0dXJuIHJ9
-LAphcDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvCmlmKGIueT09PTEwKXt0PWIuegpzPWIu
-US5jb25jYXQoYyl9ZWxzZXtzPWMKdD1ifXI9dC5jeSsiOyIrKCI8IitILlV4KHMpKyI+IikKcT1hLmVD
-LmdldChyKQppZihxIT1udWxsKXJldHVybiBxCnA9bmV3IEguSmMobnVsbCxudWxsKQpwLnk9MTAKcC56
-PXQKcC5RPXMKcC5jeT1yCm89SC5CRChhLHApCmEuZUMuc2V0KHIsbykKcmV0dXJuIG99LApOZjpmdW5j
-dGlvbihhLGIsYyl7dmFyIHQscyxyLHEscD1iLmN5LG89Yy5hLG49by5sZW5ndGgsbT1jLmIsbD1tLmxl
-bmd0aCxrPWMuYyxqPWsubGVuZ3RoLGk9IigiK0guVXgobykKaWYobD4wKWkrPShuPjA/IiwiOiIiKSsi
-WyIrSC5VeChtKSsiXSIKaWYoaj4wKWkrPShuPjA/IiwiOiIiKSsieyIrSC5TNChrKSsifSIKdD1wKyhp
-KyIpIikKcz1hLmVDLmdldCh0KQppZihzIT1udWxsKXJldHVybiBzCnI9bmV3IEguSmMobnVsbCxudWxs
-KQpyLnk9MTEKci56PWIKci5RPWMKci5jeT10CnE9SC5CRChhLHIpCmEuZUMuc2V0KHQscSkKcmV0dXJu
-IHF9LApEUzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzPWIuY3krIjwiK0guVXgoYykrIj4iLHI9YS5l
-Qy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PUguaHcoYSxiLGMscyxkKQphLmVDLnNldChzLHQp
-CnJldHVybiB0fSwKaHc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG8sbixtCmlmKGUp
-e3Q9Yy5sZW5ndGgKcz1uZXcgQXJyYXkodCkKZm9yKHI9MCxxPTA7cTx0OysrcSl7cD1jW3FdCmlmKHAu
-eT09PTEpe3NbcV09cDsrK3J9fWlmKHI+MCl7bz1ILlBMKGEsYixzLDApCm49SC5iWihhLGMscywwKQpy
-ZXR1cm4gSC5EUyhhLG8sbixjIT09bil9fW09bmV3IEguSmMobnVsbCxudWxsKQptLnk9MTIKbS56PWIK
-bS5RPWMKbS5jeT1kCnJldHVybiBILkJEKGEsbSl9LApvOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybnt1
-OmEsZTpiLHI6YyxzOltdLHA6MCxuOmR9fSwKaTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixt
-LGwsayxqLGksaD1hLnIsZz1hLnMKZm9yKHQ9aC5sZW5ndGgscz0wO3M8dDspe3I9aC5jaGFyQ29kZUF0
-KHMpCmlmKHI+PTQ4JiZyPD01NylzPUguQWwocysxLHIsaCxnKQplbHNlIGlmKCgoKHJ8MzIpPj4+MCkt
-OTcmNjU1MzUpPDI2fHxyPT09OTV8fHI9PT0zNilzPUguUjgoYSxzLGgsZywhMSkKZWxzZSBpZihyPT09
-NDYpcz1ILlI4KGEscyxoLGcsITApCmVsc2V7KytzCnN3aXRjaChyKXtjYXNlIDQ0OmJyZWFrCmNhc2Ug
-NTg6YnJlYWsKY2FzZSA1OTpnLnB1c2goSC5LUShhLnUsYS5lLGcucG9wKCkpKQpicmVhawpjYXNlIDk0
-OmcucHVzaChILkhjKGEudSxnLnBvcCgpKSkKYnJlYWsKY2FzZSAzNTpnLnB1c2goSC5tWihhLnUsNSwi
-IyIpKQpicmVhawpjYXNlIDY0OmcucHVzaChILm1aKGEudSwyLCJAIikpCmJyZWFrCmNhc2UgMTI2Omcu
-cHVzaChILm1aKGEudSwzLCJ+IikpCmJyZWFrCmNhc2UgNjA6Zy5wdXNoKGEucCkKYS5wPWcubGVuZ3Ro
-CmJyZWFrCmNhc2UgNjI6cT1hLnUKcD1nLnNwbGljZShhLnApCkguclQoYS51LGEuZSxwKQphLnA9Zy5w
-b3AoKQpvPWcucG9wKCkKaWYodHlwZW9mIG89PSJzdHJpbmciKWcucHVzaChILlEyKHEsbyxwKSkKZWxz
-ZXtuPUguS1EocSxhLmUsbykKc3dpdGNoKG4ueSl7Y2FzZSAxMTpnLnB1c2goSC5EUyhxLG4scCxhLm4p
-KQpicmVhawpkZWZhdWx0OmcucHVzaChILmFwKHEsbixwKSkKYnJlYWt9fWJyZWFrCmNhc2UgMzg6SC5J
-MyhhLGcpCmJyZWFrCmNhc2UgNDI6bT1hLnUKZy5wdXNoKEguU08obSxILktRKG0sYS5lLGcucG9wKCkp
-LGEubikpCmJyZWFrCmNhc2UgNjM6bT1hLnUKZy5wdXNoKEguQmMobSxILktRKG0sYS5lLGcucG9wKCkp
-LGEubikpCmJyZWFrCmNhc2UgNDc6bT1hLnUKZy5wdXNoKEguTE4obSxILktRKG0sYS5lLGcucG9wKCkp
-LGEubikpCmJyZWFrCmNhc2UgNDA6Zy5wdXNoKGEucCkKYS5wPWcubGVuZ3RoCmJyZWFrCmNhc2UgNDE6
-cT1hLnUKbD1uZXcgSC5FVCgpCms9cS5zRUEKaj1xLnNFQQpvPWcucG9wKCkKaWYodHlwZW9mIG89PSJu
-dW1iZXIiKXN3aXRjaChvKXtjYXNlLTE6az1nLnBvcCgpCmJyZWFrCmNhc2UtMjpqPWcucG9wKCkKYnJl
-YWsKZGVmYXVsdDpnLnB1c2gobykKYnJlYWt9ZWxzZSBnLnB1c2gobykKcD1nLnNwbGljZShhLnApCkgu
-clQoYS51LGEuZSxwKQphLnA9Zy5wb3AoKQpsLmE9cApsLmI9awpsLmM9agpnLnB1c2goSC5OZihxLEgu
-S1EocSxhLmUsZy5wb3AoKSksbCkpCmJyZWFrCmNhc2UgOTE6Zy5wdXNoKGEucCkKYS5wPWcubGVuZ3Ro
-CmJyZWFrCmNhc2UgOTM6cD1nLnNwbGljZShhLnApCkguclQoYS51LGEuZSxwKQphLnA9Zy5wb3AoKQpn
-LnB1c2gocCkKZy5wdXNoKC0xKQpicmVhawpjYXNlIDEyMzpnLnB1c2goYS5wKQphLnA9Zy5sZW5ndGgK
-YnJlYWsKY2FzZSAxMjU6cD1nLnNwbGljZShhLnApCkguV1MoYS51LGEuZSxwKQphLnA9Zy5wb3AoKQpn
-LnB1c2gocCkKZy5wdXNoKC0yKQpicmVhawpkZWZhdWx0OnRocm93IkJhZCBjaGFyYWN0ZXIgIityfX19
-aT1nLnBvcCgpCnJldHVybiBILktRKGEudSxhLmUsaSl9LApBbDpmdW5jdGlvbihhLGIsYyxkKXt2YXIg
-dCxzLHI9Yi00OApmb3IodD1jLmxlbmd0aDthPHQ7KythKXtzPWMuY2hhckNvZGVBdChhKQppZighKHM+
-PTQ4JiZzPD01NykpYnJlYWsKcj1yKjEwKyhzLTQ4KX1kLnB1c2gocikKcmV0dXJuIGF9LApSODpmdW5j
-dGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuPWIrMQpmb3IodD1jLmxlbmd0aDtuPHQ7Kytu
-KXtzPWMuY2hhckNvZGVBdChuKQppZihzPT09NDYpe2lmKGUpYnJlYWsKZT0hMH1lbHNle2lmKCEoKCgo
-c3wzMik+Pj4wKS05NyY2NTUzNSk8MjZ8fHM9PT05NXx8cz09PTM2KSlyPXM+PTQ4JiZzPD01NwplbHNl
-IHI9ITAKaWYoIXIpYnJlYWt9fXE9Yy5zdWJzdHJpbmcoYixuKQppZihlKXt0PWEudQpwPWEuZQppZihw
-Lnk9PT0xMClwPXAuegpvPUguUW8odCxwLnopW3FdCmlmKG89PW51bGwpSC52aCgnTm8gIicrcSsnIiBp
-biAiJytILm1EKHApKyciJykKZC5wdXNoKEguY0UodCxwLG8pKX1lbHNlIGQucHVzaChxKQpyZXR1cm4g
-bn0sCkkzOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5wb3AoKQppZigwPT09dCl7Yi5wdXNoKEgubVooYS51
-LDEsIjAmIikpCnJldHVybn1pZigxPT09dCl7Yi5wdXNoKEgubVooYS51LDQsIjEmIikpCnJldHVybn10
-aHJvdyBILmIoUC5oVigiVW5leHBlY3RlZCBleHRlbmRlZCBvcGVyYXRpb24gIitILmQodCkpKX0sCktR
-OmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYz09InN0cmluZyIpcmV0dXJuIEguUTIoYSxjLGEuc0VB
-KQplbHNlIGlmKHR5cGVvZiBjPT0ibnVtYmVyIilyZXR1cm4gSC5UVihhLGIsYykKZWxzZSByZXR1cm4g
-Y30sCnJUOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWMubGVuZ3RoCmZvcih0PTA7dDxzOysrdCljW3Rd
-PUguS1EoYSxiLGNbdF0pfSwKV1M6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Yy5sZW5ndGgKZm9yKHQ9
-MTt0PHM7dCs9MiljW3RdPUguS1EoYSxiLGNbdF0pfSwKVFY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
-cj1iLnkKaWYocj09PTEwKXtpZihjPT09MClyZXR1cm4gYi56CnQ9Yi5RCnM9dC5sZW5ndGgKaWYoYzw9
-cylyZXR1cm4gdFtjLTFdCmMtPXMKYj1iLnoKcj1iLnl9ZWxzZSBpZihjPT09MClyZXR1cm4gYgppZihy
-IT09OSl0aHJvdyBILmIoUC5oVigiSW5kZXhlZCBiYXNlIG11c3QgYmUgYW4gaW50ZXJmYWNlIHR5cGUi
-KSkKdD1iLlEKaWYoYzw9dC5sZW5ndGgpcmV0dXJuIHRbYy0xXQp0aHJvdyBILmIoUC5oVigiQmFkIGlu
-ZGV4ICIrYysiIGZvciAiK2IuWigwKSkpfSwKV2U6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIs
-cSxwLG8sbixtLGwsawppZihiPT09ZClyZXR1cm4hMAppZihILkE4KGQpfHxkPT09dS5LKXJldHVybiEw
-CnQ9Yi55CmlmKHQ9PT00KXJldHVybiEwCmlmKEguQTgoYikpcmV0dXJuITEKaWYoYj09PXUuUClyZXR1
-cm4hMApzPXQ9PT0xMwppZihzKWlmKEguV2UoYSxjW2Iuel0sYyxkLGUpKXJldHVybiEwCnI9ZC55Cmlm
-KHQ9PT02KXJldHVybiBILldlKGEsYi56LGMsZCxlKQppZihyPT09Nil7cT1kLnoKcmV0dXJuIEguV2Uo
-YSxiLGMscSxlKX1pZih0PT09OCl7aWYoIUguV2UoYSxiLnosYyxkLGUpKXJldHVybiExCnJldHVybiBI
-LldlKGEsSC54WihhLGIpLGMsZCxlKX1pZih0PT09Nyl7cT1ILldlKGEsYi56LGMsZCxlKQpyZXR1cm4g
-cX1pZihyPT09OCl7aWYoSC5XZShhLGIsYyxkLnosZSkpcmV0dXJuITAKcmV0dXJuIEguV2UoYSxiLGMs
-SC54WihhLGQpLGUpfWlmKHI9PT03KXtxPUguV2UoYSxiLGMsZC56LGUpCnJldHVybiBxfWlmKHMpcmV0
-dXJuITEKcT10IT09MTEKaWYoKCFxfHx0PT09MTIpJiZkPT09dS5aKXJldHVybiEwCmlmKHI9PT0xMil7
-aWYoYj09PXUuZylyZXR1cm4hMAppZih0IT09MTIpcmV0dXJuITEKcD1iLlEKbz1kLlEKbj1wLmxlbmd0
-aAppZihuIT09by5sZW5ndGgpcmV0dXJuITEKYz1jPT1udWxsP3A6cC5jb25jYXQoYykKZT1lPT1udWxs
-P286by5jb25jYXQoZSkKZm9yKHE9dS5hdixtPTA7bTxuOysrbSl7bD1wW21dCms9b1ttXQpxLmEobCkK
-cS5hKGspCmlmKCFILldlKGEsbCxjLGssZSl8fCFILldlKGEsayxlLGwsYykpcmV0dXJuITF9cmV0dXJu
-IEguYk8oYSxiLnosYyxkLnosZSl9aWYocj09PTExKXtpZihiPT09dS5nKXJldHVybiEwCmlmKHEpcmV0
-dXJuITEKcmV0dXJuIEguYk8oYSxiLGMsZCxlKX1pZih0PT09OSl7aWYociE9PTkpcmV0dXJuITEKcmV0
-dXJuIEgucEcoYSxiLGMsZCxlKX1yZXR1cm4hMX0sCmJPOmZ1bmN0aW9uKGEwLGExLGEyLGEzLGE0KXt2
-YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhCmlmKCFILldlKGEwLGExLnos
-YTIsYTMueixhNCkpcmV0dXJuITEKdD1hMS5RCnM9YTMuUQpyPXQuYQpxPXMuYQpwPXIubGVuZ3RoCm89
-cS5sZW5ndGgKaWYocD5vKXJldHVybiExCm49by1wCm09dC5iCmw9cy5iCms9bS5sZW5ndGgKaj1sLmxl
-bmd0aAppZihwK2s8bytqKXJldHVybiExCmZvcihpPTA7aTxwOysraSl7aD1yW2ldCmlmKCFILldlKGEw
-LHFbaV0sYTQsaCxhMikpcmV0dXJuITF9Zm9yKGk9MDtpPG47KytpKXtoPW1baV0KaWYoIUguV2UoYTAs
-cVtwK2ldLGE0LGgsYTIpKXJldHVybiExfWZvcihpPTA7aTxqOysraSl7aD1tW24raV0KaWYoIUguV2Uo
-YTAsbFtpXSxhNCxoLGEyKSlyZXR1cm4hMX1nPXQuYwpmPXMuYwplPWcubGVuZ3RoCmQ9Zi5sZW5ndGgK
-Zm9yKGk9MCxjPTA7YzxkO2MrPTIpe2I9ZltjXQpkb3tpZihpPj1lKXJldHVybiExCmE9Z1tpXQppKz0y
-fXdoaWxlKGE8YikKaWYoYjxhKXJldHVybiExCmg9Z1tpLTFdCmlmKCFILldlKGEwLGZbYysxXSxhNCxo
-LGEyKSlyZXR1cm4hMX1yZXR1cm4hMH0sCnBHOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEs
-cCxvLG4sbSxsPWIueixrPWQuegppZihsPT09ayl7dD1iLlEKcz1kLlEKcj10Lmxlbmd0aApmb3IocT0w
-O3E8cjsrK3Epe3A9dFtxXQpvPXNbcV0KaWYoIUguV2UoYSxwLGMsbyxlKSlyZXR1cm4hMX1yZXR1cm4h
-MH1pZihkPT09dS5LKXJldHVybiEwCm49SC5RbyhhLGwpCmlmKG49PW51bGwpcmV0dXJuITEKbT1uW2td
-CmlmKG09PW51bGwpcmV0dXJuITEKcj1tLmxlbmd0aApzPWQuUQpmb3IocT0wO3E8cjsrK3EpaWYoIUgu
-V2UoYSxILmNFKGEsYixtW3FdKSxjLHNbcV0sZSkpcmV0dXJuITEKcmV0dXJuITB9LApsUjpmdW5jdGlv
-bihhKXt2YXIgdCxzPWEueQppZighKGE9PT11LlApKWlmKCFILkE4KGEpKWlmKHMhPT03KWlmKCEocz09
-PTYmJkgubFIoYS56KSkpdD1zPT09OCYmSC5sUihhLnopCmVsc2UgdD0hMAplbHNlIHQ9ITAKZWxzZSB0
-PSEwCmVsc2UgdD0hMApyZXR1cm4gdH0sCmNjOmZ1bmN0aW9uKGEpe3JldHVybiBILkE4KGEpfHxhPT09
-dS5LfSwKQTg6ZnVuY3Rpb24oYSl7dmFyIHQscz1hLnkscj1zCmlmKHIhPT0yKWlmKHIhPT0zKWlmKHIh
-PT00KWlmKHIhPT01KXt0PXUuSwppZighKGE9PT10KSlzPXM9PT03JiZhLno9PT10CmVsc2Ugcz0hMH1l
-bHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAKcmV0dXJuIHN9LApJeDpmdW5jdGlv
-bihhLGIpe3ZhciB0LHMscj1PYmplY3Qua2V5cyhiKSxxPXIubGVuZ3RoCmZvcih0PTA7dDxxOysrdCl7
-cz1yW3RdCmFbc109YltzXX19LApKYzpmdW5jdGlvbiBKYyhhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
-PWIKXy54PV8ucj1fLmM9bnVsbApfLnk9MApfLmN5PV8uY3g9Xy5jaD1fLlE9Xy56PW51bGx9LApFVDpm
-dW5jdGlvbiBFVCgpe3RoaXMuYz10aGlzLmI9dGhpcy5hPW51bGx9LAp1OTpmdW5jdGlvbiB1OSgpe30s
-Cng6ZnVuY3Rpb24geChhKXt0aGlzLmE9YX0sClI5OmZ1bmN0aW9uKGEpe3JldHVybiB1LmQuYihhKXx8
-dS5CLmIoYSl8fHUuZHouYihhKXx8dS5JLmIoYSl8fHUuQS5iKGEpfHx1Lmc0LmIoYSl8fHUuZzIuYihh
-KX0sCkpnOmZ1bmN0aW9uKGEpe3JldHVybiB2Lm1hbmdsZWRHbG9iYWxOYW1lc1thXX19LEo9ewpRdTpm
-dW5jdGlvbihhLGIsYyxkKXtyZXR1cm57aTphLHA6YixlOmMseDpkfX0sCmtzOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxLHA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXQppZihwPT1udWxsKWlmKCQuSz09bnVs
-bCl7SC5NKCkKcD1hW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdfWlmKHAhPW51bGwpe3Q9cC5wCmlmKCEx
-PT09dClyZXR1cm4gcC5pCmlmKCEwPT09dClyZXR1cm4gYQpzPU9iamVjdC5nZXRQcm90b3R5cGVPZihh
-KQppZih0PT09cylyZXR1cm4gcC5pCmlmKHAuZT09PXMpdGhyb3cgSC5iKFAubigiUmV0dXJuIGludGVy
-Y2VwdG9yIGZvciAiK0guZCh0KGEscCkpKSl9cj1hLmNvbnN0cnVjdG9yCnE9cj09bnVsbD9udWxsOnJb
-JC5BKCldCmlmKHEhPW51bGwpcmV0dXJuIHEKcT1ILkcoYSkKaWYocSE9bnVsbClyZXR1cm4gcQppZih0
-eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gQy5ERwp0PU9iamVjdC5nZXRQcm90b3R5cGVPZihhKQpp
-Zih0PT1udWxsKXJldHVybiBDLlpRCmlmKHQ9PT1PYmplY3QucHJvdG90eXBlKXJldHVybiBDLlpRCmlm
-KHR5cGVvZiByPT0iZnVuY3Rpb24iKXtPYmplY3QuZGVmaW5lUHJvcGVydHkociwkLkEoKSx7dmFsdWU6
-Qy52QixlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1
-cm4gQy52Qn1yZXR1cm4gQy52Qn0sClFpOmZ1bmN0aW9uKGEsYil7aWYoYTwwfHxhPjQyOTQ5NjcyOTUp
-dGhyb3cgSC5iKFAuVEUoYSwwLDQyOTQ5NjcyOTUsImxlbmd0aCIsbnVsbCkpCnJldHVybiBKLnB5KG5l
-dyBBcnJheShhKSxiKX0sCnB5OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouRXAoSC5WTShhLGIuQygiamQ8
-MD4iKSkpfSwKRXA6ZnVuY3Rpb24oYSl7YS5maXhlZCRsZW5ndGg9QXJyYXkKcmV0dXJuIGF9LAp1bjpm
-dW5jdGlvbihhKXthLmZpeGVkJGxlbmd0aD1BcnJheQphLmltbXV0YWJsZSRsaXN0PUFycmF5CnJldHVy
-biBhfSwKR2E6ZnVuY3Rpb24oYSl7aWYoYTwyNTYpc3dpdGNoKGEpe2Nhc2UgOTpjYXNlIDEwOmNhc2Ug
-MTE6Y2FzZSAxMjpjYXNlIDEzOmNhc2UgMzI6Y2FzZSAxMzM6Y2FzZSAxNjA6cmV0dXJuITAKZGVmYXVs
-dDpyZXR1cm4hMX1zd2l0Y2goYSl7Y2FzZSA1NzYwOmNhc2UgODE5MjpjYXNlIDgxOTM6Y2FzZSA4MTk0
-OmNhc2UgODE5NTpjYXNlIDgxOTY6Y2FzZSA4MTk3OmNhc2UgODE5ODpjYXNlIDgxOTk6Y2FzZSA4MjAw
-OmNhc2UgODIwMTpjYXNlIDgyMDI6Y2FzZSA4MjMyOmNhc2UgODIzMzpjYXNlIDgyMzk6Y2FzZSA4Mjg3
-OmNhc2UgMTIyODg6Y2FzZSA2NTI3OTpyZXR1cm4hMApkZWZhdWx0OnJldHVybiExfX0sCm1tOmZ1bmN0
-aW9uKGEsYil7dmFyIHQscwpmb3IodD1hLmxlbmd0aDtiPHQ7KXtzPUMueEIuVyhhLGIpCmlmKHMhPT0z
-MiYmcyE9PTEzJiYhSi5HYShzKSlicmVhazsrK2J9cmV0dXJuIGJ9LApjMTpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMKZm9yKDtiPjA7Yj10KXt0PWItMQpzPUMueEIubShhLHQpCmlmKHMhPT0zMiYmcyE9PTEzJiYh
-Si5HYShzKSlicmVha31yZXR1cm4gYn0sClJFOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIGEK
+PHA7KytvKWlmKChDLnhCLldkKHEsbyl8MzIpPnIpcmV0dXJuIG59cmV0dXJuIHBhcnNlSW50KGEsYil9
+LApsaDpmdW5jdGlvbihhKXt2YXIgdD1ILkg1KGEpCnJldHVybiB0fSwKSDU6ZnVuY3Rpb24oYSl7dmFy
+IHQscyxyCmlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBILkooSC5xKGEpLG51bGwpCmlmKEouaWEo
+YSk9PT1DLk9rfHx1LmFrLmIoYSkpe3Q9Qy53YihhKQppZihILkJlKHQpKXJldHVybiB0CnM9YS5jb25z
+dHJ1Y3RvcgppZih0eXBlb2Ygcz09ImZ1bmN0aW9uIil7cj1zLm5hbWUKaWYodHlwZW9mIHI9PSJzdHJp
+bmciJiZILkJlKHIpKXJldHVybiByfX1yZXR1cm4gSC5KKEgucShhKSxudWxsKX0sCkJlOmZ1bmN0aW9u
+KGEpe3ZhciB0PWEhPT0iT2JqZWN0IiYmYSE9PSIiCnJldHVybiB0fSwKTTA6ZnVuY3Rpb24oKXtpZigh
+IXNlbGYubG9jYXRpb24pcmV0dXJuIHNlbGYubG9jYXRpb24uaHJlZgpyZXR1cm4gbnVsbH0sClZLOmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9YS5sZW5ndGgKaWYocDw9NTAwKXJldHVybiBTdHJpbmcuZnJv
+bUNoYXJDb2RlLmFwcGx5KG51bGwsYSkKZm9yKHQ9IiIscz0wO3M8cDtzPXIpe3I9cys1MDAKcT1yPHA/
+cjpwCnQrPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhLnNsaWNlKHMscSkpfXJldHVybiB0
+fSwKQ3E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9SC5WTShbXSx1LnQpCmZvcih0PWEubGVuZ3RoLHM9
+MDtzPGEubGVuZ3RoO2EubGVuZ3RoPT09dHx8KDAsSC5saykoYSksKytzKXtyPWFbc10KaWYoIUgub2so
+cikpdGhyb3cgSC5iKEgudEwocikpCmlmKHI8PTY1NTM1KUMuTm0uQShxLHIpCmVsc2UgaWYocjw9MTEx
+NDExMSl7Qy5ObS5BKHEsNTUyOTYrKEMuam4ud0coci02NTUzNiwxMCkmMTAyMykpCkMuTm0uQShxLDU2
+MzIwKyhyJjEwMjMpKX1lbHNlIHRocm93IEguYihILnRMKHIpKX1yZXR1cm4gSC5WSyhxKX0sCmVUOmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTA7czx0Oysrcyl7cj1hW3NdCmlmKCFI
+Lm9rKHIpKXRocm93IEguYihILnRMKHIpKQppZihyPDApdGhyb3cgSC5iKEgudEwocikpCmlmKHI+NjU1
+MzUpcmV0dXJuIEguQ3EoYSl9cmV0dXJuIEguVksoYSl9LApmdzpmdW5jdGlvbihhLGIsYyl7dmFyIHQs
+cyxyLHEKaWYoYzw9NTAwJiZiPT09MCYmYz09PWEubGVuZ3RoKXJldHVybiBTdHJpbmcuZnJvbUNoYXJD
+b2RlLmFwcGx5KG51bGwsYSkKZm9yKHQ9YixzPSIiO3Q8Yzt0PXIpe3I9dCs1MDAKcT1yPGM/cjpjCnMr
+PVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhLnN1YmFycmF5KHQscSkpfXJldHVybiBzfSwK
+THc6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoMDw9YSl7aWYoYTw9NjU1MzUpcmV0dXJuIFN0cmluZy5mcm9t
+Q2hhckNvZGUoYSkKaWYoYTw9MTExNDExMSl7dD1hLTY1NTM2CnJldHVybiBTdHJpbmcuZnJvbUNoYXJD
+b2RlKCg1NTI5NnxDLmpuLndHKHQsMTApKT4+PjAsNTYzMjB8dCYxMDIzKX19dGhyb3cgSC5iKFAuVEUo
+YSwwLDExMTQxMTEsbnVsbCxudWxsKSl9LApvMjpmdW5jdGlvbihhKXtpZihhLmRhdGU9PT12b2lkIDAp
+YS5kYXRlPW5ldyBEYXRlKGEuYSkKcmV0dXJuIGEuZGF0ZX0sCnRKOmZ1bmN0aW9uKGEpe3JldHVybiBh
+LmI/SC5vMihhKS5nZXRVVENGdWxsWWVhcigpKzA6SC5vMihhKS5nZXRGdWxsWWVhcigpKzB9LApOUzpm
+dW5jdGlvbihhKXtyZXR1cm4gYS5iP0gubzIoYSkuZ2V0VVRDTW9udGgoKSsxOkgubzIoYSkuZ2V0TW9u
+dGgoKSsxfSwKakE6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYj9ILm8yKGEpLmdldFVUQ0RhdGUoKSswOkgu
+bzIoYSkuZ2V0RGF0ZSgpKzB9LApLTDpmdW5jdGlvbihhKXtyZXR1cm4gYS5iP0gubzIoYSkuZ2V0VVRD
+SG91cnMoKSswOkgubzIoYSkuZ2V0SG91cnMoKSswfSwKY2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYj9I
+Lm8yKGEpLmdldFVUQ01pbnV0ZXMoKSswOkgubzIoYSkuZ2V0TWludXRlcygpKzB9LApKZDpmdW5jdGlv
+bihhKXtyZXR1cm4gYS5iP0gubzIoYSkuZ2V0VVRDU2Vjb25kcygpKzA6SC5vMihhKS5nZXRTZWNvbmRz
+KCkrMH0sClZhOmZ1bmN0aW9uKGEpe3JldHVybiBhLmI/SC5vMihhKS5nZXRVVENNaWxsaXNlY29uZHMo
+KSswOkgubzIoYSkuZ2V0TWlsbGlzZWNvbmRzKCkrMH0sCnpvOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+LHI9e30Kci5hPTAKdD1bXQpzPVtdCnIuYT1iLmxlbmd0aApDLk5tLkZWKHQsYikKci5iPSIiCmlmKGMh
+PW51bGwmJmMuYSE9PTApYy5VKDAsbmV3IEguQ2oocixzLHQpKQoiIityLmEKcmV0dXJuIEouSnkoYSxu
+ZXcgSC5MSShDLlRlLDAsdCxzLDApKX0sCkVrOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihi
+IGluc3RhbmNlb2YgQXJyYXkpdD1jPT1udWxsfHxjLmE9PT0wCmVsc2UgdD0hMQppZih0KXtzPWIKcj1z
+Lmxlbmd0aAppZihyPT09MCl7aWYoISFhLiQwKXJldHVybiBhLiQwKCl9ZWxzZSBpZihyPT09MSl7aWYo
+ISFhLiQxKXJldHVybiBhLiQxKHNbMF0pfWVsc2UgaWYocj09PTIpe2lmKCEhYS4kMilyZXR1cm4gYS4k
+MihzWzBdLHNbMV0pfWVsc2UgaWYocj09PTMpe2lmKCEhYS4kMylyZXR1cm4gYS4kMyhzWzBdLHNbMV0s
+c1syXSl9ZWxzZSBpZihyPT09NCl7aWYoISFhLiQ0KXJldHVybiBhLiQ0KHNbMF0sc1sxXSxzWzJdLHNb
+M10pfWVsc2UgaWYocj09PTUpaWYoISFhLiQ1KXJldHVybiBhLiQ1KHNbMF0sc1sxXSxzWzJdLHNbM10s
+c1s0XSkKcT1hWyIiKyIkIityXQppZihxIT1udWxsKXJldHVybiBxLmFwcGx5KGEscyl9cmV0dXJuIEgu
+RXcoYSxiLGMpfSwKRXc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrPWIgaW5z
+dGFuY2VvZiBBcnJheT9iOlAuQ0goYiwhMCx1LnopLGo9ay5sZW5ndGgsaT1hLiRSCmlmKGo8aSlyZXR1
+cm4gSC56byhhLGssYykKdD1hLiRECnM9dD09bnVsbApyPSFzP3QoKTpudWxsCnE9Si5pYShhKQpwPXEu
+JEMKaWYodHlwZW9mIHA9PSJzdHJpbmciKXA9cVtwXQppZihzKXtpZihjIT1udWxsJiZjLmEhPT0wKXJl
+dHVybiBILnpvKGEsayxjKQppZihqPT09aSlyZXR1cm4gcC5hcHBseShhLGspCnJldHVybiBILnpvKGEs
+ayxjKX1pZihyIGluc3RhbmNlb2YgQXJyYXkpe2lmKGMhPW51bGwmJmMuYSE9PTApcmV0dXJuIEguem8o
+YSxrLGMpCmlmKGo+aStyLmxlbmd0aClyZXR1cm4gSC56byhhLGssbnVsbCkKQy5ObS5GVihrLHIuc2xp
+Y2Uoai1pKSkKcmV0dXJuIHAuYXBwbHkoYSxrKX1lbHNle2lmKGo+aSlyZXR1cm4gSC56byhhLGssYykK
+bz1PYmplY3Qua2V5cyhyKQppZihjPT1udWxsKWZvcihzPW8ubGVuZ3RoLG49MDtuPG8ubGVuZ3RoO28u
+bGVuZ3RoPT09c3x8KDAsSC5saykobyksKytuKUMuTm0uQShrLHJbSC5jKG9bbl0pXSkKZWxzZXtmb3Io
+cz1vLmxlbmd0aCxtPTAsbj0wO248by5sZW5ndGg7by5sZW5ndGg9PT1zfHwoMCxILmxrKShvKSwrK24p
+e2w9SC5jKG9bbl0pCmlmKGMueDQoMCxsKSl7KyttCkMuTm0uQShrLGMucSgwLGwpKX1lbHNlIEMuTm0u
+QShrLHJbbF0pfWlmKG0hPT1jLmEpcmV0dXJuIEguem8oYSxrLGMpfXJldHVybiBwLmFwcGx5KGEsayl9
+fSwKcFk6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKEgudEwoYSkpfSwKazpmdW5jdGlvbihhLGIpe2lmKGE9
+PW51bGwpSi5IKGEpCnRocm93IEguYihILkhZKGEsYikpfSwKSFk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+LHI9ImluZGV4IgppZighSC5vayhiKSlyZXR1cm4gbmV3IFAuQVQoITAsYixyLG51bGwpCnQ9SC5XWShK
+LkgoYSkpCmlmKCEoYjwwKSl7aWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gSC5wWSh0KQpzPWI+
+PXR9ZWxzZSBzPSEwCmlmKHMpcmV0dXJuIFAudChiLGEscixudWxsLHQpCnJldHVybiBQLk83KGIscil9
+LAphdTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9IkludmFsaWQgdmFsdWUiCmlmKGE+YylyZXR1cm4gbmV3
+IFAuYkooMCxjLCEwLGEsInN0YXJ0Iix0KQppZihiIT1udWxsKXtpZighSC5vayhiKSlyZXR1cm4gbmV3
+IFAuQVQoITAsYiwiZW5kIixudWxsKQppZihiPGF8fGI+YylyZXR1cm4gbmV3IFAuYkooYSxjLCEwLGIs
+ImVuZCIsdCl9cmV0dXJuIG5ldyBQLkFUKCEwLGIsImVuZCIsbnVsbCl9LAp0TDpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IFAuQVQoITAsYSxudWxsLG51bGwpfSwKYjpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1u
+dWxsKWE9bmV3IFAuTEsoKQp0PW5ldyBFcnJvcigpCnQuZGFydEV4Y2VwdGlvbj1hCmlmKCJkZWZpbmVQ
+cm9wZXJ0eSIgaW4gT2JqZWN0KXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCwibWVzc2FnZSIse2dldDpI
+Lkp1fSkKdC5uYW1lPSIifWVsc2UgdC50b1N0cmluZz1ILkp1CnJldHVybiB0fSwKSnU6ZnVuY3Rpb24o
+KXtyZXR1cm4gSi5BYyh0aGlzLmRhcnRFeGNlcHRpb24pfSwKVmo6ZnVuY3Rpb24oYSl7dGhyb3cgSC5i
+KGEpfSwKbGs6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAuYTQoYSkpfSwKY006ZnVuY3Rpb24oYSl7dmFy
+IHQscyxyLHEscCxvCmE9SC5lQShhLnJlcGxhY2UoU3RyaW5nKHt9KSwnJHJlY2VpdmVyJCcpKQp0PWEu
+bWF0Y2goL1xcXCRbYS16QS1aXStcXFwkL2cpCmlmKHQ9PW51bGwpdD1ILlZNKFtdLHUucykKcz10Lmlu
+ZGV4T2YoIlxcJGFyZ3VtZW50c1xcJCIpCnI9dC5pbmRleE9mKCJcXCRhcmd1bWVudHNFeHByXFwkIikK
+cT10LmluZGV4T2YoIlxcJGV4cHJcXCQiKQpwPXQuaW5kZXhPZigiXFwkbWV0aG9kXFwkIikKbz10Lmlu
+ZGV4T2YoIlxcJHJlY2VpdmVyXFwkIikKcmV0dXJuIG5ldyBILmY5KGEucmVwbGFjZShuZXcgUmVnRXhw
+KCdcXFxcXFwkYXJndW1lbnRzXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJlcGxhY2UobmV3
+IFJlZ0V4cCgnXFxcXFxcJGFyZ3VtZW50c0V4cHJcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJyku
+cmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkZXhwclxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKikn
+KS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRtZXRob2RcXFxcXFwkJywnZycpLCcoKD86eHxbXnhd
+KSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkcmVjZWl2ZXJcXFxcXFwkJywnZycpLCcoKD86
+eHxbXnhdKSopJykscyxyLHEscCxvKX0sClM3OmZ1bmN0aW9uKGEpe3JldHVybiBmdW5jdGlvbigkZXhw
+ciQpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7JGV4cHIkLiRtZXRob2QkKCRh
+cmd1bWVudHNFeHByJCl9Y2F0Y2godCl7cmV0dXJuIHQubWVzc2FnZX19KGEpfSwKTWo6ZnVuY3Rpb24o
+YSl7cmV0dXJuIGZ1bmN0aW9uKCRleHByJCl7dHJ5eyRleHByJC4kbWV0aG9kJH1jYXRjaCh0KXtyZXR1
+cm4gdC5tZXNzYWdlfX0oYSl9LApJajpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5XMChhLGI9PW51
+bGw/bnVsbDpiLm1ldGhvZCl9LApUMzpmdW5jdGlvbihhLGIpe3ZhciB0PWI9PW51bGwscz10P251bGw6
+Yi5tZXRob2QKcmV0dXJuIG5ldyBILmF6KGEscyx0P251bGw6Yi5yZWNlaXZlcil9LApSdTpmdW5jdGlv
+bihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGY9bnVsbCxlPW5ldyBILkFtKGEpCmlm
+KGE9PW51bGwpcmV0dXJuIGYKaWYoYSBpbnN0YW5jZW9mIEguYnEpcmV0dXJuIGUuJDEoYS5hKQppZih0
+eXBlb2YgYSE9PSJvYmplY3QiKXJldHVybiBhCmlmKCJkYXJ0RXhjZXB0aW9uIiBpbiBhKXJldHVybiBl
+LiQxKGEuZGFydEV4Y2VwdGlvbikKZWxzZSBpZighKCJtZXNzYWdlIiBpbiBhKSlyZXR1cm4gYQp0PWEu
+bWVzc2FnZQppZigibnVtYmVyIiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9PSJudW1iZXIiKXtzPWEubnVt
+YmVyCnI9cyY2NTUzNQppZigoQy5qbi53RyhzLDE2KSY4MTkxKT09PTEwKXN3aXRjaChyKXtjYXNlIDQz
+ODpyZXR1cm4gZS4kMShILlQzKEguZCh0KSsiIChFcnJvciAiK3IrIikiLGYpKQpjYXNlIDQ0NTpjYXNl
+IDUwMDc6cmV0dXJuIGUuJDEoSC5JaihILmQodCkrIiAoRXJyb3IgIityKyIpIixmKSl9fWlmKGEgaW5z
+dGFuY2VvZiBUeXBlRXJyb3Ipe3E9JC5TbigpCnA9JC5scSgpCm89JC5OOSgpCm49JC5pSSgpCm09JC5V
+TigpCmw9JC5aaCgpCms9JC5yTigpCiQuYzMoKQpqPSQuSEsoKQppPSQucjEoKQpoPXEucVModCkKaWYo
+aCE9bnVsbClyZXR1cm4gZS4kMShILlQzKEguYyh0KSxoKSkKZWxzZXtoPXAucVModCkKaWYoaCE9bnVs
+bCl7aC5tZXRob2Q9ImNhbGwiCnJldHVybiBlLiQxKEguVDMoSC5jKHQpLGgpKX1lbHNle2g9by5xUyh0
+KQppZihoPT1udWxsKXtoPW4ucVModCkKaWYoaD09bnVsbCl7aD1tLnFTKHQpCmlmKGg9PW51bGwpe2g9
+bC5xUyh0KQppZihoPT1udWxsKXtoPWsucVModCkKaWYoaD09bnVsbCl7aD1uLnFTKHQpCmlmKGg9PW51
+bGwpe2g9ai5xUyh0KQppZihoPT1udWxsKXtoPWkucVModCkKZz1oIT1udWxsfWVsc2UgZz0hMH1lbHNl
+IGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMAppZihn
+KXJldHVybiBlLiQxKEguSWooSC5jKHQpLGgpKX19cmV0dXJuIGUuJDEobmV3IEgudlYodHlwZW9mIHQ9
+PSJzdHJpbmciP3Q6IiIpKX1pZihhIGluc3RhbmNlb2YgUmFuZ2VFcnJvcil7aWYodHlwZW9mIHQ9PSJz
+dHJpbmciJiZ0LmluZGV4T2YoImNhbGwgc3RhY2siKSE9PS0xKXJldHVybiBuZXcgUC5LWSgpCnQ9ZnVu
+Y3Rpb24oYil7dHJ5e3JldHVybiBTdHJpbmcoYil9Y2F0Y2goZCl7fXJldHVybiBudWxsfShhKQpyZXR1
+cm4gZS4kMShuZXcgUC5BVCghMSxmLGYsdHlwZW9mIHQ9PSJzdHJpbmciP3QucmVwbGFjZSgvXlJhbmdl
+RXJyb3I6XHMqLywiIik6dCkpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9yPT0iZnVuY3Rpb24iJiZhIGlu
+c3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2YgdD09InN0cmluZyImJnQ9PT0idG9vIG11Y2gg
+cmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRzOmZ1bmN0aW9uKGEpe3ZhciB0
+CmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVsbClyZXR1cm4gbmV3IEguWE8o
+YSkKdD1hLiRjYWNoZWRUcmFjZQppZih0IT1udWxsKXJldHVybiB0CnJldHVybiBhLiRjYWNoZWRUcmFj
+ZT1uZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHE9YS5sZW5ndGgKZm9yKHQ9
+MDt0PHE7dD1yKXtzPXQrMQpyPXMrMQpiLnQoMCxhW3RdLGFbc10pfXJldHVybiBifSwKZnQ6ZnVuY3Rp
+b24oYSxiLGMsZCxlLGYpe3UuWi5hKGEpCnN3aXRjaChILldZKGIpKXtjYXNlIDA6cmV0dXJuIGEuJDAo
+KQpjYXNlIDE6cmV0dXJuIGEuJDEoYykKY2FzZSAyOnJldHVybiBhLiQyKGMsZCkKY2FzZSAzOnJldHVy
+biBhLiQzKGMsZCxlKQpjYXNlIDQ6cmV0dXJuIGEuJDQoYyxkLGUsZil9dGhyb3cgSC5iKG5ldyBQLkNE
+KCJVbnN1cHBvcnRlZCBudW1iZXIgb2YgYXJndW1lbnRzIGZvciB3cmFwcGVkIGNsb3N1cmUiKSl9LAp0
+UjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG51bGwKdD1hLiRpZGVudGl0eQpp
+ZighIXQpcmV0dXJuIHQKdD1mdW5jdGlvbihjLGQsZSl7cmV0dXJuIGZ1bmN0aW9uKGYsZyxoLGkpe3Jl
+dHVybiBlKGMsZCxmLGcsaCxpKX19KGEsYixILmZ0KQphLiRpZGVudGl0eT10CnJldHVybiB0fSwKaUE6
+ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG4sbSxsPW51bGwsaz1iWzBdLGo9
+ay4kY2FsbE5hbWUsaT1lP09iamVjdC5jcmVhdGUobmV3IEguengoKS5jb25zdHJ1Y3Rvci5wcm90b3R5
+cGUpOk9iamVjdC5jcmVhdGUobmV3IEguankobCxsLGwsbCkuY29uc3RydWN0b3IucHJvdG90eXBlKQpp
+LiRpbml0aWFsaXplPWkuY29uc3RydWN0b3IKaWYoZSl0PWZ1bmN0aW9uIHN0YXRpY190ZWFyX29mZigp
+e3RoaXMuJGluaXRpYWxpemUoKX0KZWxzZXtzPSQueWoKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1
+cm4gcy5oKCkKJC55aj1zKzEKcz1uZXcgRnVuY3Rpb24oImEsYixjLGQiK3MsInRoaXMuJGluaXRpYWxp
+emUoYSxiLGMsZCIrcysiKSIpCnQ9c31pLmNvbnN0cnVjdG9yPXQKdC5wcm90b3R5cGU9aQppZighZSl7
+cj1ILmJ4KGEsayxmKQpyLiRyZWZsZWN0aW9uSW5mbz1kfWVsc2V7aS4kc3RhdGljX25hbWU9ZwpyPWt9
+cT1ILmltKGQsZSxmKQppLiRTPXEKaVtqXT1yCmZvcihwPXIsbz0xO288Yi5sZW5ndGg7KytvKXtuPWJb
+b10KbT1uLiRjYWxsTmFtZQppZihtIT1udWxsKXtuPWU/bjpILmJ4KGEsbixmKQppW21dPW59aWYobz09
+PWMpe24uJHJlZmxlY3Rpb25JbmZvPWQKcD1ufX1pLiRDPXAKaS4kUj1rLiRSCmkuJEQ9ay4kRApyZXR1
+cm4gdH0sCmltOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJu
+IGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGQoZSl9fShILkJwLGEpCmlmKHR5
+cGVvZiBhPT0ic3RyaW5nIil7aWYoYil0aHJvdyBILmIoIkNhbm5vdCBjb21wdXRlIHNpZ25hdHVyZSBm
+b3Igc3RhdGljIHRlYXJvZmYuIikKdD1jP0guUFc6SC5UbgpyZXR1cm4gZnVuY3Rpb24oZCxlKXtyZXR1
+cm4gZnVuY3Rpb24oKXtyZXR1cm4gZSh0aGlzLGQpfX0oYSx0KX10aHJvdyBILmIoIkVycm9yIGluIGZ1
+bmN0aW9uVHlwZSBvZiB0ZWFyb2ZmIil9LAp2cTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILkRWCnN3
+aXRjaChiPy0xOmEpe2Nhc2UgMDpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oKXty
+ZXR1cm4gZih0aGlzKVtlXSgpfX0oYyx0KQpjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJu
+IGZ1bmN0aW9uKGcpe3JldHVybiBmKHRoaXMpW2VdKGcpfX0oYyx0KQpjYXNlIDI6cmV0dXJuIGZ1bmN0
+aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCl7cmV0dXJuIGYodGhpcylbZV0oZyxoKX19KGMsdCkK
+Y2FzZSAzOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSl7cmV0dXJuIGYo
+dGhpcylbZV0oZyxoLGkpfX0oYyx0KQpjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1
+bmN0aW9uKGcsaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGopfX0oYyx0KQpjYXNlIDU6cmV0
+dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGosayl7cmV0dXJuIGYodGhpcylb
+ZV0oZyxoLGksaixrKX19KGMsdCkKZGVmYXVsdDpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVu
+Y3Rpb24oKXtyZXR1cm4gZS5hcHBseShmKHRoaXMpLGFyZ3VtZW50cyl9fShkLHQpfX0sCmJ4OmZ1bmN0
+aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbgppZihjKXJldHVybiBILkhmKGEsYikKdD1iLiRzdHVi
+TmFtZQpzPWIubGVuZ3RoCnI9YVt0XQpxPWI9PW51bGw/cj09bnVsbDpiPT09cgpwPSFxfHxzPj0yNwpp
+ZihwKXJldHVybiBILnZxKHMsIXEsdCxiKQppZihzPT09MCl7cT0kLnlqCmlmKHR5cGVvZiBxIT09Im51
+bWJlciIpcmV0dXJuIHEuaCgpCiQueWo9cSsxCm89InNlbGYiK3EKcT0icmV0dXJuIGZ1bmN0aW9uKCl7
+dmFyICIrbysiID0gdGhpcy4iCnA9JC5tSgpyZXR1cm4gbmV3IEZ1bmN0aW9uKHErSC5kKHA9PW51bGw/
+JC5tSj1ILkUyKCJzZWxmIik6cCkrIjtyZXR1cm4gIitvKyIuIitILmQodCkrIigpO30iKSgpfW49ImFi
+Y2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Ii5zcGxpdCgiIikuc3BsaWNlKDAscykuam9pbigiLCIpCnE9
+JC55agppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLmgoKQokLnlqPXErMQpuKz1xCnE9InJl
+dHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRoaXMuIgpwPSQubUoKcmV0dXJuIG5ldyBGdW5jdGlv
+bihxK0guZChwPT1udWxsPyQubUo9SC5FMigic2VsZiIpOnApKyIuIitILmQodCkrIigiK24rIik7fSIp
+KCl9LApaNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILkRWLHM9SC55Uwpzd2l0Y2goYj8tMTphKXtj
+YXNlIDA6dGhyb3cgSC5iKEguRWYoIkludGVyY2VwdGVkIGZ1bmN0aW9uIHdpdGggbm8gYXJndW1lbnRz
+LiIpKQpjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4g
+Zih0aGlzKVtlXShnKHRoaXMpKX19KGMsdCxzKQpjYXNlIDI6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXty
+ZXR1cm4gZnVuY3Rpb24oaCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoKX19KGMsdCxzKQpjYXNl
+IDM6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpKXtyZXR1cm4gZih0aGlz
+KVtlXShnKHRoaXMpLGgsaSl9fShjLHQscykKY2FzZSA0OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0
+dXJuIGZ1bmN0aW9uKGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqKX19KGMsdCxz
+KQpjYXNlIDU6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGosayl7cmV0
+dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksaixrKX19KGMsdCxzKQpjYXNlIDY6cmV0dXJuIGZ1bmN0
+aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGosayxsKXtyZXR1cm4gZih0aGlzKVtlXShnKHRo
+aXMpLGgsaSxqLGssbCl9fShjLHQscykKZGVmYXVsdDpyZXR1cm4gZnVuY3Rpb24oZSxmLGcsaCl7cmV0
+dXJuIGZ1bmN0aW9uKCl7aD1bZyh0aGlzKV0KQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoaCxhcmd1
+bWVudHMpCnJldHVybiBlLmFwcGx5KGYodGhpcyksaCl9fShkLHQscyl9fSwKSGY6ZnVuY3Rpb24oYSxi
+KXt2YXIgdCxzLHIscSxwLG8sbixtPSQubUoKaWYobT09bnVsbCltPSQubUo9SC5FMigic2VsZiIpCnQ9
+JC5QNAppZih0PT1udWxsKXQ9JC5QND1ILkUyKCJyZWNlaXZlciIpCnM9Yi4kc3R1Yk5hbWUKcj1iLmxl
+bmd0aApxPWFbc10KcD1iPT1udWxsP3E9PW51bGw6Yj09PXEKbz0hcHx8cj49MjgKaWYobylyZXR1cm4g
+SC5aNChyLCFwLHMsYikKaWYocj09PTEpe209InJldHVybiBmdW5jdGlvbigpe3JldHVybiB0aGlzLiIr
+SC5kKG0pKyIuIitILmQocykrIih0aGlzLiIrSC5kKHQpKyIpOyIKdD0kLnlqCmlmKHR5cGVvZiB0IT09
+Im51bWJlciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcgRnVuY3Rpb24obSt0KyJ9Iiko
+KX1uPSJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHItMSkuam9p
+bigiLCIpCm09InJldHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRoaXMuIitILmQobSkrIi4iK0gu
+ZChzKSsiKHRoaXMuIitILmQodCkrIiwgIituKyIpOyIKdD0kLnlqCmlmKHR5cGVvZiB0IT09Im51bWJl
+ciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcgRnVuY3Rpb24obSt0KyJ9IikoKX0sCnVj
+OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3JldHVybiBILmlBKGEsYixjLGQsISFlLCEhZixnKX0sClRu
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguY0Uodi50eXBlVW5pdmVyc2UsSC5xKGEuYSksYil9LApQVzpm
+dW5jdGlvbihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgucShhLmMpLGIpfSwKRFY6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVybiBhLmN9LApFMjpmdW5jdGlv
+bihhKXt2YXIgdCxzLHIscT1uZXcgSC5qeSgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIp
+LHA9Si5FcChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhxKSkKZm9yKHQ9cC5sZW5ndGgscz0wO3M8
+dDsrK3Mpe3I9cFtzXQppZihxW3JdPT09YSlyZXR1cm4gcn19LApvVDpmdW5jdGlvbihhKXtpZihhPT1u
+dWxsKUguZk8oImJvb2xlYW4gZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBudWxsIikKcmV0dXJuIGF9LApm
+TzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IEgua1koYSkpfSwKYWc6ZnVuY3Rpb24oYSl7dGhyb3cg
+SC5iKG5ldyBQLnQ3KGEpKX0sCkVmOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5FcShhKX0sCllnOmZ1
+bmN0aW9uKGEpe3JldHVybiB2LmdldElzb2xhdGVUYWcoYSl9LApWTTpmdW5jdGlvbihhLGIpe2Fbdi5h
+cnJheVJ0aV09YgpyZXR1cm4gYX0sCm9YOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwK
+cmV0dXJuIGEuJHRpfSwKSU06ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBILlk5KGFbIiRhIitILmQoYyld
+LEgub1goYikpfSwKWTk6ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBiCmE9YS5hcHBseShu
+dWxsLGIpCmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gYQpp
+Zih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gYS5hcHBseShudWxsLGIpCnJldHVybiBifSwKRlo6
+ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBhLmFwcGx5KGIsSC5ZOShKLmlhKGIpWyIkYSIrSC5kKGMpXSxI
+Lm9YKGIpKSl9LAppdzpmdW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsYix7dmFs
+dWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KX0sCkc6
+ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1ILmMoJC55LiQxKGEpKSxvPSQualtwXQppZihvIT1udWxs
+KXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVu
+dW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9
+dD0kLnZbcF0KaWYodCE9bnVsbClyZXR1cm4gdApzPXYuaW50ZXJjZXB0b3JzQnlUYWdbcF0KaWYocz09
+bnVsbCl7cD1ILmMoJC51LiQyKGEscCkpCmlmKHAhPW51bGwpe289JC5qW3BdCmlmKG8hPW51bGwpe09i
+amVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVy
+YWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX10PSQu
+dltwXQppZih0IT1udWxsKXJldHVybiB0CnM9di5pbnRlcmNlcHRvcnNCeVRhZ1twXX19aWYocz09bnVs
+bClyZXR1cm4gbnVsbAp0PXMucHJvdG90eXBlCnI9cFswXQppZihyPT09IiEiKXtvPUgubCh0KQokLmpb
+cF09bwpPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpv
+LGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBv
+Lml9aWYocj09PSJ+Iil7JC52W3BdPXQKcmV0dXJuIHR9aWYocj09PSItIil7cT1ILmwodCkKT2JqZWN0
+LmRlZmluZVByb3BlcnR5KE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSx2LmRpc3BhdGNoUHJvcGVydHlO
+YW1lLHt2YWx1ZTpxLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1
+ZX0pCnJldHVybiBxLml9aWYocj09PSIrIilyZXR1cm4gSC5MYyhhLHQpCmlmKHI9PT0iKiIpdGhyb3cg
+SC5iKFAubihwKSkKaWYodi5sZWFmVGFnc1twXT09PXRydWUpe3E9SC5sKHQpCk9iamVjdC5kZWZpbmVQ
+cm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSksdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7dmFs
+dWU6cSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1
+cm4gcS5pfWVsc2UgcmV0dXJuIEguTGMoYSx0KX0sCkxjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9T2JqZWN0
+LmdldFByb3RvdHlwZU9mKGEpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LHYuZGlzcGF0Y2hQcm9wZXJ0
+eU5hbWUse3ZhbHVlOkouUXUoYix0LG51bGwsbnVsbCksZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0
+cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIGJ9LApsOmZ1bmN0aW9uKGEpe3JldHVybiBKLlF1
+KGEsITEsbnVsbCwhIWEuJGlYail9LApWRjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9Yi5wcm90b3R5cGUK
+aWYodi5sZWFmVGFnc1thXT09PXRydWUpcmV0dXJuIEgubCh0KQplbHNlIHJldHVybiBKLlF1KHQsYyxu
+dWxsLG51bGwpfSwKTTpmdW5jdGlvbigpe2lmKCEwPT09JC5LKXJldHVybgokLks9ITAKSC5EKCl9LApE
+OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbQokLmo9T2JqZWN0LmNyZWF0ZShudWxsKQokLnY9
+T2JqZWN0LmNyZWF0ZShudWxsKQpILmEoKQp0PXYuaW50ZXJjZXB0b3JzQnlUYWcKcz1PYmplY3QuZ2V0
+T3duUHJvcGVydHlOYW1lcyh0KQppZih0eXBlb2Ygd2luZG93IT0idW5kZWZpbmVkIil7d2luZG93CnI9
+ZnVuY3Rpb24oKXt9CmZvcihxPTA7cTxzLmxlbmd0aDsrK3Epe3A9c1txXQpvPSQueDcuJDEocCkKaWYo
+byE9bnVsbCl7bj1ILlZGKHAsdFtwXSxvKQppZihuIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHko
+byx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpuLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6
+dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnIucHJvdG90eXBlPW99fX19Zm9yKHE9MDtxPHMubGVuZ3Ro
+OysrcSl7cD1zW3FdCmlmKC9eW0EtWmEtel9dLy50ZXN0KHApKXttPXRbcF0KdFsiISIrcF09bQp0WyJ+
+IitwXT1tCnRbIi0iK3BdPW0KdFsiKyIrcF09bQp0WyIqIitwXT1tfX19LAphOmZ1bmN0aW9uKCl7dmFy
+IHQscyxyLHEscCxvLG49Qy5PNCgpCm49SC5GKEMuWXEsSC5GKEMuS1UsSC5GKEMuZlEsSC5GKEMuZlEs
+SC5GKEMuaTcsSC5GKEMueGksSC5GKEMuZGsoQy53YiksbikpKSkpKSkKaWYodHlwZW9mIGRhcnROYXRp
+dmVEaXNwYXRjaEhvb2tzVHJhbnNmb3JtZXIhPSJ1bmRlZmluZWQiKXt0PWRhcnROYXRpdmVEaXNwYXRj
+aEhvb2tzVHJhbnNmb3JtZXIKaWYodHlwZW9mIHQ9PSJmdW5jdGlvbiIpdD1bdF0KaWYodC5jb25zdHJ1
+Y3Rvcj09QXJyYXkpZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3NdCmlmKHR5cGVvZiByPT0iZnVu
+Y3Rpb24iKW49cihuKXx8bn19cT1uLmdldFRhZwpwPW4uZ2V0VW5rbm93blRhZwpvPW4ucHJvdG90eXBl
+Rm9yVGFnCiQueT1uZXcgSC5yKHEpCiQudT1uZXcgSC5kQyhwKQokLng3PW5ldyBILndOKG8pfSwKRjpm
+dW5jdGlvbihhLGIpe3JldHVybiBhKGIpfHxifSwKdjQ6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0
+PWI/Im0iOiIiLHM9Yz8iIjoiaSIscj1kPyJ1IjoiIixxPWU/InMiOiIiLHA9Zj8iZyI6IiIsbz1mdW5j
+dGlvbihnLGgpe3RyeXtyZXR1cm4gbmV3IFJlZ0V4cChnLGgpfWNhdGNoKG4pe3JldHVybiBufX0oYSx0
+K3MrcitxK3ApCmlmKG8gaW5zdGFuY2VvZiBSZWdFeHApcmV0dXJuIG8KdGhyb3cgSC5iKFAucnIoIkls
+bGVnYWwgUmVnRXhwIHBhdHRlcm4gKCIrU3RyaW5nKG8pKyIpIixhLG51bGwpKX0sCm0yOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgdAppZih0eXBlb2YgYj09InN0cmluZyIpcmV0dXJuIGEuaW5kZXhPZihiLGMpPj0w
+CmVsc2UgaWYoYiBpbnN0YW5jZW9mIEguVlIpe3Q9Qy54Qi55bihhLGMpCnJldHVybiBiLmIudGVzdCh0
+KX1lbHNle3Q9Si5GTChiLEMueEIueW4oYSxjKSkKcmV0dXJuIXQuZ2wwKHQpfX0sCkE0OmZ1bmN0aW9u
+KGEpe2lmKGEuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEucmVwbGFjZSgvXCQvZywiJCQkJCIpCnJl
+dHVybiBhfSwKZUE6ZnVuY3Rpb24oYSl7aWYoL1tbXF17fSgpKis/LlxcXiR8XS8udGVzdChhKSlyZXR1
+cm4gYS5yZXBsYWNlKC9bW1xde30oKSorPy5cXF4kfF0vZywiXFwkJiIpCnJldHVybiBhfSwKeXM6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciB0PUgubk0oYSxiLGMpCnJldHVybiB0fSwKbk06ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0LHMscixxCmlmKGI9PT0iIil7aWYoYT09PSIiKXJldHVybiBjCnQ9YS5sZW5ndGgKZm9yKHM9
+YyxyPTA7cjx0OysrcilzPXMrYVtyXStjCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfXE9YS5p
+bmRleE9mKGIsMCkKaWYocTwwKXJldHVybiBhCmlmKGEubGVuZ3RoPDUwMHx8Yy5pbmRleE9mKCIkIiww
+KT49MClyZXR1cm4gYS5zcGxpdChiKS5qb2luKGMpCnJldHVybiBhLnJlcGxhY2UobmV3IFJlZ0V4cChI
+LmVBKGIpLCdnJyksSC5BNChjKSl9LApQRDpmdW5jdGlvbiBQRChhLGIpe3RoaXMuYT1hCnRoaXMuJHRp
+PWJ9LApXVTpmdW5jdGlvbiBXVSgpe30sCkxQOmZ1bmN0aW9uIExQKGEsYixjLGQpe3ZhciBfPXRoaXMK
+Xy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sClhSOmZ1bmN0aW9uIFhSKGEsYil7dGhpcy5hPWEKdGhp
+cy4kdGk9Yn0sCkxJOmZ1bmN0aW9uIExJKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9YQpfLmM9Ygpf
+LmQ9YwpfLmU9ZApfLmY9ZX0sCkNqOmZ1bmN0aW9uIENqKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0
+aGlzLmM9Y30sCmY5OmZ1bmN0aW9uIGY5KGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1i
+Cl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKVzA6ZnVuY3Rpb24gVzAoYSxiKXt0aGlzLmE9YQp0aGlz
+LmI9Yn0sCmF6OmZ1bmN0aW9uIGF6KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnZW
+OmZ1bmN0aW9uIHZWKGEpe3RoaXMuYT1hfSwKYnE6ZnVuY3Rpb24gYnEoYSxiKXt0aGlzLmE9YQp0aGlz
+LmI9Yn0sCkFtOmZ1bmN0aW9uIEFtKGEpe3RoaXMuYT1hfSwKWE86ZnVuY3Rpb24gWE8oYSl7dGhpcy5h
+PWEKdGhpcy5iPW51bGx9LApUcDpmdW5jdGlvbiBUcCgpe30sCmxjOmZ1bmN0aW9uIGxjKCl7fSwKeng6
+ZnVuY3Rpb24gengoKXt9LApqeTpmdW5jdGlvbiBqeShhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8u
+Yj1iCl8uYz1jCl8uZD1kfSwKRXE6ZnVuY3Rpb24gRXEoYSl7dGhpcy5hPWF9LAprWTpmdW5jdGlvbiBr
+WShhKXt0aGlzLmE9YX0sCk41OmZ1bmN0aW9uIE41KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5mPV8uZT1f
+LmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LAp2aDpmdW5jdGlvbiB2aChhLGIpe3ZhciBfPXRo
+aXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVuY3Rpb24gaTUoYSxiKXt0aGlzLmE9YQp0
+aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5k
+PV8uYz1udWxsCl8uJHRpPWN9LApyOmZ1bmN0aW9uIHIoYSl7dGhpcy5hPWF9LApkQzpmdW5jdGlvbiBk
+QyhhKXt0aGlzLmE9YX0sCndOOmZ1bmN0aW9uIHdOKGEpe3RoaXMuYT1hfSwKVlI6ZnVuY3Rpb24gVlIo
+YSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbH0sCkVLOmZ1bmN0aW9uIEVLKGEp
+e3RoaXMuYj1hfSwKS1c6ZnVuY3Rpb24gS1coYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1j
+fSwKUGI6ZnVuY3Rpb24gUGIoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPW51
+bGx9LAp0UTpmdW5jdGlvbiB0UShhLGIpe3RoaXMuYT1hCnRoaXMuYz1ifSwKTkY6ZnVuY3Rpb24gTkYo
+YSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKU2Q6ZnVuY3Rpb24gU2QoYSxiLGMpe3Zh
+ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPW51bGx9LApYRjpmdW5jdGlvbihhKXtyZXR1cm4g
+YX0sCkRROmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSW50OEFycmF5KGEpfSwKb2Q6ZnVuY3Rpb24oYSxi
+LGMpe2lmKGE+Pj4wIT09YXx8YT49Yyl0aHJvdyBILmIoSC5IWShiLGEpKX0sCnJNOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdAppZighKGE+Pj4wIT09YSkpdD1iPj4+MCE9PWJ8fGE+Ynx8Yj5jCmVsc2UgdD0hMApp
+Zih0KXRocm93IEguYihILmF1KGEsYixjKSkKcmV0dXJuIGJ9LApXWjpmdW5jdGlvbiBXWigpe30sCnBG
+OmZ1bmN0aW9uIHBGKCl7fSwKYjA6ZnVuY3Rpb24gYjAoKXt9LApEZzpmdW5jdGlvbiBEZygpe30sClBn
+OmZ1bmN0aW9uIFBnKCl7fSwKeGo6ZnVuY3Rpb24geGooKXt9LApkRTpmdW5jdGlvbiBkRSgpe30sClpB
+OmZ1bmN0aW9uIFpBKCl7fSwKd2Y6ZnVuY3Rpb24gd2YoKXt9LApQcTpmdW5jdGlvbiBQcSgpe30sCmVF
+OmZ1bmN0aW9uIGVFKCl7fSwKVjY6ZnVuY3Rpb24gVjYoKXt9LApSRzpmdW5jdGlvbiBSRygpe30sClZQ
+OmZ1bmN0aW9uIFZQKCl7fSwKV0I6ZnVuY3Rpb24gV0IoKXt9LApaRzpmdW5jdGlvbiBaRygpe30sCmN6
+OmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5jCnJldHVybiB0PT1udWxsP2IuYz1ILkJjKGEsYi56LCEwKTp0
+fSwKeFo6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iLmMKcmV0dXJuIHQ9PW51bGw/Yi5jPUguUTIoYSwiYjgi
+LFtiLnpdKTp0fSwKUTE6ZnVuY3Rpb24oYSl7dmFyIHQ9YS55CmlmKHQ9PT02fHx0PT09N3x8dD09PTgp
+cmV0dXJuIEguUTEoYS56KQpyZXR1cm4gdD09PTExfHx0PT09MTJ9LAptRDpmdW5jdGlvbihhKXtyZXR1
+cm4gYS5jeX0sCkRQOmZ1bmN0aW9uKGEpe3JldHVybiBILkUodi50eXBlVW5pdmVyc2UsYSwhMSl9LApQ
+TDpmdW5jdGlvbihhLGIsYyxhMCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZD1i
+LnkKc3dpdGNoKGQpe2Nhc2UgNTpjYXNlIDE6Y2FzZSAyOmNhc2UgMzpjYXNlIDQ6cmV0dXJuIGIKY2Fz
+ZSA2OnQ9Yi56CnM9SC5QTChhLHQsYyxhMCkKaWYocz09PXQpcmV0dXJuIGIKcmV0dXJuIEguU08oYSxz
+LCEwKQpjYXNlIDc6dD1iLnoKcz1ILlBMKGEsdCxjLGEwKQppZihzPT09dClyZXR1cm4gYgpyZXR1cm4g
+SC5CYyhhLHMsITApCmNhc2UgODp0PWIuegpzPUguUEwoYSx0LGMsYTApCmlmKHM9PT10KXJldHVybiBi
+CnJldHVybiBILkxOKGEscywhMCkKY2FzZSA5OnI9Yi5RCnE9SC5iWihhLHIsYyxhMCkKaWYocT09PXIp
+cmV0dXJuIGIKcmV0dXJuIEguUTIoYSxiLnoscSkKY2FzZSAxMDpwPWIuegpvPUguUEwoYSxwLGMsYTAp
+Cm49Yi5RCm09SC5iWihhLG4sYyxhMCkKaWYobz09PXAmJm09PT1uKXJldHVybiBiCnJldHVybiBILmFw
+KGEsbyxtKQpjYXNlIDExOmw9Yi56Cms9SC5QTChhLGwsYyxhMCkKaj1iLlEKaT1ILnFUKGEsaixjLGEw
+KQppZihrPT09bCYmaT09PWopcmV0dXJuIGIKcmV0dXJuIEguTmYoYSxrLGkpCmNhc2UgMTI6aD1iLlEK
+YTArPWgubGVuZ3RoCmc9SC5iWihhLGgsYyxhMCkKcD1iLnoKbz1ILlBMKGEscCxjLGEwKQppZihnPT09
+aCYmbz09PXApcmV0dXJuIGIKcmV0dXJuIEguRFMoYSxvLGcsITApCmNhc2UgMTM6Zj1iLnoKaWYoZjxh
+MClyZXR1cm4gYgplPWNbZi1hMF0KaWYoZT09bnVsbClyZXR1cm4gYgpyZXR1cm4gZQpkZWZhdWx0OnRo
+cm93IEguYihQLmhWKCJBdHRlbXB0ZWQgdG8gc3Vic3RpdHV0ZSB1bmV4cGVjdGVkIFJUSSBraW5kICIr
+ZCkpfX0sCmJaOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHA9Yi5sZW5ndGgsbz1bXQpmb3Io
+dD0hMSxzPTA7czxwOysrcyl7cj1iW3NdCnE9SC5QTChhLHIsYyxkKQppZihxIT09cil0PSEwCm8ucHVz
+aChxKX1yZXR1cm4gdD9vOmJ9LAp2TzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG89Yi5s
+ZW5ndGgsbj1bXQpmb3IodD0hMSxzPTA7czxvO3MrPTIpe3I9YltzXQpxPWJbcysxXQpwPUguUEwoYSxx
+LGMsZCkKaWYocCE9PXEpdD0hMApuLnB1c2gocikKbi5wdXNoKHApfXJldHVybiB0P246Yn0sCnFUOmZ1
+bmN0aW9uKGEsYixjLGQpe3ZhciB0LHM9Yi5hLHI9SC5iWihhLHMsYyxkKSxxPWIuYixwPUguYlooYSxx
+LGMsZCksbz1iLmMsbj1ILnZPKGEsbyxjLGQpCmlmKHI9PT1zJiZwPT09cSYmbj09PW8pcmV0dXJuIGIK
+dD1uZXcgSC5FVCgpCnQuYT1yCnQuYj1wCnQuYz1uCnJldHVybiB0fSwKSlM6ZnVuY3Rpb24oYSl7dmFy
+IHQ9YS4kUwppZih0IT1udWxsKXtpZih0eXBlb2YgdD09Im51bWJlciIpcmV0dXJuIEguQnAodCkKcmV0
+dXJuIGEuJFMoKX1yZXR1cm4gbnVsbH0sClVlOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoSC5RMShiKSlp
+ZihhIGluc3RhbmNlb2YgSC5UcCl7dD1ILkpTKGEpCmlmKHQhPW51bGwpcmV0dXJuIHR9cmV0dXJuIEgu
+cShhKX0sCnE6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYSBpbnN0YW5jZW9mIFAuTWgpe3Q9YS4kdGkKcmV0
+dXJuIHQhPW51bGw/dDpILlZVKGEpfWlmKEFycmF5LmlzQXJyYXkoYSkpcmV0dXJuIEgudDYoYSkKcmV0
+dXJuIEguVlUoSi5pYShhKSl9LAp0NjpmdW5jdGlvbihhKXt2YXIgdD1hW3YuYXJyYXlSdGldLHM9dS52
+CmlmKHQ9PW51bGwpcmV0dXJuIHMKaWYodC5jb25zdHJ1Y3RvciE9PXMuY29uc3RydWN0b3IpcmV0dXJu
+IHMKcmV0dXJuIHR9LApMaDpmdW5jdGlvbihhKXt2YXIgdD1hLiR0aQpyZXR1cm4gdCE9bnVsbD90Okgu
+VlUoYSl9LApWVTpmdW5jdGlvbihhKXt2YXIgdD1hLmNvbnN0cnVjdG9yLHM9dC4kY2NhY2hlCmlmKHMh
+PW51bGwpcmV0dXJuIHMKcmV0dXJuIEgucjkoYSx0KX0sCnI5OmZ1bmN0aW9uKGEsYil7dmFyIHQ9YSBp
+bnN0YW5jZW9mIEguVHA/YS5fX3Byb3RvX18uX19wcm90b19fLmNvbnN0cnVjdG9yOmIscz1ILmFpKHYu
+dHlwZVVuaXZlcnNlLHQubmFtZSkKYi4kY2NhY2hlPXMKcmV0dXJuIHN9LApCcDpmdW5jdGlvbihhKXt2
+YXIgdCxzPWEscj12LnR5cGVzLHE9cltzXQppZih0eXBlb2YgcT09InN0cmluZyIpe3Q9SC5FKHYudHlw
+ZVVuaXZlcnNlLHEsITEpCnJbc109dApyZXR1cm4gdH1yZXR1cm4gcX0sCkpKOmZ1bmN0aW9uKGEpe3Zh
+ciB0PXRoaXMscz1ILllPLHI9dS5LCmlmKHQ9PT1yKXtzPUgua2UKdC5hPUguVGl9ZWxzZSBpZihILkE4
+KHQpfHx0PT09cil7cz1ILkl3CnQuYT1ILmhufWVsc2UgaWYodD09PXUuUylzPUgub2sKZWxzZSBpZih0
+PT09dS5nUilzPUguS0gKZWxzZSBpZih0PT09dS5kaSlzPUguS0gKZWxzZSBpZih0PT09dS5OKXM9SC5N
+TQplbHNlIGlmKHQ9PT11Lnkpcz1ILnJRCmVsc2UgaWYodC55PT09OSl7cj10LnoKaWYodC5RLmV2ZXJ5
+KEguY2MpKXt0LnI9IiRpIityCnM9SC50NH19dC5iPXMKcmV0dXJuIHQuYihhKX0sCllPOmZ1bmN0aW9u
+KGEpe3ZhciB0PXRoaXMKcmV0dXJuIEguV2Uodi50eXBlVW5pdmVyc2UsSC5VZShhLHQpLG51bGwsdCxu
+dWxsKX0sCnQ0OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz10LnIKaWYoYSBpbnN0YW5jZW9mIFAuTWgp
+cmV0dXJuISFhW3NdCnJldHVybiEhSi5pYShhKVtzXX0sCk96OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMK
+aWYoYT09bnVsbClyZXR1cm4gYQplbHNlIGlmKHQuYihhKSlyZXR1cm4gYQp0aHJvdyBILmIoSC5aYyhI
+LnAoYSxILlVlKGEsdCksSC5KKHQsbnVsbCkpKSl9LApEaDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1u
+dWxsCmlmKEguV2Uodi50eXBlVW5pdmVyc2UsYSx0LGIsdCkpcmV0dXJuIGEKdGhyb3cgSC5iKEguWmMo
+IlRoZSB0eXBlIGFyZ3VtZW50ICciK0guZChILkooYSx0KSkrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0
+aGUgdHlwZSB2YXJpYWJsZSBib3VuZCAnIitILmQoSC5KKGIsdCkpKyInIG9mIHR5cGUgdmFyaWFibGUg
+JyIrYysiJyBpbiAnIitILmQoZCkrIicuIikpfSwKcDpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9UC5oKGEp
+LHM9SC5KKGI9PW51bGw/SC5xKGEpOmIsbnVsbCkKcmV0dXJuIHQrIjogdHlwZSAnIitILmQocykrIicg
+aXMgbm90IGEgc3VidHlwZSBvZiB0eXBlICciK0guZChjKSsiJyJ9LApaYzpmdW5jdGlvbihhKXtyZXR1
+cm4gbmV3IEgueCgiVHlwZUVycm9yOiAiK2EpfSwKQjpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC54
+KCJUeXBlRXJyb3I6ICIrSC5wKGEsbnVsbCxiKSl9LAprZTpmdW5jdGlvbihhKXtyZXR1cm4hMH0sClRp
+OmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKSXc6ZnVuY3Rpb24oYSl7cmV0dXJuITB9LApobjpmdW5jdGlv
+bihhKXtyZXR1cm4gYX0sCnJROmZ1bmN0aW9uKGEpe3JldHVybiEwPT09YXx8ITE9PT1hfSwKRTk6ZnVu
+Y3Rpb24oYSl7aWYoITA9PT1hfHwhMT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJv
+dyBILmIoSC5CKGEsImJvb2wiKSl9LApkajpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIp
+cmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5CKGEsImRvdWJsZSIpKX0sCm9r
+OmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hfSwK
+V1k6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1
+cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILkIoYSwiaW50IikpfSwKS0g6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVtYmVyIn0sCnVVOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBh
+PT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILkIoYSwibnVt
+IikpfSwKTU06ZnVuY3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ic3RyaW5nIn0sCmM6ZnVuY3Rpb24o
+YSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cg
+SC5iKEguQihhLCJTdHJpbmciKSl9LAp3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PSIiLHM9
+IiIscj0wO3I8YS5sZW5ndGg7KytyLHM9IiwgIil0Kz1DLnhCLmgocyxILkooYVtyXSxiKSkKcmV0dXJu
+IHR9LApmOmZ1bmN0aW9uKGExLGEyLGEzKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYs
+ZSxkLGMsYixhLGEwPSIsICIKaWYoYTMhPW51bGwpe3Q9YTMubGVuZ3RoCmlmKGEyPT1udWxsKXthMj1I
+LlZNKFtdLHUucykKcz1udWxsfWVsc2Ugcz1hMi5sZW5ndGgKcj1hMi5sZW5ndGgKZm9yKHE9dDtxPjA7
+LS1xKUMuTm0uQShhMiwiVCIrKHIrcSkpCmZvcihwPXUuSyxvPSI8IixuPSIiLHE9MDtxPHQ7KytxLG49
+YTApe28rPW4KbT1hMi5sZW5ndGgKbD1tLTEtcQppZihsPDApcmV0dXJuIEguayhhMixsKQpvPUMueEIu
+aChvLGEyW2xdKQprPWEzW3FdCmlmKCEoSC5BOChrKXx8az09PXApKW09IShrPT09cCkKZWxzZSBtPSEx
+CmlmKG0pbys9Qy54Qi5oKCIgZXh0ZW5kcyAiLEguSihrLGEyKSl9bys9Ij4ifWVsc2V7bz0iIgpzPW51
+bGx9cD1hMS56Cmo9YTEuUQppPWouYQpoPWkubGVuZ3RoCmc9ai5iCmY9Zy5sZW5ndGgKZT1qLmMKZD1l
+Lmxlbmd0aApjPUguSihwLGEyKQpmb3IoYj0iIixhPSIiLHE9MDtxPGg7KytxLGE9YTApYis9Qy54Qi5o
+KGEsSC5KKGlbcV0sYTIpKQppZihmPjApe2IrPWErIlsiCmZvcihhPSIiLHE9MDtxPGY7KytxLGE9YTAp
+Yis9Qy54Qi5oKGEsSC5KKGdbcV0sYTIpKQpiKz0iXSJ9aWYoZD4wKXtiKz1hKyJ7Igpmb3IoYT0iIixx
+PTA7cTxkO3ErPTIsYT1hMCliKz1DLnhCLmgoYSxILkooZVtxKzFdLGEyKSkrIiAiK2VbcV0KYis9In0i
+fWlmKHMhPW51bGwpYTIubGVuZ3RoPXMKcmV0dXJuIG8rIigiK2IrIikgPT4gIitILmQoYyl9LApKOmZ1
+bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbT1hLnkKaWYobT09PTUpcmV0dXJuImVyYXNlZCIK
+aWYobT09PTIpcmV0dXJuImR5bmFtaWMiCmlmKG09PT0zKXJldHVybiJ2b2lkIgppZihtPT09MSlyZXR1
+cm4iTmV2ZXIiCmlmKG09PT00KXJldHVybiJhbnkiCmlmKG09PT02KXt0PUguSihhLnosYikKcmV0dXJu
+IHR9aWYobT09PTcpe3M9YS56CnQ9SC5KKHMsYikKcj1zLnkKcmV0dXJuIEoubShyPT09MTF8fHI9PT0x
+Mj9DLnhCLmgoIigiLHQpKyIpIjp0LCI/Iil9aWYobT09PTgpcmV0dXJuIkZ1dHVyZU9yPCIrSC5kKEgu
+SihhLnosYikpKyI+IgppZihtPT09OSl7cT1ILkMoYS56KQpwPWEuUQpyZXR1cm4gcC5sZW5ndGghPT0w
+P3ErKCI8IitILncocCxiKSsiPiIpOnF9aWYobT09PTExKXJldHVybiBILmYoYSxiLG51bGwpCmlmKG09
+PT0xMilyZXR1cm4gSC5mKGEueixiLGEuUSkKaWYobT09PTEzKXtvPWEuegpuPWIubGVuZ3RoCm89bi0x
+LW8KaWYobzwwfHxvPj1uKXJldHVybiBILmsoYixvKQpyZXR1cm4gYltvXX1yZXR1cm4iPyJ9LApDOmZ1
+bmN0aW9uKGEpe3ZhciB0LHM9SC5KZyhhKQppZihzIT1udWxsKXJldHVybiBzCnQ9Im1pbmlmaWVkOiIr
+YQpyZXR1cm4gdH0sClFvOmZ1bmN0aW9uKGEsYil7dmFyIHQ9YS50UltiXQpmb3IoO3R5cGVvZiB0PT0i
+c3RyaW5nIjspdD1hLnRSW3RdCnJldHVybiB0fSwKYWk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
+LG89YS5lVCxuPW9bYl0KaWYobj09bnVsbClyZXR1cm4gSC5FKGEsYiwhMSkKZWxzZSBpZih0eXBlb2Yg
+bj09Im51bWJlciIpe3Q9bgpzPUgubVooYSw1LCIjIikKcj1bXQpmb3IocT0wO3E8dDsrK3Epci5wdXNo
+KHMpCnA9SC5RMihhLGIscikKb1tiXT1wCnJldHVybiBwfWVsc2UgcmV0dXJuIG59LAp4YjpmdW5jdGlv
+bihhLGIpe3JldHVybiBILkl4KGEudFIsYil9LApGRjpmdW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEu
+ZVQsYil9LApFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWEuZUMscj1zLmdldChiKQppZihyIT1udWxs
+KXJldHVybiByCnQ9SC56KGEsbnVsbCxiLGMpCnMuc2V0KGIsdCkKcmV0dXJuIHR9LApjRTpmdW5jdGlv
+bihhLGIsYyl7dmFyIHQscyxyPWIuY2gKaWYocj09bnVsbClyPWIuY2g9bmV3IE1hcCgpCnQ9ci5nZXQo
+YykKaWYodCE9bnVsbClyZXR1cm4gdApzPUgueihhLGIsYywhMCkKci5zZXQoYyxzKQpyZXR1cm4gc30s
+CnY1OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT1iLmN4CmlmKHE9PW51bGwpcT1iLmN4PW5ldyBN
+YXAoKQp0PWMuY3kKcz1xLmdldCh0KQppZihzIT1udWxsKXJldHVybiBzCnI9SC5hcChhLGIsYy55PT09
+MTA/Yy5ROltjXSkKcS5zZXQodCxyKQpyZXR1cm4gcn0sCno6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9
+SC5pKEgubyhhLGIsYyxkKSkKaWYodCE9bnVsbClyZXR1cm4gdAp0aHJvdyBILmIoUC5uKCdfVW5pdmVy
+c2UuX3BhcnNlUmVjaXBlKCInK0guZChjKSsnIiknKSl9LApCRDpmdW5jdGlvbihhLGIpe2IuYT1ILk96
+CmIuYj1ILkpKCnJldHVybiBifSwKbVo6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscj1hLmVDLmdldChj
+KQppZihyIT1udWxsKXJldHVybiByCnQ9bmV3IEguSmMobnVsbCxudWxsKQp0Lnk9Ygp0LmN5PWMKcz1I
+LkJEKGEsdCkKYS5lQy5zZXQoYyxzKQpyZXR1cm4gc30sClNPOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+PWIuY3krIioiLHI9YS5lQy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PUguWjcoYSxiLHMsYykK
+YS5lQy5zZXQocyx0KQpyZXR1cm4gdH0sClo3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMKaWYoZCl7
+dD1iLnkKaWYoSC5BOChiKXx8Yj09PXUuS3x8Yj09PXUuUHx8dD09PTd8fHQ9PT02KXJldHVybiBifXM9
+bmV3IEguSmMobnVsbCxudWxsKQpzLnk9NgpzLno9YgpzLmN5PWMKcmV0dXJuIEguQkQoYSxzKX0sCkJj
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuY3krIj8iLHI9YS5lQy5nZXQocykKaWYociE9bnVsbCly
+ZXR1cm4gcgp0PUgubGwoYSxiLHMsYykKYS5lQy5zZXQocyx0KQpyZXR1cm4gdH0sCmxsOmZ1bmN0aW9u
+KGEsYixjLGQpe3ZhciB0LHMscixxLHAKaWYoZCl7dD1iLnkKaWYoIUguQTgoYikpaWYoIShiPT09dS5Q
+KSlpZih0IT09NylzPXQ9PT04JiZILmxSKGIueikKZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAK
+aWYocylyZXR1cm4gYgplbHNlIGlmKHQ9PT0xKXJldHVybiB1LlAKZWxzZSBpZih0PT09Nil7cj1iLnoK
+cT1yLnkKaWYocT09PTEpcmV0dXJuIHUuUAplbHNlIGlmKHE9PT04JiZILmxSKHIueikpcmV0dXJuIHIK
+ZWxzZSByZXR1cm4gSC5jeihhLGIpfX1wPW5ldyBILkpjKG51bGwsbnVsbCkKcC55PTcKcC56PWIKcC5j
+eT1jCnJldHVybiBILkJEKGEscCl9LApMTjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1iLmN5KyIvIixy
+PWEuZUMuZ2V0KHMpCmlmKHIhPW51bGwpcmV0dXJuIHIKdD1ILmVWKGEsYixzLGMpCmEuZUMuc2V0KHMs
+dCkKcmV0dXJuIHR9LAplVjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzCmlmKGQpe3Q9Yi55CmlmKEgu
+QTgoYil8fGI9PT11Lkt8fGI9PT11LkspcmV0dXJuIGIKZWxzZSBpZih0PT09MSlyZXR1cm4gSC5RMihh
+LCJiOCIsW2JdKQplbHNlIGlmKGI9PT11LlApcmV0dXJuIHUuYVF9cz1uZXcgSC5KYyhudWxsLG51bGwp
+CnMueT04CnMuej1iCnMuY3k9YwpyZXR1cm4gSC5CRChhLHMpfSwKSGM6ZnVuY3Rpb24oYSxiKXt2YXIg
+dCxzLHI9IiIrYisiXiIscT1hLmVDLmdldChyKQppZihxIT1udWxsKXJldHVybiBxCnQ9bmV3IEguSmMo
+bnVsbCxudWxsKQp0Lnk9MTMKdC56PWIKdC5jeT1yCnM9SC5CRChhLHQpCmEuZUMuc2V0KHIscykKcmV0
+dXJuIHN9LApVeDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmxlbmd0aApmb3IodD0iIixzPSIiLHI9
+MDtyPHE7KytyLHM9IiwiKXQrPXMrYVtyXS5jeQpyZXR1cm4gdH0sClM0OmZ1bmN0aW9uKGEpe3ZhciB0
+LHMscixxLHAsbz1hLmxlbmd0aApmb3IodD0iIixzPSIiLHI9MDtyPG87cis9MixzPSIsIil7cT1hW3Jd
+CnA9YVtyKzFdLmN5CnQrPXMrcSsiOiIrcH1yZXR1cm4gdH0sClEyOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzLHIscT1iCmlmKGMubGVuZ3RoIT09MClxKz0iPCIrSC5VeChjKSsiPiIKdD1hLmVDLmdldChxKQpp
+Zih0IT1udWxsKXJldHVybiB0CnM9bmV3IEguSmMobnVsbCxudWxsKQpzLnk9OQpzLno9YgpzLlE9Ywpp
+ZihjLmxlbmd0aD4wKXMuYz1jWzBdCnMuY3k9cQpyPUguQkQoYSxzKQphLmVDLnNldChxLHIpCnJldHVy
+biByfSwKYXA6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbwppZihiLnk9PT0xMCl7dD1iLnoK
+cz1iLlEuY29uY2F0KGMpfWVsc2V7cz1jCnQ9Yn1yPXQuY3krIjsiKygiPCIrSC5VeChzKSsiPiIpCnE9
+YS5lQy5nZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpwPW5ldyBILkpjKG51bGwsbnVsbCkKcC55PTEw
+CnAuej10CnAuUT1zCnAuY3k9cgpvPUguQkQoYSxwKQphLmVDLnNldChyLG8pCnJldHVybiBvfSwKTmY6
+ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHA9Yi5jeSxvPWMuYSxuPW8ubGVuZ3RoLG09Yy5iLGw9
+bS5sZW5ndGgsaz1jLmMsaj1rLmxlbmd0aCxpPSIoIitILlV4KG8pCmlmKGw+MClpKz0obj4wPyIsIjoi
+IikrIlsiK0guVXgobSkrIl0iCmlmKGo+MClpKz0obj4wPyIsIjoiIikrInsiK0guUzQoaykrIn0iCnQ9
+cCsoaSsiKSIpCnM9YS5lQy5nZXQodCkKaWYocyE9bnVsbClyZXR1cm4gcwpyPW5ldyBILkpjKG51bGws
+bnVsbCkKci55PTExCnIuej1iCnIuUT1jCnIuY3k9dApxPUguQkQoYSxyKQphLmVDLnNldCh0LHEpCnJl
+dHVybiBxfSwKRFM6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscz1iLmN5KyI8IitILlV4KGMpKyI+Iixy
+PWEuZUMuZ2V0KHMpCmlmKHIhPW51bGwpcmV0dXJuIHIKdD1ILmh3KGEsYixjLHMsZCkKYS5lQy5zZXQo
+cyx0KQpyZXR1cm4gdH0sCmh3OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscCxvLG4sbQpp
+ZihlKXt0PWMubGVuZ3RoCnM9bmV3IEFycmF5KHQpCmZvcihyPTAscT0wO3E8dDsrK3Epe3A9Y1txXQpp
+ZihwLnk9PT0xKXtzW3FdPXA7KytyfX1pZihyPjApe289SC5QTChhLGIscywwKQpuPUguYlooYSxjLHMs
+MCkKcmV0dXJuIEguRFMoYSxvLG4sYyE9PW4pfX1tPW5ldyBILkpjKG51bGwsbnVsbCkKbS55PTEyCm0u
+ej1iCm0uUT1jCm0uY3k9ZApyZXR1cm4gSC5CRChhLG0pfSwKbzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1
+cm57dTphLGU6YixyOmMsczpbXSxwOjAsbjpkfX0sCmk6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxv
+LG4sbSxsLGssaixpLGg9YS5yLGc9YS5zCmZvcih0PWgubGVuZ3RoLHM9MDtzPHQ7KXtyPWguY2hhckNv
+ZGVBdChzKQppZihyPj00OCYmcjw9NTcpcz1ILkFsKHMrMSxyLGgsZykKZWxzZSBpZigoKChyfDMyKT4+
+PjApLTk3JjY1NTM1KTwyNnx8cj09PTk1fHxyPT09MzYpcz1ILlI4KGEscyxoLGcsITEpCmVsc2UgaWYo
+cj09PTQ2KXM9SC5SOChhLHMsaCxnLCEwKQplbHNleysrcwpzd2l0Y2gocil7Y2FzZSA0NDpicmVhawpj
+YXNlIDU4OmJyZWFrCmNhc2UgNTk6Zy5wdXNoKEguS1EoYS51LGEuZSxnLnBvcCgpKSkKYnJlYWsKY2Fz
+ZSA5NDpnLnB1c2goSC5IYyhhLnUsZy5wb3AoKSkpCmJyZWFrCmNhc2UgMzU6Zy5wdXNoKEgubVooYS51
+LDUsIiMiKSkKYnJlYWsKY2FzZSA2NDpnLnB1c2goSC5tWihhLnUsMiwiQCIpKQpicmVhawpjYXNlIDEy
+NjpnLnB1c2goSC5tWihhLnUsMywifiIpKQpicmVhawpjYXNlIDYwOmcucHVzaChhLnApCmEucD1nLmxl
+bmd0aApicmVhawpjYXNlIDYyOnE9YS51CnA9Zy5zcGxpY2UoYS5wKQpILnJUKGEudSxhLmUscCkKYS5w
+PWcucG9wKCkKbz1nLnBvcCgpCmlmKHR5cGVvZiBvPT0ic3RyaW5nIilnLnB1c2goSC5RMihxLG8scCkp
+CmVsc2V7bj1ILktRKHEsYS5lLG8pCnN3aXRjaChuLnkpe2Nhc2UgMTE6Zy5wdXNoKEguRFMocSxuLHAs
+YS5uKSkKYnJlYWsKZGVmYXVsdDpnLnB1c2goSC5hcChxLG4scCkpCmJyZWFrfX1icmVhawpjYXNlIDM4
+OkguSTMoYSxnKQpicmVhawpjYXNlIDQyOm09YS51CmcucHVzaChILlNPKG0sSC5LUShtLGEuZSxnLnBv
+cCgpKSxhLm4pKQpicmVhawpjYXNlIDYzOm09YS51CmcucHVzaChILkJjKG0sSC5LUShtLGEuZSxnLnBv
+cCgpKSxhLm4pKQpicmVhawpjYXNlIDQ3Om09YS51CmcucHVzaChILkxOKG0sSC5LUShtLGEuZSxnLnBv
+cCgpKSxhLm4pKQpicmVhawpjYXNlIDQwOmcucHVzaChhLnApCmEucD1nLmxlbmd0aApicmVhawpjYXNl
+IDQxOnE9YS51Cmw9bmV3IEguRVQoKQprPXEuc0VBCmo9cS5zRUEKbz1nLnBvcCgpCmlmKHR5cGVvZiBv
+PT0ibnVtYmVyIilzd2l0Y2gobyl7Y2FzZS0xOms9Zy5wb3AoKQpicmVhawpjYXNlLTI6aj1nLnBvcCgp
+CmJyZWFrCmRlZmF1bHQ6Zy5wdXNoKG8pCmJyZWFrfWVsc2UgZy5wdXNoKG8pCnA9Zy5zcGxpY2UoYS5w
+KQpILnJUKGEudSxhLmUscCkKYS5wPWcucG9wKCkKbC5hPXAKbC5iPWsKbC5jPWoKZy5wdXNoKEguTmYo
+cSxILktRKHEsYS5lLGcucG9wKCkpLGwpKQpicmVhawpjYXNlIDkxOmcucHVzaChhLnApCmEucD1nLmxl
+bmd0aApicmVhawpjYXNlIDkzOnA9Zy5zcGxpY2UoYS5wKQpILnJUKGEudSxhLmUscCkKYS5wPWcucG9w
+KCkKZy5wdXNoKHApCmcucHVzaCgtMSkKYnJlYWsKY2FzZSAxMjM6Zy5wdXNoKGEucCkKYS5wPWcubGVu
+Z3RoCmJyZWFrCmNhc2UgMTI1OnA9Zy5zcGxpY2UoYS5wKQpILldTKGEudSxhLmUscCkKYS5wPWcucG9w
+KCkKZy5wdXNoKHApCmcucHVzaCgtMikKYnJlYWsKZGVmYXVsdDp0aHJvdyJCYWQgY2hhcmFjdGVyICIr
+cn19fWk9Zy5wb3AoKQpyZXR1cm4gSC5LUShhLnUsYS5lLGkpfSwKQWw6ZnVuY3Rpb24oYSxiLGMsZCl7
+dmFyIHQscyxyPWItNDgKZm9yKHQ9Yy5sZW5ndGg7YTx0OysrYSl7cz1jLmNoYXJDb2RlQXQoYSkKaWYo
+IShzPj00OCYmczw9NTcpKWJyZWFrCnI9cioxMCsocy00OCl9ZC5wdXNoKHIpCnJldHVybiBhfSwKUjg6
+ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG8sbj1iKzEKZm9yKHQ9Yy5sZW5ndGg7bjx0
+Oysrbil7cz1jLmNoYXJDb2RlQXQobikKaWYocz09PTQ2KXtpZihlKWJyZWFrCmU9ITB9ZWxzZXtpZigh
+KCgoKHN8MzIpPj4+MCktOTcmNjU1MzUpPDI2fHxzPT09OTV8fHM9PT0zNikpcj1zPj00OCYmczw9NTcK
+ZWxzZSByPSEwCmlmKCFyKWJyZWFrfX1xPWMuc3Vic3RyaW5nKGIsbikKaWYoZSl7dD1hLnUKcD1hLmUK
+aWYocC55PT09MTApcD1wLnoKbz1ILlFvKHQscC56KVtxXQppZihvPT1udWxsKUguVmooJ05vICInK3Er
+JyIgaW4gIicrSC5tRChwKSsnIicpCmQucHVzaChILmNFKHQscCxvKSl9ZWxzZSBkLnB1c2gocSkKcmV0
+dXJuIG59LApJMzpmdW5jdGlvbihhLGIpe3ZhciB0PWIucG9wKCkKaWYoMD09PXQpe2IucHVzaChILm1a
+KGEudSwxLCIwJiIpKQpyZXR1cm59aWYoMT09PXQpe2IucHVzaChILm1aKGEudSw0LCIxJiIpKQpyZXR1
+cm59dGhyb3cgSC5iKFAuaFYoIlVuZXhwZWN0ZWQgZXh0ZW5kZWQgb3BlcmF0aW9uICIrSC5kKHQpKSl9
+LApLUTpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGM9PSJzdHJpbmciKXJldHVybiBILlEyKGEsYyxh
+LnNFQSkKZWxzZSBpZih0eXBlb2YgYz09Im51bWJlciIpcmV0dXJuIEguVFYoYSxiLGMpCmVsc2UgcmV0
+dXJuIGN9LApyVDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1jLmxlbmd0aApmb3IodD0wO3Q8czsrK3Qp
+Y1t0XT1ILktRKGEsYixjW3RdKX0sCldTOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWMubGVuZ3RoCmZv
+cih0PTE7dDxzO3QrPTIpY1t0XT1ILktRKGEsYixjW3RdKX0sClRWOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzLHI9Yi55CmlmKHI9PT0xMCl7aWYoYz09PTApcmV0dXJuIGIuegp0PWIuUQpzPXQubGVuZ3RoCmlm
+KGM8PXMpcmV0dXJuIHRbYy0xXQpjLT1zCmI9Yi56CnI9Yi55fWVsc2UgaWYoYz09PTApcmV0dXJuIGIK
+aWYociE9PTkpdGhyb3cgSC5iKFAuaFYoIkluZGV4ZWQgYmFzZSBtdXN0IGJlIGFuIGludGVyZmFjZSB0
+eXBlIikpCnQ9Yi5RCmlmKGM8PXQubGVuZ3RoKXJldHVybiB0W2MtMV0KdGhyb3cgSC5iKFAuaFYoIkJh
+ZCBpbmRleCAiK2MrIiBmb3IgIitiLlooMCkpKX0sCldlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQs
+cyxyLHEscCxvLG4sbSxsLGsKaWYoYj09PWQpcmV0dXJuITAKaWYoSC5BOChkKXx8ZD09PXUuSylyZXR1
+cm4hMAp0PWIueQppZih0PT09NClyZXR1cm4hMAppZihILkE4KGIpKXJldHVybiExCmlmKGI9PT11LlAp
+cmV0dXJuITAKcz10PT09MTMKaWYocylpZihILldlKGEsY1tiLnpdLGMsZCxlKSlyZXR1cm4hMApyPWQu
+eQppZih0PT09NilyZXR1cm4gSC5XZShhLGIueixjLGQsZSkKaWYocj09PTYpe3E9ZC56CnJldHVybiBI
+LldlKGEsYixjLHEsZSl9aWYodD09PTgpe2lmKCFILldlKGEsYi56LGMsZCxlKSlyZXR1cm4hMQpyZXR1
+cm4gSC5XZShhLEgueFooYSxiKSxjLGQsZSl9aWYodD09PTcpe3E9SC5XZShhLGIueixjLGQsZSkKcmV0
+dXJuIHF9aWYocj09PTgpe2lmKEguV2UoYSxiLGMsZC56LGUpKXJldHVybiEwCnJldHVybiBILldlKGEs
+YixjLEgueFooYSxkKSxlKX1pZihyPT09Nyl7cT1ILldlKGEsYixjLGQueixlKQpyZXR1cm4gcX1pZihz
+KXJldHVybiExCnE9dCE9PTExCmlmKCghcXx8dD09PTEyKSYmZD09PXUuWilyZXR1cm4hMAppZihyPT09
+MTIpe2lmKGI9PT11LmcpcmV0dXJuITAKaWYodCE9PTEyKXJldHVybiExCnA9Yi5RCm89ZC5RCm49cC5s
+ZW5ndGgKaWYobiE9PW8ubGVuZ3RoKXJldHVybiExCmM9Yz09bnVsbD9wOnAuY29uY2F0KGMpCmU9ZT09
+bnVsbD9vOm8uY29uY2F0KGUpCmZvcihxPXUuYXYsbT0wO208bjsrK20pe2w9cFttXQprPW9bbV0KcS5h
+KGwpCnEuYShrKQppZighSC5XZShhLGwsYyxrLGUpfHwhSC5XZShhLGssZSxsLGMpKXJldHVybiExfXJl
+dHVybiBILmJPKGEsYi56LGMsZC56LGUpfWlmKHI9PT0xMSl7aWYoYj09PXUuZylyZXR1cm4hMAppZihx
+KXJldHVybiExCnJldHVybiBILmJPKGEsYixjLGQsZSl9aWYodD09PTkpe2lmKHIhPT05KXJldHVybiEx
+CnJldHVybiBILnBHKGEsYixjLGQsZSl9cmV0dXJuITF9LApiTzpmdW5jdGlvbihhMCxhMSxhMixhMyxh
+NCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYQppZighSC5XZShhMCxh
+MS56LGEyLGEzLnosYTQpKXJldHVybiExCnQ9YTEuUQpzPWEzLlEKcj10LmEKcT1zLmEKcD1yLmxlbmd0
+aApvPXEubGVuZ3RoCmlmKHA+bylyZXR1cm4hMQpuPW8tcAptPXQuYgpsPXMuYgprPW0ubGVuZ3RoCmo9
+bC5sZW5ndGgKaWYocCtrPG8railyZXR1cm4hMQpmb3IoaT0wO2k8cDsrK2kpe2g9cltpXQppZighSC5X
+ZShhMCxxW2ldLGE0LGgsYTIpKXJldHVybiExfWZvcihpPTA7aTxuOysraSl7aD1tW2ldCmlmKCFILldl
+KGEwLHFbcCtpXSxhNCxoLGEyKSlyZXR1cm4hMX1mb3IoaT0wO2k8ajsrK2kpe2g9bVtuK2ldCmlmKCFI
+LldlKGEwLGxbaV0sYTQsaCxhMikpcmV0dXJuITF9Zz10LmMKZj1zLmMKZT1nLmxlbmd0aApkPWYubGVu
+Z3RoCmZvcihpPTAsYz0wO2M8ZDtjKz0yKXtiPWZbY10KZG97aWYoaT49ZSlyZXR1cm4hMQphPWdbaV0K
+aSs9Mn13aGlsZShhPGIpCmlmKGI8YSlyZXR1cm4hMQpoPWdbaS0xXQppZighSC5XZShhMCxmW2MrMV0s
+YTQsaCxhMikpcmV0dXJuITF9cmV0dXJuITB9LApwRzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMs
+cixxLHAsbyxuLG0sbD1iLnosaz1kLnoKaWYobD09PWspe3Q9Yi5RCnM9ZC5RCnI9dC5sZW5ndGgKZm9y
+KHE9MDtxPHI7KytxKXtwPXRbcV0Kbz1zW3FdCmlmKCFILldlKGEscCxjLG8sZSkpcmV0dXJuITF9cmV0
+dXJuITB9aWYoZD09PXUuSylyZXR1cm4hMApuPUguUW8oYSxsKQppZihuPT1udWxsKXJldHVybiExCm09
+bltrXQppZihtPT1udWxsKXJldHVybiExCnI9bS5sZW5ndGgKcz1kLlEKZm9yKHE9MDtxPHI7KytxKWlm
+KCFILldlKGEsSC5jRShhLGIsbVtxXSksYyxzW3FdLGUpKXJldHVybiExCnJldHVybiEwfSwKbFI6ZnVu
+Y3Rpb24oYSl7dmFyIHQscz1hLnkKaWYoIShhPT09dS5QKSlpZighSC5BOChhKSlpZihzIT09NylpZigh
+KHM9PT02JiZILmxSKGEueikpKXQ9cz09PTgmJkgubFIoYS56KQplbHNlIHQ9ITAKZWxzZSB0PSEwCmVs
+c2UgdD0hMAplbHNlIHQ9ITAKcmV0dXJuIHR9LApjYzpmdW5jdGlvbihhKXtyZXR1cm4gSC5BOChhKXx8
+YT09PXUuS30sCkE4OmZ1bmN0aW9uKGEpe3ZhciB0LHM9YS55LHI9cwppZihyIT09MilpZihyIT09Mylp
+ZihyIT09NClpZihyIT09NSl7dD11LksKaWYoIShhPT09dCkpcz1zPT09NyYmYS56PT09dAplbHNlIHM9
+ITB9ZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEwCnJldHVybiBzfSwKSXg6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdCxzLHI9T2JqZWN0LmtleXMoYikscT1yLmxlbmd0aApmb3IodD0wO3Q8cTsr
+K3Qpe3M9clt0XQphW3NdPWJbc119fSwKSmM6ZnVuY3Rpb24gSmMoYSxiKXt2YXIgXz10aGlzCl8uYT1h
+Cl8uYj1iCl8ueD1fLnI9Xy5jPW51bGwKXy55PTAKXy5jeT1fLmN4PV8uY2g9Xy5RPV8uej1udWxsfSwK
+RVQ6ZnVuY3Rpb24gRVQoKXt0aGlzLmM9dGhpcy5iPXRoaXMuYT1udWxsfSwKa1M6ZnVuY3Rpb24ga1Mo
+KXt9LAp4OmZ1bmN0aW9uIHgoYSl7dGhpcy5hPWF9LApSOTpmdW5jdGlvbihhKXtyZXR1cm4gdS5kLmIo
+YSl8fHUuQi5iKGEpfHx1LmR6LmIoYSl8fHUuSS5iKGEpfHx1LkEuYihhKXx8dS5nNC5iKGEpfHx1Lmcy
+LmIoYSl9LApKZzpmdW5jdGlvbihhKXtyZXR1cm4gdi5tYW5nbGVkR2xvYmFsTmFtZXNbYV19fSxKPXsK
+UXU6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJue2k6YSxwOmIsZTpjLHg6ZH19LAprczpmdW5jdGlvbihh
+KXt2YXIgdCxzLHIscSxwPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0KaWYocD09bnVsbClpZigkLks9
+PW51bGwpe0guTSgpCnA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXX1pZihwIT1udWxsKXt0PXAucApp
+ZighMT09PXQpcmV0dXJuIHAuaQppZighMD09PXQpcmV0dXJuIGEKcz1PYmplY3QuZ2V0UHJvdG90eXBl
+T2YoYSkKaWYodD09PXMpcmV0dXJuIHAuaQppZihwLmU9PT1zKXRocm93IEguYihQLm4oIlJldHVybiBp
+bnRlcmNlcHRvciBmb3IgIitILmQodChhLHApKSkpfXI9YS5jb25zdHJ1Y3RvcgpxPXI9PW51bGw/bnVs
+bDpyWyQuQSgpXQppZihxIT1udWxsKXJldHVybiBxCnE9SC5HKGEpCmlmKHEhPW51bGwpcmV0dXJuIHEK
+aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEMuREcKdD1PYmplY3QuZ2V0UHJvdG90eXBlT2Yo
+YSkKaWYodD09bnVsbClyZXR1cm4gQy5aUQppZih0PT09T2JqZWN0LnByb3RvdHlwZSlyZXR1cm4gQy5a
+UQppZih0eXBlb2Ygcj09ImZ1bmN0aW9uIil7T2JqZWN0LmRlZmluZVByb3BlcnR5KHIsJC5BKCkse3Zh
+bHVlOkMudkIsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkK
+cmV0dXJuIEMudkJ9cmV0dXJuIEMudkJ9LApRaTpmdW5jdGlvbihhLGIpe2lmKGE8MHx8YT40Mjk0OTY3
+Mjk1KXRocm93IEguYihQLlRFKGEsMCw0Mjk0OTY3Mjk1LCJsZW5ndGgiLG51bGwpKQpyZXR1cm4gSi5w
+eShuZXcgQXJyYXkoYSksYil9LApweTpmdW5jdGlvbihhLGIpe3JldHVybiBKLkVwKEguVk0oYSxiLkMo
+ImpkPDA+IikpKX0sCkVwOmZ1bmN0aW9uKGEpe2EuZml4ZWQkbGVuZ3RoPUFycmF5CnJldHVybiBhfSwK
+dW46ZnVuY3Rpb24oYSl7YS5maXhlZCRsZW5ndGg9QXJyYXkKYS5pbW11dGFibGUkbGlzdD1BcnJheQpy
+ZXR1cm4gYX0sCkdhOmZ1bmN0aW9uKGEpe2lmKGE8MjU2KXN3aXRjaChhKXtjYXNlIDk6Y2FzZSAxMDpj
+YXNlIDExOmNhc2UgMTI6Y2FzZSAxMzpjYXNlIDMyOmNhc2UgMTMzOmNhc2UgMTYwOnJldHVybiEwCmRl
+ZmF1bHQ6cmV0dXJuITF9c3dpdGNoKGEpe2Nhc2UgNTc2MDpjYXNlIDgxOTI6Y2FzZSA4MTkzOmNhc2Ug
+ODE5NDpjYXNlIDgxOTU6Y2FzZSA4MTk2OmNhc2UgODE5NzpjYXNlIDgxOTg6Y2FzZSA4MTk5OmNhc2Ug
+ODIwMDpjYXNlIDgyMDE6Y2FzZSA4MjAyOmNhc2UgODIzMjpjYXNlIDgyMzM6Y2FzZSA4MjM5OmNhc2Ug
+ODI4NzpjYXNlIDEyMjg4OmNhc2UgNjUyNzk6cmV0dXJuITAKZGVmYXVsdDpyZXR1cm4hMX19LAptbTpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMKZm9yKHQ9YS5sZW5ndGg7Yjx0Oyl7cz1DLnhCLldkKGEsYikKaWYo
+cyE9PTMyJiZzIT09MTMmJiFKLkdhKHMpKWJyZWFrOysrYn1yZXR1cm4gYn0sCmMxOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQscwpmb3IoO2I+MDtiPXQpe3Q9Yi0xCnM9Qy54Qi5PMihhLHQpCmlmKHMhPT0zMiYmcyE9
+PTEzJiYhSi5HYShzKSlicmVha31yZXR1cm4gYn0sClJFOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0
+dXJuIGEKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4g
+Si5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJu
+IEoua3MoYSl9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEoucUku
+cHJvdG90eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09
+bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUK
 aWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5w
 cm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3Mo
-YSl9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEoucUkucHJvdG90
-eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVsbCly
-ZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlw
-ZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5
-cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApV
-NjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlm
-KGE9PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90
-eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEou
-YzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJldHVybiBK
-LmtzKGEpfSwKaWE6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXtpZihNYXRoLmZsb29y
-KGEpPT1hKXJldHVybiBKLnVyLnByb3RvdHlwZQpyZXR1cm4gSi5WQS5wcm90b3R5cGV9aWYodHlwZW9m
-IGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBKLllFLnBy
-b3RvdHlwZQppZih0eXBlb2YgYT09ImJvb2xlYW4iKXJldHVybiBKLnlFLnByb3RvdHlwZQppZihhLmNv
-bnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3Qi
-KXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYo
-YSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlvbihhKXtp
-Zih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJu
-IGEKaWYoIShhIGluc3RhbmNlb2YgUC5NaCkpcmV0dXJuIEoua2QucHJvdG90eXBlCnJldHVybiBhfSwK
-dzE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSly
-ZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1
-bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgp
-cmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApBYzpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS5aKGEp
-fSwKQ006ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuZHUoYSxiLGMsZCl9LApGTDpmdW5j
-dGlvbihhLGIpe3JldHVybiBKLnJZKGEpLmRkKGEsYil9LApHQTpmdW5jdGlvbihhLGIpe3JldHVybiBK
-LncxKGEpLkUoYSxiKX0sCkdyOmZ1bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLmdtVyhhKX0sCkg6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIEouVTYoYSkuZ0EoYSl9LApJVDpmdW5jdGlvbihhKXtyZXR1cm4gSi53MShh
-KS5na3ooYSl9LApKeTpmdW5jdGlvbihhLGIpe3JldHVybiBKLmlhKGEpLmU3KGEsYil9LApLVjpmdW5j
-dGlvbihhLGIpe3JldHVybiBKLnJZKGEpLkcoYSxiKX0sCkx0OmZ1bmN0aW9uKGEpe3JldHVybiBKLlJF
-KGEpLndnKGEpfSwKTTE6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLncxKGEpLkUyKGEsYixjKX0sClF6
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclkoYSkuVyhhLGIpfSwKUk06ZnVuY3Rpb24oYSxiKXtpZihh
-PT1udWxsKXJldHVybiBiPT1udWxsCmlmKHR5cGVvZiBhIT0ib2JqZWN0IilyZXR1cm4gYiE9bnVsbCYm
-YT09PWIKcmV0dXJuIEouaWEoYSkuRE4oYSxiKX0sClQwOmZ1bmN0aW9uKGEpe3JldHVybiBKLnJZKGEp
-LmJTKGEpfSwKYTY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5tKGEsYil9LApiVDpmdW5jdGlv
-bihhKXtyZXR1cm4gSi5SRShhKS5ENChhKX0sCmNIOmZ1bmN0aW9uKGEpe3JldHVybiBKLnJZKGEpLmhj
-KGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkuZ0QoYSl9LApkWjpmdW5jdGlvbihhLGIs
-YyxkKXtyZXR1cm4gSi5SRShhKS5PbihhLGIsYyxkKX0sCmRnOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVy
-biBKLnJZKGEpLmk3KGEsYixjLGQpfSwKZGg6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkudG4oYSl9
-LApoZjpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS5naU8oYSl9LAppZzpmdW5jdGlvbihhKXtyZXR1
-cm4gSi5SRShhKS5nUWcoYSl9LApsNTpmdW5jdGlvbihhLGIpe3JldHVybiBKLlJFKGEpLnNoZihhLGIp
-fSwKbGQ6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZKGEpLncoYSxiLGMpfSwKbTpmdW5jdGlvbihh
-LGIpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmdHlwZW9mIGI9PSJudW1iZXIiKXJldHVybiBhK2IKcmV0
-dXJuIEouVEooYSkuaChhLGIpfSwKcDQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5UYyhhLGIp
-fSwKcTA6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZKGEpLlFpKGEsYixjKX0sCnFGOmZ1bmN0aW9u
-KGEpe3JldHVybiBKLlJFKGEpLmdWbChhKX0sCnRIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5SRShh
-KS5wayhhLGIsYyl9LAp4OTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiPT09Im51bWJlciIpaWYoYS5j
-b25zdHJ1Y3Rvcj09QXJyYXl8fHR5cGVvZiBhPT0ic3RyaW5nInx8SC53VihhLGFbdi5kaXNwYXRjaFBy
-b3BlcnR5TmFtZV0pKWlmKGI+Pj4wPT09YiYmYjxhLmxlbmd0aClyZXR1cm4gYVtiXQpyZXR1cm4gSi5V
-NihhKS5xKGEsYil9LAp6bDpmdW5jdGlvbihhLGIpe3JldHVybiBKLlU2KGEpLnRnKGEsYil9LAp2Qjpm
-dW5jdGlvbiB2Qigpe30sCnlFOmZ1bmN0aW9uIHlFKCl7fSwKWUU6ZnVuY3Rpb24gWUUoKXt9LApNRjpm
-dW5jdGlvbiBNRigpe30sCmlDOmZ1bmN0aW9uIGlDKCl7fSwKa2Q6ZnVuY3Rpb24ga2QoKXt9LApjNTpm
-dW5jdGlvbiBjNSgpe30sCmpkOmZ1bmN0aW9uIGpkKGEpe3RoaXMuJHRpPWF9LApQbzpmdW5jdGlvbiBQ
-byhhKXt0aGlzLiR0aT1hfSwKbTE6ZnVuY3Rpb24gbTEoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
-PWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCnFJOmZ1bmN0aW9uIHFJKCl7fSwKdXI6ZnVuY3Rpb24g
-dXIoKXt9LApWQTpmdW5jdGlvbiBWQSgpe30sCkRyOmZ1bmN0aW9uIERyKCl7fX0sUD17Ck9qOmZ1bmN0
-aW9uKCl7dmFyIHQscyxyPXt9CmlmKHNlbGYuc2NoZWR1bGVJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAu
-RVgoKQppZihzZWxmLk11dGF0aW9uT2JzZXJ2ZXIhPW51bGwmJnNlbGYuZG9jdW1lbnQhPW51bGwpe3Q9
-c2VsZi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKQpzPXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxl
-bWVudCgic3BhbiIpCnIuYT1udWxsCm5ldyBzZWxmLk11dGF0aW9uT2JzZXJ2ZXIoSC50UihuZXcgUC50
-aChyKSwxKSkub2JzZXJ2ZSh0LHtjaGlsZExpc3Q6dHJ1ZX0pCnJldHVybiBuZXcgUC5oYShyLHQscyl9
-ZWxzZSBpZihzZWxmLnNldEltbWVkaWF0ZSE9bnVsbClyZXR1cm4gUC55dCgpCnJldHVybiBQLnFXKCl9
-LApaVjpmdW5jdGlvbihhKXtzZWxmLnNjaGVkdWxlSW1tZWRpYXRlKEgudFIobmV3IFAuVnModS5NLmEo
-YSkpLDApKX0sCm9BOmZ1bmN0aW9uKGEpe3NlbGYuc2V0SW1tZWRpYXRlKEgudFIobmV3IFAuRnQodS5N
-LmEoYSkpLDApKX0sCkJ6OmZ1bmN0aW9uKGEpe3UuTS5hKGEpClAuUU4oMCxhKX0sClFOOmZ1bmN0aW9u
-KGEsYil7dmFyIHQ9bmV3IFAuVzMoKQp0LkNZKGEsYikKcmV0dXJuIHR9LApGWDpmdW5jdGlvbihhKXty
-ZXR1cm4gbmV3IFAuaWgobmV3IFAudnMoJC5YMyxhLkMoInZzPDA+IikpLGEuQygiaWg8MD4iKSl9LApE
-STpmdW5jdGlvbihhLGIpe2EuJDIoMCxudWxsKQpiLmI9ITAKcmV0dXJuIGIuYX0sCmpROmZ1bmN0aW9u
-KGEsYil7UC5KZShhLGIpfSwKeUM6ZnVuY3Rpb24oYSxiKXtiLmFNKDAsYSl9LApmMzpmdW5jdGlvbihh
-LGIpe2IudzAoSC5SdShhKSxILnRzKGEpKX0sCkplOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPW5ldyBQ
-LldNKGIpLHE9bmV3IFAuU1goYikKaWYoYSBpbnN0YW5jZW9mIFAudnMpYS5RZChyLHEsdS56KQplbHNl
-e3Q9dS56CmlmKHUuYy5iKGEpKWEuU3EocixxLHQpCmVsc2V7cz1uZXcgUC52cygkLlgzLHUuXykKcy5h
-PTQKcy5jPWEKcy5RZChyLHEsdCl9fX0sCmx6OmZ1bmN0aW9uKGEpe3ZhciB0PWZ1bmN0aW9uKGIsYyl7
-cmV0dXJuIGZ1bmN0aW9uKGQsZSl7d2hpbGUodHJ1ZSl0cnl7YihkLGUpCmJyZWFrfWNhdGNoKHMpe2U9
-cwpkPWN9fX0oYSwxKQpyZXR1cm4gJC5YMy5MaihuZXcgUC5Hcyh0KSx1LlAsdS5TLHUueil9LApHUTpm
-dW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuRnkoYSwxKX0sClRoOmZ1bmN0aW9uKCl7cmV0dXJuIEMud1F9
-LApZbTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuRnkoYSwzKX0sCmwwOmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIG5ldyBQLnE0KGEsYi5DKCJxNDwwPiIpKX0sCmszOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmIu
-YT0xCnRyeXthLlNxKG5ldyBQLnBWKGIpLG5ldyBQLlU3KGIpLHUuUCl9Y2F0Y2gocil7dD1ILlJ1KHIp
-CnM9SC50cyhyKQpQLnJiKG5ldyBQLnZyKGIsdCxzKSl9fSwKQTk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
-LHIKZm9yKHQ9dS5fO3M9YS5hLHM9PT0yOylhPXQuYShhLmMpCmlmKHM+PTQpe3I9Yi5haCgpCmIuYT1h
-LmEKYi5jPWEuYwpQLkhaKGIscil9ZWxzZXtyPXUueC5hKGIuYykKYi5hPTIKYi5jPWEKYS5qUShyKX19
-LApIWjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlPW51bGws
-ZD17fSxjPWQuYT1hCmZvcih0PXUubixzPXUueCxyPXUuYzshMDspe3E9e30KcD1jLmE9PT04CmlmKGI9
-PW51bGwpe2lmKHApe289dC5hKGMuYykKUC5MMihlLGUsYy5iLG8uYSxvLmIpfXJldHVybn1mb3IoO249
-Yi5hLG4hPW51bGw7Yj1uKXtiLmE9bnVsbApQLkhaKGQuYSxiKX1jPWQuYQptPWMuYwpxLmE9cApxLmI9
-bQpsPSFwCmlmKGwpe2s9Yi5jCms9KGsmMSkhPT0wfHwoayYxNSk9PT04fWVsc2Ugaz0hMAppZihrKXtr
-PWIuYgpqPWsuYgppZihwKXtpPWMuYj09PWoKaT0hKGl8fGkpfWVsc2UgaT0hMQppZihpKXt0LmEobSkK
-UC5MMihlLGUsYy5iLG0uYSxtLmIpCnJldHVybn1oPSQuWDMKaWYoaCE9PWopJC5YMz1qCmVsc2UgaD1l
-CmM9Yi5jCmlmKChjJjE1KT09PTgpbmV3IFAuUlQoZCxxLGIscCkuJDAoKQplbHNlIGlmKGwpe2lmKChj
-JjEpIT09MCluZXcgUC5ycShxLGIsbSkuJDAoKX1lbHNlIGlmKChjJjIpIT09MCluZXcgUC5SVyhkLHEs
-YikuJDAoKQppZihoIT1udWxsKSQuWDM9aApjPXEuYgppZihyLmIoYykpe2lmKGMuYT49NCl7Zz1zLmEo
-ay5jKQprLmM9bnVsbApiPWsuTjgoZykKay5hPWMuYQprLmM9Yy5jCmQuYT1jCmNvbnRpbnVlfWVsc2Ug
-UC5BOShjLGspCnJldHVybn19Zj1iLmIKZz1zLmEoZi5jKQpmLmM9bnVsbApiPWYuTjgoZykKYz1xLmEK
-bD1xLmIKaWYoIWMpe2YuJHRpLmMuYShsKQpmLmE9NApmLmM9bH1lbHNle3QuYShsKQpmLmE9OApmLmM9
-bH1kLmE9ZgpjPWZ9fSwKVkg6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZih1LmFnLmIoYSkpcmV0dXJuIGIu
-TGooYSx1LnosdS5LLHUubCkKdD11LkYKaWYodC5iKGEpKXJldHVybiB0LmEoYSkKdGhyb3cgSC5iKFAu
-TDMoYSwib25FcnJvciIsIkVycm9yIGhhbmRsZXIgbXVzdCBhY2NlcHQgb25lIE9iamVjdCBvciBvbmUg
-T2JqZWN0IGFuZCBhIFN0YWNrVHJhY2UgYXMgYXJndW1lbnRzLCBhbmQgcmV0dXJuIGEgYSB2YWxpZCBy
-ZXN1bHQiKSl9LApwdTpmdW5jdGlvbigpe3ZhciB0LHMKZm9yKDt0PSQuUzYsdCE9bnVsbDspeyQubWc9
-bnVsbApzPXQuYgokLlM2PXMKaWYocz09bnVsbCkkLms4PW51bGwKdC5hLiQwKCl9fSwKZU46ZnVuY3Rp
-b24oKXskLlVEPSEwCnRyeXtQLnB1KCl9ZmluYWxseXskLm1nPW51bGwKJC5VRD0hMQppZigkLlM2IT1u
-dWxsKSQudXQoKS4kMShQLlY5KCkpfX0sCmVXOmZ1bmN0aW9uKGEpe3ZhciB0PW5ldyBQLk9NKGEpCmlm
-KCQuUzY9PW51bGwpeyQuUzY9JC5rOD10CmlmKCEkLlVEKSQudXQoKS4kMShQLlY5KCkpfWVsc2UgJC5r
-OD0kLms4LmI9dH0sCnJSOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj0kLlM2CmlmKHI9PW51bGwpe1AuZVco
-YSkKJC5tZz0kLms4CnJldHVybn10PW5ldyBQLk9NKGEpCnM9JC5tZwppZihzPT1udWxsKXt0LmI9cgok
-LlM2PSQubWc9dH1lbHNle3QuYj1zLmIKJC5tZz1zLmI9dAppZih0LmI9PW51bGwpJC5rOD10fX0sCnJi
-OmZ1bmN0aW9uKGEpe3ZhciB0PW51bGwscz0kLlgzCmlmKEMuTlU9PT1zKXtQLlRrKHQsdCxDLk5VLGEp
-CnJldHVybn1QLlRrKHQsdCxzLHUuTS5hKHMuR1koYSkpKX0sClF3OmZ1bmN0aW9uKGEsYil7aWYoYT09
-bnVsbClILnZoKFAuRWUoInN0cmVhbSIpKQpyZXR1cm4gbmV3IFAueEkoYi5DKCJ4STwwPiIpKX0sClRs
-OmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yj09bnVsbD9QLnYwKGEpOmIKUC5VSShhLCJlcnJvciIsdS5LKQpy
-ZXR1cm4gbmV3IFAuT0goYSx0KX0sCnYwOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKHUuVy5iKGEpKXt0PWEu
-Z0lJKCkKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gQy5wZH0sCkwyOmZ1bmN0aW9uKGEsYixjLGQs
-ZSl7dmFyIHQ9e30KdC5hPWQKdC5iPWUKaWYoZD09bnVsbCl7dC5hPW5ldyBQLkFUKCExLG51bGwsImVy
-cm9yIiwiTXVzdCBub3QgYmUgbnVsbCIpCnQuYj1QLlpiKCl9UC5yUihuZXcgUC5wSyh0KSl9LApUODpm
-dW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMCgpCiQuWDM9
-Ywp0PXMKdHJ5e3M9ZC4kMCgpCnJldHVybiBzfWZpbmFsbHl7JC5YMz10fX0sCnl2OmZ1bmN0aW9uKGEs
-YixjLGQsZSxmLGcpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMShlKQokLlgzPWMKdD1z
-CnRyeXtzPWQuJDEoZSkKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwKUXg6ZnVuY3Rpb24oYSxiLGMs
-ZCxlLGYsZyxoLGkpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMihlLGYpCiQuWDM9Ywp0
-PXMKdHJ5e3M9ZC4kMihlLGYpCnJldHVybiBzfWZpbmFsbHl7JC5YMz10fX0sClRrOmZ1bmN0aW9uKGEs
-YixjLGQpe3ZhciB0CnUuTS5hKGQpCnQ9Qy5OVSE9PWMKaWYodClkPSEoIXR8fCExKT9jLkdZKGQpOmMu
-UlQoZCx1LkgpClAuZVcoZCl9LAp0aDpmdW5jdGlvbiB0aChhKXt0aGlzLmE9YX0sCmhhOmZ1bmN0aW9u
-IGhhKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClZzOmZ1bmN0aW9uIFZzKGEpe3Ro
-aXMuYT1hfSwKRnQ6ZnVuY3Rpb24gRnQoYSl7dGhpcy5hPWF9LApXMzpmdW5jdGlvbiBXMygpe30sCnlI
-OmZ1bmN0aW9uIHlIKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAppaDpmdW5jdGlvbiBpaChhLGIpe3Ro
-aXMuYT1hCnRoaXMuYj0hMQp0aGlzLiR0aT1ifSwKV006ZnVuY3Rpb24gV00oYSl7dGhpcy5hPWF9LApT
-WDpmdW5jdGlvbiBTWChhKXt0aGlzLmE9YX0sCkdzOmZ1bmN0aW9uIEdzKGEpe3RoaXMuYT1hfSwKRnk6
-ZnVuY3Rpb24gRnkoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkdWOmZ1bmN0aW9uIEdWKGEsYil7dmFy
-IF89dGhpcwpfLmE9YQpfLmQ9Xy5jPV8uYj1udWxsCl8uJHRpPWJ9LApxNDpmdW5jdGlvbiBxNChhLGIp
-e3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApiODpmdW5jdGlvbiBiOCgpe30sClBmOmZ1bmN0aW9uIFBmKCl7
-fSwKWmY6ZnVuY3Rpb24gWmYoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKRmU6ZnVuY3Rpb24gRmUo
-YSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uYT1udWxsCl8uYj1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uJHRp
-PWV9LAp2czpmdW5jdGlvbiB2cyhhLGIpe3ZhciBfPXRoaXMKXy5hPTAKXy5iPWEKXy5jPW51bGwKXy4k
-dGk9Yn0sCmRhOmZ1bmN0aW9uIGRhKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApvUTpmdW5jdGlvbiBv
-UShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKcFY6ZnVuY3Rpb24gcFYoYSl7dGhpcy5hPWF9LApVNzpm
-dW5jdGlvbiBVNyhhKXt0aGlzLmE9YX0sCnZyOmZ1bmN0aW9uIHZyKGEsYixjKXt0aGlzLmE9YQp0aGlz
-LmI9Ygp0aGlzLmM9Y30sCnJIOmZ1bmN0aW9uIHJIKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLRjpm
-dW5jdGlvbiBLRihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWkw6ZnVuY3Rpb24gWkwoYSxiLGMpe3Ro
-aXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKUlQ6ZnVuY3Rpb24gUlQoYSxiLGMsZCl7dmFyIF89dGhp
-cwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmpaOmZ1bmN0aW9uIGpaKGEpe3RoaXMuYT1hfSwKcnE6
-ZnVuY3Rpb24gcnEoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKUlc6ZnVuY3Rpb24g
-UlcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKT006ZnVuY3Rpb24gT00oYSl7dGhp
-cy5hPWEKdGhpcy5iPW51bGx9LApxaDpmdW5jdGlvbiBxaCgpe30sCkI1OmZ1bmN0aW9uIEI1KGEsYil7
-dGhpcy5hPWEKdGhpcy5iPWJ9LApQSTpmdW5jdGlvbiBQSShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwK
-TU86ZnVuY3Rpb24gTU8oKXt9LAprVDpmdW5jdGlvbiBrVCgpe30sCnhJOmZ1bmN0aW9uIHhJKGEpe3Ro
-aXMuJHRpPWF9LApPSDpmdW5jdGlvbiBPSChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKbTA6ZnVuY3Rp
-b24gbTAoKXt9LApwSzpmdW5jdGlvbiBwSyhhKXt0aGlzLmE9YX0sCkppOmZ1bmN0aW9uIEppKCl7fSwK
-aGo6ZnVuY3Rpb24gaGooYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKVnA6ZnVuY3Rp
-b24gVnAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk9SOmZ1bmN0aW9uIE9SKGEsYixjKXt0aGlzLmE9
-YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCkVGOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYi5DKCJAPDA+Iiku
-S3EoYykuQygiRm88MSwyPiIpLmEoSC5CNyhhLG5ldyBILk41KGIuQygiQDwwPiIpLktxKGMpLkMoIk41
-PDEsMj4iKSkpKX0sCkZsOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILk41KGEuQygiQDwwPiIpLktx
-KGIpLkMoIk41PDEsMj4iKSl9LApMczpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuYjYoYS5DKCJiNjww
-PiIpKX0sClQyOmZ1bmN0aW9uKCl7dmFyIHQ9T2JqZWN0LmNyZWF0ZShudWxsKQp0WyI8bm9uLWlkZW50
-aWZpZXIta2V5PiJdPXQKZGVsZXRlIHRbIjxub24taWRlbnRpZmllci1rZXk+Il0KcmV0dXJuIHR9LApy
-ajpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9bmV3IFAubG0oYSxiLGMuQygibG08MD4iKSkKdC5jPWEuZQpy
-ZXR1cm4gdH0sCkVQOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzCmlmKFAuaEIoYSkpe2lmKGI9PT0iKCIm
-JmM9PT0iKSIpcmV0dXJuIiguLi4pIgpyZXR1cm4gYisiLi4uIitjfXQ9SC5WTShbXSx1LnMpCkMuTm0u
-aSgkLnhnLGEpCnRyeXtQLlZyKGEsdCl9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5r
-KCQueGcsLTEpCiQueGcucG9wKCl9cz1QLnZnKGIsdS5SLmEodCksIiwgIikrYwpyZXR1cm4gcy5jaGFy
-Q29kZUF0KDApPT0wP3M6c30sCldFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzCmlmKFAuaEIoYSkpcmV0
-dXJuIGIrIi4uLiIrYwp0PW5ldyBQLlJuKGIpCkMuTm0uaSgkLnhnLGEpCnRyeXtzPXQKcy5hPVAudmco
-cy5hLGEsIiwgIil9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5rKCQueGcsLTEpCiQu
-eGcucG9wKCl9dC5hKz1jCnM9dC5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKaEI6ZnVu
-Y3Rpb24oYSl7dmFyIHQscwpmb3IodD0kLnhnLmxlbmd0aCxzPTA7czx0OysrcylpZihhPT09JC54Z1tz
-XSlyZXR1cm4hMApyZXR1cm4hMX0sClZyOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbT1h
-LmdreihhKSxsPTAsaz0wCndoaWxlKCEwKXtpZighKGw8ODB8fGs8MykpYnJlYWsKaWYoIW0uRigpKXJl
-dHVybgp0PUguZChtLmdsKCkpCkMuTm0uaShiLHQpCmwrPXQubGVuZ3RoKzI7KytrfWlmKCFtLkYoKSl7
-aWYoazw9NSlyZXR1cm4KaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguayhiLC0xKQpzPWIucG9wKCkKaWYo
-MD49Yi5sZW5ndGgpcmV0dXJuIEguayhiLC0xKQpyPWIucG9wKCl9ZWxzZXtxPW0uZ2woKTsrK2sKaWYo
-IW0uRigpKXtpZihrPD00KXtDLk5tLmkoYixILmQocSkpCnJldHVybn1zPUguZChxKQppZigwPj1iLmxl
-bmd0aClyZXR1cm4gSC5rKGIsLTEpCnI9Yi5wb3AoKQpsKz1zLmxlbmd0aCsyfWVsc2V7cD1tLmdsKCk7
-KytrCmZvcig7bS5GKCk7cT1wLHA9byl7bz1tLmdsKCk7KytrCmlmKGs+MTAwKXt3aGlsZSghMCl7aWYo
-IShsPjc1JiZrPjMpKWJyZWFrCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILmsoYiwtMSkKbC09Yi5wb3Ao
-KS5sZW5ndGgrMjstLWt9Qy5ObS5pKGIsIi4uLiIpCnJldHVybn19cj1ILmQocSkKcz1ILmQocCkKbCs9
-cy5sZW5ndGgrci5sZW5ndGgrNH19aWYoaz5iLmxlbmd0aCsyKXtsKz01Cm49Ii4uLiJ9ZWxzZSBuPW51
-bGwKd2hpbGUoITApe2lmKCEobD44MCYmYi5sZW5ndGg+MykpYnJlYWsKaWYoMD49Yi5sZW5ndGgpcmV0
-dXJuIEguayhiLC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyCmlmKG49PW51bGwpe2wrPTUKbj0iLi4uIn19
-aWYobiE9bnVsbClDLk5tLmkoYixuKQpDLk5tLmkoYixyKQpDLk5tLmkoYixzKX0sCnRNOmZ1bmN0aW9u
-KGEsYil7dmFyIHQscyxyPVAuTHMoYikKZm9yKHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5ndGg7YS5sZW5n
-dGg9PT10fHwoMCxILmxrKShhKSwrK3Mpci5pKDAsYi5hKGFbc10pKQpyZXR1cm4gcn0sCm5POmZ1bmN0
-aW9uKGEpe3ZhciB0LHM9e30KaWYoUC5oQihhKSlyZXR1cm4iey4uLn0iCnQ9bmV3IFAuUm4oIiIpCnRy
-eXtDLk5tLmkoJC54ZyxhKQp0LmErPSJ7IgpzLmE9ITAKYS5LKDAsbmV3IFAucmEocyx0KSkKdC5hKz0i
-fSJ9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5rKCQueGcsLTEpCiQueGcucG9wKCl9
-cz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApiNjpmdW5jdGlvbiBiNihhKXt2YXIg
-Xz10aGlzCl8uYT0wCl8uZj1fLmU9Xy5kPV8uYz1fLmI9bnVsbApfLnI9MApfLiR0aT1hfSwKYm46ZnVu
-Y3Rpb24gYm4oYSl7dGhpcy5hPWEKdGhpcy5jPXRoaXMuYj1udWxsfSwKbG06ZnVuY3Rpb24gbG0oYSxi
-LGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsCl8uJHRpPWN9LAptVzpmdW5jdGlv
-biBtVygpe30sCkxVOmZ1bmN0aW9uIExVKCl7fSwKbEQ6ZnVuY3Rpb24gbEQoKXt9LAppbDpmdW5jdGlv
-biBpbCgpe30sCnJhOmZ1bmN0aW9uIHJhKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApZazpmdW5jdGlv
-biBZaygpe30sCnlROmZ1bmN0aW9uIHlRKGEpe3RoaXMuYT1hfSwKS1A6ZnVuY3Rpb24gS1AoKXt9LApQ
-bjpmdW5jdGlvbiBQbigpe30sCkdqOmZ1bmN0aW9uIEdqKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0s
-Ck1hOmZ1bmN0aW9uIE1hKCl7fSwKVmo6ZnVuY3Rpb24gVmooKXt9LApYdjpmdW5jdGlvbiBYdigpe30s
-Cm5ZOmZ1bmN0aW9uIG5ZKCl7fSwKVEM6ZnVuY3Rpb24gVEMoKXt9LApSVTpmdW5jdGlvbiBSVSgpe30s
-CkJTOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKaWYodHlwZW9mIGEhPSJzdHJpbmciKXRocm93IEgu
-YihILkkoYSkpCnQ9bnVsbAp0cnl7dD1KU09OLnBhcnNlKGEpfWNhdGNoKHIpe3M9SC5SdShyKQpxPVAu
-cnIoU3RyaW5nKHMpLG51bGwsbnVsbCkKdGhyb3cgSC5iKHEpfXE9UC5RZSh0KQpyZXR1cm4gcX0sClFl
-OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYodHlwZW9mIGEhPSJvYmpl
-Y3QiKXJldHVybiBhCmlmKE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSE9PUFycmF5LnByb3RvdHlwZSly
-ZXR1cm4gbmV3IFAudXcoYSxPYmplY3QuY3JlYXRlKG51bGwpKQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0
-KWFbdF09UC5RZShhW3RdKQpyZXR1cm4gYX0sCmt5OmZ1bmN0aW9uKGEsYixjLGQpe2lmKGIgaW5zdGFu
-Y2VvZiBVaW50OEFycmF5KXJldHVybiBQLlJQKCExLGIsYyxkKQpyZXR1cm4gbnVsbH0sClJQOmZ1bmN0
-aW9uKGEsYixjLGQpe3ZhciB0LHMscj0kLnRMKCkKaWYocj09bnVsbClyZXR1cm4gbnVsbAp0PTA9PT1j
-CmlmKHQmJiEwKXJldHVybiBQLk9RKHIsYikKcz1iLmxlbmd0aApkPVAuakIoYyxkLHMpCmlmKHQmJmQ9
-PT1zKXJldHVybiBQLk9RKHIsYikKcmV0dXJuIFAuT1EocixiLnN1YmFycmF5KGMsZCkpfSwKT1E6ZnVu
-Y3Rpb24oYSxiKXtpZihQLkFqKGIpKXJldHVybiBudWxsCnJldHVybiBQLkpoKGEsYil9LApKaDpmdW5j
-dGlvbihhLGIpe3ZhciB0LHMKdHJ5e3Q9YS5kZWNvZGUoYikKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShz
-KX1yZXR1cm4gbnVsbH0sCkFqOmZ1bmN0aW9uKGEpe3ZhciB0LHM9YS5sZW5ndGgtMgpmb3IodD0wO3Q8
-czsrK3QpaWYoYVt0XT09PTIzNylpZigoYVt0KzFdJjIyNCk9PT0xNjApcmV0dXJuITAKcmV0dXJuITF9
-LApXSTpmdW5jdGlvbigpe3ZhciB0LHMKdHJ5e3Q9bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2ZhdGFs
-OnRydWV9KQpyZXR1cm4gdH1jYXRjaChzKXtILlJ1KHMpfXJldHVybiBudWxsfSwKY1A6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciB0LHMscgpmb3IodD1KLlU2KGEpLHM9YjtzPGM7KytzKXtyPXQucShhLHMpCmlmKHR5
-cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIuek0oKQppZigociYxMjcpIT09cilyZXR1cm4gcy1ifXJl
-dHVybiBjLWJ9LAp4TTpmdW5jdGlvbihhLGIsYyxkLGUsZil7aWYoQy5qbi56WShmLDQpIT09MCl0aHJv
-dyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQgcGFkZGluZywgcGFkZGVkIGxlbmd0aCBtdXN0IGJlIG11
-bHRpcGxlIG9mIGZvdXIsIGlzICIrZixhLGMpKQppZihkK2UhPT1mKXRocm93IEguYihQLnJyKCJJbnZh
-bGlkIGJhc2U2NCBwYWRkaW5nLCAnPScgbm90IGF0IHRoZSBlbmQiLGEsYikpCmlmKGU+Mil0aHJvdyBI
-LmIoUC5ycigiSW52YWxpZCBiYXNlNjQgcGFkZGluZywgbW9yZSB0aGFuIHR3byAnPScgY2hhcmFjdGVy
-cyIsYSxiKSl9LAp1dzpmdW5jdGlvbiB1dyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1udWxs
-fSwKaTg6ZnVuY3Rpb24gaTgoYSl7dGhpcy5hPWF9LApDVjpmdW5jdGlvbiBDVigpe30sClU4OmZ1bmN0
-aW9uIFU4KCl7fSwKVWs6ZnVuY3Rpb24gVWsoKXt9LAp3STpmdW5jdGlvbiB3SSgpe30sClppOmZ1bmN0
-aW9uIFppKCl7fSwKYnk6ZnVuY3Rpb24gYnkoKXt9LApNeDpmdW5jdGlvbiBNeChhKXt0aGlzLmE9YX0s
-CnU1OmZ1bmN0aW9uIHU1KCl7fSwKRTM6ZnVuY3Rpb24gRTMoKXt9LApSdzpmdW5jdGlvbiBSdyhhKXt0
-aGlzLmI9MAp0aGlzLmM9YX0sCkdZOmZ1bmN0aW9uIEdZKGEpe3RoaXMuYT1hfSwKYno6ZnVuY3Rpb24g
-YnooYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0hMApfLmY9Xy5lPV8uZD0wfSwKUUE6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciB0PUguSHAoYSxjKQppZih0IT1udWxsKXJldHVybiB0CmlmKGIhPW51bGwp
-cmV0dXJuIGIuJDEoYSkKdGhyb3cgSC5iKFAucnIoYSxudWxsLG51bGwpKX0sCm9zOmZ1bmN0aW9uKGEp
-e2lmKGEgaW5zdGFuY2VvZiBILlRwKXJldHVybiBhLlooMCkKcmV0dXJuIkluc3RhbmNlIG9mICciK0gu
-ZChILmxoKGEpKSsiJyJ9LApPODpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1KLlFpKGEsYykKaWYoYSE9
-PTAmJiEwKWZvcih0PTA7dDxzLmxlbmd0aDsrK3QpQy5ObS5ZKHMsdCxiKQpyZXR1cm4gc30sCkNIOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdCxzPUguVk0oW10sYy5DKCJqZDwwPiIpKQpmb3IodD1KLklUKGEpO3Qu
-RigpOylDLk5tLmkocyxjLmEodC5nbCgpKSkKaWYoYilyZXR1cm4gcwpyZXR1cm4gYy5DKCJ6TTwwPiIp
-LmEoSi5FcChzKSl9LApBRjpmdW5jdGlvbihhLGIpe3JldHVybiBiLkMoInpNPDA+IikuYShKLnVuKFAu
-Q0goYSwhMSxiKSkpfSwKSE06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKEFycmF5LmlzQXJyYXkoYSkp
-e3UudC5hKGEpCnQ9YS5sZW5ndGgKYz1QLmpCKGIsYyx0KQpyZXR1cm4gSC5lVChiPjB8fGM8dD9DLk5t
-LkQ2KGEsYixjKTphKX1pZih1LmJtLmIoYSkpcmV0dXJuIEguZncoYSxiLFAuakIoYixjLGEubGVuZ3Ro
-KSkKcmV0dXJuIFAuYncoYSxiLGMpfSwKT286ZnVuY3Rpb24oYSl7cmV0dXJuIEguTHcoYSl9LApidzpm
-dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscD1udWxsCmlmKGI8MCl0aHJvdyBILmIoUC5URShiLDAs
-Si5IKGEpLHAscCkpCnQ9Yz09bnVsbAppZighdCYmYzxiKXRocm93IEguYihQLlRFKGMsYixKLkgoYSks
-cCxwKSkKcz1KLklUKGEpCmZvcihyPTA7cjxiOysrcilpZighcy5GKCkpdGhyb3cgSC5iKFAuVEUoYiww
-LHIscCxwKSkKcT1bXQppZih0KWZvcig7cy5GKCk7KXEucHVzaChzLmdsKCkpCmVsc2UgZm9yKHI9Yjty
-PGM7KytyKXtpZighcy5GKCkpdGhyb3cgSC5iKFAuVEUoYyxiLHIscCxwKSkKcS5wdXNoKHMuZ2woKSl9
-cmV0dXJuIEguZVQocSl9LApudTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguVlIoYSxILnY0KGEsITEs
-ITAsITEsITEsITEpKX0sCnZnOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1KLklUKGIpCmlmKCF0LkYoKSly
-ZXR1cm4gYQppZihjLmxlbmd0aD09PTApe2RvIGErPUguZCh0LmdsKCkpCndoaWxlKHQuRigpKX1lbHNl
-e2ErPUguZCh0LmdsKCkpCmZvcig7dC5GKCk7KWE9YStjK0guZCh0LmdsKCkpfXJldHVybiBhfSwKbHI6
-ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIG5ldyBQLm1wKGEsYixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2
-YXIgdD1ILk0wKCkKaWYodCE9bnVsbClyZXR1cm4gUC5oSyh0KQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5i
-YXNlJyBpcyBub3Qgc3VwcG9ydGVkIikpfSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEs
-cCxvLG49IjAxMjM0NTY3ODlBQkNERUYiCmlmKGM9PT1DLnhNKXt0PSQuejQoKS5iCmlmKHR5cGVvZiBi
-IT0ic3RyaW5nIilILnZoKEguSShiKSkKdD10LnRlc3QoYil9ZWxzZSB0PSExCmlmKHQpcmV0dXJuIGIK
-SC5MaChjKS5DKCJVay5TIikuYShiKQpzPWMuZ1pFKCkuV0ooYikKZm9yKHQ9cy5sZW5ndGgscj0wLHE9
-IiI7cjx0Oysrcil7cD1zW3JdCmlmKHA8MTI4KXtvPXA+Pj40CmlmKG8+PTgpcmV0dXJuIEguayhhLG8p
-Cm89KGFbb10mMTw8KHAmMTUpKSE9PTB9ZWxzZSBvPSExCmlmKG8pcSs9SC5MdyhwKQplbHNlIHE9ZCYm
-cD09PTMyP3ErIisiOnErIiUiK25bcD4+PjQmMTVdK25bcCYxNV19cmV0dXJuIHEuY2hhckNvZGVBdCgw
-KT09MD9xOnF9LApaYjpmdW5jdGlvbigpe3ZhciB0LHMKaWYoSC5vVCgkLnA2KCkpKXJldHVybiBILnRz
-KG5ldyBFcnJvcigpKQp0cnl7dGhyb3cgSC5iKCIiKX1jYXRjaChzKXtILlJ1KHMpCnQ9SC50cyhzKQpy
-ZXR1cm4gdH19LApHcTpmdW5jdGlvbihhKXt2YXIgdD1NYXRoLmFicyhhKSxzPWE8MD8iLSI6IiIKaWYo
-dD49MTAwMClyZXR1cm4iIithCmlmKHQ+PTEwMClyZXR1cm4gcysiMCIrdAppZih0Pj0xMClyZXR1cm4g
-cysiMDAiK3QKcmV0dXJuIHMrIjAwMCIrdH0sClZ4OmZ1bmN0aW9uKGEpe2lmKGE+PTEwMClyZXR1cm4i
-IithCmlmKGE+PTEwKXJldHVybiIwIithCnJldHVybiIwMCIrYX0sCmgwOmZ1bmN0aW9uKGEpe2lmKGE+
-PTEwKXJldHVybiIiK2EKcmV0dXJuIjAiK2F9LApoOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVt
-YmVyInx8SC5yUShhKXx8bnVsbD09YSlyZXR1cm4gSi5BYyhhKQppZih0eXBlb2YgYT09InN0cmluZyIp
-cmV0dXJuIEpTT04uc3RyaW5naWZ5KGEpCnJldHVybiBQLm9zKGEpfSwKaFY6ZnVuY3Rpb24oYSl7cmV0
-dXJuIG5ldyBQLkM2KGEpfSwKeFk6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkFUKCExLG51bGwsbnVs
-bCxhKX0sCkwzOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbmV3IFAuQVQoITAsYSxiLGMpfSwKRWU6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIG5ldyBQLkFUKCExLG51bGwsYSwiTXVzdCBub3QgYmUgbnVsbCIpfSwKVUk6
-ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpdGhyb3cgSC5iKFAuRWUoYikpCnJldHVybiBhfSwKTzc6
-ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuYkoobnVsbCxudWxsLCEwLGEsYiwiVmFsdWUgbm90IGlu
-IHJhbmdlIil9LApURTpmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVybiBuZXcgUC5iSihiLGMsITAsYSxk
-LCJJbnZhbGlkIHZhbHVlIil9LAp3QTpmdW5jdGlvbihhLGIsYyxkKXtpZihhPGJ8fGE+Yyl0aHJvdyBI
-LmIoUC5URShhLGIsYyxkLG51bGwpKQpyZXR1cm4gYX0sCmpCOmZ1bmN0aW9uKGEsYixjKXtpZigwPmF8
-fGE+Yyl0aHJvdyBILmIoUC5URShhLDAsYywic3RhcnQiLG51bGwpKQppZihiIT1udWxsKXtpZihhPmJ8
-fGI+Yyl0aHJvdyBILmIoUC5URShiLGEsYywiZW5kIixudWxsKSkKcmV0dXJuIGJ9cmV0dXJuIGN9LApr
-MTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBhIT09Im51bWJlciIpcmV0dXJuIGEuSigpCmlmKGE8MCl0
-aHJvdyBILmIoUC5URShhLDAsbnVsbCxiLG51bGwpKQpyZXR1cm4gYX0sCnQ6ZnVuY3Rpb24oYSxiLGMs
-ZCxlKXt2YXIgdD1ILldZKGU9PW51bGw/Si5IKGIpOmUpCnJldHVybiBuZXcgUC5lWSh0LCEwLGEsYywi
-SW5kZXggb3V0IG9mIHJhbmdlIil9LApMNDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAudWIoYSl9LApu
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5kcyhhKX0sClBWOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcg
-UC5saihhKX0sCmE0OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5VVihhKX0sCnJyOmZ1bmN0aW9uKGEs
-YixjKXtyZXR1cm4gbmV3IFAuYUUoYSxiLGMpfSwKZEg6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscz1I
-LlZNKFtdLGQuQygiamQ8MD4iKSkKQy5ObS5zQShzLGEpCmZvcih0PTA7dDxhOysrdClDLk5tLlkocyx0
-LGIuJDEodCkpCnJldHVybiBzfSwKaEs6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGss
-aixpLGgsZyxmLGU9bnVsbCxkPWEubGVuZ3RoCmlmKGQ+PTUpe3Q9KChKLlF6KGEsNCleNTgpKjN8Qy54
-Qi5XKGEsMCleMTAwfEMueEIuVyhhLDEpXjk3fEMueEIuVyhhLDIpXjExNnxDLnhCLlcoYSwzKV45Nyk+
-Pj4wCmlmKHQ9PT0wKXJldHVybiBQLktEKGQ8ZD9DLnhCLncoYSwwLGQpOmEsNSxlKS5nbFIoKQplbHNl
-IGlmKHQ9PT0zMilyZXR1cm4gUC5LRChDLnhCLncoYSw1LGQpLDAsZSkuZ2xSKCl9cz1uZXcgQXJyYXko
-OCkKcy5maXhlZCRsZW5ndGg9QXJyYXkKcj1ILlZNKHMsdS50KQpDLk5tLlkociwwLDApCkMuTm0uWShy
-LDEsLTEpCkMuTm0uWShyLDIsLTEpCkMuTm0uWShyLDcsLTEpCkMuTm0uWShyLDMsMCkKQy5ObS5ZKHIs
-NCwwKQpDLk5tLlkociw1LGQpCkMuTm0uWShyLDYsZCkKaWYoUC5VQihhLDAsZCwwLHIpPj0xNClDLk5t
-Llkociw3LGQpCnE9clsxXQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLnRCKCkKaWYocT49
-MClpZihQLlVCKGEsMCxxLDIwLHIpPT09MjApcls3XT1xCnM9clsyXQppZih0eXBlb2YgcyE9PSJudW1i
-ZXIiKXJldHVybiBzLmgoKQpwPXMrMQpvPXJbM10Kbj1yWzRdCm09cls1XQpsPXJbNl0KaWYodHlwZW9m
-IGwhPT0ibnVtYmVyIilyZXR1cm4gbC5KKCkKaWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gSC5w
-WShtKQppZihsPG0pbT1sCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4uSigpCmlmKG48cClu
-PW0KZWxzZSBpZihuPD1xKW49cSsxCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8uSigpCmlm
-KG88cClvPW4Kcz1yWzddCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSigpCms9czwwCmlm
-KGspaWYocD5xKzMpe2o9ZQprPSExfWVsc2V7cz1vPjAKaWYocyYmbysxPT09bil7aj1lCms9ITF9ZWxz
-ZXtpZighKG08ZCYmbT09PW4rMiYmSi5xMChhLCIuLiIsbikpKWk9bT5uKzImJkoucTAoYSwiLy4uIixt
-LTMpCmVsc2UgaT0hMAppZihpKXtqPWUKaz0hMX1lbHNle2lmKHE9PT00KWlmKEoucTAoYSwiZmlsZSIs
-MCkpe2lmKHA8PTApe2lmKCFDLnhCLlFpKGEsIi8iLG4pKXtoPSJmaWxlOi8vLyIKdD0zfWVsc2V7aD0i
-ZmlsZTovLyIKdD0yfWE9aCtDLnhCLncoYSxuLGQpCnEtPTAKcz10LTAKbSs9cwpsKz1zCmQ9YS5sZW5n
-dGgKcD03Cm89NwpuPTd9ZWxzZSBpZihuPT09bSl7Zz1tKzE7KytsCmE9Qy54Qi5pNyhhLG4sbSwiLyIp
-OysrZAptPWd9aj0iZmlsZSJ9ZWxzZSBpZihDLnhCLlFpKGEsImh0dHAiLDApKXtpZihzJiZvKzM9PT1u
-JiZDLnhCLlFpKGEsIjgwIixvKzEpKXtmPW4tMwptLT0zCmwtPTMKYT1DLnhCLmk3KGEsbyxuLCIiKQpk
-LT0zCm49Zn1qPSJodHRwIn1lbHNlIGo9ZQplbHNlIGlmKHE9PT01JiZKLnEwKGEsImh0dHBzIiwwKSl7
-aWYocyYmbys0PT09biYmSi5xMChhLCI0NDMiLG8rMSkpe2Y9bi00Cm0tPTQKbC09NAphPUouZGcoYSxv
-LG4sIiIpCmQtPTMKbj1mfWo9Imh0dHBzIn1lbHNlIGo9ZQprPSEwfX19ZWxzZSBqPWUKaWYoayl7cz1h
-Lmxlbmd0aAppZihkPHMpe2E9Si5sZChhLDAsZCkKcS09MApwLT0wCm8tPTAKbi09MAptLT0wCmwtPTB9
-cmV0dXJuIG5ldyBQLlVmKGEscSxwLG8sbixtLGwsail9cmV0dXJuIFAuanYoYSwwLGQscSxwLG8sbixt
-LGwsail9LApNdDpmdW5jdGlvbihhKXtILmMoYSkKcmV0dXJuIFAua3UoYSwwLGEubGVuZ3RoLEMueE0s
-ITEpfSwKV1g6ZnVuY3Rpb24oYSl7dmFyIHQ9dS5OCnJldHVybiBDLk5tLk4wKEguVk0oYS5zcGxpdCgi
-JiIpLHUucyksUC5GbCh0LHQpLG5ldyBQLm4xKEMueE0pLHUuZil9LApIaDpmdW5jdGlvbihhLGIsYyl7
-dmFyIHQscyxyLHEscCxvLG4sbT1udWxsLGw9IklQdjQgYWRkcmVzcyBzaG91bGQgY29udGFpbiBleGFj
-dGx5IDQgcGFydHMiLGs9ImVhY2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSAwLi4yNTUiLGo9bmV3
-IFAuY1MoYSksaT1uZXcgVWludDhBcnJheSg0KQpmb3IodD1pLmxlbmd0aCxzPWIscj1zLHE9MDtzPGM7
-KytzKXtwPUMueEIubShhLHMpCmlmKHAhPT00Nil7aWYoKHBeNDgpPjkpai4kMigiaW52YWxpZCBjaGFy
-YWN0ZXIiLHMpfWVsc2V7aWYocT09PTMpai4kMihsLHMpCm89UC5RQShDLnhCLncoYSxyLHMpLG0sbSkK
-aWYodHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4gby5vcygpCmlmKG8+MjU1KWouJDIoayxyKQpuPXEr
-MQppZihxPj10KXJldHVybiBILmsoaSxxKQppW3FdPW8Kcj1zKzEKcT1ufX1pZihxIT09MylqLiQyKGws
-YykKbz1QLlFBKEMueEIudyhhLHIsYyksbSxtKQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBv
-Lm9zKCkKaWYobz4yNTUpai4kMihrLHIpCmlmKHE+PXQpcmV0dXJuIEguayhpLHEpCmlbcV09bwpyZXR1
-cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxm
-LGUsZD1uZXcgUC5WQyhhKSxjPW5ldyBQLkpUKGQsYSkKaWYoYS5sZW5ndGg8MilkLiQxKCJhZGRyZXNz
-IGlzIHRvbyBzaG9ydCIpCnQ9SC5WTShbXSx1LnQpCmZvcihzPWIscj1zLHE9ITEscD0hMTtzPGEwOysr
-cyl7bz1DLnhCLm0oYSxzKQppZihvPT09NTgpe2lmKHM9PT1iKXsrK3MKaWYoQy54Qi5tKGEscykhPT01
-OClkLiQyKCJpbnZhbGlkIHN0YXJ0IGNvbG9uLiIscykKcj1zfWlmKHM9PT1yKXtpZihxKWQuJDIoIm9u
-bHkgb25lIHdpbGRjYXJkIGA6OmAgaXMgYWxsb3dlZCIscykKQy5ObS5pKHQsLTEpCnE9ITB9ZWxzZSBD
-Lk5tLmkodCxjLiQyKHIscykpCnI9cysxfWVsc2UgaWYobz09PTQ2KXA9ITB9aWYodC5sZW5ndGg9PT0w
-KWQuJDEoInRvbyBmZXcgcGFydHMiKQpuPXI9PT1hMAptPUMuTm0uZ3JaKHQpCmlmKG4mJm0hPT0tMSlk
-LiQyKCJleHBlY3RlZCBhIHBhcnQgYWZ0ZXIgbGFzdCBgOmAiLGEwKQppZighbilpZighcClDLk5tLmko
-dCxjLiQyKHIsYTApKQplbHNle2w9UC5IaChhLHIsYTApCkMuTm0uaSh0LChsWzBdPDw4fGxbMV0pPj4+
-MCkKQy5ObS5pKHQsKGxbMl08PDh8bFszXSk+Pj4wKX1pZihxKXtpZih0Lmxlbmd0aD43KWQuJDEoImFu
-IGFkZHJlc3Mgd2l0aCBhIHdpbGRjYXJkIG11c3QgaGF2ZSBsZXNzIHRoYW4gNyBwYXJ0cyIpfWVsc2Ug
-aWYodC5sZW5ndGghPT04KWQuJDEoImFuIGFkZHJlc3Mgd2l0aG91dCBhIHdpbGRjYXJkIG11c3QgY29u
-dGFpbiBleGFjdGx5IDggcGFydHMiKQprPW5ldyBVaW50OEFycmF5KDE2KQpmb3IobT10Lmxlbmd0aCxq
-PWsubGVuZ3RoLGk9OS1tLHM9MCxoPTA7czxtOysrcyl7Zz10W3NdCmlmKGc9PT0tMSlmb3IoZj0wO2Y8
-aTsrK2Ype2lmKGg8MHx8aD49ailyZXR1cm4gSC5rKGssaCkKa1toXT0wCmU9aCsxCmlmKGU+PWopcmV0
-dXJuIEguayhrLGUpCmtbZV09MApoKz0yfWVsc2V7ZT1DLmpuLndHKGcsOCkKaWYoaDwwfHxoPj1qKXJl
-dHVybiBILmsoayxoKQprW2hdPWUKZT1oKzEKaWYoZT49ailyZXR1cm4gSC5rKGssZSkKa1tlXT1nJjI1
-NQpoKz0yfX1yZXR1cm4ga30sCmp2OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcsaCxpLGope3ZhciB0LHMs
-cixxLHAsbyxuLG09bnVsbAppZihqPT1udWxsKWlmKGQ+YilqPVAuUGkoYSxiLGQpCmVsc2V7aWYoZD09
-PWIpUC5SMyhhLGIsIkludmFsaWQgZW1wdHkgc2NoZW1lIikKaj0iIn1pZihlPmIpe3Q9ZCszCnM9dDxl
-P1AuelIoYSx0LGUtMSk6IiIKcj1QLk9lKGEsZSxmLCExKQppZih0eXBlb2YgZiE9PSJudW1iZXIiKXJl
-dHVybiBmLmgoKQpxPWYrMQppZih0eXBlb2YgZyE9PSJudW1iZXIiKXJldHVybiBILnBZKGcpCnA9cTxn
-P1Aud0IoUC5RQShKLmxkKGEscSxnKSxuZXcgUC5lMShhLGYpLG0pLGopOm19ZWxzZXtwPW0Kcj1wCnM9
-IiJ9bz1QLmthKGEsZyxoLG0saixyIT1udWxsKQppZih0eXBlb2YgaCE9PSJudW1iZXIiKXJldHVybiBo
-LkooKQpuPWg8aT9QLmxlKGEsaCsxLGksbSk6bQpyZXR1cm4gbmV3IFAuRG4oaixzLHIscCxvLG4saTxj
-P1AudEcoYSxpKzEsYyk6bSl9LAp3SzpmdW5jdGlvbihhKXtpZihhPT09Imh0dHAiKXJldHVybiA4MApp
-ZihhPT09Imh0dHBzIilyZXR1cm4gNDQzCnJldHVybiAwfSwKUjM6ZnVuY3Rpb24oYSxiLGMpe3Rocm93
-IEguYihQLnJyKGMsYSxiKSl9LAprRTpmdW5jdGlvbihhLGIpe0MuTm0uSyhhLG5ldyBQLk5ZKCExKSl9
-LApITjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyCmZvcih0PUgucUMoYSxjLG51bGwsSC50NihhKS5j
-KSx0PW5ldyBILmE3KHQsdC5nQSh0KSx0LiR0aS5DKCJhNzxhTC5FPiIpKTt0LkYoKTspe3M9dC5kCnI9
-UC5udSgnWyIqLzo8Pj9cXFxcfF0nKQpzLnRvU3RyaW5nCmlmKEgubTIocyxyLDApKXt0PVAuTDQoIkls
-bGVnYWwgY2hhcmFjdGVyIGluIHBhdGg6ICIrcykKdGhyb3cgSC5iKHQpfX19LApyZzpmdW5jdGlvbihh
-LGIpe3ZhciB0CmlmKCEoNjU8PWEmJmE8PTkwKSl0PTk3PD1hJiZhPD0xMjIKZWxzZSB0PSEwCmlmKHQp
-cmV0dXJuCnQ9UC5MNCgiSWxsZWdhbCBkcml2ZSBsZXR0ZXIgIitQLk9vKGEpKQp0aHJvdyBILmIodCl9
-LAp3QjpmdW5jdGlvbihhLGIpe2lmKGEhPW51bGwmJmE9PT1QLndLKGIpKXJldHVybiBudWxsCnJldHVy
-biBhfSwKT2U6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvCmlmKGE9PW51bGwpcmV0dXJu
-IG51bGwKaWYoYj09PWMpcmV0dXJuIiIKaWYoQy54Qi5tKGEsYik9PT05MSl7aWYodHlwZW9mIGMhPT0i
-bnVtYmVyIilyZXR1cm4gYy5ITigpCnQ9Yy0xCmlmKEMueEIubShhLHQpIT09OTMpUC5SMyhhLGIsIk1p
-c3NpbmcgZW5kIGBdYCB0byBtYXRjaCBgW2AgaW4gaG9zdCIpCnM9YisxCnI9UC50byhhLHMsdCkKaWYo
-dHlwZW9mIHIhPT0ibnVtYmVyIilyZXR1cm4gci5KKCkKaWYocjx0KXtxPXIrMQpwPVAuT0EoYSxDLnhC
-LlFpKGEsIjI1IixxKT9yKzM6cSx0LCIlMjUiKX1lbHNlIHA9IiIKUC5lZyhhLHMscikKcmV0dXJuIEMu
-eEIudyhhLGIscikudG9Mb3dlckNhc2UoKStwKyJdIn1pZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVy
-biBILnBZKGMpCm89Ygpmb3IoO288YzsrK28paWYoQy54Qi5tKGEsbyk9PT01OCl7cj1DLnhCLlhVKGEs
-IiUiLGIpCmlmKCEocj49YiYmcjxjKSlyPWMKaWYocjxjKXtxPXIrMQpwPVAuT0EoYSxDLnhCLlFpKGEs
-IjI1IixxKT9yKzM6cSxjLCIlMjUiKX1lbHNlIHA9IiIKUC5lZyhhLGIscikKcmV0dXJuIlsiK0MueEIu
-dyhhLGIscikrcCsiXSJ9cmV0dXJuIFAuT0woYSxiLGMpfSwKdG86ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
-LHM9Qy54Qi5YVShhLCIlIixiKQppZihzPj1iKXtpZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBI
-LnBZKGMpCnQ9czxjfWVsc2UgdD0hMQpyZXR1cm4gdD9zOmN9LApPQTpmdW5jdGlvbihhLGIsYyxkKXt2
-YXIgdCxzLHIscSxwLG8sbixtLGwsaz1kIT09IiI/bmV3IFAuUm4oZCk6bnVsbAppZih0eXBlb2YgYyE9
-PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj0hMApmb3IoO3Q8Yzspe3E9Qy54Qi5tKGEs
-dCkKaWYocT09PTM3KXtwPVAucnYoYSx0LCEwKQpvPXA9PW51bGwKaWYobyYmcil7dCs9Mwpjb250aW51
-ZX1pZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCm49ay5hKz1DLnhCLncoYSxzLHQpCmlmKG8pcD1DLnhC
-LncoYSx0LHQrMykKZWxzZSBpZihwPT09IiUiKVAuUjMoYSx0LCJab25lSUQgc2hvdWxkIG5vdCBjb250
-YWluICUgYW55bW9yZSIpCmsuYT1uK3AKdCs9MwpzPXQKcj0hMH1lbHNle2lmKHE8MTI3KXtvPXE+Pj40
-CmlmKG8+PTgpcmV0dXJuIEguayhDLkYzLG8pCm89KEMuRjNbb10mMTw8KHEmMTUpKSE9PTB9ZWxzZSBv
-PSExCmlmKG8pe2lmKHImJjY1PD1xJiY5MD49cSl7aWYoaz09bnVsbClrPW5ldyBQLlJuKCIiKQppZihz
-PHQpe2suYSs9Qy54Qi53KGEscyx0KQpzPXR9cj0hMX0rK3R9ZWxzZXtpZigocSY2NDUxMik9PT01NTI5
-NiYmdCsxPGMpe209Qy54Qi5tKGEsdCsxKQppZigobSY2NDUxMik9PT01NjMyMCl7cT02NTUzNnwocSYx
-MDIzKTw8MTB8bSYxMDIzCmw9Mn1lbHNlIGw9MX1lbHNlIGw9MQppZihrPT1udWxsKWs9bmV3IFAuUm4o
-IiIpCmsuYSs9Qy54Qi53KGEscyx0KQprLmErPVAuSEgocSkKdCs9bApzPXR9fX1pZihrPT1udWxsKXJl
-dHVybiBDLnhCLncoYSxiLGMpCmlmKHM8YylrLmErPUMueEIudyhhLHMsYykKbz1rLmEKcmV0dXJuIG8u
-Y2hhckNvZGVBdCgwKT09MD9vOm99LApPTDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4s
-bSxsLGssagppZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj1udWxs
-CnE9ITAKZm9yKDt0PGM7KXtwPUMueEIubShhLHQpCmlmKHA9PT0zNyl7bz1QLnJ2KGEsdCwhMCkKbj1v
-PT1udWxsCmlmKG4mJnEpe3QrPTMKY29udGludWV9aWYocj09bnVsbClyPW5ldyBQLlJuKCIiKQptPUMu
-eEIudyhhLHMsdCkKbD1yLmErPSFxP20udG9Mb3dlckNhc2UoKTptCmlmKG4pe289Qy54Qi53KGEsdCx0
-KzMpCms9M31lbHNlIGlmKG89PT0iJSIpe289IiUyNSIKaz0xfWVsc2Ugaz0zCnIuYT1sK28KdCs9awpz
-PXQKcT0hMH1lbHNle2lmKHA8MTI3KXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguayhDLmVhLG4pCm49
-KEMuZWFbbl0mMTw8KHAmMTUpKSE9PTB9ZWxzZSBuPSExCmlmKG4pe2lmKHEmJjY1PD1wJiY5MD49cCl7
-aWYocj09bnVsbClyPW5ldyBQLlJuKCIiKQppZihzPHQpe3IuYSs9Qy54Qi53KGEscyx0KQpzPXR9cT0h
-MX0rK3R9ZWxzZXtpZihwPD05Myl7bj1wPj4+NAppZihuPj04KXJldHVybiBILmsoQy5hayxuKQpuPShD
-LmFrW25dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKVAuUjMoYSx0LCJJbnZhbGlkIGNoYXJh
-Y3RlciIpCmVsc2V7aWYoKHAmNjQ1MTIpPT09NTUyOTYmJnQrMTxjKXtqPUMueEIubShhLHQrMSkKaWYo
-KGomNjQ1MTIpPT09NTYzMjApe3A9NjU1MzZ8KHAmMTAyMyk8PDEwfGomMTAyMwprPTJ9ZWxzZSBrPTF9
-ZWxzZSBrPTEKaWYocj09bnVsbClyPW5ldyBQLlJuKCIiKQptPUMueEIudyhhLHMsdCkKci5hKz0hcT9t
-LnRvTG93ZXJDYXNlKCk6bQpyLmErPVAuSEgocCkKdCs9awpzPXR9fX19aWYocj09bnVsbClyZXR1cm4g
-Qy54Qi53KGEsYixjKQppZihzPGMpe209Qy54Qi53KGEscyxjKQpyLmErPSFxP20udG9Mb3dlckNhc2Uo
-KTptfW49ci5hCnJldHVybiBuLmNoYXJDb2RlQXQoMCk9PTA/bjpufSwKUGk6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0LHMscixxCmlmKGI9PT1jKXJldHVybiIiCmlmKCFQLkV0KEouclkoYSkuVyhhLGIpKSlQLlIz
-KGEsYiwiU2NoZW1lIG5vdCBzdGFydGluZyB3aXRoIGFscGhhYmV0aWMgY2hhcmFjdGVyIikKZm9yKHQ9
-YixzPSExO3Q8YzsrK3Qpe3I9Qy54Qi5XKGEsdCkKaWYocjwxMjgpe3E9cj4+PjQKaWYocT49OClyZXR1
-cm4gSC5rKEMubUsscSkKcT0oQy5tS1txXSYxPDwociYxNSkpIT09MH1lbHNlIHE9ITEKaWYoIXEpUC5S
-MyhhLHQsIklsbGVnYWwgc2NoZW1lIGNoYXJhY3RlciIpCmlmKDY1PD1yJiZyPD05MClzPSEwfWE9Qy54
-Qi53KGEsYixjKQpyZXR1cm4gUC5ZYShzP2EudG9Mb3dlckNhc2UoKTphKX0sCllhOmZ1bmN0aW9uKGEp
-e2lmKGE9PT0iaHR0cCIpcmV0dXJuImh0dHAiCmlmKGE9PT0iZmlsZSIpcmV0dXJuImZpbGUiCmlmKGE9
-PT0iaHR0cHMiKXJldHVybiJodHRwcyIKaWYoYT09PSJwYWNrYWdlIilyZXR1cm4icGFja2FnZSIKcmV0
-dXJuIGF9LAp6UjpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4iIgpyZXR1cm4gUC51Tyhh
-LGIsYyxDLnRvLCExKX0sCmthOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgdCxzPWU9PT0iZmlsZSIs
-cj1zfHxmLHE9YT09bnVsbAppZihxJiYhMClyZXR1cm4gcz8iLyI6IiIKdD0hcT9QLnVPKGEsYixjLEMu
-V2QsITApOkMuak4uRTIoZCxuZXcgUC5SWigpLHUuTikuelYoMCwiLyIpCmlmKHQubGVuZ3RoPT09MCl7
-aWYocylyZXR1cm4iLyJ9ZWxzZSBpZihyJiYhQy54Qi5uKHQsIi8iKSl0PSIvIit0CnJldHVybiBQLkpy
+YSl9LApVNjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90
+eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQu
+cHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0
+dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJl
+dHVybiBKLmtzKGEpfSwKaWE6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXtpZihNYXRo
+LmZsb29yKGEpPT1hKXJldHVybiBKLnVyLnByb3RvdHlwZQpyZXR1cm4gSi5WQS5wcm90b3R5cGV9aWYo
+dHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBK
+LllFLnByb3RvdHlwZQppZih0eXBlb2YgYT09ImJvb2xlYW4iKXJldHVybiBKLnlFLnByb3RvdHlwZQpp
+ZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJv
+YmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJu
+IGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlv
+bihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwp
+cmV0dXJuIGEKaWYoIShhIGluc3RhbmNlb2YgUC5NaCkpcmV0dXJuIEoua2QucHJvdG90eXBlCnJldHVy
+biBhfSwKenE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1B
+cnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2Yg
+YT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9m
+IFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApBYzpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShh
+KS5aKGEpfSwKQ006ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuZHUoYSxiLGMsZCl9LApG
+TDpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLmRkKGEsYil9LApHQTpmdW5jdGlvbihhLGIpe3Jl
+dHVybiBKLnpxKGEpLlcoYSxiKX0sCkdyOmZ1bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLmdtVyhhKX0s
+Ckg6ZnVuY3Rpb24oYSl7cmV0dXJuIEouVTYoYSkuZ2soYSl9LApJOmZ1bmN0aW9uKGEpe3JldHVybiBK
+LmlhKGEpLmdpKGEpfSwKSVQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEouenEoYSkuZ3coYSl9LApKeTpmdW5j
+dGlvbihhLGIpe3JldHVybiBKLmlhKGEpLmU3KGEsYil9LApLVjpmdW5jdGlvbihhLGIpe3JldHVybiBK
+LnJZKGEpLnluKGEsYil9LApMdDpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS53ZyhhKX0sCk0xOmZ1
+bmN0aW9uKGEsYixjKXtyZXR1cm4gSi56cShhKS5FMihhLGIsYyl9LApRTTpmdW5jdGlvbihhKXtyZXR1
+cm4gSi5SRShhKS5nUHUoYSl9LApRejpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLldkKGEsYil9
+LApSTTpmdW5jdGlvbihhLGIpe2lmKGE9PW51bGwpcmV0dXJuIGI9PW51bGwKaWYodHlwZW9mIGEhPSJv
+YmplY3QiKXJldHVybiBiIT1udWxsJiZhPT09YgpyZXR1cm4gSi5pYShhKS5ETihhLGIpfSwKVDA6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIEouclkoYSkuYlMoYSl9LAphNjpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZ
+KGEpLk8yKGEsYil9LApiVDpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5ENChhKX0sCmNIOmZ1bmN0
+aW9uKGEpe3JldHVybiBKLnJZKGEpLmhjKGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSku
+Z0REKGEpfSwKZFo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuT24oYSxiLGMsZCl9LApk
+ZzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5yWShhKS5pNyhhLGIsYyxkKX0sCmRoOmZ1bmN0aW9u
+KGEpe3JldHVybiBKLlJFKGEpLnRuKGEpfSwKaEU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi56cShhKS5V
+KGEsYil9LAppZzpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nUWcoYSl9LApsNTpmdW5jdGlvbihh
+LGIpe3JldHVybiBKLlJFKGEpLnNoZihhLGIpfSwKbGQ6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZ
+KGEpLk5qKGEsYixjKX0sCm06ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYT09Im51bWJlciImJnR5cGVv
+ZiBiPT0ibnVtYmVyIilyZXR1cm4gYStiCnJldHVybiBKLlRKKGEpLmgoYSxiKX0sCnA0OmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIEouclkoYSkuVGMoYSxiKX0sCnEwOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5y
+WShhKS5RaShhLGIsYyl9LApxRjpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nVmwoYSl9LAp0SDpm
+dW5jdGlvbihhLGIsYyl7cmV0dXJuIEouUkUoYSkucGsoYSxiLGMpfSwKdTk6ZnVuY3Rpb24oYSxiLGMp
+e3JldHVybiBKLnpxKGEpLnQoYSxiLGMpfSwKeDk6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYj09PSJu
+dW1iZXIiKWlmKGEuY29uc3RydWN0b3I9PUFycmF5fHx0eXBlb2YgYT09InN0cmluZyJ8fEguWHQoYSxh
+W3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdKSlpZihiPj4+MD09PWImJmI8YS5sZW5ndGgpcmV0dXJuIGFb
+Yl0KcmV0dXJuIEouVTYoYSkucShhLGIpfSwKemw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5VNihhKS50
+ZyhhLGIpfSwKdkI6ZnVuY3Rpb24gdkIoKXt9LAp5RTpmdW5jdGlvbiB5RSgpe30sCllFOmZ1bmN0aW9u
+IFlFKCl7fSwKTUY6ZnVuY3Rpb24gTUYoKXt9LAppQzpmdW5jdGlvbiBpQygpe30sCmtkOmZ1bmN0aW9u
+IGtkKCl7fSwKYzU6ZnVuY3Rpb24gYzUoKXt9LApqZDpmdW5jdGlvbiBqZChhKXt0aGlzLiR0aT1hfSwK
+UG86ZnVuY3Rpb24gUG8oYSl7dGhpcy4kdGk9YX0sCm0xOmZ1bmN0aW9uIG0xKGEsYixjKXt2YXIgXz10
+aGlzCl8uYT1hCl8uYj1iCl8uYz0wCl8uZD1udWxsCl8uJHRpPWN9LApxSTpmdW5jdGlvbiBxSSgpe30s
+CnVyOmZ1bmN0aW9uIHVyKCl7fSwKVkE6ZnVuY3Rpb24gVkEoKXt9LApEcjpmdW5jdGlvbiBEcigpe319
+LFA9ewpPajpmdW5jdGlvbigpe3ZhciB0LHMscj17fQppZihzZWxmLnNjaGVkdWxlSW1tZWRpYXRlIT1u
+dWxsKXJldHVybiBQLkVYKCkKaWYoc2VsZi5NdXRhdGlvbk9ic2VydmVyIT1udWxsJiZzZWxmLmRvY3Vt
+ZW50IT1udWxsKXt0PXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2IikKcz1zZWxmLmRvY3Vt
+ZW50LmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpyLmE9bnVsbApuZXcgc2VsZi5NdXRhdGlvbk9ic2VydmVy
+KEgudFIobmV3IFAudGgociksMSkpLm9ic2VydmUodCx7Y2hpbGRMaXN0OnRydWV9KQpyZXR1cm4gbmV3
+IFAuaGEocix0LHMpfWVsc2UgaWYoc2VsZi5zZXRJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAueXQoKQpy
+ZXR1cm4gUC5xVygpfSwKWlY6ZnVuY3Rpb24oYSl7c2VsZi5zY2hlZHVsZUltbWVkaWF0ZShILnRSKG5l
+dyBQLlZzKHUuTS5hKGEpKSwwKSl9LApxRzpmdW5jdGlvbihhKXtzZWxmLnNldEltbWVkaWF0ZShILnRS
+KG5ldyBQLkZ0KHUuTS5hKGEpKSwwKSl9LApCejpmdW5jdGlvbihhKXt1Lk0uYShhKQpQLlFOKDAsYSl9
+LApRTjpmdW5jdGlvbihhLGIpe3ZhciB0PW5ldyBQLlczKCkKdC5DWShhLGIpCnJldHVybiB0fSwKRlg6
+ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmloKG5ldyBQLnZzKCQuWDMsYS5DKCJ2czwwPiIpKSxhLkMo
+ImloPDA+IikpfSwKREk6ZnVuY3Rpb24oYSxiKXthLiQyKDAsbnVsbCkKYi5iPSEwCnJldHVybiBiLmF9
+LApqUTpmdW5jdGlvbihhLGIpe1AuSmUoYSxiKX0sCnlDOmZ1bmN0aW9uKGEsYil7Yi5hTSgwLGEpfSwK
+ZjM6ZnVuY3Rpb24oYSxiKXtiLncwKEguUnUoYSksSC50cyhhKSl9LApKZTpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscj1uZXcgUC5XTShiKSxxPW5ldyBQLlNYKGIpCmlmKGEgaW5zdGFuY2VvZiBQLnZzKWEuUWQo
+cixxLHUueikKZWxzZXt0PXUuegppZih1LmMuYihhKSlhLlNxKHIscSx0KQplbHNle3M9bmV3IFAudnMo
+JC5YMyx1Ll8pCnMuYT00CnMuYz1hCnMuUWQocixxLHQpfX19LApsejpmdW5jdGlvbihhKXt2YXIgdD1m
+dW5jdGlvbihiLGMpe3JldHVybiBmdW5jdGlvbihkLGUpe3doaWxlKHRydWUpdHJ5e2IoZCxlKQpicmVh
+a31jYXRjaChzKXtlPXMKZD1jfX19KGEsMSkKcmV0dXJuICQuWDMuTGoobmV3IFAuR3ModCksdS5QLHUu
+Uyx1LnopfSwKR1E6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkZ5KGEsMSl9LApUaDpmdW5jdGlvbigp
+e3JldHVybiBDLndRfSwKWW06ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkZ5KGEsMyl9LApsMDpmdW5j
+dGlvbihhLGIpe3JldHVybiBuZXcgUC5xNChhLGIuQygicTQ8MD4iKSl9LAprMzpmdW5jdGlvbihhLGIp
+e3ZhciB0LHMscgpiLmE9MQp0cnl7YS5TcShuZXcgUC5wVihiKSxuZXcgUC5VNyhiKSx1LlApfWNhdGNo
+KHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5yYihuZXcgUC52cihiLHQscykpfX0sCkE5OmZ1bmN0aW9u
+KGEsYil7dmFyIHQscyxyCmZvcih0PXUuXztzPWEuYSxzPT09MjspYT10LmEoYS5jKQppZihzPj00KXty
+PWIuYWgoKQpiLmE9YS5hCmIuYz1hLmMKUC5IWihiLHIpfWVsc2V7cj11LnguYShiLmMpCmIuYT0yCmIu
+Yz1hCmEualEocil9fSwKSFo6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGks
+aCxnLGYsZT1udWxsLGQ9e30sYz1kLmE9YQpmb3IodD11Lm4scz11Lngscj11LmM7ITA7KXtxPXt9CnA9
+Yy5hPT09OAppZihiPT1udWxsKXtpZihwKXtvPXQuYShjLmMpClAuTDIoZSxlLGMuYixvLmEsby5iKX1y
+ZXR1cm59Zm9yKDtuPWIuYSxuIT1udWxsO2I9bil7Yi5hPW51bGwKUC5IWihkLmEsYil9Yz1kLmEKbT1j
+LmMKcS5hPXAKcS5iPW0KbD0hcAppZihsKXtrPWIuYwprPShrJjEpIT09MHx8KGsmMTUpPT09OH1lbHNl
+IGs9ITAKaWYoayl7az1iLmIKaj1rLmIKaWYocCl7aT1jLmI9PT1qCmk9IShpfHxpKX1lbHNlIGk9ITEK
+aWYoaSl7dC5hKG0pClAuTDIoZSxlLGMuYixtLmEsbS5iKQpyZXR1cm59aD0kLlgzCmlmKGghPT1qKSQu
+WDM9agplbHNlIGg9ZQpjPWIuYwppZigoYyYxNSk9PT04KW5ldyBQLlJUKGQscSxiLHApLiQwKCkKZWxz
+ZSBpZihsKXtpZigoYyYxKSE9PTApbmV3IFAucnEocSxiLG0pLiQwKCl9ZWxzZSBpZigoYyYyKSE9PTAp
+bmV3IFAuUlcoZCxxLGIpLiQwKCkKaWYoaCE9bnVsbCkkLlgzPWgKYz1xLmIKaWYoci5iKGMpKXtpZihj
+LmE+PTQpe2c9cy5hKGsuYykKay5jPW51bGwKYj1rLk44KGcpCmsuYT1jLmEKay5jPWMuYwpkLmE9Ywpj
+b250aW51ZX1lbHNlIFAuQTkoYyxrKQpyZXR1cm59fWY9Yi5iCmc9cy5hKGYuYykKZi5jPW51bGwKYj1m
+Lk44KGcpCmM9cS5hCmw9cS5iCmlmKCFjKXtmLiR0aS5jLmEobCkKZi5hPTQKZi5jPWx9ZWxzZXt0LmEo
+bCkKZi5hPTgKZi5jPWx9ZC5hPWYKYz1mfX0sClZIOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYodS5hZy5i
+KGEpKXJldHVybiBiLkxqKGEsdS56LHUuSyx1LmwpCnQ9dS5iSQppZih0LmIoYSkpcmV0dXJuIHQuYShh
+KQp0aHJvdyBILmIoUC5MMyhhLCJvbkVycm9yIiwiRXJyb3IgaGFuZGxlciBtdXN0IGFjY2VwdCBvbmUg
+T2JqZWN0IG9yIG9uZSBPYmplY3QgYW5kIGEgU3RhY2tUcmFjZSBhcyBhcmd1bWVudHMsIGFuZCByZXR1
+cm4gYSBhIHZhbGlkIHJlc3VsdCIpKX0sCnB1OmZ1bmN0aW9uKCl7dmFyIHQscwpmb3IoO3Q9JC5TNix0
+IT1udWxsOyl7JC5tZz1udWxsCnM9dC5iCiQuUzY9cwppZihzPT1udWxsKSQuazg9bnVsbAp0LmEuJDAo
+KX19LAplTjpmdW5jdGlvbigpeyQuVUQ9ITAKdHJ5e1AucHUoKX1maW5hbGx5eyQubWc9bnVsbAokLlVE
+PSExCmlmKCQuUzYhPW51bGwpJC51dCgpLiQxKFAuVjkoKSl9fSwKZVc6ZnVuY3Rpb24oYSl7dmFyIHQ9
+bmV3IFAuT00oYSkKaWYoJC5TNj09bnVsbCl7JC5TNj0kLms4PXQKaWYoISQuVUQpJC51dCgpLiQxKFAu
+VjkoKSl9ZWxzZSAkLms4PSQuazguYj10fSwKclI6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPSQuUzYKaWYo
+cj09bnVsbCl7UC5lVyhhKQokLm1nPSQuazgKcmV0dXJufXQ9bmV3IFAuT00oYSkKcz0kLm1nCmlmKHM9
+PW51bGwpe3QuYj1yCiQuUzY9JC5tZz10fWVsc2V7dC5iPXMuYgokLm1nPXMuYj10CmlmKHQuYj09bnVs
+bCkkLms4PXR9fSwKcmI6ZnVuY3Rpb24oYSl7dmFyIHQ9bnVsbCxzPSQuWDMKaWYoQy5OVT09PXMpe1Au
+VGsodCx0LEMuTlUsYSkKcmV0dXJufVAuVGsodCx0LHMsdS5NLmEocy5HWShhKSkpfSwKUXc6ZnVuY3Rp
+b24oYSxiKXtpZihhPT1udWxsKUguVmooUC5oRygic3RyZWFtIikpCnJldHVybiBuZXcgUC54SShiLkMo
+InhJPDA+IikpfSwKVGw6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iPT1udWxsP1AudjAoYSk6YgpQLlVJKGEs
+ImVycm9yIix1LkspCnJldHVybiBuZXcgUC5PSChhLHQpfSwKdjA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYo
+dS5tLmIoYSkpe3Q9YS5nSUkoKQppZih0IT1udWxsKXJldHVybiB0fXJldHVybiBDLnBkfSwKTDI6ZnVu
+Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdD17fQp0LmE9ZAp0LmI9ZQppZihkPT1udWxsKXt0LmE9bmV3IFAu
+QVQoITEsbnVsbCwiZXJyb3IiLCJNdXN0IG5vdCBiZSBudWxsIikKdC5iPVAuWmIoKX1QLnJSKG5ldyBQ
+LnBLKHQpKX0sClQ4OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVy
+biBkLiQwKCkKJC5YMz1jCnQ9cwp0cnl7cz1kLiQwKCkKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwK
+eXY6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQx
+KGUpCiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMShlKQpyZXR1cm4gc31maW5hbGx5eyQuWDM9dH19LApReDpm
+dW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQy
+KGUsZikKJC5YMz1jCnQ9cwp0cnl7cz1kLiQyKGUsZikKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwK
+VGs6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKdS5NLmEoZCkKdD1DLk5VIT09YwppZih0KWQ9ISghdHx8
+ITEpP2MuR1koZCk6Yy5SVChkLHUuSCkKUC5lVyhkKX0sCnRoOmZ1bmN0aW9uIHRoKGEpe3RoaXMuYT1h
+fSwKaGE6ZnVuY3Rpb24gaGEoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKVnM6ZnVu
+Y3Rpb24gVnMoYSl7dGhpcy5hPWF9LApGdDpmdW5jdGlvbiBGdChhKXt0aGlzLmE9YX0sClczOmZ1bmN0
+aW9uIFczKCl7fSwKeUg6ZnVuY3Rpb24geUgoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmloOmZ1bmN0
+aW9uIGloKGEsYil7dGhpcy5hPWEKdGhpcy5iPSExCnRoaXMuJHRpPWJ9LApXTTpmdW5jdGlvbiBXTShh
+KXt0aGlzLmE9YX0sClNYOmZ1bmN0aW9uIFNYKGEpe3RoaXMuYT1hfSwKR3M6ZnVuY3Rpb24gR3MoYSl7
+dGhpcy5hPWF9LApGeTpmdW5jdGlvbiBGeShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKR1Y6ZnVuY3Rp
+b24gR1YoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uZD1fLmM9Xy5iPW51bGwKXy4kdGk9Yn0sCnE0OmZ1
+bmN0aW9uIHE0KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmI4OmZ1bmN0aW9uIGI4KCl7fSwKUGY6
+ZnVuY3Rpb24gUGYoKXt9LApaZjpmdW5jdGlvbiBaZihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApG
+ZTpmdW5jdGlvbiBGZShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPW51bGwKXy5iPWEKXy5jPWIKXy5k
+PWMKXy5lPWQKXy4kdGk9ZX0sCnZzOmZ1bmN0aW9uIHZzKGEsYil7dmFyIF89dGhpcwpfLmE9MApfLmI9
+YQpfLmM9bnVsbApfLiR0aT1ifSwKZGE6ZnVuY3Rpb24gZGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0s
+Cm9ROmZ1bmN0aW9uIG9RKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApwVjpmdW5jdGlvbiBwVihhKXt0
+aGlzLmE9YX0sClU3OmZ1bmN0aW9uIFU3KGEpe3RoaXMuYT1hfSwKdnI6ZnVuY3Rpb24gdnIoYSxiLGMp
+e3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKckg6ZnVuY3Rpb24gckgoYSxiKXt0aGlzLmE9YQp0
+aGlzLmI9Yn0sCktGOmZ1bmN0aW9uIEtGKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApaTDpmdW5jdGlv
+biBaTChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApSVDpmdW5jdGlvbiBSVChhLGIs
+YyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKalo6ZnVuY3Rpb24galooYSl7
+dGhpcy5hPWF9LApycTpmdW5jdGlvbiBycShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9
+LApSVzpmdW5jdGlvbiBSVyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApPTTpmdW5j
+dGlvbiBPTShhKXt0aGlzLmE9YQp0aGlzLmI9bnVsbH0sCnFoOmZ1bmN0aW9uIHFoKCl7fSwKQjU6ZnVu
+Y3Rpb24gQjUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sClBJOmZ1bmN0aW9uIFBJKGEsYil7dGhpcy5h
+PWEKdGhpcy5iPWJ9LApNTzpmdW5jdGlvbiBNTygpe30sCmtUOmZ1bmN0aW9uIGtUKCl7fSwKeEk6ZnVu
+Y3Rpb24geEkoYSl7dGhpcy4kdGk9YX0sCk9IOmZ1bmN0aW9uIE9IKGEsYil7dGhpcy5hPWEKdGhpcy5i
+PWJ9LAptMDpmdW5jdGlvbiBtMCgpe30sCnBLOmZ1bmN0aW9uIHBLKGEpe3RoaXMuYT1hfSwKSmk6ZnVu
+Y3Rpb24gSmkoKXt9LApoajpmdW5jdGlvbiBoaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5j
+PWN9LApWcDpmdW5jdGlvbiBWcChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKT1I6ZnVuY3Rpb24gT1Io
+YSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKRUY6ZnVuY3Rpb24oYSxiLGMpe3JldHVy
+biBiLkMoIkA8MD4iKS5LKGMpLkMoIkZvPDEsMj4iKS5hKEguQjcoYSxuZXcgSC5ONShiLkMoIkA8MD4i
+KS5LKGMpLkMoIk41PDEsMj4iKSkpKX0sCkZsOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILk41KGEu
+QygiQDwwPiIpLksoYikuQygiTjU8MSwyPiIpKX0sCkxzOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5i
+NihhLkMoImI2PDA+IikpfSwKVDI6ZnVuY3Rpb24oKXt2YXIgdD1PYmplY3QuY3JlYXRlKG51bGwpCnRb
+Ijxub24taWRlbnRpZmllci1rZXk+Il09dApkZWxldGUgdFsiPG5vbi1pZGVudGlmaWVyLWtleT4iXQpy
+ZXR1cm4gdH0sCnJqOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1uZXcgUC5sbShhLGIsYy5DKCJsbTwwPiIp
+KQp0LmM9YS5lCnJldHVybiB0fSwKRVA6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoUC5oQihhKSl7
+aWYoYj09PSIoIiYmYz09PSIpIilyZXR1cm4iKC4uLikiCnJldHVybiBiKyIuLi4iK2N9dD1ILlZNKFtd
+LHUucykKQy5ObS5BKCQueGcsYSkKdHJ5e1AuVnIoYSx0KX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3Ro
+KXJldHVybiBILmsoJC54ZywtMSkKJC54Zy5wb3AoKX1zPVAudmcoYix1LlIuYSh0KSwiLCAiKStjCnJl
+dHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKV0U6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYo
+UC5oQihhKSlyZXR1cm4gYisiLi4uIitjCnQ9bmV3IFAuUm4oYikKQy5ObS5BKCQueGcsYSkKdHJ5e3M9
+dApzLmE9UC52ZyhzLmEsYSwiLCAiKX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILmso
+JC54ZywtMSkKJC54Zy5wb3AoKX10LmErPWMKcz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9z
+OnN9LApoQjpmdW5jdGlvbihhKXt2YXIgdCxzCmZvcih0PSQueGcubGVuZ3RoLHM9MDtzPHQ7KytzKWlm
+KGE9PT0kLnhnW3NdKXJldHVybiEwCnJldHVybiExfSwKVnI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIs
+cSxwLG8sbixtPWEuZ3coYSksbD0wLGs9MAp3aGlsZSghMCl7aWYoIShsPDgwfHxrPDMpKWJyZWFrCmlm
+KCFtLm0oKSlyZXR1cm4KdD1ILmQobS5nUihtKSkKQy5ObS5BKGIsdCkKbCs9dC5sZW5ndGgrMjsrK2t9
+aWYoIW0ubSgpKXtpZihrPD01KXJldHVybgppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCnM9
+Yi5wb3AoKQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCnI9Yi5wb3AoKX1lbHNle3E9bS5n
+UihtKTsrK2sKaWYoIW0ubSgpKXtpZihrPD00KXtDLk5tLkEoYixILmQocSkpCnJldHVybn1zPUguZChx
+KQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCnI9Yi5wb3AoKQpsKz1zLmxlbmd0aCsyfWVs
+c2V7cD1tLmdSKG0pOysrawpmb3IoO20ubSgpO3E9cCxwPW8pe289bS5nUihtKTsrK2sKaWYoaz4xMDAp
+e3doaWxlKCEwKXtpZighKGw+NzUmJms+MykpYnJlYWsKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguayhi
+LC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyOy0ta31DLk5tLkEoYiwiLi4uIikKcmV0dXJufX1yPUguZChx
+KQpzPUguZChwKQpsKz1zLmxlbmd0aCtyLmxlbmd0aCs0fX1pZihrPmIubGVuZ3RoKzIpe2wrPTUKbj0i
+Li4uIn1lbHNlIG49bnVsbAp3aGlsZSghMCl7aWYoIShsPjgwJiZiLmxlbmd0aD4zKSlicmVhawppZigw
+Pj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCmwtPWIucG9wKCkubGVuZ3RoKzIKaWYobj09bnVsbCl7
+bCs9NQpuPSIuLi4ifX1pZihuIT1udWxsKUMuTm0uQShiLG4pCkMuTm0uQShiLHIpCkMuTm0uQShiLHMp
+fSwKdE06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9UC5McyhiKQpmb3IodD1hLmxlbmd0aCxzPTA7czxh
+Lmxlbmd0aDthLmxlbmd0aD09PXR8fCgwLEgubGspKGEpLCsrcylyLkEoMCxiLmEoYVtzXSkpCnJldHVy
+biByfSwKbk86ZnVuY3Rpb24oYSl7dmFyIHQscz17fQppZihQLmhCKGEpKXJldHVybiJ7Li4ufSIKdD1u
+ZXcgUC5SbigiIikKdHJ5e0MuTm0uQSgkLnhnLGEpCnQuYSs9InsiCnMuYT0hMApKLmhFKGEsbmV3IFAu
+cmEocyx0KSkKdC5hKz0ifSJ9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5rKCQueGcs
+LTEpCiQueGcucG9wKCl9cz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApiNjpmdW5j
+dGlvbiBiNihhKXt2YXIgXz10aGlzCl8uYT0wCl8uZj1fLmU9Xy5kPV8uYz1fLmI9bnVsbApfLnI9MApf
+LiR0aT1hfSwKYm46ZnVuY3Rpb24gYm4oYSl7dGhpcy5hPWEKdGhpcy5jPXRoaXMuYj1udWxsfSwKbG06
+ZnVuY3Rpb24gbG0oYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsCl8uJHRp
+PWN9LAptVzpmdW5jdGlvbiBtVygpe30sCkxVOmZ1bmN0aW9uIExVKCl7fSwKbEQ6ZnVuY3Rpb24gbEQo
+KXt9LAppbDpmdW5jdGlvbiBpbCgpe30sCnJhOmZ1bmN0aW9uIHJhKGEsYil7dGhpcy5hPWEKdGhpcy5i
+PWJ9LApZazpmdW5jdGlvbiBZaygpe30sCnlROmZ1bmN0aW9uIHlRKGEpe3RoaXMuYT1hfSwKS1A6ZnVu
+Y3Rpb24gS1AoKXt9LApQbjpmdW5jdGlvbiBQbigpe30sCkdqOmZ1bmN0aW9uIEdqKGEsYil7dGhpcy5h
+PWEKdGhpcy4kdGk9Yn0sCk1hOmZ1bmN0aW9uIE1hKCl7fSwKUks6ZnVuY3Rpb24gUksoKXt9LApYdjpm
+dW5jdGlvbiBYdigpe30sCm5ZOmZ1bmN0aW9uIG5ZKCl7fSwKTGo6ZnVuY3Rpb24gTGooKXt9LApSVTpm
+dW5jdGlvbiBSVSgpe30sCkJTOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKaWYodHlwZW9mIGEhPSJz
+dHJpbmciKXRocm93IEguYihILnRMKGEpKQp0PW51bGwKdHJ5e3Q9SlNPTi5wYXJzZShhKX1jYXRjaChy
+KXtzPUguUnUocikKcT1QLnJyKFN0cmluZyhzKSxudWxsLG51bGwpCnRocm93IEguYihxKX1xPVAuUWUo
+dCkKcmV0dXJuIHF9LApRZTpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBudWxsCmlm
+KHR5cGVvZiBhIT0ib2JqZWN0IilyZXR1cm4gYQppZihPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkhPT1B
+cnJheS5wcm90b3R5cGUpcmV0dXJuIG5ldyBQLnV3KGEsT2JqZWN0LmNyZWF0ZShudWxsKSkKZm9yKHQ9
+MDt0PGEubGVuZ3RoOysrdClhW3RdPVAuUWUoYVt0XSkKcmV0dXJuIGF9LApreTpmdW5jdGlvbihhLGIs
+YyxkKXtpZihiIGluc3RhbmNlb2YgVWludDhBcnJheSlyZXR1cm4gUC5SUCghMSxiLGMsZCkKcmV0dXJu
+IG51bGx9LApSUDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHI9JC5yZigpCmlmKHI9PW51bGwpcmV0
+dXJuIG51bGwKdD0wPT09YwppZih0JiYhMClyZXR1cm4gUC5PUShyLGIpCnM9Yi5sZW5ndGgKZD1QLmpC
+KGMsZCxzKQppZih0JiZkPT09cylyZXR1cm4gUC5PUShyLGIpCnJldHVybiBQLk9RKHIsYi5zdWJhcnJh
+eShjLGQpKX0sCk9ROmZ1bmN0aW9uKGEsYil7aWYoUC5BaihiKSlyZXR1cm4gbnVsbApyZXR1cm4gUC5K
+aChhLGIpfSwKSmg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnRyeXt0PWEuZGVjb2RlKGIpCnJldHVybiB0
+fWNhdGNoKHMpe0guUnUocyl9cmV0dXJuIG51bGx9LApBajpmdW5jdGlvbihhKXt2YXIgdCxzPWEubGVu
+Z3RoLTIKZm9yKHQ9MDt0PHM7Kyt0KWlmKGFbdF09PT0yMzcpaWYoKGFbdCsxXSYyMjQpPT09MTYwKXJl
+dHVybiEwCnJldHVybiExfSwKV0k6ZnVuY3Rpb24oKXt2YXIgdCxzCnRyeXt0PW5ldyBUZXh0RGVjb2Rl
+cigidXRmLTgiLHtmYXRhbDp0cnVlfSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKX1yZXR1cm4gbnVs
+bH0sCmNQOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIKZm9yKHQ9Si5VNihhKSxzPWI7czxjOysrcyl7
+cj10LnEoYSxzKQppZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLnpNKCkKaWYoKHImMTI3KSE9
+PXIpcmV0dXJuIHMtYn1yZXR1cm4gYy1ifSwKeE06ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe2lmKEMuam4u
+elkoZiw0KSE9PTApdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsIHBhZGRlZCBs
+ZW5ndGggbXVzdCBiZSBtdWx0aXBsZSBvZiBmb3VyLCBpcyAiK2YsYSxjKSkKaWYoZCtlIT09Zil0aHJv
+dyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQgcGFkZGluZywgJz0nIG5vdCBhdCB0aGUgZW5kIixhLGIp
+KQppZihlPjIpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsIG1vcmUgdGhhbiB0
+d28gJz0nIGNoYXJhY3RlcnMiLGEsYikpfSwKdXc6ZnVuY3Rpb24gdXcoYSxiKXt0aGlzLmE9YQp0aGlz
+LmI9Ygp0aGlzLmM9bnVsbH0sCmk4OmZ1bmN0aW9uIGk4KGEpe3RoaXMuYT1hfSwKQ1Y6ZnVuY3Rpb24g
+Q1YoKXt9LAp2QTpmdW5jdGlvbiB2QSgpe30sClVrOmZ1bmN0aW9uIFVrKCl7fSwKd0k6ZnVuY3Rpb24g
+d0koKXt9LApaaTpmdW5jdGlvbiBaaSgpe30sCmJ5OmZ1bmN0aW9uIGJ5KCl7fSwKTXg6ZnVuY3Rpb24g
+TXgoYSl7dGhpcy5hPWF9LAp1NTpmdW5jdGlvbiB1NSgpe30sCkUzOmZ1bmN0aW9uIEUzKCl7fSwKUnc6
+ZnVuY3Rpb24gUncoYSl7dGhpcy5iPTAKdGhpcy5jPWF9LApHWTpmdW5jdGlvbiBHWShhKXt0aGlzLmE9
+YX0sCmJ6OmZ1bmN0aW9uIGJ6KGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9ITAKXy5mPV8u
+ZT1fLmQ9MH0sClFBOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkhwKGEsYykKaWYodCE9bnVsbClyZXR1
+cm4gdAppZihiIT1udWxsKXJldHVybiBiLiQxKGEpCnRocm93IEguYihQLnJyKGEsbnVsbCxudWxsKSl9
+LApvczpmdW5jdGlvbihhKXtpZihhIGluc3RhbmNlb2YgSC5UcClyZXR1cm4gYS5aKDApCnJldHVybiJJ
+bnN0YW5jZSBvZiAnIitILmQoSC5saChhKSkrIicifSwKTzg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9
+Si5RaShhLGMpCmlmKGEhPT0wJiYhMClmb3IodD0wO3Q8cy5sZW5ndGg7Kyt0KUMuTm0udChzLHQsYikK
+cmV0dXJuIHN9LApDSDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1ILlZNKFtdLGMuQygiamQ8MD4iKSkK
+Zm9yKHQ9Si5JVChhKTt0Lm0oKTspQy5ObS5BKHMsYy5hKHQuZ1IodCkpKQppZihiKXJldHVybiBzCnJl
+dHVybiBjLkMoInpNPDA+IikuYShKLkVwKHMpKX0sCkFGOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGIuQygi
+ek08MD4iKS5hKEoudW4oUC5DSChhLCExLGIpKSl9LApITTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYo
+QXJyYXkuaXNBcnJheShhKSl7dS50LmEoYSkKdD1hLmxlbmd0aApjPVAuakIoYixjLHQpCnJldHVybiBI
+LmVUKGI+MHx8Yzx0P0MuTm0uRDYoYSxiLGMpOmEpfWlmKHUuYm0uYihhKSlyZXR1cm4gSC5mdyhhLGIs
+UC5qQihiLGMsYS5sZW5ndGgpKQpyZXR1cm4gUC5idyhhLGIsYyl9LApPbzpmdW5jdGlvbihhKXtyZXR1
+cm4gSC5MdyhhKX0sCmJ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwPW51bGwKaWYoYjwwKXRo
+cm93IEguYihQLlRFKGIsMCxKLkgoYSkscCxwKSkKdD1jPT1udWxsCmlmKCF0JiZjPGIpdGhyb3cgSC5i
+KFAuVEUoYyxiLEouSChhKSxwLHApKQpzPUouSVQoYSkKZm9yKHI9MDtyPGI7KytyKWlmKCFzLm0oKSl0
+aHJvdyBILmIoUC5URShiLDAscixwLHApKQpxPVtdCmlmKHQpZm9yKDtzLm0oKTspcS5wdXNoKHMuZ1Io
+cykpCmVsc2UgZm9yKHI9YjtyPGM7KytyKXtpZighcy5tKCkpdGhyb3cgSC5iKFAuVEUoYyxiLHIscCxw
+KSkKcS5wdXNoKHMuZ1IocykpfXJldHVybiBILmVUKHEpfSwKbnU6ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
+dyBILlZSKGEsSC52NChhLCExLCEwLCExLCExLCExKSl9LAp2ZzpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9
+Si5JVChiKQppZighdC5tKCkpcmV0dXJuIGEKaWYoYy5sZW5ndGg9PT0wKXtkbyBhKz1ILmQodC5nUih0
+KSkKd2hpbGUodC5tKCkpfWVsc2V7YSs9SC5kKHQuZ1IodCkpCmZvcig7dC5tKCk7KWE9YStjK0guZCh0
+LmdSKHQpKX1yZXR1cm4gYX0sCmxyOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBuZXcgUC5tcChhLGIs
+YyxkKX0sCnVvOmZ1bmN0aW9uKCl7dmFyIHQ9SC5NMCgpCmlmKHQhPW51bGwpcmV0dXJuIFAuaEsodCkK
+dGhyb3cgSC5iKFAuTDQoIidVcmkuYmFzZScgaXMgbm90IHN1cHBvcnRlZCIpKX0sCmVQOmZ1bmN0aW9u
+KGEsYixjLGQpe3ZhciB0LHMscixxLHAsbyxuPSIwMTIzNDU2Nzg5QUJDREVGIgppZihjPT09Qy54TSl7
+dD0kLno0KCkuYgppZih0eXBlb2YgYiE9InN0cmluZyIpSC5WaihILnRMKGIpKQp0PXQudGVzdChiKX1l
+bHNlIHQ9ITEKaWYodClyZXR1cm4gYgpILkxoKGMpLkMoIlVrLlMiKS5hKGIpCnM9Yy5nWkUoKS5XSihi
+KQpmb3IodD1zLmxlbmd0aCxyPTAscT0iIjtyPHQ7KytyKXtwPXNbcl0KaWYocDwxMjgpe289cD4+PjQK
+aWYobz49OClyZXR1cm4gSC5rKGEsbykKbz0oYVtvXSYxPDwocCYxNSkpIT09MH1lbHNlIG89ITEKaWYo
+bylxKz1ILkx3KHApCmVsc2UgcT1kJiZwPT09MzI/cSsiKyI6cSsiJSIrbltwPj4+NCYxNV0rbltwJjE1
+XX1yZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sClpiOmZ1bmN0aW9uKCl7dmFyIHQscwppZihI
+Lm9UKCQucDYoKSkpcmV0dXJuIEgudHMobmV3IEVycm9yKCkpCnRyeXt0aHJvdyBILmIoIiIpfWNhdGNo
+KHMpe0guUnUocykKdD1ILnRzKHMpCnJldHVybiB0fX0sCkdxOmZ1bmN0aW9uKGEpe3ZhciB0PU1hdGgu
+YWJzKGEpLHM9YTwwPyItIjoiIgppZih0Pj0xMDAwKXJldHVybiIiK2EKaWYodD49MTAwKXJldHVybiBz
+KyIwIit0CmlmKHQ+PTEwKXJldHVybiBzKyIwMCIrdApyZXR1cm4gcysiMDAwIit0fSwKVng6ZnVuY3Rp
+b24oYSl7aWYoYT49MTAwKXJldHVybiIiK2EKaWYoYT49MTApcmV0dXJuIjAiK2EKcmV0dXJuIjAwIith
+fSwKaDA6ZnVuY3Rpb24oYSl7aWYoYT49MTApcmV0dXJuIiIrYQpyZXR1cm4iMCIrYX0sCmg6ZnVuY3Rp
+b24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIifHxILnJRKGEpfHxudWxsPT1hKXJldHVybiBKLkFjKGEp
+CmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSlNPTi5zdHJpbmdpZnkoYSkKcmV0dXJuIFAub3Mo
+YSl9LApoVjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQzYoYSl9LAp4WTpmdW5jdGlvbihhKXtyZXR1
+cm4gbmV3IFAuQVQoITEsbnVsbCxudWxsLGEpfSwKTDM6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcg
+UC5BVCghMCxhLGIsYyl9LApoRzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQVQoITEsbnVsbCxhLCJN
+dXN0IG5vdCBiZSBudWxsIil9LApVSTpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbCl0aHJvdyBILmIo
+UC5oRyhiKSkKcmV0dXJuIGF9LApPNzpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5iSihudWxsLG51
+bGwsITAsYSxiLCJWYWx1ZSBub3QgaW4gcmFuZ2UiKX0sClRFOmZ1bmN0aW9uKGEsYixjLGQsZSl7cmV0
+dXJuIG5ldyBQLmJKKGIsYywhMCxhLGQsIkludmFsaWQgdmFsdWUiKX0sCndBOmZ1bmN0aW9uKGEsYixj
+LGQpe2lmKGE8Ynx8YT5jKXRocm93IEguYihQLlRFKGEsYixjLGQsbnVsbCkpCnJldHVybiBhfSwKakI6
+ZnVuY3Rpb24oYSxiLGMpe2lmKDA+YXx8YT5jKXRocm93IEguYihQLlRFKGEsMCxjLCJzdGFydCIsbnVs
+bCkpCmlmKGIhPW51bGwpe2lmKGE+Ynx8Yj5jKXRocm93IEguYihQLlRFKGIsYSxjLCJlbmQiLG51bGwp
+KQpyZXR1cm4gYn1yZXR1cm4gY30sCmsxOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGEhPT0ibnVtYmVy
+IilyZXR1cm4gYS5KKCkKaWYoYTwwKXRocm93IEguYihQLlRFKGEsMCxudWxsLGIsbnVsbCkpCnJldHVy
+biBhfSwKdDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PUguV1koZT09bnVsbD9KLkgoYik6ZSkKcmV0
+dXJuIG5ldyBQLmVZKHQsITAsYSxjLCJJbmRleCBvdXQgb2YgcmFuZ2UiKX0sCkw0OmZ1bmN0aW9uKGEp
+e3JldHVybiBuZXcgUC51YihhKX0sCm46ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmRzKGEpfSwKUFY6
+ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmxqKGEpfSwKYTQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQ
+LlVWKGEpfSwKcnI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcgUC5hRShhLGIsYyl9LApkSDpmdW5j
+dGlvbihhLGIsYyxkKXt2YXIgdCxzPUguVk0oW10sZC5DKCJqZDwwPiIpKQpDLk5tLnNrKHMsYSkKZm9y
+KHQ9MDt0PGE7Kyt0KUMuTm0udChzLHQsYi4kMSh0KSkKcmV0dXJuIHN9LApoSzpmdW5jdGlvbihhKXt2
+YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT1udWxsLGQ9YS5sZW5ndGgKaWYoZD49NSl7
+dD0oKEouUXooYSw0KV41OCkqM3xDLnhCLldkKGEsMCleMTAwfEMueEIuV2QoYSwxKV45N3xDLnhCLldk
+KGEsMileMTE2fEMueEIuV2QoYSwzKV45Nyk+Pj4wCmlmKHQ9PT0wKXJldHVybiBQLktEKGQ8ZD9DLnhC
+Lk5qKGEsMCxkKTphLDUsZSkuZ2xSKCkKZWxzZSBpZih0PT09MzIpcmV0dXJuIFAuS0QoQy54Qi5Oaihh
+LDUsZCksMCxlKS5nbFIoKX1zPW5ldyBBcnJheSg4KQpzLmZpeGVkJGxlbmd0aD1BcnJheQpyPUguVk0o
+cyx1LnQpCkMuTm0udChyLDAsMCkKQy5ObS50KHIsMSwtMSkKQy5ObS50KHIsMiwtMSkKQy5ObS50KHIs
+NywtMSkKQy5ObS50KHIsMywwKQpDLk5tLnQociw0LDApCkMuTm0udChyLDUsZCkKQy5ObS50KHIsNixk
+KQppZihQLlVCKGEsMCxkLDAscik+PTE0KUMuTm0udChyLDcsZCkKcT1yWzFdCmlmKHR5cGVvZiBxIT09
+Im51bWJlciIpcmV0dXJuIHEudEIoKQppZihxPj0wKWlmKFAuVUIoYSwwLHEsMjAscik9PT0yMClyWzdd
+PXEKcz1yWzJdCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuaCgpCnA9cysxCm89clszXQpu
+PXJbNF0KbT1yWzVdCmw9cls2XQppZih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLkooKQppZih0
+eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBILnBZKG0pCmlmKGw8bSltPWwKaWYodHlwZW9mIG4hPT0i
+bnVtYmVyIilyZXR1cm4gbi5KKCkKaWYobjxwKW49bQplbHNlIGlmKG48PXEpbj1xKzEKaWYodHlwZW9m
+IG8hPT0ibnVtYmVyIilyZXR1cm4gby5KKCkKaWYobzxwKW89bgpzPXJbN10KaWYodHlwZW9mIHMhPT0i
+bnVtYmVyIilyZXR1cm4gcy5KKCkKaz1zPDAKaWYoaylpZihwPnErMyl7aj1lCms9ITF9ZWxzZXtzPW8+
+MAppZihzJiZvKzE9PT1uKXtqPWUKaz0hMX1lbHNle2lmKCEobTxkJiZtPT09bisyJiZKLnEwKGEsIi4u
+IixuKSkpaT1tPm4rMiYmSi5xMChhLCIvLi4iLG0tMykKZWxzZSBpPSEwCmlmKGkpe2o9ZQprPSExfWVs
+c2V7aWYocT09PTQpaWYoSi5xMChhLCJmaWxlIiwwKSl7aWYocDw9MCl7aWYoIUMueEIuUWkoYSwiLyIs
+bikpe2g9ImZpbGU6Ly8vIgp0PTN9ZWxzZXtoPSJmaWxlOi8vIgp0PTJ9YT1oK0MueEIuTmooYSxuLGQp
+CnEtPTAKcz10LTAKbSs9cwpsKz1zCmQ9YS5sZW5ndGgKcD03Cm89NwpuPTd9ZWxzZSBpZihuPT09bSl7
+Zz1tKzE7KytsCmE9Qy54Qi5pNyhhLG4sbSwiLyIpOysrZAptPWd9aj0iZmlsZSJ9ZWxzZSBpZihDLnhC
+LlFpKGEsImh0dHAiLDApKXtpZihzJiZvKzM9PT1uJiZDLnhCLlFpKGEsIjgwIixvKzEpKXtmPW4tMwpt
+LT0zCmwtPTMKYT1DLnhCLmk3KGEsbyxuLCIiKQpkLT0zCm49Zn1qPSJodHRwIn1lbHNlIGo9ZQplbHNl
+IGlmKHE9PT01JiZKLnEwKGEsImh0dHBzIiwwKSl7aWYocyYmbys0PT09biYmSi5xMChhLCI0NDMiLG8r
+MSkpe2Y9bi00Cm0tPTQKbC09NAphPUouZGcoYSxvLG4sIiIpCmQtPTMKbj1mfWo9Imh0dHBzIn1lbHNl
+IGo9ZQprPSEwfX19ZWxzZSBqPWUKaWYoayl7cz1hLmxlbmd0aAppZihkPHMpe2E9Si5sZChhLDAsZCkK
+cS09MApwLT0wCm8tPTAKbi09MAptLT0wCmwtPTB9cmV0dXJuIG5ldyBQLlVmKGEscSxwLG8sbixtLGws
+ail9cmV0dXJuIFAuanYoYSwwLGQscSxwLG8sbixtLGwsail9LApNdDpmdW5jdGlvbihhKXtILmMoYSkK
+cmV0dXJuIFAua3UoYSwwLGEubGVuZ3RoLEMueE0sITEpfSwKV1g6ZnVuY3Rpb24oYSl7dmFyIHQ9dS5O
+CnJldHVybiBDLk5tLk4wKEguVk0oYS5zcGxpdCgiJiIpLHUucyksUC5GbCh0LHQpLG5ldyBQLm4xKEMu
+eE0pLHUuZil9LApIaDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbT1udWxsLGw9IklQ
+djQgYWRkcmVzcyBzaG91bGQgY29udGFpbiBleGFjdGx5IDQgcGFydHMiLGs9ImVhY2ggcGFydCBtdXN0
+IGJlIGluIHRoZSByYW5nZSAwLi4yNTUiLGo9bmV3IFAuY1MoYSksaT1uZXcgVWludDhBcnJheSg0KQpm
+b3IodD1pLmxlbmd0aCxzPWIscj1zLHE9MDtzPGM7KytzKXtwPUMueEIuTzIoYSxzKQppZihwIT09NDYp
+e2lmKChwXjQ4KT45KWouJDIoImludmFsaWQgY2hhcmFjdGVyIixzKX1lbHNle2lmKHE9PT0zKWouJDIo
+bCxzKQpvPVAuUUEoQy54Qi5OaihhLHIscyksbSxtKQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVy
+biBvLm9zKCkKaWYobz4yNTUpai4kMihrLHIpCm49cSsxCmlmKHE+PXQpcmV0dXJuIEguayhpLHEpCmlb
+cV09bwpyPXMrMQpxPW59fWlmKHEhPT0zKWouJDIobCxjKQpvPVAuUUEoQy54Qi5OaihhLHIsYyksbSxt
+KQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBvLm9zKCkKaWYobz4yNTUpai4kMihrLHIpCmlm
+KHE+PXQpcmV0dXJuIEguayhpLHEpCmlbcV09bwpyZXR1cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7
+dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZD1uZXcgUC5WQyhhKSxjPW5ldyBQLkpU
+KGQsYSkKaWYoYS5sZW5ndGg8MilkLiQxKCJhZGRyZXNzIGlzIHRvbyBzaG9ydCIpCnQ9SC5WTShbXSx1
+LnQpCmZvcihzPWIscj1zLHE9ITEscD0hMTtzPGEwOysrcyl7bz1DLnhCLk8yKGEscykKaWYobz09PTU4
+KXtpZihzPT09Yil7KytzCmlmKEMueEIuTzIoYSxzKSE9PTU4KWQuJDIoImludmFsaWQgc3RhcnQgY29s
+b24uIixzKQpyPXN9aWYocz09PXIpe2lmKHEpZC4kMigib25seSBvbmUgd2lsZGNhcmQgYDo6YCBpcyBh
+bGxvd2VkIixzKQpDLk5tLkEodCwtMSkKcT0hMH1lbHNlIEMuTm0uQSh0LGMuJDIocixzKSkKcj1zKzF9
+ZWxzZSBpZihvPT09NDYpcD0hMH1pZih0Lmxlbmd0aD09PTApZC4kMSgidG9vIGZldyBwYXJ0cyIpCm49
+cj09PWEwCm09Qy5ObS5ncloodCkKaWYobiYmbSE9PS0xKWQuJDIoImV4cGVjdGVkIGEgcGFydCBhZnRl
+ciBsYXN0IGA6YCIsYTApCmlmKCFuKWlmKCFwKUMuTm0uQSh0LGMuJDIocixhMCkpCmVsc2V7bD1QLkho
+KGEscixhMCkKQy5ObS5BKHQsKGxbMF08PDh8bFsxXSk+Pj4wKQpDLk5tLkEodCwobFsyXTw8OHxsWzNd
+KT4+PjApfWlmKHEpe2lmKHQubGVuZ3RoPjcpZC4kMSgiYW4gYWRkcmVzcyB3aXRoIGEgd2lsZGNhcmQg
+bXVzdCBoYXZlIGxlc3MgdGhhbiA3IHBhcnRzIil9ZWxzZSBpZih0Lmxlbmd0aCE9PTgpZC4kMSgiYW4g
+YWRkcmVzcyB3aXRob3V0IGEgd2lsZGNhcmQgbXVzdCBjb250YWluIGV4YWN0bHkgOCBwYXJ0cyIpCms9
+bmV3IFVpbnQ4QXJyYXkoMTYpCmZvcihtPXQubGVuZ3RoLGo9ay5sZW5ndGgsaT05LW0scz0wLGg9MDtz
+PG07KytzKXtnPXRbc10KaWYoZz09PS0xKWZvcihmPTA7ZjxpOysrZil7aWYoaDwwfHxoPj1qKXJldHVy
+biBILmsoayxoKQprW2hdPTAKZT1oKzEKaWYoZT49ailyZXR1cm4gSC5rKGssZSkKa1tlXT0wCmgrPTJ9
+ZWxzZXtlPUMuam4ud0coZyw4KQppZihoPDB8fGg+PWopcmV0dXJuIEguayhrLGgpCmtbaF09ZQplPWgr
+MQppZihlPj1qKXJldHVybiBILmsoayxlKQprW2VdPWcmMjU1CmgrPTJ9fXJldHVybiBrfSwKanY6ZnVu
+Y3Rpb24oYSxiLGMsZCxlLGYsZyxoLGksail7dmFyIHQscyxyLHEscCxvLG4sbT1udWxsCmlmKGo9PW51
+bGwpaWYoZD5iKWo9UC5QaShhLGIsZCkKZWxzZXtpZihkPT09YilQLlIzKGEsYiwiSW52YWxpZCBlbXB0
+eSBzY2hlbWUiKQpqPSIifWlmKGU+Yil7dD1kKzMKcz10PGU/UC56UihhLHQsZS0xKToiIgpyPVAuT2Uo
+YSxlLGYsITEpCmlmKHR5cGVvZiBmIT09Im51bWJlciIpcmV0dXJuIGYuaCgpCnE9ZisxCmlmKHR5cGVv
+ZiBnIT09Im51bWJlciIpcmV0dXJuIEgucFkoZykKcD1xPGc/UC53QihQLlFBKEoubGQoYSxxLGcpLG5l
+dyBQLmUxKGEsZiksbSksaik6bX1lbHNle3A9bQpyPXAKcz0iIn1vPVAua2EoYSxnLGgsbSxqLHIhPW51
+bGwpCmlmKHR5cGVvZiBoIT09Im51bWJlciIpcmV0dXJuIGguSigpCm49aDxpP1AubGUoYSxoKzEsaSxt
+KTptCnJldHVybiBuZXcgUC5EbihqLHMscixwLG8sbixpPGM/UC50RyhhLGkrMSxjKTptKX0sCndLOmZ1
+bmN0aW9uKGEpe2lmKGE9PT0iaHR0cCIpcmV0dXJuIDgwCmlmKGE9PT0iaHR0cHMiKXJldHVybiA0NDMK
+cmV0dXJuIDB9LApSMzpmdW5jdGlvbihhLGIsYyl7dGhyb3cgSC5iKFAucnIoYyxhLGIpKX0sCmtFOmZ1
+bmN0aW9uKGEsYil7Qy5ObS5VKGEsbmV3IFAuTlkoITEpKX0sCkhOOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzLHIKZm9yKHQ9SC5xQyhhLGMsbnVsbCxILnQ2KGEpLmMpLHQ9bmV3IEguYTcodCx0LmdrKHQpLHQu
+JHRpLkMoImE3PGFMLkU+IikpO3QubSgpOyl7cz10LmQKcj1QLm51KCdbIiovOjw+P1xcXFx8XScpCnMu
+dG9TdHJpbmcKaWYoSC5tMihzLHIsMCkpe3Q9UC5MNCgiSWxsZWdhbCBjaGFyYWN0ZXIgaW4gcGF0aDog
+IitzKQp0aHJvdyBILmIodCl9fX0sCnJnOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoISg2NTw9YSYmYTw9
+OTApKXQ9OTc8PWEmJmE8PTEyMgplbHNlIHQ9ITAKaWYodClyZXR1cm4KdD1QLkw0KCJJbGxlZ2FsIGRy
+aXZlIGxldHRlciAiK1AuT28oYSkpCnRocm93IEguYih0KX0sCndCOmZ1bmN0aW9uKGEsYil7aWYoYSE9
+bnVsbCYmYT09PVAud0soYikpcmV0dXJuIG51bGwKcmV0dXJuIGF9LApPZTpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgdCxzLHIscSxwLG8KaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZihiPT09YylyZXR1cm4iIgpp
+ZihDLnhCLk8yKGEsYik9PT05MSl7aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gYy5ITigpCnQ9
+Yy0xCmlmKEMueEIuTzIoYSx0KSE9PTkzKVAuUjMoYSxiLCJNaXNzaW5nIGVuZCBgXWAgdG8gbWF0Y2gg
+YFtgIGluIGhvc3QiKQpzPWIrMQpyPVAudG8oYSxzLHQpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0
+dXJuIHIuSigpCmlmKHI8dCl7cT1yKzEKcD1QLk9BKGEsQy54Qi5RaShhLCIyNSIscSk/ciszOnEsdCwi
+JTI1Iil9ZWxzZSBwPSIiClAuZWcoYSxzLHIpCnJldHVybiBDLnhCLk5qKGEsYixyKS50b0xvd2VyQ2Fz
+ZSgpK3ArIl0ifWlmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIEgucFkoYykKbz1iCmZvcig7bzxj
+OysrbylpZihDLnhCLk8yKGEsbyk9PT01OCl7cj1DLnhCLlhVKGEsIiUiLGIpCmlmKCEocj49YiYmcjxj
+KSlyPWMKaWYocjxjKXtxPXIrMQpwPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixxKT9yKzM6cSxjLCIlMjUi
+KX1lbHNlIHA9IiIKUC5lZyhhLGIscikKcmV0dXJuIlsiK0MueEIuTmooYSxiLHIpK3ArIl0ifXJldHVy
+biBQLk9MKGEsYixjKX0sCnRvOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPUMueEIuWFUoYSwiJSIsYikK
+aWYocz49Yil7aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShjKQp0PXM8Y31lbHNlIHQ9
+ITEKcmV0dXJuIHQ/czpjfSwKT0E6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvLG4sbSxs
+LGs9ZCE9PSIiP25ldyBQLlJuKGQpOm51bGwKaWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5w
+WShjKQp0PWIKcz10CnI9ITAKZm9yKDt0PGM7KXtxPUMueEIuTzIoYSx0KQppZihxPT09Mzcpe3A9UC5y
+dihhLHQsITApCm89cD09bnVsbAppZihvJiZyKXt0Kz0zCmNvbnRpbnVlfWlmKGs9PW51bGwpaz1uZXcg
+UC5SbigiIikKbj1rLmErPUMueEIuTmooYSxzLHQpCmlmKG8pcD1DLnhCLk5qKGEsdCx0KzMpCmVsc2Ug
+aWYocD09PSIlIilQLlIzKGEsdCwiWm9uZUlEIHNob3VsZCBub3QgY29udGFpbiAlIGFueW1vcmUiKQpr
+LmE9bitwCnQrPTMKcz10CnI9ITB9ZWxzZXtpZihxPDEyNyl7bz1xPj4+NAppZihvPj04KXJldHVybiBI
+LmsoQy5GMyxvKQpvPShDLkYzW29dJjE8PChxJjE1KSkhPT0wfWVsc2Ugbz0hMQppZihvKXtpZihyJiY2
+NTw9cSYmOTA+PXEpe2lmKGs9PW51bGwpaz1uZXcgUC5SbigiIikKaWYoczx0KXtrLmErPUMueEIuTmoo
+YSxzLHQpCnM9dH1yPSExfSsrdH1lbHNle2lmKChxJjY0NTEyKT09PTU1Mjk2JiZ0KzE8Yyl7bT1DLnhC
+Lk8yKGEsdCsxKQppZigobSY2NDUxMik9PT01NjMyMCl7cT02NTUzNnwocSYxMDIzKTw8MTB8bSYxMDIz
+Cmw9Mn1lbHNlIGw9MX1lbHNlIGw9MQppZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmsuYSs9Qy54Qi5O
+aihhLHMsdCkKay5hKz1QLkhIKHEpCnQrPWwKcz10fX19aWYoaz09bnVsbClyZXR1cm4gQy54Qi5Oaihh
+LGIsYykKaWYoczxjKWsuYSs9Qy54Qi5OaihhLHMsYykKbz1rLmEKcmV0dXJuIG8uY2hhckNvZGVBdCgw
+KT09MD9vOm99LApPTDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssagppZih0
+eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj1udWxsCnE9ITAKZm9yKDt0
+PGM7KXtwPUMueEIuTzIoYSx0KQppZihwPT09Mzcpe289UC5ydihhLHQsITApCm49bz09bnVsbAppZihu
+JiZxKXt0Kz0zCmNvbnRpbnVlfWlmKHI9PW51bGwpcj1uZXcgUC5SbigiIikKbT1DLnhCLk5qKGEscyx0
+KQpsPXIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm0KaWYobil7bz1DLnhCLk5qKGEsdCx0KzMpCms9M31l
+bHNlIGlmKG89PT0iJSIpe289IiUyNSIKaz0xfWVsc2Ugaz0zCnIuYT1sK28KdCs9awpzPXQKcT0hMH1l
+bHNle2lmKHA8MTI3KXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguayhDLmVhLG4pCm49KEMuZWFbbl0m
+MTw8KHAmMTUpKSE9PTB9ZWxzZSBuPSExCmlmKG4pe2lmKHEmJjY1PD1wJiY5MD49cCl7aWYocj09bnVs
+bClyPW5ldyBQLlJuKCIiKQppZihzPHQpe3IuYSs9Qy54Qi5OaihhLHMsdCkKcz10fXE9ITF9Kyt0fWVs
+c2V7aWYocDw9OTMpe249cD4+PjQKaWYobj49OClyZXR1cm4gSC5rKEMuYWssbikKbj0oQy5ha1tuXSYx
+PDwocCYxNSkpIT09MH1lbHNlIG49ITEKaWYobilQLlIzKGEsdCwiSW52YWxpZCBjaGFyYWN0ZXIiKQpl
+bHNle2lmKChwJjY0NTEyKT09PTU1Mjk2JiZ0KzE8Yyl7aj1DLnhCLk8yKGEsdCsxKQppZigoaiY2NDUx
+Mik9PT01NjMyMCl7cD02NTUzNnwocCYxMDIzKTw8MTB8aiYxMDIzCms9Mn1lbHNlIGs9MX1lbHNlIGs9
+MQppZihyPT1udWxsKXI9bmV3IFAuUm4oIiIpCm09Qy54Qi5OaihhLHMsdCkKci5hKz0hcT9tLnRvTG93
+ZXJDYXNlKCk6bQpyLmErPVAuSEgocCkKdCs9awpzPXR9fX19aWYocj09bnVsbClyZXR1cm4gQy54Qi5O
+aihhLGIsYykKaWYoczxjKXttPUMueEIuTmooYSxzLGMpCnIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm19
+bj1yLmEKcmV0dXJuIG4uY2hhckNvZGVBdCgwKT09MD9uOm59LApQaTpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQscyxyLHEKaWYoYj09PWMpcmV0dXJuIiIKaWYoIVAuRXQoSi5yWShhKS5XZChhLGIpKSlQLlIzKGEs
+YiwiU2NoZW1lIG5vdCBzdGFydGluZyB3aXRoIGFscGhhYmV0aWMgY2hhcmFjdGVyIikKZm9yKHQ9Yixz
+PSExO3Q8YzsrK3Qpe3I9Qy54Qi5XZChhLHQpCmlmKHI8MTI4KXtxPXI+Pj40CmlmKHE+PTgpcmV0dXJu
+IEguayhDLm1LLHEpCnE9KEMubUtbcV0mMTw8KHImMTUpKSE9PTB9ZWxzZSBxPSExCmlmKCFxKVAuUjMo
+YSx0LCJJbGxlZ2FsIHNjaGVtZSBjaGFyYWN0ZXIiKQppZig2NTw9ciYmcjw9OTApcz0hMH1hPUMueEIu
+TmooYSxiLGMpCnJldHVybiBQLllhKHM/YS50b0xvd2VyQ2FzZSgpOmEpfSwKWWE6ZnVuY3Rpb24oYSl7
+aWYoYT09PSJodHRwIilyZXR1cm4iaHR0cCIKaWYoYT09PSJmaWxlIilyZXR1cm4iZmlsZSIKaWYoYT09
+PSJodHRwcyIpcmV0dXJuImh0dHBzIgppZihhPT09InBhY2thZ2UiKXJldHVybiJwYWNrYWdlIgpyZXR1
+cm4gYX0sCnpSOmZ1bmN0aW9uKGEsYixjKXtpZihhPT1udWxsKXJldHVybiIiCnJldHVybiBQLnVPKGEs
+YixjLEMudG8sITEpfSwKa2E6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0LHM9ZT09PSJmaWxlIixy
+PXN8fGYscT1hPT1udWxsCmlmKHEmJiEwKXJldHVybiBzPyIvIjoiIgp0PSFxP1AudU8oYSxiLGMsQy5X
+ZCwhMCk6Qy5qTi5FMihkLG5ldyBQLlJaKCksdS5OKS56VigwLCIvIikKaWYodC5sZW5ndGg9PT0wKXtp
+ZihzKXJldHVybiIvIn1lbHNlIGlmKHImJiFDLnhCLm5DKHQsIi8iKSl0PSIvIit0CnJldHVybiBQLkpy
 KHQsZSxmKX0sCkpyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLmxlbmd0aD09PTAKaWYodCYmIWMmJiFD
-LnhCLm4oYSwiLyIpKXJldHVybiBQLndGKGEsIXR8fGMpCnJldHVybiBQLnhlKGEpfSwKbGU6ZnVuY3Rp
-b24oYSxiLGMsZCl7dmFyIHQscz17fQppZihhIT1udWxsKXtpZihkIT1udWxsKXRocm93IEguYihQLnhZ
-KCJCb3RoIHF1ZXJ5IGFuZCBxdWVyeVBhcmFtZXRlcnMgc3BlY2lmaWVkIikpCnJldHVybiBQLnVPKGEs
-YixjLEMuVkMsITApfWlmKGQ9PW51bGwpcmV0dXJuIG51bGwKdD1uZXcgUC5SbigiIikKcy5hPSIiCmQu
-SygwLG5ldyBQLnk1KG5ldyBQLk1FKHMsdCkpKQpzPXQuYQpyZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0w
-P3M6c30sCnRHOmZ1bmN0aW9uKGEsYixjKXtpZihhPT1udWxsKXJldHVybiBudWxsCnJldHVybiBQLnVP
-KGEsYixjLEMuVkMsITApfSwKcnY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbz1iKzIKaWYo
-bz49YS5sZW5ndGgpcmV0dXJuIiUiCnQ9Qy54Qi5tKGEsYisxKQpzPUMueEIubShhLG8pCnI9SC5vbyh0
-KQpxPUgub28ocykKaWYocjwwfHxxPDApcmV0dXJuIiUiCnA9cioxNitxCmlmKHA8MTI3KXtvPUMuam4u
-d0cocCw0KQppZihvPj04KXJldHVybiBILmsoQy5GMyxvKQpvPShDLkYzW29dJjE8PChwJjE1KSkhPT0w
-fWVsc2Ugbz0hMQppZihvKXJldHVybiBILkx3KGMmJjY1PD1wJiY5MD49cD8ocHwzMik+Pj4wOnApCmlm
-KHQ+PTk3fHxzPj05NylyZXR1cm4gQy54Qi53KGEsYixiKzMpLnRvVXBwZXJDYXNlKCkKcmV0dXJuIG51
-bGx9LApISDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbj0iMDEyMzQ1Njc4OUFCQ0RFRiIKaWYo
-YTwxMjgpe3Q9bmV3IEFycmF5KDMpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9SC5WTSh0LHUudCkKQy5O
-bS5ZKHMsMCwzNykKQy5ObS5ZKHMsMSxDLnhCLlcobixhPj4+NCkpCkMuTm0uWShzLDIsQy54Qi5XKG4s
-YSYxNSkpfWVsc2V7aWYoYT4yMDQ3KWlmKGE+NjU1MzUpe3I9MjQwCnE9NH1lbHNle3I9MjI0CnE9M31l
-bHNle3I9MTkyCnE9Mn10PW5ldyBBcnJheSgzKnEpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9SC5WTSh0
-LHUudCkKZm9yKHA9MDstLXEscT49MDtyPTEyOCl7bz1DLmpuLmJmKGEsNipxKSY2M3xyCkMuTm0uWShz
-LHAsMzcpCkMuTm0uWShzLHArMSxDLnhCLlcobixvPj4+NCkpCkMuTm0uWShzLHArMixDLnhCLlcobixv
-JjE1KSkKcCs9M319cmV0dXJuIFAuSE0ocywwLG51bGwpfSwKdU86ZnVuY3Rpb24oYSxiLGMsZCxlKXt2
-YXIgdD1QLlVsKGEsYixjLGQsZSkKcmV0dXJuIHQ9PW51bGw/Qy54Qi53KGEsYixjKTp0fSwKVWw6ZnVu
-Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG89bnVsbCxuPSFlLG09YixsPW0saz1vCndoaWxl
-KCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQppZih0eXBlb2YgYyE9PSJudW1i
-ZXIiKXJldHVybiBILnBZKGMpCmlmKCEobTxjKSlicmVhawpjJDA6e3Q9Qy54Qi5tKGEsbSkKaWYodDwx
-Mjcpe3M9dD4+PjQKaWYocz49OClyZXR1cm4gSC5rKGQscykKcz0oZFtzXSYxPDwodCYxNSkpIT09MH1l
-bHNlIHM9ITEKaWYocykrK20KZWxzZXtpZih0PT09Mzcpe3I9UC5ydihhLG0sITEpCmlmKHI9PW51bGwp
-e20rPTMKYnJlYWsgYyQwfWlmKCIlIj09PXIpe3I9IiUyNSIKcT0xfWVsc2UgcT0zfWVsc2V7aWYobilp
-Zih0PD05Myl7cz10Pj4+NAppZihzPj04KXJldHVybiBILmsoQy5hayxzKQpzPShDLmFrW3NdJjE8PCh0
-JjE1KSkhPT0wfWVsc2Ugcz0hMQplbHNlIHM9ITEKaWYocyl7UC5SMyhhLG0sIkludmFsaWQgY2hhcmFj
-dGVyIikKcT1vCnI9cX1lbHNle2lmKCh0JjY0NTEyKT09PTU1Mjk2KXtzPW0rMQppZihzPGMpe3A9Qy54
-Qi5tKGEscykKaWYoKHAmNjQ1MTIpPT09NTYzMjApe3Q9NjU1MzZ8KHQmMTAyMyk8PDEwfHAmMTAyMwpx
-PTJ9ZWxzZSBxPTF9ZWxzZSBxPTF9ZWxzZSBxPTEKcj1QLkhIKHQpfX1pZihrPT1udWxsKWs9bmV3IFAu
-Um4oIiIpCmsuYSs9Qy54Qi53KGEsbCxtKQprLmErPUguZChyKQppZih0eXBlb2YgcSE9PSJudW1iZXIi
-KXJldHVybiBILnBZKHEpCm0rPXEKbD1tfX19aWYoaz09bnVsbClyZXR1cm4gbwppZih0eXBlb2YgbCE9
-PSJudW1iZXIiKXJldHVybiBsLkooKQppZihsPGMpay5hKz1DLnhCLncoYSxsLGMpCm49ay5hCnJldHVy
-biBuLmNoYXJDb2RlQXQoMCk9PTA/bjpufSwKeUI6ZnVuY3Rpb24oYSl7aWYoQy54Qi5uKGEsIi4iKSly
-ZXR1cm4hMApyZXR1cm4gQy54Qi5PWShhLCIvLiIpIT09LTF9LAp4ZTpmdW5jdGlvbihhKXt2YXIgdCxz
-LHIscSxwLG8sbgppZighUC55QihhKSlyZXR1cm4gYQp0PUguVk0oW10sdS5zKQpmb3Iocz1hLnNwbGl0
-KCIvIikscj1zLmxlbmd0aCxxPSExLHA9MDtwPHI7KytwKXtvPXNbcF0KaWYoSi5STShvLCIuLiIpKXtu
-PXQubGVuZ3RoCmlmKG4hPT0wKXtpZigwPj1uKXJldHVybiBILmsodCwtMSkKdC5wb3AoKQppZih0Lmxl
-bmd0aD09PTApQy5ObS5pKHQsIiIpfXE9ITB9ZWxzZSBpZigiLiI9PT1vKXE9ITAKZWxzZXtDLk5tLmko
-dCxvKQpxPSExfX1pZihxKUMuTm0uaSh0LCIiKQpyZXR1cm4gQy5ObS56Vih0LCIvIil9LAp3RjpmdW5j
-dGlvbihhLGIpe3ZhciB0LHMscixxLHAsbwppZighUC55QihhKSlyZXR1cm4hYj9QLkMxKGEpOmEKdD1I
-LlZNKFtdLHUucykKZm9yKHM9YS5zcGxpdCgiLyIpLHI9cy5sZW5ndGgscT0hMSxwPTA7cDxyOysrcCl7
-bz1zW3BdCmlmKCIuLiI9PT1vKWlmKHQubGVuZ3RoIT09MCYmQy5ObS5ncloodCkhPT0iLi4iKXtpZigw
-Pj10Lmxlbmd0aClyZXR1cm4gSC5rKHQsLTEpCnQucG9wKCkKcT0hMH1lbHNle0MuTm0uaSh0LCIuLiIp
-CnE9ITF9ZWxzZSBpZigiLiI9PT1vKXE9ITAKZWxzZXtDLk5tLmkodCxvKQpxPSExfX1zPXQubGVuZ3Ro
-CmlmKHMhPT0wKWlmKHM9PT0xKXtpZigwPj1zKXJldHVybiBILmsodCwwKQpzPXRbMF0ubGVuZ3RoPT09
-MH1lbHNlIHM9ITEKZWxzZSBzPSEwCmlmKHMpcmV0dXJuIi4vIgppZihxfHxDLk5tLmdyWih0KT09PSIu
-LiIpQy5ObS5pKHQsIiIpCmlmKCFiKXtpZigwPj10Lmxlbmd0aClyZXR1cm4gSC5rKHQsMCkKQy5ObS5Z
-KHQsMCxQLkMxKHRbMF0pKX1yZXR1cm4gQy5ObS56Vih0LCIvIil9LApDMTpmdW5jdGlvbihhKXt2YXIg
-dCxzLHIscT1hLmxlbmd0aAppZihxPj0yJiZQLkV0KEouUXooYSwwKSkpZm9yKHQ9MTt0PHE7Kyt0KXtz
-PUMueEIuVyhhLHQpCmlmKHM9PT01OClyZXR1cm4gQy54Qi53KGEsMCx0KSsiJTNBIitDLnhCLkcoYSx0
-KzEpCmlmKHM8PTEyNyl7cj1zPj4+NAppZihyPj04KXJldHVybiBILmsoQy5tSyxyKQpyPShDLm1LW3Jd
-JjE8PChzJjE1KSk9PT0wfWVsc2Ugcj0hMAppZihyKWJyZWFrfXJldHVybiBhfSwKbW46ZnVuY3Rpb24o
-YSl7dmFyIHQscyxyLHE9YS5nRmooKSxwPXEubGVuZ3RoCmlmKHA+MCYmSi5IKHFbMF0pPT09MiYmSi5h
-NihxWzBdLDEpPT09NTgpe2lmKDA+PXApcmV0dXJuIEguayhxLDApClAucmcoSi5hNihxWzBdLDApLCEx
-KQpQLkhOKHEsITEsMSkKdD0hMH1lbHNle1AuSE4ocSwhMSwwKQp0PSExfXM9YS5ndFQoKSYmIXQ/Ilxc
-IjoiIgppZihhLmdjaigpKXtyPWEuZ0pmKGEpCmlmKHIubGVuZ3RoIT09MClzPXMrIlxcIityKyJcXCJ9
-cz1QLnZnKHMscSwiXFwiKQpwPXQmJnA9PT0xP3MrIlxcIjpzCnJldHVybiBwLmNoYXJDb2RlQXQoMCk9
-PTA/cDpwfSwKSWg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKZm9yKHQ9MCxzPTA7czwyOysrcyl7cj1D
-LnhCLlcoYSxiK3MpCmlmKDQ4PD1yJiZyPD01Nyl0PXQqMTYrci00OAplbHNle3J8PTMyCmlmKDk3PD1y
-JiZyPD0xMDIpdD10KjE2K3ItODcKZWxzZSB0aHJvdyBILmIoUC54WSgiSW52YWxpZCBVUkwgZW5jb2Rp
-bmciKSl9fXJldHVybiB0fSwKa3U6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwPUouclko
-YSksbz1iCndoaWxlKCEwKXtpZighKG88Yykpe3Q9ITAKYnJlYWt9cz1wLlcoYSxvKQppZihzPD0xMjcp
-aWYocyE9PTM3KXI9ZSYmcz09PTQzCmVsc2Ugcj0hMAplbHNlIHI9ITAKaWYocil7dD0hMQpicmVha30r
-K299aWYodCl7aWYoQy54TSE9PWQpcj0hMQplbHNlIHI9ITAKaWYocilyZXR1cm4gcC53KGEsYixjKQpl
-bHNlIHE9bmV3IEgucWoocC53KGEsYixjKSl9ZWxzZXtxPUguVk0oW10sdS50KQpmb3Iobz1iO288Yzsr
-K28pe3M9cC5XKGEsbykKaWYocz4xMjcpdGhyb3cgSC5iKFAueFkoIklsbGVnYWwgcGVyY2VudCBlbmNv
-ZGluZyBpbiBVUkkiKSkKaWYocz09PTM3KXtpZihvKzM+YS5sZW5ndGgpdGhyb3cgSC5iKFAueFkoIlRy
-dW5jYXRlZCBVUkkiKSkKQy5ObS5pKHEsUC5JaChhLG8rMSkpCm8rPTJ9ZWxzZSBpZihlJiZzPT09NDMp
-Qy5ObS5pKHEsMzIpCmVsc2UgQy5ObS5pKHEscyl9fXUuTC5hKHEpCnJldHVybiBuZXcgUC5HWSghMSku
-V0oocSl9LApFdDpmdW5jdGlvbihhKXt2YXIgdD1hfDMyCnJldHVybiA5Nzw9dCYmdDw9MTIyfSwKS0Q6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbD0iSW52YWxpZCBNSU1FIHR5cGUiLGs9
-SC5WTShbYi0xXSx1LnQpCmZvcih0PWEubGVuZ3RoLHM9YixyPS0xLHE9bnVsbDtzPHQ7KytzKXtxPUMu
-eEIuVyhhLHMpCmlmKHE9PT00NHx8cT09PTU5KWJyZWFrCmlmKHE9PT00Nyl7aWYocjwwKXtyPXMKY29u
-dGludWV9dGhyb3cgSC5iKFAucnIobCxhLHMpKX19aWYocjwwJiZzPmIpdGhyb3cgSC5iKFAucnIobCxh
-LHMpKQpmb3IoO3EhPT00NDspe0MuTm0uaShrLHMpOysrcwpmb3IocD0tMTtzPHQ7KytzKXtxPUMueEIu
-VyhhLHMpCmlmKHE9PT02MSl7aWYocDwwKXA9c31lbHNlIGlmKHE9PT01OXx8cT09PTQ0KWJyZWFrfWlm
-KHA+PTApQy5ObS5pKGsscCkKZWxzZXtvPUMuTm0uZ3JaKGspCmlmKHEhPT00NHx8cyE9PW8rN3x8IUMu
-eEIuUWkoYSwiYmFzZTY0IixvKzEpKXRocm93IEguYihQLnJyKCJFeHBlY3RpbmcgJz0nIixhLHMpKQpi
-cmVha319Qy5ObS5pKGsscykKbj1zKzEKaWYoKGsubGVuZ3RoJjEpPT09MSlhPUMuaDkueXIoYSxuLHQp
-CmVsc2V7bT1QLlVsKGEsbix0LEMuVkMsITApCmlmKG0hPW51bGwpYT1DLnhCLmk3KGEsbix0LG0pfXJl
-dHVybiBuZXcgUC5QRShhLGssYyl9LApLTjpmdW5jdGlvbigpe3ZhciB0PSIwMTIzNDU2Nzg5QUJDREVG
-R0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei0uX34hJCYnKCkqKyw7
-PSIscz0iLiIscj0iOiIscT0iLyIscD0iPyIsbz0iIyIsbj11LmdjLG09UC5kSCgyMixuZXcgUC5xMygp
-LCEwLG4pLGw9bmV3IFAueUkobSksaz1uZXcgUC5jNigpLGo9bmV3IFAucWQoKSxpPW4uYShsLiQyKDAs
-MjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLHMsMTQpCmsuJDMoaSxyLDM0KQprLiQzKGkscSwzKQprLiQz
-KGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxNCwyMjUpKQprLiQzKGksdCwxKQprLiQz
-KGkscywxNSkKay4kMyhpLHIsMzQpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywy
-MDUpCmk9bi5hKGwuJDIoMTUsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLCIlIiwyMjUpCmsuJDMoaSxy
-LDM0KQprLiQzKGkscSw5KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxLDIy
-NSkpCmsuJDMoaSx0LDEpCmsuJDMoaSxyLDM0KQprLiQzKGkscSwxMCkKay4kMyhpLHAsMTcyKQprLiQz
-KGksbywyMDUpCmk9bi5hKGwuJDIoMiwyMzUpKQprLiQzKGksdCwxMzkpCmsuJDMoaSxxLDEzMSkKay4k
-MyhpLHMsMTQ2KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigzLDIzNSkpCmsu
-JDMoaSx0LDExKQprLiQzKGkscSw2OCkKay4kMyhpLHMsMTgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8s
-MjA1KQppPW4uYShsLiQyKDQsMjI5KSkKay4kMyhpLHQsNSkKai4kMyhpLCJBWiIsMjI5KQprLiQzKGks
-ciwxMDIpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSwiWyIsMjMyKQprLiQzKGkscSwxMzgpCmsuJDMoaSxw
-LDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDUsMjI5KSkKay4kMyhpLHQsNSkKai4kMyhpLCJB
-WiIsMjI5KQprLiQzKGksciwxMDIpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAs
-MTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNiwyMzEpKQpqLiQzKGksIjE5Iiw3KQprLiQzKGks
-IkAiLDY4KQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQy
-KDcsMjMxKSkKai4kMyhpLCIwOSIsNykKay4kMyhpLCJAIiw2OCkKay4kMyhpLHEsMTM4KQprLiQzKGks
-cCwxNzIpCmsuJDMoaSxvLDIwNSkKay4kMyhuLmEobC4kMig4LDgpKSwiXSIsNSkKaT1uLmEobC4kMig5
-LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscywxNikKay4kMyhpLHEsMjM0KQprLiQzKGkscCwxNzIp
-CmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxNiwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMsMTcp
-CmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoMTcsMjM1
-KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDkpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4u
-YShsLiQyKDEwLDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscywxOCkKay4kMyhpLHEsMjM0KQprLiQz
-KGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxOCwyMzUpKQprLiQzKGksdCwxMSkKay4k
-MyhpLHMsMTkpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwu
-JDIoMTksMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGks
-bywyMDUpCmk9bi5hKGwuJDIoMTEsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDEwKQprLiQzKGks
-cCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxMiwyMzYpKQprLiQzKGksdCwxMikKay4kMyhp
-LHAsMTIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxMywyMzcpKQprLiQzKGksdCwxMykKay4kMyhp
-LHAsMTMpCmouJDMobi5hKGwuJDIoMjAsMjQ1KSksImF6IiwyMSkKbD1uLmEobC4kMigyMSwyNDUpKQpq
-LiQzKGwsImF6IiwyMSkKai4kMyhsLCIwOSIsMjEpCmsuJDMobCwiKy0uIiwyMSkKcmV0dXJuIG19LApV
-QjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbz0kLnZaKCkKZm9yKHQ9Si5yWShhKSxz
-PWI7czxjOysrcyl7aWYoZDwwfHxkPj1vLmxlbmd0aClyZXR1cm4gSC5rKG8sZCkKcj1vW2RdCnE9dC5X
-KGEscyleOTYKaWYocT45NSlxPTMxCmlmKHE+PXIubGVuZ3RoKXJldHVybiBILmsocixxKQpwPXJbcV0K
-ZD1wJjMxCkMuTm0uWShlLHA+Pj41LHMpfXJldHVybiBkfSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCmEyOmZ1bmN0aW9uIGEyKCl7fSwKaVA6ZnVuY3Rpb24gaVAoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCkNQOmZ1bmN0aW9uIENQKCl7fSwKWFM6ZnVuY3Rpb24gWFMoKXt9LApDNjpm
-dW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCkxLOmZ1bmN0aW9uIExLKCl7fSwKQVQ6ZnVuY3Rpb24gQVQo
-YSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmJKOmZ1bmN0aW9uIGJK
-KGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uZT1hCl8uZj1iCl8uYT1jCl8uYj1kCl8uYz1lCl8uZD1m
-fSwKZVk6ZnVuY3Rpb24gZVkoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uZj1hCl8uYT1iCl8uYj1jCl8u
-Yz1kCl8uZD1lfSwKbXA6ZnVuY3Rpb24gbXAoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
-LmM9YwpfLmQ9ZH0sCnViOmZ1bmN0aW9uIHViKGEpe3RoaXMuYT1hfSwKZHM6ZnVuY3Rpb24gZHMoYSl7
-dGhpcy5hPWF9LApsajpmdW5jdGlvbiBsaihhKXt0aGlzLmE9YX0sClVWOmZ1bmN0aW9uIFVWKGEpe3Ro
-aXMuYT1hfSwKazU6ZnVuY3Rpb24gazUoKXt9LApLWTpmdW5jdGlvbiBLWSgpe30sCnQ3OmZ1bmN0aW9u
-IHQ3KGEpe3RoaXMuYT1hfSwKQ0Q6ZnVuY3Rpb24gQ0QoYSl7dGhpcy5hPWF9LAphRTpmdW5jdGlvbiBh
-RShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApFSDpmdW5jdGlvbiBFSCgpe30sCklm
-OmZ1bmN0aW9uIElmKCl7fSwKY1g6ZnVuY3Rpb24gY1goKXt9LApBbjpmdW5jdGlvbiBBbigpe30sCnpN
-OmZ1bmN0aW9uIHpNKCl7fSwKWjA6ZnVuY3Rpb24gWjAoKXt9LApOMzpmdW5jdGlvbiBOMyhhLGIsYyl7
-dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCmM4OmZ1bmN0aW9uIGM4KCl7fSwKbGY6ZnVuY3Rp
-b24gbGYoKXt9LApNaDpmdW5jdGlvbiBNaCgpe30sCk9kOmZ1bmN0aW9uIE9kKCl7fSwKaWI6ZnVuY3Rp
-b24gaWIoKXt9LAp4dTpmdW5jdGlvbiB4dSgpe30sCkd6OmZ1bmN0aW9uIEd6KCl7fSwKWmQ6ZnVuY3Rp
-b24gWmQoKXt9LApxVTpmdW5jdGlvbiBxVSgpe30sClJuOmZ1bmN0aW9uIFJuKGEpe3RoaXMuYT1hfSwK
-R0Q6ZnVuY3Rpb24gR0QoKXt9LApuMTpmdW5jdGlvbiBuMShhKXt0aGlzLmE9YX0sCmNTOmZ1bmN0aW9u
-IGNTKGEpe3RoaXMuYT1hfSwKVkM6ZnVuY3Rpb24gVkMoYSl7dGhpcy5hPWF9LApKVDpmdW5jdGlvbiBK
-VChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKRG46ZnVuY3Rpb24gRG4oYSxiLGMsZCxlLGYsZyl7dmFy
-IF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9ZwpfLlE9Xy56PV8u
-eT1fLng9bnVsbH0sCmUxOmZ1bmN0aW9uIGUxKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApOWTpmdW5j
-dGlvbiBOWShhKXt0aGlzLmE9YX0sClJaOmZ1bmN0aW9uIFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxi
-KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1OmZ1bmN0aW9uIHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rp
-b24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcTM6ZnVuY3Rpb24gcTMoKXt9
-LAp5STpmdW5jdGlvbiB5SShhKXt0aGlzLmE9YX0sCmM2OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6ZnVuY3Rp
-b24gcWQoKXt9LApVZjpmdW5jdGlvbiBVZihhLGIsYyxkLGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEK
-Xy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy54PWgKXy55PW51bGx9LApxZTpmdW5j
-dGlvbiBxZShhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8u
-ZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1udWxsfSwKaUo6ZnVuY3Rpb24gaUooKXt9LApq
-ZzpmdW5jdGlvbiBqZyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxiKXt0
-aGlzLmE9YQp0aGlzLmI9Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApB
-czpmdW5jdGlvbiBBcygpe30sCkdFOmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKTjc6ZnVuY3Rpb24g
-TjcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnVROmZ1bmN0aW9uIHVRKCl7fSwKaEY6ZnVuY3Rpb24g
-aEYoKXt9LApSNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKSC5FOShiKQp1LmouYShkKQppZihI
-Lm9UKGIpKXt0PVtjXQpDLk5tLkZWKHQsZCkKZD10fXM9dS56CnI9UC5DSChKLk0xKGQsUC53MCgpLHMp
-LCEwLHMpCnUuWi5hKGEpCnJldHVybiBQLndZKEguRWsoYSxyLG51bGwpKX0sCkRtOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdAp0cnl7aWYoT2JqZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90b3R5cGUu
-aGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpj
-fSkKcmV0dXJuITB9fWNhdGNoKHQpe0guUnUodCl9cmV0dXJuITF9LApPbTpmdW5jdGlvbihhLGIpe2lm
-KE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBhW2JdCnJldHVy
-biBudWxsfSwKd1k6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBl
-b2YgYT09Im51bWJlciJ8fEguclEoYSkpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAuRTQpcmV0dXJu
-IGEuYQppZihILlI5KGEpKXJldHVybiBhCmlmKHUudy5iKGEpKXJldHVybiBhCmlmKGEgaW5zdGFuY2Vv
-ZiBQLmlQKXJldHVybiBILm8yKGEpCmlmKHUuWi5iKGEpKXJldHVybiBQLmhFKGEsIiRkYXJ0X2pzRnVu
-Y3Rpb24iLG5ldyBQLlBDKCkpCnJldHVybiBQLmhFKGEsIl8kZGFydF9qc09iamVjdCIsbmV3IFAubXQo
-JC5rSSgpKSl9LApoRTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9UC5PbShhLGIpCmlmKHQ9PW51bGwpe3Q9
-Yy4kMShhKQpQLkRtKGEsYix0KX1yZXR1cm4gdH0sCkw3OmZ1bmN0aW9uKGEpe3ZhciB0LHMKaWYoYT09
-bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fHR5cGVvZiBhPT0iYm9v
-bGVhbiIpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgT2JqZWN0JiZILlI5KGEpKXJldHVybiBh
-CmVsc2UgaWYoYSBpbnN0YW5jZW9mIE9iamVjdCYmdS53LmIoYSkpcmV0dXJuIGEKZWxzZSBpZihhIGlu
-c3RhbmNlb2YgRGF0ZSl7dD1ILldZKGEuZ2V0VGltZSgpKQppZihNYXRoLmFicyh0KTw9ODY0ZTEzKXM9
-ITEKZWxzZSBzPSEwCmlmKHMpSC52aChQLnhZKCJEYXRlVGltZSBpcyBvdXRzaWRlIHZhbGlkIHJhbmdl
-OiAiK3QpKQpQLlVJKCExLCJpc1V0YyIsdS55KQpyZXR1cm4gbmV3IFAuaVAodCwhMSl9ZWxzZSBpZihh
-LmNvbnN0cnVjdG9yPT09JC5rSSgpKXJldHVybiBhLm8KZWxzZSByZXR1cm4gUC5ORChhKX0sCk5EOmZ1
-bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBQLmlRKGEsJC53USgpLG5ldyBQ
-Lk56KCkpCmlmKGEgaW5zdGFuY2VvZiBBcnJheSlyZXR1cm4gUC5pUShhLCQuQ3IoKSxuZXcgUC5ucCgp
-KQpyZXR1cm4gUC5pUShhLCQuQ3IoKSxuZXcgUC5VdCgpKX0sCmlROmZ1bmN0aW9uKGEsYixjKXt2YXIg
-dD1QLk9tKGEsYikKaWYodD09bnVsbHx8IShhIGluc3RhbmNlb2YgT2JqZWN0KSl7dD1jLiQxKGEpClAu
-RG0oYSxiLHQpfXJldHVybiB0fSwKUEM6ZnVuY3Rpb24gUEMoKXt9LAptdDpmdW5jdGlvbiBtdChhKXt0
-aGlzLmE9YX0sCk56OmZ1bmN0aW9uIE56KCl7fSwKbnA6ZnVuY3Rpb24gbnAoKXt9LApVdDpmdW5jdGlv
-biBVdCgpe30sCkU0OmZ1bmN0aW9uIEU0KGEpe3RoaXMuYT1hfSwKcjc6ZnVuY3Rpb24gcjcoYSl7dGhp
-cy5hPWF9LApUejpmdW5jdGlvbiBUeihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApjbzpmdW5jdGlv
-biBjbygpe30sCm5kOmZ1bmN0aW9uIG5kKCl7fSwKS2U6ZnVuY3Rpb24gS2UoYSl7dGhpcy5hPWF9LApk
-NTpmdW5jdGlvbiBkNSgpe30sCm42OmZ1bmN0aW9uIG42KCl7fX0sVz17CngzOmZ1bmN0aW9uKCl7cmV0
-dXJuIHdpbmRvd30sClpyOmZ1bmN0aW9uKCl7cmV0dXJuIGRvY3VtZW50fSwKVTk6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0PWRvY3VtZW50LmJvZHkscz0odCYmQy5SWSkucjYodCxhLGIsYykKcy50b1N0cmluZwp0
-PXUuYWMKdD1uZXcgSC5VNShuZXcgVy5lNyhzKSx0LkMoImEyKGxELkUpIikuYShuZXcgVy5DdigpKSx0
-LkMoIlU1PGxELkU+IikpCnJldHVybiB1LmguYSh0LmdyOCh0KSl9LApyUzpmdW5jdGlvbihhKXt2YXIg
-dCxzLHI9ImVsZW1lbnQgdGFnIHVuYXZhaWxhYmxlIgp0cnl7dD1KLlJFKGEpCmlmKHR5cGVvZiB0Lmdu
-cyhhKT09InN0cmluZyIpcj10LmducyhhKX1jYXRjaChzKXtILlJ1KHMpfXJldHVybiByfSwKcUQ6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPW5ldyBQLnZzKCQuWDMsdS5hbykscD1uZXcgUC5aZihxLHUu
-YmopLG89bmV3IFhNTEh0dHBSZXF1ZXN0KCkKQy5EdC5lbyhvLGI9PW51bGw/IkdFVCI6YixhLCEwKQpj
-LksoMCxuZXcgVy5iVShvKSkKdD11LmFuCnM9dC5hKG5ldyBXLmhIKG8scCkpCnUuTS5hKG51bGwpCnI9
-dS5wClcuSkUobywibG9hZCIscywhMSxyKQpXLkpFKG8sImVycm9yIix0LmEocC5nWUooKSksITEscikK
-by5zZW5kKCkKcmV0dXJuIHF9LApDMDpmdW5jdGlvbihhLGIpe2E9NTM2ODcwOTExJmErYgphPTUzNjg3
-MDkxMSZhKygoNTI0Mjg3JmEpPDwxMCkKcmV0dXJuIGFeYT4+PjZ9LApyRTpmdW5jdGlvbihhLGIsYyxk
-KXt2YXIgdD1XLkMwKFcuQzAoVy5DMChXLkMwKDAsYSksYiksYyksZCkscz01MzY4NzA5MTEmdCsoKDY3
-MTA4ODYzJnQpPDwzKQpzXj1zPj4+MTEKcmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8PDE1KX0s
-ClROOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPWEuY2xhc3NMaXN0CmZvcih0PWIubGVuZ3RoLHM9MDtz
-PGIubGVuZ3RoO2IubGVuZ3RoPT09dHx8KDAsSC5saykoYiksKytzKXIuYWRkKGJbc10pfSwKSkU6ZnVu
-Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1XLmFGKG5ldyBXLnZOKGMpLHUuQikKaWYodCE9bnVsbCYmITAp
-Si5kWihhLGIsdCwhMSkKcmV0dXJuIG5ldyBXLnhDKGEsYix0LCExLGUuQygieEM8MD4iKSl9LApUdzpm
-dW5jdGlvbihhKXt2YXIgdD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJhIikscz1uZXcgVy5tayh0LHdp
-bmRvdy5sb2NhdGlvbikKcz1uZXcgVy5KUShzKQpzLkNZKGEpCnJldHVybiBzfSwKeVc6ZnVuY3Rpb24o
-YSxiLGMsZCl7dS5oLmEoYSkKSC5jKGIpCkguYyhjKQp1Lk8uYShkKQpyZXR1cm4hMH0sClFXOmZ1bmN0
-aW9uKGEsYixjLGQpe3ZhciB0LHMscgp1LmguYShhKQpILmMoYikKSC5jKGMpCnQ9dS5PLmEoZCkuYQpz
-PXQuYQpzLmhyZWY9YwpyPXMuaG9zdG5hbWUKdD10LmIKaWYoIShyPT10Lmhvc3RuYW1lJiZzLnBvcnQ9
-PXQucG9ydCYmcy5wcm90b2NvbD09dC5wcm90b2NvbCkpaWYocj09PSIiKWlmKHMucG9ydD09PSIiKXt0
-PXMucHJvdG9jb2wKdD10PT09IjoifHx0PT09IiJ9ZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITAK
-cmV0dXJuIHR9LApCbDpmdW5jdGlvbigpe3ZhciB0PXUuTixzPVAudE0oQy5ReCx0KSxyPXUuZEcuYShu
-ZXcgVy5JQSgpKSxxPUguVk0oWyJURU1QTEFURSJdLHUucykKdD1uZXcgVy5jdChzLFAuTHModCksUC5M
-cyh0KSxQLkxzKHQpLG51bGwpCnQuQ1kobnVsbCxuZXcgSC5sSihDLlF4LHIsdS5kdikscSxudWxsKQpy
-ZXR1cm4gdH0sClB2OmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIFcuUDEo
-YSl9LApxYzpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBudWxsCmlmKCJwb3N0TWVz
-c2FnZSIgaW4gYSl7dD1XLlAxKGEpCnJldHVybiB0fWVsc2UgcmV0dXJuIHUuYVMuYShhKX0sClAxOmZ1
-bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cpcmV0dXJuIHUuY2kuYShhKQplbHNlIHJldHVybiBuZXcgVy5k
-VyhhKX0sCnpYOmZ1bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cubG9jYXRpb24pcmV0dXJuIGEKZWxzZSBy
-ZXR1cm4gbmV3IFcuRmIoKX0sCmFGOmZ1bmN0aW9uKGEsYil7dmFyIHQ9JC5YMwppZih0PT09Qy5OVSly
-ZXR1cm4gYQpyZXR1cm4gdC5QeShhLGIpfSwKcUU6ZnVuY3Rpb24gcUUoKXt9LApHaDpmdW5jdGlvbiBH
-aCgpe30sCmZZOmZ1bmN0aW9uIGZZKCl7fSwKbkI6ZnVuY3Rpb24gbkIoKXt9LApBejpmdW5jdGlvbiBB
-eigpe30sClFQOmZ1bmN0aW9uIFFQKCl7fSwKbng6ZnVuY3Rpb24gbngoKXt9LApvSjpmdW5jdGlvbiBv
-Sigpe30sCmlkOmZ1bmN0aW9uIGlkKCl7fSwKUUY6ZnVuY3Rpb24gUUYoKXt9LApOaDpmdW5jdGlvbiBO
-aCgpe30sCklCOmZ1bmN0aW9uIElCKCl7fSwKbjc6ZnVuY3Rpb24gbjcoKXt9LAp3ejpmdW5jdGlvbiB3
-eihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApjdjpmdW5jdGlvbiBjdigpe30sCkN2OmZ1bmN0aW9u
-IEN2KCl7fSwKZWE6ZnVuY3Rpb24gZWEoKXt9LApEMDpmdW5jdGlvbiBEMCgpe30sClQ1OmZ1bmN0aW9u
-IFQ1KCl7fSwKaDQ6ZnVuY3Rpb24gaDQoKXt9LApicjpmdW5jdGlvbiBicigpe30sClZiOmZ1bmN0aW9u
-IFZiKCl7fSwKZko6ZnVuY3Rpb24gZkooKXt9LApiVTpmdW5jdGlvbiBiVShhKXt0aGlzLmE9YX0sCmhI
-OmZ1bmN0aW9uIGhIKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp3YTpmdW5jdGlvbiB3YSgpe30sClNn
-OmZ1bmN0aW9uIFNnKCl7fSwKdTg6ZnVuY3Rpb24gdTgoKXt9LApPSzpmdW5jdGlvbiBPSygpe30sCmU3
-OmZ1bmN0aW9uIGU3KGEpe3RoaXMuYT1hfSwKdUg6ZnVuY3Rpb24gdUgoKXt9LApCSDpmdW5jdGlvbiBC
-SCgpe30sClNOOmZ1bmN0aW9uIFNOKCl7fSwKZXc6ZnVuY3Rpb24gZXcoKXt9LApscDpmdW5jdGlvbiBs
-cCgpe30sClRiOmZ1bmN0aW9uIFRiKCl7fSwKSXY6ZnVuY3Rpb24gSXYoKXt9LApCVDpmdW5jdGlvbiBC
-VCgpe30sCnlZOmZ1bmN0aW9uIHlZKCl7fSwKdzY6ZnVuY3Rpb24gdzYoKXt9LApLNTpmdW5jdGlvbiBL
-NSgpe30sCkNtOmZ1bmN0aW9uIENtKCl7fSwKQ1E6ZnVuY3Rpb24gQ1EoKXt9LAp3NDpmdW5jdGlvbiB3
-NCgpe30sCnJoOmZ1bmN0aW9uIHJoKCl7fSwKY2Y6ZnVuY3Rpb24gY2YoKXt9LAppNzpmdW5jdGlvbiBp
-NyhhKXt0aGlzLmE9YX0sClN5OmZ1bmN0aW9uIFN5KGEpe3RoaXMuYT1hfSwKS1M6ZnVuY3Rpb24gS1Mo
-YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkEzOmZ1bmN0aW9uIEEzKGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LApJNDpmdW5jdGlvbiBJNChhKXt0aGlzLmE9YX0sCkZrOmZ1bmN0aW9uIEZrKGEsYil7dGhpcy5h
-PWEKdGhpcy4kdGk9Yn0sClJPOmZ1bmN0aW9uIFJPKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
-PWIKXy5jPWMKXy4kdGk9ZH0sCmV1OmZ1bmN0aW9uIGV1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEK
-Xy5iPWIKXy5jPWMKXy4kdGk9ZH0sCnhDOmZ1bmN0aW9uIHhDKGEsYixjLGQsZSl7dmFyIF89dGhpcwpf
-LmI9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLiR0aT1lfSwKdk46ZnVuY3Rpb24gdk4oYSl7dGhpcy5hPWF9
-LApKUTpmdW5jdGlvbiBKUShhKXt0aGlzLmE9YX0sCkdtOmZ1bmN0aW9uIEdtKCl7fSwKdkQ6ZnVuY3Rp
-b24gdkQoYSl7dGhpcy5hPWF9LApVdjpmdW5jdGlvbiBVdihhKXt0aGlzLmE9YX0sCkVnOmZ1bmN0aW9u
-IEVnKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCm02OmZ1bmN0aW9uIG02KCl7fSwK
-RW86ZnVuY3Rpb24gRW8oKXt9LApXazpmdW5jdGlvbiBXaygpe30sCmN0OmZ1bmN0aW9uIGN0KGEsYixj
-LGQsZSl7dmFyIF89dGhpcwpfLmU9YQpfLmE9YgpfLmI9YwpfLmM9ZApfLmQ9ZX0sCklBOmZ1bmN0aW9u
-IElBKCl7fSwKT3c6ZnVuY3Rpb24gT3coKXt9LApXOTpmdW5jdGlvbiBXOShhLGIsYyl7dmFyIF89dGhp
-cwpfLmE9YQpfLmI9YgpfLmM9LTEKXy5kPW51bGwKXy4kdGk9Y30sCmRXOmZ1bmN0aW9uIGRXKGEpe3Ro
-aXMuYT1hfSwKRmI6ZnVuY3Rpb24gRmIoKXt9LAprRjpmdW5jdGlvbiBrRigpe30sCm1rOmZ1bmN0aW9u
-IG1rKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLbzpmdW5jdGlvbiBLbyhhKXt0aGlzLmE9YQp0aGlz
-LmI9ITF9LApmbTpmdW5jdGlvbiBmbShhKXt0aGlzLmE9YX0sCkxlOmZ1bmN0aW9uIExlKCl7fSwKSzc6
-ZnVuY3Rpb24gSzcoKXt9LApyQjpmdW5jdGlvbiByQigpe30sClhXOmZ1bmN0aW9uIFhXKCl7fSwKb2E6
-ZnVuY3Rpb24gb2EoKXt9fSxVPXsKeXU6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49SC5WTShb
-XSx1LmJQKQpmb3IodD1KLlU2KGEpLHM9Si5JVCh1LlIuYSh0LnEoYSwiZGV0YWlscyIpKSk7cy5GKCk7
-KXtyPXMuZ2woKQpxPUouVTYocikKcD1ILmMocS5xKHIsImRlc2NyaXB0aW9uIikpCnE9cS5xKHIsImxp
-bmsiKQppZihxPT1udWxsKXE9bnVsbAplbHNle289Si5VNihxKQpxPW5ldyBVLk1sKEguYyhvLnEocSwi
-aHJlZiIpKSxILldZKG8ucShxLCJsaW5lIikpLEguYyhvLnEocSwicGF0aCIpKSl9Qy5ObS5pKG4sbmV3
-IFUudUYocCxxKSl9cmV0dXJuIG5ldyBVLmQyKG4sVS5qZih0LnEoYSwiZWRpdHMiKSksSC5jKHQucShh
-LCJleHBsYW5hdGlvbiIpKSxILldZKHQucShhLCJsaW5lIikpLEguYyh0LnEoYSwicGF0aCIpKSxVLk5k
-KHQucShhLCJ0cmFjZXMiKSkpfSwKamY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEKaWYoYT09bnVsbCl0
-PW51bGwKZWxzZXt0PUguVk0oW10sdS5mQSkKZm9yKHM9Si5JVCh1LlIuYShhKSk7cy5GKCk7KXtyPXMu
-Z2woKQpxPUouVTYocikKQy5ObS5pKHQsbmV3IFUuU2UoSC5jKHEucShyLCJkZXNjcmlwdGlvbiIpKSxI
-LmMocS5xKHIsImhyZWYiKSkpKX19cmV0dXJuIHR9LApOZDpmdW5jdGlvbihhKXt2YXIgdCxzCmlmKGE9
-PW51bGwpdD1udWxsCmVsc2V7dD1ILlZNKFtdLHUuaGgpCmZvcihzPUouSVQodS5SLmEoYSkpO3MuRigp
-OylDLk5tLmkodCxVLkpqKHMuZ2woKSkpfXJldHVybiB0fSwKSmo6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
-LHEscCxvPSJkZXNjcmlwdGlvbiIsbj1KLlU2KGEpLG09SC5jKG4ucShhLG8pKSxsPUguVk0oW10sdS5h
-SikKZm9yKG49Si5JVCh1LlIuYShuLnEoYSwiZW50cmllcyIpKSk7bi5GKCk7KXt0PW4uZ2woKQpzPUou
-VTYodCkKcj1ILmMocy5xKHQsbykpCnE9SC5jKHMucSh0LCJmdW5jdGlvbiIpKQpzPXMucSh0LCJsaW5r
-IikKaWYocz09bnVsbClzPW51bGwKZWxzZXtwPUouVTYocykKcz1uZXcgVS5NbChILmMocC5xKHMsImhy
-ZWYiKSksSC5XWShwLnEocywibGluZSIpKSxILmMocC5xKHMsInBhdGgiKSkpfUMuTm0uaShsLG5ldyBV
-LndiKHIscSxzKSl9cmV0dXJuIG5ldyBVLnlEKG0sbCl9LApkMjpmdW5jdGlvbiBkMihhLGIsYyxkLGUs
-Zil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sClNlOmZ1bmN0
-aW9uIFNlKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp1RjpmdW5jdGlvbiB1RihhLGIpe3RoaXMuYT1h
-CnRoaXMuYj1ifSwKTWw6ZnVuY3Rpb24gTWwoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1j
-fSwKeUQ6ZnVuY3Rpb24geUQoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCndiOmZ1bmN0aW9uIHdiKGEs
-YixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y319LEI9ewpZZjpmdW5jdGlvbihhKXt2YXIgdCxz
-LHIscT1ILmMoYS5xKDAsInJlZ2lvbnMiKSkscD1ILmMoYS5xKDAsIm5hdmlnYXRpb25Db250ZW50Iikp
-LG89SC5jKGEucSgwLCJzb3VyY2VDb2RlIikpLG49SC5WTShbXSx1LnUpCmZvcih0PUouSVQodS5SLmEo
-YS5xKDAsImVkaXRzIikpKTt0LkYoKTspe3M9dC5nbCgpCnI9Si5VNihzKQpDLk5tLmkobixuZXcgQi5q
-OChILldZKHIucShzLCJsaW5lIikpLEguYyhyLnEocywiZXhwbGFuYXRpb24iKSksSC5XWShyLnEocywi
-b2Zmc2V0IikpKSl9cmV0dXJuIG5ldyBCLnFwKHEscCxvLG4pfSwKajg6ZnVuY3Rpb24gajgoYSxiLGMp
-e3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcXA6ZnVuY3Rpb24gcXAoYSxiLGMsZCl7dmFyIF89
-dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCkx1OmZ1bmN0aW9uIEx1KCl7fSwKT1M6ZnVuY3Rp
-b24oYSl7dmFyIHQKaWYoIShhPj02NSYmYTw9OTApKXQ9YT49OTcmJmE8PTEyMgplbHNlIHQ9ITAKcmV0
-dXJuIHR9LApZdTpmdW5jdGlvbihhLGIpe3ZhciB0PWEubGVuZ3RoLHM9YisyCmlmKHQ8cylyZXR1cm4h
-MQppZighQi5PUyhDLnhCLm0oYSxiKSkpcmV0dXJuITEKaWYoQy54Qi5tKGEsYisxKSE9PTU4KXJldHVy
-biExCmlmKHQ9PT1zKXJldHVybiEwCnJldHVybiBDLnhCLm0oYSxzKT09PTQ3fX0sVD17bVE6ZnVuY3Rp
-b24gbVEoKXt9fSxMPXsKSXE6ZnVuY3Rpb24oKXtDLkJaLkIoZG9jdW1lbnQsIkRPTUNvbnRlbnRMb2Fk
-ZWQiLG5ldyBMLmUoKSkKQy5vbC5CKHdpbmRvdywicG9wc3RhdGUiLG5ldyBMLkwoKSl9LAprejpmdW5j
-dGlvbihhKXt2YXIgdCxzPXUuaC5hKGEucGFyZW50Tm9kZSkucXVlcnlTZWxlY3RvcigiOnNjb3BlID4g
-dWwiKSxyPXMuc3R5bGUscT0iIitDLkNELnpRKHMub2Zmc2V0SGVpZ2h0KSoyKyJweCIKci5tYXhIZWln
-aHQ9cQpyPUoucUYoYSkKcT1yLiR0aQp0PXEuQygifigxKSIpLmEobmV3IEwuV3gocyxhKSkKdS5NLmEo
-bnVsbCkKVy5KRShyLmEsci5iLHQsITEscS5jKX0sCnlYOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEs
-cCxvPSJxdWVyeVNlbGVjdG9yQWxsIixuPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYSksbT11LmgKbi50
-b1N0cmluZwpILkRoKG0sbSwiVCIsbykKdD11LlQKcz1uZXcgVy53eihuLnF1ZXJ5U2VsZWN0b3JBbGwo
-Ii5uYXYtbGluayIpLHQpCnMuSyhzLG5ldyBMLkFPKGIpKQpILkRoKG0sbSwiVCIsbykKcj1uZXcgVy53
-eihuLnF1ZXJ5U2VsZWN0b3JBbGwoIi5yZWdpb24iKSx0KQppZihyLmdBKHIpIT09MCl7cT1uLnF1ZXJ5
-U2VsZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0iKQpxLnRvU3RyaW5nCnIuSyhyLG5ldyBMLkhvKHEuZ2V0
-QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcocSkpLk8oInBhdGgiKSkpKX1ILkRoKG0s
-bSwiVCIsbykKcD1uZXcgVy53eihuLnF1ZXJ5U2VsZWN0b3JBbGwoIi5wb3N0LWxpbmsiKSx0KQpwLkso
-cCxuZXcgTC5JQygpKX0sClE2OmZ1bmN0aW9uKGEsYil7dmFyIHQ9dS5OCnJldHVybiBXLnFEKEwuUTQo
-YSxiKSxudWxsLFAuRUYoWyJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PVVU
-Ri04Il0sdCx0KSl9LAp0eTpmdW5jdGlvbihhKXt2YXIgdD11Lk4KcmV0dXJuIFcucUQoTC5RNChhLFAu
-RmwodCx0KSksIlBPU1QiLFAuRUYoWyJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9qc29uOyBjaGFy
-c2V0PVVURi04Il0sdCx0KSkuVzcobmV3IEwuTDEoKSx1LnIpfSwKYUs6ZnVuY3Rpb24oYSl7dmFyIHQ9
-UC5oSyhhKS5naFkoKS5xKDAsImxpbmUiKQpyZXR1cm4gdD09bnVsbD9udWxsOkguSHAodCxudWxsKX0s
-Ckc2OmZ1bmN0aW9uKGEpe3ZhciB0PVAuaEsoYSkuZ2hZKCkucSgwLCJvZmZzZXQiKQpyZXR1cm4gdD09
-bnVsbD9udWxsOkguSHAodCxudWxsKX0sCnQyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8s
-bj17fSxtPXUuaC5hKFcucWMoYS5jdXJyZW50VGFyZ2V0KSkKYS5wcmV2ZW50RGVmYXVsdCgpCnQ9bi5h
-PW0uZ2V0QXR0cmlidXRlKCJocmVmIikKaWYoSi56bCh0LCI/Iikpe3M9Qy54Qi53KHQsMCxDLnhCLk9Z
-KHQsIj8iKSkKbi5hPXMKcj1zfWVsc2Ugcj10CmlmKGMhPW51bGwpe3E9JC5uVSgpCnI9bi5hPXEubzUo
-RC5ucihxLnRNKGMpLHIpKX1wPUwuRzYodCkKbz1MLmFLKHQpCmlmKHAhPW51bGwpTC5hZihyLHAsbyxi
-LG5ldyBMLm5UKG4scCxvKSkKZWxzZSBMLmFmKHIsbnVsbCxudWxsLGIsbmV3IEwuQloobikpfSwKdW06
-ZnVuY3Rpb24oYSl7cmV0dXJuIEwuUVModS5WLmEoYSkpfSwKUVM6ZnVuY3Rpb24oYSl7dmFyIHQ9MCxz
-PVAuRlgodS56KSxyPTEscSxwPVtdLG8sbixtLGwsayxqCnZhciAkYXN5bmMkdW09UC5seihmdW5jdGlv
-bihiLGMpe2lmKGI9PT0xKXtxPWMKdD1yfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nhc2UgMDprPXUuaC5h
-KFcucWMoYS5jdXJyZW50VGFyZ2V0KSkuZ2V0QXR0cmlidXRlKCJocmVmIikKYS5wcmV2ZW50RGVmYXVs
-dCgpCm09ZG9jdW1lbnQKbS5ib2R5LmNsYXNzTGlzdC5hZGQoInJlcnVubmluZyIpCnI9Mwp0PTYKcmV0
-dXJuIFAualEoTC50eShrKSwkYXN5bmMkdW0pCmNhc2UgNjp1LmFfLmEoSi5HcihXLlB2KG0uZGVmYXVs
-dFZpZXcpKSkucmVsb2FkKCkKcC5wdXNoKDUpCnQ9NApicmVhawpjYXNlIDM6cj0yCmo9cQpvPUguUnUo
-aikKbj1ILnRzKGopCkwucUooImhhbmRsZVBvc3RMaW5rQ2xpY2s6ICIrSC5kKG8pLG4pCndpbmRvdy5h
-bGVydCgiQ291bGQgbm90IGxvYWQgIitILmQoaykrIiAoIitILmQobykrIikuIikKcC5wdXNoKDUpCnQ9
-NApicmVhawpjYXNlIDI6cD1bMV0KY2FzZSA0OnI9MQptLmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgicmVy
-dW5uaW5nIikKdD1wLnBvcCgpCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHMpCmNhc2UgMTpy
-ZXR1cm4gUC5mMyhxLHMpfX0pCnJldHVybiBQLkRJKCRhc3luYyR1bSxzKX0sCnZVOmZ1bmN0aW9uKCl7
-dmFyIHQ9ZG9jdW1lbnQscz11LmgKSC5EaChzLHMsIlQiLCJxdWVyeVNlbGVjdG9yQWxsIikKdD1uZXcg
-Vy53eih0LnF1ZXJ5U2VsZWN0b3JBbGwoIi5jb2RlIiksdS5UKQp0LksodCxuZXcgTC5HSCgpKX0sCmhY
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdD11Lk4KTC5RNihhLFAuRUYoWyJyZWdpb24iLCJyZWdpb24iLCJv
-ZmZzZXQiLEguZChiKV0sdCx0KSkuVzcobmV3IEwuRFQoYSxiLGMpLHUuUCkuT0EobmV3IEwuZUgoYSkp
-fSwKRzc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdAppZighSi5wNChhLCIuZGFydCIpKXtMLkJFKGEs
-bmV3IEIucXAoIiIsIiIsIiIsQy54RCksZCkKTC5CWChhLG51bGwpCmlmKGUhPW51bGwpZS4kMCgpCnJl
-dHVybn10PXUuTgpMLlE2KGEsUC5FRihbImlubGluZSIsInRydWUiXSx0LHQpKS5XNyhuZXcgTC56RChh
-LGQsYixjLGUpLHUuUCkuT0EobmV3IEwuT0UoYSkpfSwKR2U6ZnVuY3Rpb24oKXt2YXIgdD0iL19wcmV2
-aWV3L25hdmlnYXRpb25UcmVlLmpzb24iCkwuUTYodCxDLkNNKS5XNyhuZXcgTC5UVygpLHUuUCkuT0Eo
-bmV3IEwueHIodCkpfSwKcUo6ZnVuY3Rpb24oYSxiKXt2YXIgdAp3aW5kb3cKaWYodHlwZW9mIGNvbnNv
-bGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9yKGEpCndpbmRvdwp0PUguZChiKQppZih0
-eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3IodCl9LApxTzpmdW5j
-dGlvbihhKXt2YXIgdCxzPWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkscj1DLkNELnpRKCQuZmkoKS5v
-ZmZzZXRIZWlnaHQpLHE9d2luZG93LmlubmVySGVpZ2h0LHA9Qy5DRC56USgkLkRXKCkub2Zmc2V0SGVp
-Z2h0KQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLkhOKCkKdD1zLmJvdHRvbQppZih0eXBl
-b2YgdCE9PSJudW1iZXIiKXJldHVybiB0Lm9zKCkKaWYodD5xLShwKzE0KSlKLmRoKGEpCmVsc2V7cT1z
-LnRvcAppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLkooKQppZihxPHIrMTQpSi5kaChhKX19
-LApmRzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgppZihhIT1udWxsKXt0PWRvY3VtZW50CnM9dC5nZXRF
-bGVtZW50QnlJZCgibyIrSC5kKGEpKQpyPXQucXVlcnlTZWxlY3RvcigiLmxpbmUtIitILmQoYikpCmlm
-KHMhPW51bGwpe0wucU8ocykKSi5kUihzKS5pKDAsInRhcmdldCIpfWVsc2UgaWYociE9bnVsbClMLnFP
-KHIucGFyZW50RWxlbWVudCkKaWYociE9bnVsbClKLmRSKHUuaC5hKHIucGFyZW50Tm9kZSkpLmkoMCwi
-aGlnaGxpZ2h0Iil9ZWxzZSBMLnFPKCQuRDkoKSl9LAphZjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0
-LHMscj1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKSxxPUwuYUsod2luZG93LmxvY2F0aW9uLmhyZWYp
-CmlmKHIhPW51bGwpe3Q9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm8iK0guZChyKSkKaWYodCE9bnVs
-bClKLmRSKHQpLlIoMCwidGFyZ2V0Iil9aWYocSE9bnVsbCl7cz1kb2N1bWVudC5xdWVyeVNlbGVjdG9y
-KCIubGluZS0iK0guZChxKSkKaWYocyE9bnVsbClKLmRSKHMucGFyZW50RWxlbWVudCkuUigwLCJoaWdo
-bGlnaHQiKX1pZihhPT13aW5kb3cubG9jYXRpb24ucGF0aG5hbWUpe0wuZkcoYixjKQplLiQwKCl9ZWxz
-ZSBMLkc3KGEsYixjLGQsZSl9LApRNDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1QLmhLKGEpLHE9dS5O
-CnE9UC5GbChxLHEpCmZvcih0PXIuZ2hZKCksdD10LmdQdSh0KSx0PXQuZ2t6KHQpO3QuRigpOyl7cz10
-LmdsKCkKcS5ZKDAscy5hLHMuYil9Zm9yKHQ9Yi5nUHUoYiksdD10Lmdreih0KTt0LkYoKTspe3M9dC5n
-bCgpCnEuWSgwLHMuYSxzLmIpfXEuWSgwLCJhdXRoVG9rZW4iLCQuVUUoKSkKcmV0dXJuIHIubm0oMCxx
-KS5aKDApfSwKTHg6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihhPT09MSl0PWIKZWxzZSB0PWIrInMiCnJl
-dHVybiB0fSwKVDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPSQuaEwoKQpKLmw1KGws
-IiIpCmlmKGE9PW51bGwpe3Q9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgicCIpCnQudGV4dENvbnRlbnQ9
-IlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQgZWRpdC4iCkMuTHQuc0QodCxILlZNKFsicGxhY2Vo
-b2xkZXIiXSx1LnMpKQpKLmRoKHUuaC5hKGwuYXBwZW5kQ2hpbGQodCkpKQpyZXR1cm59cz1hLmUKdD0k
-Lm5VKCkKcj10LnRNKHMpCnE9YS5jCnA9ZG9jdW1lbnQKbz10LkhQKHMsSi5UMChwLnF1ZXJ5U2VsZWN0
-b3IoIi5yb290IikudGV4dENvbnRlbnQpKQpuPWEuZAp0PXAuY3JlYXRlRWxlbWVudCgicCIpCm09dS5o
-LmEobC5hcHBlbmRDaGlsZCh0KSkKbS5hcHBlbmRDaGlsZChwLmNyZWF0ZVRleHROb2RlKEguZChxKSsi
-IGF0ICIrSC5kKG8pKyI6IitILmQobikrIi4iKSkKSi5kaChtKQpMLkNDKGEsbCxyKQpMLkZ6KGEsbCkK
-TC5ORyhhLGwscil9LApMSDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixp
-LGgsZyxmLGUsZD0kLnlQKCkKSi5sNShkLCIiKQp0PWRvY3VtZW50CnM9dC5jcmVhdGVFbGVtZW50KCJw
-IikKcj11LmgKcT1yLmEoZC5hcHBlbmRDaGlsZChzKSkKcD1iLmxlbmd0aAppZihwPT09MClxLmFwcGVu
-ZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUoIk5vIHByb3Bvc2VkIGVkaXRzIikpCmVsc2UgcS5hcHBlbmRD
-aGlsZCh0LmNyZWF0ZVRleHROb2RlKCIiK3ArIiBwcm9wb3NlZCAiK0wuTHgocCwiZWRpdCIpKyI6Iikp
-CnM9dC5jcmVhdGVFbGVtZW50KCJ1bCIpCm89ci5hKGQuYXBwZW5kQ2hpbGQocykpCmZvcihkPWIubGVu
-Z3RoLHM9dS5pLG49dS5RLG09bi5DKCJ+KDEpIiksbD11Lk0sbj1uLmMsaz0wO2s8Yi5sZW5ndGg7Yi5s
-ZW5ndGg9PT1kfHwoMCxILmxrKShiKSwrK2spe2o9YltrXQppPXQuY3JlYXRlRWxlbWVudCgibGkiKQpo
-PXIuYShvLmFwcGVuZENoaWxkKGkpKQpKLmRSKGgpLmkoMCwiZWRpdCIpCmk9dC5jcmVhdGVFbGVtZW50
-KCJhIikKZz1zLmEoaC5hcHBlbmRDaGlsZChpKSkKZy5jbGFzc0xpc3QuYWRkKCJlZGl0LWxpbmsiKQpm
-PWouYwppPUguZChmKQpnLnNldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGcpKS5P
-KCJvZmZzZXQiKSxpKQplPWouYQppPUguZChlKQpnLnNldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5
-KG5ldyBXLmk3KGcpKS5PKCJsaW5lIiksaSkKZy5hcHBlbmRDaGlsZCh0LmNyZWF0ZVRleHROb2RlKCJs
-aW5lICIrSC5kKGUpKSkKaT1tLmEobmV3IEwuRUUoZixlLGEpKQpsLmEobnVsbCkKVy5KRShnLCJjbGlj
-ayIsaSwhMSxuKQpoLmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUoIjogIitILmQoai5iKSkpfWlm
-KGMpTC5UMShudWxsKX0sCkZyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9d2luZG93LmxvY2F0aW9u
-LHE9UC5oSygociYmQy5FeCkuZ0RyKHIpK0guZChhKSkKcj11Lk4Kcj1QLkZsKHIscikKaWYoYiE9bnVs
-bClyLlkoMCwib2Zmc2V0IixILmQoYikpCmlmKGMhPW51bGwpci5ZKDAsImxpbmUiLEguZChjKSkKci5Z
-KDAsImF1dGhUb2tlbiIsJC5VRSgpKQpxPXEubm0oMCxyKQpyPXdpbmRvdy5oaXN0b3J5CnQ9dS56CnM9
-cS5aKDApCnIudG9TdHJpbmcKci5wdXNoU3RhdGUobmV3IFAuQmYoW10sW10pLlB2KFAuRmwodCx0KSks
-IiIscyl9LApFbjpmdW5jdGlvbihhKXt2YXIgdD1KLm0oZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnJv
-b3QiKS50ZXh0Q29udGVudCwiLyIpCmlmKEMueEIubihhLHQpKXJldHVybiBDLnhCLkcoYSx0Lmxlbmd0
-aCkKZWxzZSByZXR1cm4gYX0sCkJYOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXt9CnIuYT1hCmE9TC5F
-bihhKQpyLmE9YQokLkQ5KCkudGV4dENvbnRlbnQ9YQp0PWRvY3VtZW50CnM9dS5oCkguRGgocyxzLCJU
-IiwicXVlcnlTZWxlY3RvckFsbCIpCnQ9bmV3IFcud3oodC5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LXBh
-bmVsIC5uYXYtbGluayIpLHUuVCkKdC5LKHQsbmV3IEwuVlMocikpfSwKQkU6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0PSIucmVnaW9ucyIscz1kb2N1bWVudCxyPXMucXVlcnlTZWxlY3Rvcih0KSxxPXMucXVlcnlT
-ZWxlY3RvcigiLmNvZGUiKQpKLnRIKHIsYi5hLCQuS0coKSkKSi50SChxLGIuYiwkLktHKCkpCkwuTEgo
-YSxiLmQsYykKTC52VSgpCkwueVgoIi5jb2RlIiwhMCkKTC55WCh0LCEwKX0sCnRYOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpPWRvY3VtZW50LGg9aS5jcmVhdGVFbGVtZW50KCJ1
-bCIpLGc9dS5oLGY9Zy5hKGEuYXBwZW5kQ2hpbGQoaCkpCmZvcihoPWIubGVuZ3RoLHQ9dS5NLHM9MDtz
-PGIubGVuZ3RoO2IubGVuZ3RoPT09aHx8KDAsSC5saykoYiksKytzKXtyPWJbc10KcT1pLmNyZWF0ZUVs
-ZW1lbnQoImxpIikKcD1nLmEoZi5hcHBlbmRDaGlsZChxKSkKcT1KLlJFKHApCmlmKHIuYT09PUMuWTIp
-e3EuZ0QocCkuaSgwLCJkaXIiKQpxPWkuY3JlYXRlRWxlbWVudCgic3BhbiIpCm89Zy5hKHAuYXBwZW5k
-Q2hpbGQocSkpCnE9Si5SRShvKQpxLmdEKG8pLmkoMCwiYXJyb3ciKQpxLnNoZihvLCImI3gyNUJDOyIp
-CnE9aS5jcmVhdGVFbGVtZW50KCJzcGFuIikKSi5sNShnLmEocC5hcHBlbmRDaGlsZChxKSksIiYjeDFG
-NEMxOyIpCnAuYXBwZW5kQ2hpbGQoaS5jcmVhdGVUZXh0Tm9kZShyLmIpKQpMLnRYKHAsci5jKQpMLmt6
-KG8pfWVsc2V7cS5zaGYocCwiJiN4MUY0QzQ7IikKcT1pLmNyZWF0ZUVsZW1lbnQoImEiKQpuPWcuYShw
-LmFwcGVuZENoaWxkKHEpKQpxPUouUkUobikKcS5nRChuKS5pKDAsIm5hdi1saW5rIikKbi5zZXRBdHRy
-aWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhuKSkuTygibmFtZSIpLHIuZCkKbi5zZXRBdHRy
-aWJ1dGUoImhyZWYiLHIuZSkKbi5hcHBlbmRDaGlsZChpLmNyZWF0ZVRleHROb2RlKHIuYikpCnE9cS5n
-VmwobikKbT1xLiR0aQpsPW0uQygifigxKSIpLmEobmV3IEwuVEQoKSkKdC5hKG51bGwpClcuSkUocS5h
-LHEuYixsLCExLG0uYykKaz1yLmYKaWYodHlwZW9mIGshPT0ibnVtYmVyIilyZXR1cm4gay5vcygpCmlm
-KGs+MCl7cT1pLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpqPWcuYShwLmFwcGVuZENoaWxkKHEpKQpKLmRS
-KGopLmkoMCwiZWRpdC1jb3VudCIpCnE9IiIraysiICIKaWYoaz09PTEpbT0iZWRpdCIKZWxzZSBtPSJl
-ZGl0cyIKai5zZXRBdHRyaWJ1dGUoInRpdGxlIixxK20pCmouYXBwZW5kQ2hpbGQoaS5jcmVhdGVUZXh0
-Tm9kZShDLmpuLlooaykpKX19fX0sCmM0OmZ1bmN0aW9uKGEsYil7dmFyIHQ9ZG9jdW1lbnQscz10LmNy
-ZWF0ZUVsZW1lbnQoImEiKQp1LmkuYShzKQpzLmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUoSC5k
-KGEuYykrIjoiK0guZChhLmIpKSkKdD1ELm5yKGIsYS5hKQpzLnNldEF0dHJpYnV0ZSgiaHJlZiIsJC5u
-VSgpLm81KHQpKQpzLmNsYXNzTGlzdC5hZGQoIm5hdi1saW5rIikKcmV0dXJuIHN9LApGejpmdW5jdGlv
-bihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1hLmIKaWYoaSE9bnVsbClmb3IodD1pLmxl
-bmd0aCxzPXUuaCxyPXUucyxxPXUuWCxwPTA7cDxpLmxlbmd0aDtpLmxlbmd0aD09PXR8fCgwLEgubGsp
-KGkpLCsrcCl7bz1pW3BdCm49ZG9jdW1lbnQKbT1uLmNyZWF0ZUVsZW1lbnQoInAiKQpsPXMuYShiLmFw
-cGVuZENoaWxkKG0pKQptPW4uY3JlYXRlRWxlbWVudCgiYSIpCms9cy5hKGwuYXBwZW5kQ2hpbGQobSkp
-CmsuYXBwZW5kQ2hpbGQobi5jcmVhdGVUZXh0Tm9kZShvLmEpKQprLnNldEF0dHJpYnV0ZSgiaHJlZiIs
-by5iKQpuPXEuYShILlZNKFsicG9zdC1saW5rIiwiYmVmb3JlLWFwcGx5Il0scikpCmo9Si5kUihrKQpq
-LlYxKDApCmouRlYoMCxuKX19LApORzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxs
-PWEuYQppZihsLmxlbmd0aCE9PTApe3Q9ZG9jdW1lbnQKcz10LmNyZWF0ZUVsZW1lbnQoInAiKQpzLnRl
-eHRDb250ZW50PSJFZGl0IHJhdGlvbmFsZSAoZXhwZXJpbWVudGFsKToiCmIuYXBwZW5kQ2hpbGQocykK
-cz10LmNyZWF0ZUVsZW1lbnQoInVsIikKcj11LmguYShiLmFwcGVuZENoaWxkKHMpKQpmb3Iocz1sLmxl
-bmd0aCxxPTA7cTxsLmxlbmd0aDtsLmxlbmd0aD09PXN8fCgwLEgubGspKGwpLCsrcSl7cD1sW3FdCm89
-dC5jcmVhdGVFbGVtZW50KCJsaSIpCm49ci5hcHBlbmRDaGlsZChvKQpuLmFwcGVuZENoaWxkKHQuY3Jl
-YXRlVGV4dE5vZGUocC5hKSkKbT1wLmIKaWYobSE9bnVsbCl7bi5hcHBlbmRDaGlsZCh0LmNyZWF0ZVRl
-eHROb2RlKCIgKCIpKQpuLmFwcGVuZENoaWxkKEwuYzQobSxjKSkKbi5hcHBlbmRDaGlsZCh0LmNyZWF0
-ZVRleHROb2RlKCIpIikpfX19fSwKQ0M6ZnVuY3Rpb24oYSxiLGEwKXt2YXIgdCxzLHIscSxwLG8sbixt
-LGwsayxqLGksaCxnLGYsZSxkLGMKZm9yKHQ9YS5mLHM9dC5sZW5ndGgscj11LnMscT11LlgscD0wO3A8
-dC5sZW5ndGg7dC5sZW5ndGg9PT1zfHwoMCxILmxrKSh0KSwrK3Ape289dFtwXQpuPWRvY3VtZW50Cm09
-bi5jcmVhdGVFbGVtZW50KCJwIikKbD1xLmEoSC5WTShbInRyYWNlIl0scikpCms9Si5kUihtKQprLlYx
-KDApCmsuRlYoMCxsKQpqPWIuYXBwZW5kQ2hpbGQobSkKbT1uLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQps
-PXEuYShILlZNKFsidHlwZS1kZXNjcmlwdGlvbiJdLHIpKQprPUouZFIobSkKay5WMSgwKQprLkZWKDAs
-bCkKbS5hcHBlbmRDaGlsZChuLmNyZWF0ZVRleHROb2RlKG8uYSkpCmouYXBwZW5kQ2hpbGQobSkKai5h
-cHBlbmRDaGlsZChuLmNyZWF0ZVRleHROb2RlKCI6IikpCm09bi5jcmVhdGVFbGVtZW50KCJ1bCIpCmw9
-cS5hKEguVk0oWyJ0cmFjZSJdLHIpKQprPUouZFIobSkKay5WMSgwKQprLkZWKDAsbCkKaT1qLmFwcGVu
-ZENoaWxkKG0pCmZvcihtPW8uYixsPW0ubGVuZ3RoLGg9MDtoPG0ubGVuZ3RoO20ubGVuZ3RoPT09bHx8
-KDAsSC5saykobSksKytoKXtnPW1baF0KZj1uLmNyZWF0ZUVsZW1lbnQoImxpIikKSi5sNShmLCImI3gy
-NzRGOyAiKQplPWkuYXBwZW5kQ2hpbGQoZikKZj1uLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpkPXEuYShI
-LlZNKFsiZnVuY3Rpb24iXSxyKSkKaz1KLmRSKGYpCmsuVjEoMCkKay5GVigwLGQpCmQ9Zy5iCmlmKGQ9
-PW51bGwpZD0idW5rbm93biIKZi5hcHBlbmRDaGlsZChuLmNyZWF0ZVRleHROb2RlKGQpKQplLmFwcGVu
-ZENoaWxkKGYpCmM9Zy5jCmlmKGMhPW51bGwpe2UuYXBwZW5kQ2hpbGQobi5jcmVhdGVUZXh0Tm9kZSgi
-ICgiKSkKZS5hcHBlbmRDaGlsZChMLmM0KGMsYTApKQplLmFwcGVuZENoaWxkKG4uY3JlYXRlVGV4dE5v
-ZGUoIikiKSl9ZS5hcHBlbmRDaGlsZChuLmNyZWF0ZVRleHROb2RlKCI6ICIpKQplLmFwcGVuZENoaWxk
-KG4uY3JlYXRlVGV4dE5vZGUoZy5hKSl9fX0sCmU6ZnVuY3Rpb24gZSgpe30sClZXOmZ1bmN0aW9uIFZX
-KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCm9aOmZ1bmN0aW9uIG9aKCl7fSwKanI6
-ZnVuY3Rpb24ganIoKXt9LApxbDpmdW5jdGlvbiBxbCgpe30sCnk4OmZ1bmN0aW9uIHk4KCl7fSwKTDpm
-dW5jdGlvbiBMKCl7fSwKV3g6ZnVuY3Rpb24gV3goYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkFPOmZ1
-bmN0aW9uIEFPKGEpe3RoaXMuYT1hfSwKZE46ZnVuY3Rpb24gZE4oYSl7dGhpcy5hPWF9LApIbzpmdW5j
-dGlvbiBIbyhhKXt0aGlzLmE9YX0sCnh6OmZ1bmN0aW9uIHh6KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9
-LApJQzpmdW5jdGlvbiBJQygpe30sCkwxOmZ1bmN0aW9uIEwxKCl7fSwKblQ6ZnVuY3Rpb24gblQoYSxi
-LGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKQlo6ZnVuY3Rpb24gQlooYSl7dGhpcy5hPWF9
-LApHSDpmdW5jdGlvbiBHSCgpe30sCkRUOmZ1bmN0aW9uIERUKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9
-Ygp0aGlzLmM9Y30sCmVIOmZ1bmN0aW9uIGVIKGEpe3RoaXMuYT1hfSwKekQ6ZnVuY3Rpb24gekQoYSxi
-LGMsZCxlKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lfSwKT0U6ZnVuY3Rp
-b24gT0UoYSl7dGhpcy5hPWF9LApUVzpmdW5jdGlvbiBUVygpe30sCnhyOmZ1bmN0aW9uIHhyKGEpe3Ro
-aXMuYT1hfSwKRUU6ZnVuY3Rpb24gRUUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwK
-UUw6ZnVuY3Rpb24gUUwoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sClZTOmZ1bmN0aW9uIFZTKGEpe3Ro
-aXMuYT1hfSwKVEQ6ZnVuY3Rpb24gVEQoKXt9LApYQTpmdW5jdGlvbiBYQSgpe30sCm1LOmZ1bmN0aW9u
-KGEpe3ZhciB0LHMscixxLHAsbyxuPUguVk0oW10sdS5maCkKZm9yKHQ9Si5JVCh1LlIuYShhKSk7dC5G
-KCk7KXtzPXQuZ2woKQpyPUouVTYocykKcT1MLnAyKEguYyhyLnEocywidHlwZSIpKSkKcD1ILmMoci5x
-KHMsIm5hbWUiKSkKbz1yLnEocywic3VidHJlZSIpCm89bz09bnVsbD9udWxsOkwubUsobykKQy5ObS5p
-KG4sbmV3IEwuWloocSxwLG8sSC5jKHIucShzLCJwYXRoIikpLEguYyhyLnEocywiaHJlZiIpKSxILldZ
-KHIucShzLCJlZGl0Q291bnQiKSkpKX1yZXR1cm4gbn0sCnAyOmZ1bmN0aW9uKGEpe3N3aXRjaChhKXtj
-YXNlImRpcmVjdG9yeSI6cmV0dXJuIEMuWTIKY2FzZSJmaWxlIjpyZXR1cm4gQy5yZgpkZWZhdWx0OnRo
-cm93IEguYihQLlBWKCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlwZTogIitILmQo
-YSkpKX19LApaWjpmdW5jdGlvbiBaWihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
-LmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sCk85OmZ1bmN0aW9uIE85KGEpe3RoaXMuYj1hfSwKSVY6ZnVu
-Y3Rpb24gSVYoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9ZH19LE09ewpZ
-RjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuCmZvcih0PWIubGVuZ3RoLHM9MTtzPHQ7Kytz
-KXtpZihiW3NdPT1udWxsfHxiW3MtMV0hPW51bGwpY29udGludWUKZm9yKDt0Pj0xO3Q9cil7cj10LTEK
-aWYoYltyXSE9bnVsbClicmVha31xPW5ldyBQLlJuKCIiKQpwPWErIigiCnEuYT1wCm89SC5xQyhiLDAs
-dCxILnQ2KGIpLmMpCm49by4kdGkKbj1wK25ldyBILmxKKG8sbi5DKCJxVShhTC5FKSIpLmEobmV3IE0u
-Tm8oKSksbi5DKCJsSjxhTC5FLHFVPiIpKS56VigwLCIsICIpCnEuYT1uCnEuYT1uKygiKTogcGFydCAi
-KyhzLTEpKyIgd2FzIG51bGwsIGJ1dCBwYXJ0ICIrcysiIHdhcyBub3QuIikKdGhyb3cgSC5iKFAueFko
-cS5aKDApKSl9fSwKbEk6ZnVuY3Rpb24gbEkoYSl7dGhpcy5hPWF9LApNaTpmdW5jdGlvbiBNaSgpe30s
-CnE3OmZ1bmN0aW9uIHE3KCl7fSwKTm86ZnVuY3Rpb24gTm8oKXt9fSxYPXsKQ0w6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzLHIscSxwLG89Yi54WihhKQpiLmhLKGEpCmlmKG8hPW51bGwpYT1KLktWKGEsby5sZW5n
-dGgpCnQ9dS5zCnM9SC5WTShbXSx0KQpyPUguVk0oW10sdCkKdD1hLmxlbmd0aAppZih0IT09MCYmYi5y
-NChDLnhCLlcoYSwwKSkpe2lmKDA+PXQpcmV0dXJuIEguayhhLDApCkMuTm0uaShyLGFbMF0pCnE9MX1l
-bHNle0MuTm0uaShyLCIiKQpxPTB9Zm9yKHA9cTtwPHQ7KytwKWlmKGIucjQoQy54Qi5XKGEscCkpKXtD
-Lk5tLmkocyxDLnhCLncoYSxxLHApKQpDLk5tLmkocixhW3BdKQpxPXArMX1pZihxPHQpe0MuTm0uaShz
-LEMueEIuRyhhLHEpKQpDLk5tLmkociwiIil9cmV0dXJuIG5ldyBYLldEKGIsbyxzLHIpfSwKV0Q6ZnVu
-Y3Rpb24gV0QoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9YwpfLmU9ZH0sCnFSOmZ1
-bmN0aW9uIHFSKGEpe3RoaXMuYT1hfSwKSTc6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBYLmR2KGEpfSwK
-ZHY6ZnVuY3Rpb24gZHYoYSl7dGhpcy5hPWF9fSxPPXsKUmg6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxw
-LG8sbixtLGwsayxqLGk9bnVsbAppZihQLnVvKCkuZ0ZpKCkhPT0iZmlsZSIpcmV0dXJuICQuRWIoKQp0
-PVAudW8oKQppZighQy54Qi5UYyh0LmdJaSh0KSwiLyIpKXJldHVybiAkLkViKCkKcz1QLlBpKGksMCww
-KQpyPVAuelIoaSwwLDApCnE9UC5PZShpLDAsMCwhMSkKcD1QLmxlKGksMCwwLGkpCm89UC50RyhpLDAs
-MCkKbj1QLndCKGkscykKbT1zPT09ImZpbGUiCmlmKHE9PW51bGwpdD1yLmxlbmd0aCE9PTB8fG4hPW51
-bGx8fG0KZWxzZSB0PSExCmlmKHQpcT0iIgp0PXE9PW51bGwKbD0hdAprPVAua2EoImEvYiIsMCwzLGks
-cyxsKQpqPXMubGVuZ3RoPT09MAppZihqJiZ0JiYhQy54Qi5uKGssIi8iKSlrPVAud0Yoaywhanx8bCkK
-ZWxzZSBrPVAueGUoaykKaWYobmV3IFAuRG4ocyxyLHQmJkMueEIubihrLCIvLyIpPyIiOnEsbixrLHAs
-bykudDQoKT09PSJhXFxiIilyZXR1cm4gJC5LaygpCnJldHVybiAkLmJEKCl9LAp6TDpmdW5jdGlvbiB6
-TCgpe319LEU9e09GOmZ1bmN0aW9uIE9GKGEsYixjKXt0aGlzLmQ9YQp0aGlzLmU9Ygp0aGlzLmY9Y319
-LEY9e3J1OmZ1bmN0aW9uIHJ1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5kPWEKXy5lPWIKXy5mPWMKXy5y
-PWR9fSxEPXsKUlg6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9UC51bygpCmlmKEouUk0ociwkLkk2KSlyZXR1
-cm4gJC5GZgokLkk2PXIKaWYoJC5IaygpPT0kLkViKCkpcmV0dXJuICQuRmY9ci5aSSgiLiIpLlooMCkK
-ZWxzZXt0PXIudDQoKQpzPXQubGVuZ3RoLTEKcmV0dXJuICQuRmY9cz09PTA/dDpDLnhCLncodCwwLHMp
-fX0sCm5yOmZ1bmN0aW9uKGEsYil7dmFyIHQ9bnVsbApyZXR1cm4gJC5uVSgpLnE3KDAsYSxiLHQsdCx0
-LHQsdCx0KX19CnZhciB3PVtDLEgsSixQLFcsVSxCLFQsTCxNLFgsTyxFLEYsRF0KaHVua0hlbHBlcnMu
-c2V0RnVuY3Rpb25OYW1lc0lmTmVjZXNzYXJ5KHcpCnZhciAkPXt9CkguRksucHJvdG90eXBlPXt9Ckou
-dkIucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09PWJ9LApnaU86ZnVuY3Rpb24o
-YSl7cmV0dXJuIEguZVEoYSl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiJJbnN0YW5jZSBvZiAnIitILmQo
-SC5saChhKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1Lm8uYShiKQp0aHJvdyBILmIoUC5scihhLGIu
-Z1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9fQpKLnlFLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0
-dXJuIFN0cmluZyhhKX0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gYT81MTkwMTg6MjE4MTU5fSwKJGlh
-MjoxfQpKLllFLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG51bGw9PWJ9LApaOmZ1
-bmN0aW9uKGEpe3JldHVybiJudWxsIn0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH0sCmU3OmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIHRoaXMuU2ooYSx1Lm8uYShiKSl9LAokaWM4OjF9CkouTUYucHJvdG90eXBl
-PXsKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEp
-fSwKJGl2bToxfQpKLmlDLnByb3RvdHlwZT17fQpKLmtkLnByb3RvdHlwZT17fQpKLmM1LnByb3RvdHlw
-ZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9YVskLndRKCldCmlmKHQ9PW51bGwpcmV0dXJuIHRoaXMudChh
-KQpyZXR1cm4iSmF2YVNjcmlwdCBmdW5jdGlvbiBmb3IgIitILmQoSi5BYyh0KSl9LAokUzpmdW5jdGlv
-bigpe3JldHVybntmdW5jOjEsb3B0OlssLCwsLCwsLCwsLCwsLCwsXX19LAokaUVIOjF9CkouamQucHJv
-dG90eXBlPXsKaTpmdW5jdGlvbihhLGIpe0gudDYoYSkuYy5hKGIpCmlmKCEhYS5maXhlZCRsZW5ndGgp
-SC52aChQLkw0KCJhZGQiKSkKYS5wdXNoKGIpfSwKVzQ6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZighIWEu
-Zml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgicmVtb3ZlQXQiKSkKdD1hLmxlbmd0aAppZihiPj10KXRocm93
-IEguYihQLk83KGIsbnVsbCkpCnJldHVybiBhLnNwbGljZShiLDEpWzBdfSwKVUc6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0LHMscgpILnQ2KGEpLkMoImNYPDE+IikuYShjKQppZighIWEuZml4ZWQkbGVuZ3RoKUgu
-dmgoUC5MNCgiaW5zZXJ0QWxsIikpCnQ9YS5sZW5ndGgKUC53QShiLDAsdCwiaW5kZXgiKQpzPWMubGVu
-Z3RoCnRoaXMuc0EoYSx0K3MpCnI9YitzCnRoaXMuWVcoYSxyLGEubGVuZ3RoLGEsYikKdGhpcy52Zyhh
-LGIscixjKX0sCm12OmZ1bmN0aW9uKGEpe2lmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJyZW1v
-dmVMYXN0IikpCmlmKGEubGVuZ3RoPT09MCl0aHJvdyBILmIoSC5IWShhLC0xKSkKcmV0dXJuIGEucG9w
-KCl9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0CkgudDYoYSkuQygiY1g8MT4iKS5hKGIpCmlmKCEhYS5m
-aXhlZCRsZW5ndGgpSC52aChQLkw0KCJhZGRBbGwiKSkKZm9yKHQ9Si5JVChiKTt0LkYoKTspYS5wdXNo
-KHQuZ2woKSl9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnQ2KGEpLkMoIn4oMSkiKS5hKGIpCnQ9
-YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKXtiLiQxKGFbc10pCmlmKGEubGVuZ3RoIT09dCl0aHJvdyBI
-LmIoUC5hNChhKSl9fSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUgudDYoYSkKcmV0dXJuIG5ldyBI
-LmxKKGEsdC5LcShjKS5DKCIxKDIpIikuYShiKSx0LkMoIkA8MT4iKS5LcShjKS5DKCJsSjwxLDI+Iikp
-fSwKelY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPW5ldyBBcnJheShhLmxlbmd0aCkKcy5maXhlZCRsZW5n
-dGg9QXJyYXkKZm9yKHQ9MDt0PGEubGVuZ3RoOysrdCl0aGlzLlkocyx0LEguZChhW3RdKSkKcmV0dXJu
-IHMuam9pbihiKX0sCk4wOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscgpkLmEoYikKSC50NihhKS5L
-cShkKS5DKCIxKDEsMikiKS5hKGMpCnQ9YS5sZW5ndGgKZm9yKHM9YixyPTA7cjx0Oysrcil7cz1jLiQy
-KHMsYVtyXSkKaWYoYS5sZW5ndGghPT10KXRocm93IEguYihQLmE0KGEpKX1yZXR1cm4gc30sCkU6ZnVu
-Y3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0s
-CkQ2OmZ1bmN0aW9uKGEsYixjKXtpZihiPDB8fGI+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYiwwLGEu
-bGVuZ3RoLCJzdGFydCIsbnVsbCkpCmlmKGM8Ynx8Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShjLGIs
-YS5sZW5ndGgsImVuZCIsbnVsbCkpCmlmKGI9PT1jKXJldHVybiBILlZNKFtdLEgudDYoYSkpCnJldHVy
-biBILlZNKGEuc2xpY2UoYixjKSxILnQ2KGEpKX0sCmdyWjpmdW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0
-aAppZih0PjApcmV0dXJuIGFbdC0xXQp0aHJvdyBILmIoSC5XcCgpKX0sCllXOmZ1bmN0aW9uKGEsYixj
-LGQsZSl7dmFyIHQscyxyPUgudDYoYSkKci5DKCJjWDwxPiIpLmEoZCkKaWYoISFhLmltbXV0YWJsZSRs
-aXN0KUgudmgoUC5MNCgic2V0UmFuZ2UiKSkKUC5qQihiLGMsYS5sZW5ndGgpCnQ9Yy1iCmlmKHQ9PT0w
-KXJldHVybgpQLmsxKGUsInNraXBDb3VudCIpCnIuQygiek08MT4iKS5hKGQpCnI9Si5VNihkKQppZihl
-K3Q+ci5nQShkKSl0aHJvdyBILmIoSC5hcigpKQppZihlPGIpZm9yKHM9dC0xO3M+PTA7LS1zKWFbYitz
-XT1yLnEoZCxlK3MpCmVsc2UgZm9yKHM9MDtzPHQ7KytzKWFbYitzXT1yLnEoZCxlK3MpfSwKdmc6ZnVu
-Y3Rpb24oYSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0sClZyOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscwpILnQ2KGEpLkMoImEyKDEpIikuYShiKQp0PWEubGVuZ3RoCmZvcihzPTA7czx0Oysrcyl7
-aWYoSC5vVChiLiQxKGFbc10pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9PXQpdGhyb3cgSC5iKFAuYTQo
-YSkpfXJldHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0
-KWlmKEouUk0oYVt0XSxiKSlyZXR1cm4hMApyZXR1cm4hMX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIFAu
-V0UoYSwiWyIsIl0iKX0sCmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEoubTEoYSxhLmxlbmd0aCxI
-LnQ2KGEpLkMoIm0xPDE+IikpfSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKZ0E6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKc0E6ZnVuY3Rpb24oYSxiKXtpZighIWEuZml4ZWQkbGVu
-Z3RoKUgudmgoUC5MNCgic2V0IGxlbmd0aCIpKQppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLG51bGws
-Im5ld0xlbmd0aCIsbnVsbCkpCmEubGVuZ3RoPWJ9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihi
-Pj1hLmxlbmd0aHx8YjwwKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlv
-bihhLGIsYyl7SC50NihhKS5jLmEoYykKaWYoISFhLmltbXV0YWJsZSRsaXN0KUgudmgoUC5MNCgiaW5k
-ZXhlZCBzZXQiKSkKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQphW2JdPWN9
-LAokaWJROjEsCiRpY1g6MSwKJGl6TToxfQpKLlBvLnByb3RvdHlwZT17fQpKLm0xLnByb3RvdHlwZT17
-CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMscj1z
-LmEscT1yLmxlbmd0aAppZihzLmIhPT1xKXRocm93IEguYihILmxrKHIpKQp0PXMuYwppZih0Pj1xKXtz
-LnNIKG51bGwpCnJldHVybiExfXMuc0goclt0XSk7KytzLmMKcmV0dXJuITB9LApzSDpmdW5jdGlvbihh
-KXt0aGlzLmQ9dGhpcy4kdGkuYy5hKGEpfSwKJGlBbjoxfQpKLnFJLnByb3RvdHlwZT17Cnl1OmZ1bmN0
-aW9uKGEpe3ZhciB0CmlmKGE+PS0yMTQ3NDgzNjQ4JiZhPD0yMTQ3NDgzNjQ3KXJldHVybiBhfDAKaWYo
-aXNGaW5pdGUoYSkpe3Q9YTwwP01hdGguY2VpbChhKTpNYXRoLmZsb29yKGEpCnJldHVybiB0KzB9dGhy
-b3cgSC5iKFAuTDQoIiIrYSsiLnRvSW50KCkiKSl9LAp6UTpmdW5jdGlvbihhKXtpZihhPjApe2lmKGEh
-PT0xLzApcmV0dXJuIE1hdGgucm91bmQoYSl9ZWxzZSBpZihhPi0xLzApcmV0dXJuIDAtTWF0aC5yb3Vu
-ZCgwLWEpCnRocm93IEguYihQLkw0KCIiK2ErIi5yb3VuZCgpIikpfSwKRDg6ZnVuY3Rpb24oYSxiKXt2
-YXIgdCxzLHIscQppZihiPDJ8fGI+MzYpdGhyb3cgSC5iKFAuVEUoYiwyLDM2LCJyYWRpeCIsbnVsbCkp
-CnQ9YS50b1N0cmluZyhiKQppZihDLnhCLm0odCx0Lmxlbmd0aC0xKSE9PTQxKXJldHVybiB0CnM9L14o
-W1xkYS16XSspKD86XC4oW1xkYS16XSspKT9cKGVcKyhcZCspXCkkLy5leGVjKHQpCmlmKHM9PW51bGwp
-SC52aChQLkw0KCJVbmV4cGVjdGVkIHRvU3RyaW5nIHJlc3VsdDogIit0KSkKcj1zLmxlbmd0aAppZigx
-Pj1yKXJldHVybiBILmsocywxKQp0PXNbMV0KaWYoMz49cilyZXR1cm4gSC5rKHMsMykKcT0rc1szXQpy
-PXNbMl0KaWYociE9bnVsbCl7dCs9cgpxLT1yLmxlbmd0aH1yZXR1cm4gdCtDLnhCLkl4KCIwIixxKX0s
-Clo6ZnVuY3Rpb24oYSl7aWYoYT09PTAmJjEvYTwwKXJldHVybiItMC4wIgplbHNlIHJldHVybiIiK2F9
-LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1hfDAKaWYoYT09PXApcmV0dXJuIDUzNjg3MDkx
-MSZwCnQ9TWF0aC5hYnMoYSkKcz1NYXRoLmxvZyh0KS8wLjY5MzE0NzE4MDU1OTk0NTN8MApyPU1hdGgu
-cG93KDIscykKcT10PDE/dC9yOnIvdApyZXR1cm4gNTM2ODcwOTExJigocSo5MDA3MTk5MjU0NzQwOTky
-fDApKyhxKjM1NDIyNDMxODExNzY1MjF8MCkpKjU5OTE5NytzKjEyNTl9LAp6WTpmdW5jdGlvbihhLGIp
-e3ZhciB0PWElYgppZih0PT09MClyZXR1cm4gMAppZih0PjApcmV0dXJuIHQKaWYoYjwwKXJldHVybiB0
-LWIKZWxzZSByZXR1cm4gdCtifSwKd0c6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihhPjApdD10aGlzLnAz
-KGEsYikKZWxzZXt0PWI+MzE/MzE6Ygp0PWE+PnQ+Pj4wfXJldHVybiB0fSwKYmY6ZnVuY3Rpb24oYSxi
-KXtpZihiPDApdGhyb3cgSC5iKEguSShiKSkKcmV0dXJuIHRoaXMucDMoYSxiKX0sCnAzOmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIGI+MzE/MDphPj4+Yn0sCiRpQ1A6MSwKJGlsZjoxfQpKLnVyLnByb3RvdHlwZT17
-JGlJZjoxfQpKLlZBLnByb3RvdHlwZT17fQpKLkRyLnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oYSxiKXtp
-ZihiPDApdGhyb3cgSC5iKEguSFkoYSxiKSkKaWYoYj49YS5sZW5ndGgpSC52aChILkhZKGEsYikpCnJl
-dHVybiBhLmNoYXJDb2RlQXQoYil9LApXOmZ1bmN0aW9uKGEsYil7aWYoYj49YS5sZW5ndGgpdGhyb3cg
-SC5iKEguSFkoYSxiKSkKcmV0dXJuIGEuY2hhckNvZGVBdChiKX0sCmRkOmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIG5ldyBILk5GKGIsYSwwKX0sCmg6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyIp
-dGhyb3cgSC5iKFAuTDMoYixudWxsLG51bGwpKQpyZXR1cm4gYStifSwKVGM6ZnVuY3Rpb24oYSxiKXt2
-YXIgdD1iLmxlbmd0aCxzPWEubGVuZ3RoCmlmKHQ+cylyZXR1cm4hMQpyZXR1cm4gYj09PXRoaXMuRyhh
-LHMtdCl9LAppNzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzCmM9UC5qQihiLGMsYS5sZW5ndGgpCnQ9
-YS5zdWJzdHJpbmcoMCxiKQpzPWEuc3Vic3RyaW5nKGMpCnJldHVybiB0K2Qrc30sClFpOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdAppZighSC5vayhjKSlILnZoKEguSShjKSkKaWYodHlwZW9mIGMhPT0ibnVtYmVy
-IilyZXR1cm4gYy5KKCkKaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0
-aCxudWxsLG51bGwpKQp0PWMrYi5sZW5ndGgKaWYodD5hLmxlbmd0aClyZXR1cm4hMQpyZXR1cm4gYj09
-PWEuc3Vic3RyaW5nKGMsdCl9LApuOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuUWkoYSxiLDApfSwK
-dzpmdW5jdGlvbihhLGIsYyl7aWYoIUgub2soYikpSC52aChILkkoYikpCmlmKGM9PW51bGwpYz1hLmxl
+LnhCLm5DKGEsIi8iKSlyZXR1cm4gUC53RihhLCF0fHxjKQpyZXR1cm4gUC54ZShhKX0sCmxlOmZ1bmN0
+aW9uKGEsYixjLGQpe3ZhciB0LHM9e30KaWYoYSE9bnVsbCl7aWYoZCE9bnVsbCl0aHJvdyBILmIoUC54
+WSgiQm90aCBxdWVyeSBhbmQgcXVlcnlQYXJhbWV0ZXJzIHNwZWNpZmllZCIpKQpyZXR1cm4gUC51Tyhh
+LGIsYyxDLlZDLCEwKX1pZihkPT1udWxsKXJldHVybiBudWxsCnQ9bmV3IFAuUm4oIiIpCnMuYT0iIgpk
+LlUoMCxuZXcgUC55NShuZXcgUC5NRShzLHQpKSkKcz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09
+MD9zOnN9LAp0RzpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4gbnVsbApyZXR1cm4gUC51
+TyhhLGIsYyxDLlZDLCEwKX0sCnJ2OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG89YisyCmlm
+KG8+PWEubGVuZ3RoKXJldHVybiIlIgp0PUMueEIuTzIoYSxiKzEpCnM9Qy54Qi5PMihhLG8pCnI9SC5v
+byh0KQpxPUgub28ocykKaWYocjwwfHxxPDApcmV0dXJuIiUiCnA9cioxNitxCmlmKHA8MTI3KXtvPUMu
+am4ud0cocCw0KQppZihvPj04KXJldHVybiBILmsoQy5GMyxvKQpvPShDLkYzW29dJjE8PChwJjE1KSkh
+PT0wfWVsc2Ugbz0hMQppZihvKXJldHVybiBILkx3KGMmJjY1PD1wJiY5MD49cD8ocHwzMik+Pj4wOnAp
+CmlmKHQ+PTk3fHxzPj05NylyZXR1cm4gQy54Qi5OaihhLGIsYiszKS50b1VwcGVyQ2FzZSgpCnJldHVy
+biBudWxsfSwKSEg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49IjAxMjM0NTY3ODlBQkNERUYi
+CmlmKGE8MTI4KXt0PW5ldyBBcnJheSgzKQp0LmZpeGVkJGxlbmd0aD1BcnJheQpzPUguVk0odCx1LnQp
+CkMuTm0udChzLDAsMzcpCkMuTm0udChzLDEsQy54Qi5XZChuLGE+Pj40KSkKQy5ObS50KHMsMixDLnhC
+LldkKG4sYSYxNSkpfWVsc2V7aWYoYT4yMDQ3KWlmKGE+NjU1MzUpe3I9MjQwCnE9NH1lbHNle3I9MjI0
+CnE9M31lbHNle3I9MTkyCnE9Mn10PW5ldyBBcnJheSgzKnEpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9
+SC5WTSh0LHUudCkKZm9yKHA9MDstLXEscT49MDtyPTEyOCl7bz1DLmpuLmJmKGEsNipxKSY2M3xyCkMu
+Tm0udChzLHAsMzcpCkMuTm0udChzLHArMSxDLnhCLldkKG4sbz4+PjQpKQpDLk5tLnQocyxwKzIsQy54
+Qi5XZChuLG8mMTUpKQpwKz0zfX1yZXR1cm4gUC5ITShzLDAsbnVsbCl9LAp1TzpmdW5jdGlvbihhLGIs
+YyxkLGUpe3ZhciB0PVAuVWwoYSxiLGMsZCxlKQpyZXR1cm4gdD09bnVsbD9DLnhCLk5qKGEsYixjKTp0
+fSwKVWw6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG89bnVsbCxuPSFlLG09YixsPW0s
+az1vCndoaWxlKCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQppZih0eXBlb2Yg
+YyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCmlmKCEobTxjKSlicmVhawpjJDA6e3Q9Qy54Qi5PMihh
+LG0pCmlmKHQ8MTI3KXtzPXQ+Pj40CmlmKHM+PTgpcmV0dXJuIEguayhkLHMpCnM9KGRbc10mMTw8KHQm
+MTUpKSE9PTB9ZWxzZSBzPSExCmlmKHMpKyttCmVsc2V7aWYodD09PTM3KXtyPVAucnYoYSxtLCExKQpp
+ZihyPT1udWxsKXttKz0zCmJyZWFrIGMkMH1pZigiJSI9PT1yKXtyPSIlMjUiCnE9MX1lbHNlIHE9M31l
+bHNle2lmKG4paWYodDw9OTMpe3M9dD4+PjQKaWYocz49OClyZXR1cm4gSC5rKEMuYWsscykKcz0oQy5h
+a1tzXSYxPDwodCYxNSkpIT09MH1lbHNlIHM9ITEKZWxzZSBzPSExCmlmKHMpe1AuUjMoYSxtLCJJbnZh
+bGlkIGNoYXJhY3RlciIpCnE9bwpyPXF9ZWxzZXtpZigodCY2NDUxMik9PT01NTI5Nil7cz1tKzEKaWYo
+czxjKXtwPUMueEIuTzIoYSxzKQppZigocCY2NDUxMik9PT01NjMyMCl7dD02NTUzNnwodCYxMDIzKTw8
+MTB8cCYxMDIzCnE9Mn1lbHNlIHE9MX1lbHNlIHE9MX1lbHNlIHE9MQpyPVAuSEgodCl9fWlmKGs9PW51
+bGwpaz1uZXcgUC5SbigiIikKay5hKz1DLnhCLk5qKGEsbCxtKQprLmErPUguZChyKQppZih0eXBlb2Yg
+cSE9PSJudW1iZXIiKXJldHVybiBILnBZKHEpCm0rPXEKbD1tfX19aWYoaz09bnVsbClyZXR1cm4gbwpp
+Zih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLkooKQppZihsPGMpay5hKz1DLnhCLk5qKGEsbCxj
+KQpuPWsuYQpyZXR1cm4gbi5jaGFyQ29kZUF0KDApPT0wP246bn0sCnlCOmZ1bmN0aW9uKGEpe2lmKEMu
+eEIubkMoYSwiLiIpKXJldHVybiEwCnJldHVybiBDLnhCLk9ZKGEsIi8uIikhPT0tMX0sCnhlOmZ1bmN0
+aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuCmlmKCFQLnlCKGEpKXJldHVybiBhCnQ9SC5WTShbXSx1LnMp
+CmZvcihzPWEuc3BsaXQoIi8iKSxyPXMubGVuZ3RoLHE9ITEscD0wO3A8cjsrK3Ape289c1twXQppZihK
+LlJNKG8sIi4uIikpe249dC5sZW5ndGgKaWYobiE9PTApe2lmKDA+PW4pcmV0dXJuIEguayh0LC0xKQp0
+LnBvcCgpCmlmKHQubGVuZ3RoPT09MClDLk5tLkEodCwiIil9cT0hMH1lbHNlIGlmKCIuIj09PW8pcT0h
+MAplbHNle0MuTm0uQSh0LG8pCnE9ITF9fWlmKHEpQy5ObS5BKHQsIiIpCnJldHVybiBDLk5tLnpWKHQs
+Ii8iKX0sCndGOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvCmlmKCFQLnlCKGEpKXJldHVybiFi
+P1AuQzEoYSk6YQp0PUguVk0oW10sdS5zKQpmb3Iocz1hLnNwbGl0KCIvIikscj1zLmxlbmd0aCxxPSEx
+LHA9MDtwPHI7KytwKXtvPXNbcF0KaWYoIi4uIj09PW8paWYodC5sZW5ndGghPT0wJiZDLk5tLmdyWih0
+KSE9PSIuLiIpe2lmKDA+PXQubGVuZ3RoKXJldHVybiBILmsodCwtMSkKdC5wb3AoKQpxPSEwfWVsc2V7
+Qy5ObS5BKHQsIi4uIikKcT0hMX1lbHNlIGlmKCIuIj09PW8pcT0hMAplbHNle0MuTm0uQSh0LG8pCnE9
+ITF9fXM9dC5sZW5ndGgKaWYocyE9PTApaWYocz09PTEpe2lmKDA+PXMpcmV0dXJuIEguayh0LDApCnM9
+dFswXS5sZW5ndGg9PT0wfWVsc2Ugcz0hMQplbHNlIHM9ITAKaWYocylyZXR1cm4iLi8iCmlmKHF8fEMu
+Tm0uZ3JaKHQpPT09Ii4uIilDLk5tLkEodCwiIikKaWYoIWIpe2lmKDA+PXQubGVuZ3RoKXJldHVybiBI
+LmsodCwwKQpDLk5tLnQodCwwLFAuQzEodFswXSkpfXJldHVybiBDLk5tLnpWKHQsIi8iKX0sCkMxOmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscixxPWEubGVuZ3RoCmlmKHE+PTImJlAuRXQoSi5ReihhLDApKSlmb3Io
+dD0xO3Q8cTsrK3Qpe3M9Qy54Qi5XZChhLHQpCmlmKHM9PT01OClyZXR1cm4gQy54Qi5OaihhLDAsdCkr
+IiUzQSIrQy54Qi55bihhLHQrMSkKaWYoczw9MTI3KXtyPXM+Pj40CmlmKHI+PTgpcmV0dXJuIEguayhD
+Lm1LLHIpCnI9KEMubUtbcl0mMTw8KHMmMTUpKT09PTB9ZWxzZSByPSEwCmlmKHIpYnJlYWt9cmV0dXJu
+IGF9LAptbjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmdGaigpLHA9cS5sZW5ndGgKaWYocD4wJiZK
+LkgocVswXSk9PT0yJiZKLmE2KHFbMF0sMSk9PT01OCl7aWYoMD49cClyZXR1cm4gSC5rKHEsMCkKUC5y
+ZyhKLmE2KHFbMF0sMCksITEpClAuSE4ocSwhMSwxKQp0PSEwfWVsc2V7UC5ITihxLCExLDApCnQ9ITF9
+cz1hLmd0VCgpJiYhdD8iXFwiOiIiCmlmKGEuZ2NqKCkpe3I9YS5nSmYoYSkKaWYoci5sZW5ndGghPT0w
+KXM9cysiXFwiK3IrIlxcIn1zPVAudmcocyxxLCJcXCIpCnA9dCYmcD09PTE/cysiXFwiOnMKcmV0dXJu
+IHAuY2hhckNvZGVBdCgwKT09MD9wOnB9LApJaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgpmb3IodD0w
+LHM9MDtzPDI7KytzKXtyPUMueEIuV2QoYSxiK3MpCmlmKDQ4PD1yJiZyPD01Nyl0PXQqMTYrci00OApl
+bHNle3J8PTMyCmlmKDk3PD1yJiZyPD0xMDIpdD10KjE2K3ItODcKZWxzZSB0aHJvdyBILmIoUC54WSgi
+SW52YWxpZCBVUkwgZW5jb2RpbmciKSl9fXJldHVybiB0fSwKa3U6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2
+YXIgdCxzLHIscSxwPUouclkoYSksbz1iCndoaWxlKCEwKXtpZighKG88Yykpe3Q9ITAKYnJlYWt9cz1w
+LldkKGEsbykKaWYoczw9MTI3KWlmKHMhPT0zNylyPWUmJnM9PT00MwplbHNlIHI9ITAKZWxzZSByPSEw
+CmlmKHIpe3Q9ITEKYnJlYWt9KytvfWlmKHQpe2lmKEMueE0hPT1kKXI9ITEKZWxzZSByPSEwCmlmKHIp
+cmV0dXJuIHAuTmooYSxiLGMpCmVsc2UgcT1uZXcgSC5xaihwLk5qKGEsYixjKSl9ZWxzZXtxPUguVk0o
+W10sdS50KQpmb3Iobz1iO288YzsrK28pe3M9cC5XZChhLG8pCmlmKHM+MTI3KXRocm93IEguYihQLnhZ
+KCJJbGxlZ2FsIHBlcmNlbnQgZW5jb2RpbmcgaW4gVVJJIikpCmlmKHM9PT0zNyl7aWYobyszPmEubGVu
+Z3RoKXRocm93IEguYihQLnhZKCJUcnVuY2F0ZWQgVVJJIikpCkMuTm0uQShxLFAuSWgoYSxvKzEpKQpv
+Kz0yfWVsc2UgaWYoZSYmcz09PTQzKUMuTm0uQShxLDMyKQplbHNlIEMuTm0uQShxLHMpfX11LkwuYShx
+KQpyZXR1cm4gbmV3IFAuR1koITEpLldKKHEpfSwKRXQ6ZnVuY3Rpb24oYSl7dmFyIHQ9YXwzMgpyZXR1
+cm4gOTc8PXQmJnQ8PTEyMn0sCktEOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9
+IkludmFsaWQgTUlNRSB0eXBlIixrPUguVk0oW2ItMV0sdS50KQpmb3IodD1hLmxlbmd0aCxzPWIscj0t
+MSxxPW51bGw7czx0Oysrcyl7cT1DLnhCLldkKGEscykKaWYocT09PTQ0fHxxPT09NTkpYnJlYWsKaWYo
+cT09PTQ3KXtpZihyPDApe3I9cwpjb250aW51ZX10aHJvdyBILmIoUC5ycihsLGEscykpfX1pZihyPDAm
+JnM+Yil0aHJvdyBILmIoUC5ycihsLGEscykpCmZvcig7cSE9PTQ0Oyl7Qy5ObS5BKGsscyk7KytzCmZv
+cihwPS0xO3M8dDsrK3Mpe3E9Qy54Qi5XZChhLHMpCmlmKHE9PT02MSl7aWYocDwwKXA9c31lbHNlIGlm
+KHE9PT01OXx8cT09PTQ0KWJyZWFrfWlmKHA+PTApQy5ObS5BKGsscCkKZWxzZXtvPUMuTm0uZ3JaKGsp
+CmlmKHEhPT00NHx8cyE9PW8rN3x8IUMueEIuUWkoYSwiYmFzZTY0IixvKzEpKXRocm93IEguYihQLnJy
+KCJFeHBlY3RpbmcgJz0nIixhLHMpKQpicmVha319Qy5ObS5BKGsscykKbj1zKzEKaWYoKGsubGVuZ3Ro
+JjEpPT09MSlhPUMuaDkueXIoMCxhLG4sdCkKZWxzZXttPVAuVWwoYSxuLHQsQy5WQywhMCkKaWYobSE9
+bnVsbClhPUMueEIuaTcoYSxuLHQsbSl9cmV0dXJuIG5ldyBQLlBFKGEsayxjKX0sCktOOmZ1bmN0aW9u
+KCl7dmFyIHQ9IjAxMjM0NTY3ODlBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1u
+b3BxcnN0dXZ3eHl6LS5ffiEkJicoKSorLDs9IixzPSIuIixyPSI6IixxPSIvIixwPSI/IixvPSIjIixu
+PXUuZ2MsbT1QLmRIKDIyLG5ldyBQLnEzKCksITAsbiksbD1uZXcgUC55SShtKSxrPW5ldyBQLmM2KCks
+aj1uZXcgUC5xZCgpLGk9bi5hKGwuJDIoMCwyMjUpKQprLiQzKGksdCwxKQprLiQzKGkscywxNCkKay4k
+MyhpLHIsMzQpCmsuJDMoaSxxLDMpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQy
+KDE0LDIyNSkpCmsuJDMoaSx0LDEpCmsuJDMoaSxzLDE1KQprLiQzKGksciwzNCkKay4kMyhpLHEsMjM0
+KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxNSwyMjUpKQprLiQzKGksdCwx
+KQprLiQzKGksIiUiLDIyNSkKay4kMyhpLHIsMzQpCmsuJDMoaSxxLDkpCmsuJDMoaSxwLDE3MikKay4k
+MyhpLG8sMjA1KQppPW4uYShsLiQyKDEsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLHIsMzQpCmsuJDMo
+aSxxLDEwKQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigyLDIzNSkpCmsuJDMo
+aSx0LDEzOSkKay4kMyhpLHEsMTMxKQprLiQzKGkscywxNDYpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8s
+MjA1KQppPW4uYShsLiQyKDMsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDY4KQprLiQzKGkscywx
+OCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNCwyMjkpKQprLiQzKGksdCw1
+KQpqLiQzKGksIkFaIiwyMjkpCmsuJDMoaSxyLDEwMikKay4kMyhpLCJAIiw2OCkKay4kMyhpLCJbIiwy
+MzIpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNSwy
+MjkpKQprLiQzKGksdCw1KQpqLiQzKGksIkFaIiwyMjkpCmsuJDMoaSxyLDEwMikKay4kMyhpLCJAIiw2
+OCkKay4kMyhpLHEsMTM4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMig2LDIz
+MSkpCmouJDMoaSwiMTkiLDcpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcy
+KQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNywyMzEpKQpqLiQzKGksIjA5Iiw3KQprLiQzKGksIkAi
+LDY4KQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQprLiQzKG4uYShsLiQy
+KDgsOCkpLCJdIiw1KQppPW4uYShsLiQyKDksMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxzLDE2KQpr
+LiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDE2LDIzNSkp
+CmsuJDMoaSx0LDExKQprLiQzKGkscywxNykKay4kMyhpLHEsMjM0KQprLiQzKGkscCwxNzIpCmsuJDMo
+aSxvLDIwNSkKaT1uLmEobC4kMigxNywyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHEsOSkKay4kMyhp
+LHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoMTAsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMo
+aSxzLDE4KQprLiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQy
+KDE4LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscywxOSkKay4kMyhpLHEsMjM0KQprLiQzKGkscCwx
+NzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxOSwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHEs
+MjM0KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxMSwyMzUpKQprLiQzKGks
+dCwxMSkKay4kMyhpLHEsMTApCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDEy
+LDIzNikpCmsuJDMoaSx0LDEyKQprLiQzKGkscCwxMikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDEz
+LDIzNykpCmsuJDMoaSx0LDEzKQprLiQzKGkscCwxMykKai4kMyhuLmEobC4kMigyMCwyNDUpKSwiYXoi
+LDIxKQpsPW4uYShsLiQyKDIxLDI0NSkpCmouJDMobCwiYXoiLDIxKQpqLiQzKGwsIjA5IiwyMSkKay4k
+MyhsLCIrLS4iLDIxKQpyZXR1cm4gbX0sClVCOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEs
+cCxvPSQudlooKQpmb3IodD1KLnJZKGEpLHM9YjtzPGM7KytzKXtpZihkPDB8fGQ+PW8ubGVuZ3RoKXJl
+dHVybiBILmsobyxkKQpyPW9bZF0KcT10LldkKGEscyleOTYKaWYocT45NSlxPTMxCmlmKHE+PXIubGVu
+Z3RoKXJldHVybiBILmsocixxKQpwPXJbcV0KZD1wJjMxCkMuTm0udChlLHA+Pj41LHMpfXJldHVybiBk
+fSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmEyOmZ1bmN0aW9uIGEyKCl7
+fSwKaVA6ZnVuY3Rpb24gaVAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkNQOmZ1bmN0aW9uIENQKCl7
+fSwKWFM6ZnVuY3Rpb24gWFMoKXt9LApDNjpmdW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCkxLOmZ1bmN0
+aW9uIExLKCl7fSwKQVQ6ZnVuY3Rpb24gQVQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
+LmM9YwpfLmQ9ZH0sCmJKOmZ1bmN0aW9uIGJKKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uZT1hCl8u
+Zj1iCl8uYT1jCl8uYj1kCl8uYz1lCl8uZD1mfSwKZVk6ZnVuY3Rpb24gZVkoYSxiLGMsZCxlKXt2YXIg
+Xz10aGlzCl8uZj1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwKbXA6ZnVuY3Rpb24gbXAoYSxiLGMs
+ZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCnViOmZ1bmN0aW9uIHViKGEpe3Ro
+aXMuYT1hfSwKZHM6ZnVuY3Rpb24gZHMoYSl7dGhpcy5hPWF9LApsajpmdW5jdGlvbiBsaihhKXt0aGlz
+LmE9YX0sClVWOmZ1bmN0aW9uIFVWKGEpe3RoaXMuYT1hfSwKazU6ZnVuY3Rpb24gazUoKXt9LApLWTpm
+dW5jdGlvbiBLWSgpe30sCnQ3OmZ1bmN0aW9uIHQ3KGEpe3RoaXMuYT1hfSwKQ0Q6ZnVuY3Rpb24gQ0Qo
+YSl7dGhpcy5hPWF9LAphRTpmdW5jdGlvbiBhRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5j
+PWN9LApFSDpmdW5jdGlvbiBFSCgpe30sCklmOmZ1bmN0aW9uIElmKCl7fSwKTHk6ZnVuY3Rpb24gTHko
+KXt9LApBbjpmdW5jdGlvbiBBbigpe30sCnpNOmZ1bmN0aW9uIHpNKCl7fSwKWjA6ZnVuY3Rpb24gWjAo
+KXt9LApOMzpmdW5jdGlvbiBOMyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCmM4
+OmZ1bmN0aW9uIGM4KCl7fSwKbGY6ZnVuY3Rpb24gbGYoKXt9LApNaDpmdW5jdGlvbiBNaCgpe30sCk9k
+OmZ1bmN0aW9uIE9kKCl7fSwKaWI6ZnVuY3Rpb24gaWIoKXt9LAp4dTpmdW5jdGlvbiB4dSgpe30sCkd6
+OmZ1bmN0aW9uIEd6KCl7fSwKWmQ6ZnVuY3Rpb24gWmQoKXt9LApxVTpmdW5jdGlvbiBxVSgpe30sClJu
+OmZ1bmN0aW9uIFJuKGEpe3RoaXMuYT1hfSwKR0Q6ZnVuY3Rpb24gR0QoKXt9LApuMTpmdW5jdGlvbiBu
+MShhKXt0aGlzLmE9YX0sCmNTOmZ1bmN0aW9uIGNTKGEpe3RoaXMuYT1hfSwKVkM6ZnVuY3Rpb24gVkMo
+YSl7dGhpcy5hPWF9LApKVDpmdW5jdGlvbiBKVChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKRG46ZnVu
+Y3Rpb24gRG4oYSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApf
+LmU9ZQpfLmY9ZgpfLnI9ZwpfLlE9Xy56PV8ueT1fLng9bnVsbH0sCmUxOmZ1bmN0aW9uIGUxKGEsYil7
+dGhpcy5hPWEKdGhpcy5iPWJ9LApOWTpmdW5jdGlvbiBOWShhKXt0aGlzLmE9YX0sClJaOmZ1bmN0aW9u
+IFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1OmZ1bmN0aW9u
+IHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRo
+aXMuYz1jfSwKcTM6ZnVuY3Rpb24gcTMoKXt9LAp5STpmdW5jdGlvbiB5SShhKXt0aGlzLmE9YX0sCmM2
+OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6ZnVuY3Rpb24gcWQoKXt9LApVZjpmdW5jdGlvbiBVZihhLGIsYyxk
+LGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5y
+PWcKXy54PWgKXy55PW51bGx9LApxZTpmdW5jdGlvbiBxZShhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlz
+Cl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1u
+dWxsfSwKbVI6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscAppZihhPT1udWxsKXJldHVybiBudWxsCnQ9
+UC5GbCh1Lk4sdS56KQpzPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGEpCmZvcihyPXMubGVuZ3Ro
+LHE9MDtxPHMubGVuZ3RoO3MubGVuZ3RoPT09cnx8KDAsSC5saykocyksKytxKXtwPUguYyhzW3FdKQp0
+LnQoMCxwLGFbcF0pfXJldHVybiB0fSwKaTY6ZnVuY3Rpb24gaTYoKXt9LApqZzpmdW5jdGlvbiBqZyhh
+LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
+Yn0sCmFKOmZ1bmN0aW9uIGFKKCl7fSwKSzU6ZnVuY3Rpb24gSzUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
+Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp6ZzpmdW5jdGlvbiB6Zyhh
+LGIpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz0hMX0sCmRNOmZ1bmN0aW9uIGRNKCl7fSwKR0U6ZnVu
+Y3Rpb24gR0UoYSl7dGhpcy5hPWF9LApONzpmdW5jdGlvbiBONyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
+fSwKdVE6ZnVuY3Rpb24gdVEoKXt9LApXMjpmdW5jdGlvbiBXMigpe30sCmUzOmZ1bmN0aW9uIGUzKCl7
+fSwKaEY6ZnVuY3Rpb24gaEYoKXt9LApCVjpmdW5jdGlvbiBCVigpe30sClI0OmZ1bmN0aW9uKGEsYixj
+LGQpe3ZhciB0LHMscgpILkU5KGIpCnUuai5hKGQpCmlmKEgub1QoYikpe3Q9W2NdCkMuTm0uRlYodCxk
+KQpkPXR9cz11LnoKcj1QLkNIKEouTTEoZCxQLncwKCkscyksITAscykKdS5aLmEoYSkKcmV0dXJuIFAu
+d1koSC5FayhhLHIsbnVsbCkpfSwKRG06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CnRyeXtpZihPYmplY3Qu
+aXNFeHRlbnNpYmxlKGEpJiYhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGEsYikp
+e09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLGIse3ZhbHVlOmN9KQpyZXR1cm4hMH19Y2F0Y2godCl7SC5S
+dSh0KX1yZXR1cm4hMX0sCk9tOmZ1bmN0aW9uKGEsYil7aWYoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Q
+cm9wZXJ0eS5jYWxsKGEsYikpcmV0dXJuIGFbYl0KcmV0dXJuIG51bGx9LAp3WTpmdW5jdGlvbihhKXtp
+ZihhPT1udWxsfHx0eXBlb2YgYT09InN0cmluZyJ8fHR5cGVvZiBhPT0ibnVtYmVyInx8SC5yUShhKSly
+ZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNClyZXR1cm4gYS5hCmlmKEguUjkoYSkpcmV0dXJuIGEK
+aWYodS5ELmIoYSkpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAuaVApcmV0dXJuIEgubzIoYSkKaWYo
+dS5aLmIoYSkpcmV0dXJuIFAuYjMoYSwiJGRhcnRfanNGdW5jdGlvbiIsbmV3IFAuUEMoKSkKcmV0dXJu
+IFAuYjMoYSwiXyRkYXJ0X2pzT2JqZWN0IixuZXcgUC5tdCgkLmtJKCkpKX0sCmIzOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdD1QLk9tKGEsYikKaWYodD09bnVsbCl7dD1jLiQxKGEpClAuRG0oYSxiLHQpfXJldHVy
+biB0fSwKTDc6ZnVuY3Rpb24oYSl7dmFyIHQscwppZihhPT1udWxsfHx0eXBlb2YgYT09InN0cmluZyJ8
+fHR5cGVvZiBhPT0ibnVtYmVyInx8dHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gYQplbHNlIGlmKGEg
+aW5zdGFuY2VvZiBPYmplY3QmJkguUjkoYSkpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgT2Jq
+ZWN0JiZ1LkQuYihhKSlyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBEYXRlKXt0PUguV1koYS5n
+ZXRUaW1lKCkpCnM9bmV3IFAuaVAodCwhMSkKcy5Yayh0LCExKQpyZXR1cm4gc31lbHNlIGlmKGEuY29u
+c3RydWN0b3I9PT0kLmtJKCkpcmV0dXJuIGEubwplbHNlIHJldHVybiBQLk5EKGEpfSwKTkQ6ZnVuY3Rp
+b24oYSl7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIFAuaVEoYSwkLndRKCksbmV3IFAuTnoo
+KSkKaWYoYSBpbnN0YW5jZW9mIEFycmF5KXJldHVybiBQLmlRKGEsJC5DcigpLG5ldyBQLm5wKCkpCnJl
+dHVybiBQLmlRKGEsJC5DcigpLG5ldyBQLlV0KCkpfSwKaVE6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PVAu
+T20oYSxiKQppZih0PT1udWxsfHwhKGEgaW5zdGFuY2VvZiBPYmplY3QpKXt0PWMuJDEoYSkKUC5EbShh
+LGIsdCl9cmV0dXJuIHR9LApQQzpmdW5jdGlvbiBQQygpe30sCm10OmZ1bmN0aW9uIG10KGEpe3RoaXMu
+YT1hfSwKTno6ZnVuY3Rpb24gTnooKXt9LApucDpmdW5jdGlvbiBucCgpe30sClV0OmZ1bmN0aW9uIFV0
+KCl7fSwKRTQ6ZnVuY3Rpb24gRTQoYSl7dGhpcy5hPWF9LApyNzpmdW5jdGlvbiByNyhhKXt0aGlzLmE9
+YX0sClR6OmZ1bmN0aW9uIFR6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmNvOmZ1bmN0aW9uIGNv
+KCl7fSwKVTg6ZnVuY3Rpb24oYSxiKXt2YXIgdD1uZXcgUC52cygkLlgzLGIuQygidnM8MD4iKSkscz1u
+ZXcgUC5aZih0LGIuQygiWmY8MD4iKSkKYS50aGVuKEgudFIobmV3IFAudksocyxiKSwxKSxILnRSKG5l
+dyBQLnBVKHMpLDEpKQpyZXR1cm4gdH0sCnZLOmZ1bmN0aW9uIHZLKGEsYil7dGhpcy5hPWEKdGhpcy5i
+PWJ9LApwVTpmdW5jdGlvbiBwVShhKXt0aGlzLmE9YX0sCklOOmZ1bmN0aW9uIElOKCl7fSwKdG46ZnVu
+Y3Rpb24gdG4oKXt9LAp1ajpmdW5jdGlvbiB1aigpe30sCngwOmZ1bmN0aW9uIHgwKCl7fSwKcTY6ZnVu
+Y3Rpb24gcTYoKXt9LAp1UDpmdW5jdGlvbiB1UCgpe30sCkxaOmZ1bmN0aW9uIExaKCl7fSwKRUQ6ZnVu
+Y3Rpb24gRUQoKXt9LApuZDpmdW5jdGlvbiBuZCgpe30sCktxOmZ1bmN0aW9uIEtxKCl7fSwKS2U6ZnVu
+Y3Rpb24gS2UoYSl7dGhpcy5hPWF9LApkNTpmdW5jdGlvbiBkNSgpe30sCnpZOmZ1bmN0aW9uIHpZKCl7
+fSwKTkM6ZnVuY3Rpb24gTkMoKXt9LApmVTpmdW5jdGlvbiBmVSgpe30sCkdDOmZ1bmN0aW9uIEdDKCl7
+fSwKakc6ZnVuY3Rpb24gakcoKXt9LApqUzpmdW5jdGlvbiBqUygpe30sCnhXOmZ1bmN0aW9uIHhXKCl7
+fSwKZFM6ZnVuY3Rpb24gZFMoKXt9LAp3ajpmdW5jdGlvbiB3aigpe30sCk1ZOmZ1bmN0aW9uIE1ZKCl7
+fSwKbjY6ZnVuY3Rpb24gbjYoKXt9LApyMjpmdW5jdGlvbiByMigpe30sCnJPOmZ1bmN0aW9uIHJPKCl7
+fSwKRFg6ZnVuY3Rpb24gRFgoKXt9LApxZjpmdW5jdGlvbiBxZihhKXt0aGlzLmE9YX0sCmZvOmZ1bmN0
+aW9uIGZvKCl7fSwKVjg6ZnVuY3Rpb24gVjgoKXt9LApHbjpmdW5jdGlvbiBHbigpe30sClUzOmZ1bmN0
+aW9uIFUzKCl7fSwKRm46ZnVuY3Rpb24gRm4oKXt9LAptbzpmdW5jdGlvbiBtbygpe30sCktnOmZ1bmN0
+aW9uIEtnKCl7fX0sVz17CngzOmZ1bmN0aW9uKCl7cmV0dXJuIHdpbmRvd30sClpyOmZ1bmN0aW9uKCl7
+cmV0dXJuIGRvY3VtZW50fSwKVTk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PWRvY3VtZW50LmJvZHkscz0o
+dCYmQy5SWSkucjYodCxhLGIsYykKcy50b1N0cmluZwp0PXUuYWMKdD1uZXcgSC5VNShuZXcgVy5lNyhz
+KSx0LkMoImEyKGxELkUpIikuYShuZXcgVy5DdigpKSx0LkMoIlU1PGxELkU+IikpCnJldHVybiB1Lmgu
+YSh0LmdyOCh0KSl9LApyUzpmdW5jdGlvbihhKXt2YXIgdCxzLHI9ImVsZW1lbnQgdGFnIHVuYXZhaWxh
+YmxlIgp0cnl7dD1KLlJFKGEpCmlmKHR5cGVvZiB0LmducyhhKT09InN0cmluZyIpcj10LmducyhhKX1j
+YXRjaChzKXtILlJ1KHMpfXJldHVybiByfSwKcUQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPW5l
+dyBQLnZzKCQuWDMsdS5hbykscD1uZXcgUC5aZihxLHUuYmopLG89bmV3IFhNTEh0dHBSZXF1ZXN0KCkK
+Qy5EdC5lbyhvLGI9PW51bGw/IkdFVCI6YixhLCEwKQpjLlUoMCxuZXcgVy5iVShvKSkKdD11LmFuCnM9
+dC5hKG5ldyBXLmhIKG8scCkpCnUuTS5hKG51bGwpCnI9dS5wClcuSkUobywibG9hZCIscywhMSxyKQpX
+LkpFKG8sImVycm9yIix0LmEocC5nWUooKSksITEscikKby5zZW5kKCkKcmV0dXJuIHF9LApDMDpmdW5j
+dGlvbihhLGIpe2E9NTM2ODcwOTExJmErYgphPTUzNjg3MDkxMSZhKygoNTI0Mjg3JmEpPDwxMCkKcmV0
+dXJuIGFeYT4+PjZ9LApyRTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1XLkMwKFcuQzAoVy5DMChXLkMw
+KDAsYSksYiksYyksZCkscz01MzY4NzA5MTEmdCsoKDY3MTA4ODYzJnQpPDwzKQpzXj1zPj4+MTEKcmV0
+dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8PDE1KX0sClROOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
+PWEuY2xhc3NMaXN0CmZvcih0PWIubGVuZ3RoLHM9MDtzPGIubGVuZ3RoO2IubGVuZ3RoPT09dHx8KDAs
+SC5saykoYiksKytzKXIuYWRkKGJbc10pfSwKSkU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1XLmFG
+KG5ldyBXLnZOKGMpLHUuQikKaWYodCE9bnVsbCYmITApSi5kWihhLGIsdCwhMSkKcmV0dXJuIG5ldyBX
+LnhDKGEsYix0LCExLGUuQygieEM8MD4iKSl9LApUdzpmdW5jdGlvbihhKXt2YXIgdD1kb2N1bWVudC5j
+cmVhdGVFbGVtZW50KCJhIikscz1uZXcgVy5tayh0LHdpbmRvdy5sb2NhdGlvbikKcz1uZXcgVy5KUShz
+KQpzLkNZKGEpCnJldHVybiBzfSwKVXc6ZnVuY3Rpb24oYSxiLGMsZCl7dS5oLmEoYSkKSC5jKGIpCkgu
+YyhjKQp1LmNyLmEoZCkKcmV0dXJuITB9LApuWjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdS5o
+LmEoYSkKSC5jKGIpCkguYyhjKQp0PXUuY3IuYShkKS5hCnM9dC5hCnMuaHJlZj1jCnI9cy5ob3N0bmFt
+ZQp0PXQuYgppZighKHI9PXQuaG9zdG5hbWUmJnMucG9ydD09dC5wb3J0JiZzLnByb3RvY29sPT10LnBy
+b3RvY29sKSlpZihyPT09IiIpaWYocy5wb3J0PT09IiIpe3Q9cy5wcm90b2NvbAp0PXQ9PT0iOiJ8fHQ9
+PT0iIn1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMApyZXR1cm4gdH0sCkJsOmZ1bmN0aW9uKCl7
+dmFyIHQ9dS5OLHM9UC50TShDLlF4LHQpLHI9dS5kRy5hKG5ldyBXLklBKCkpLHE9SC5WTShbIlRFTVBM
+QVRFIl0sdS5zKQp0PW5ldyBXLmN0KHMsUC5Mcyh0KSxQLkxzKHQpLFAuTHModCksbnVsbCkKdC5DWShu
+dWxsLG5ldyBILmxKKEMuUXgscix1LmR2KSxxLG51bGwpCnJldHVybiB0fSwKUHY6ZnVuY3Rpb24oYSl7
+aWYoYT09bnVsbClyZXR1cm4gbnVsbApyZXR1cm4gVy5QMShhKX0sCnFjOmZ1bmN0aW9uKGEpe3ZhciB0
+CmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoInBvc3RNZXNzYWdlIiBpbiBhKXt0PVcuUDEoYSkKcmV0
+dXJuIHR9ZWxzZSByZXR1cm4gdS5hUy5hKGEpfSwKUDE6ZnVuY3Rpb24oYSl7aWYoYT09PXdpbmRvdyly
+ZXR1cm4gdS5jaS5hKGEpCmVsc2UgcmV0dXJuIG5ldyBXLmRXKGEpfSwKelg6ZnVuY3Rpb24oYSl7aWYo
+YT09PXdpbmRvdy5sb2NhdGlvbilyZXR1cm4gYQplbHNlIHJldHVybiBuZXcgVy5GYigpfSwKYUY6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdD0kLlgzCmlmKHQ9PT1DLk5VKXJldHVybiBhCnJldHVybiB0LlB5KGEsYil9
+LApxRTpmdW5jdGlvbiBxRSgpe30sClllOmZ1bmN0aW9uIFllKCl7fSwKR2g6ZnVuY3Rpb24gR2goKXt9
+LApmWTpmdW5jdGlvbiBmWSgpe30sCm5COmZ1bmN0aW9uIG5CKCl7fSwKQXo6ZnVuY3Rpb24gQXooKXt9
+LApQVTpmdW5jdGlvbiBQVSgpe30sClFQOmZ1bmN0aW9uIFFQKCl7fSwKSUY6ZnVuY3Rpb24gSUYoKXt9
+LApueDpmdW5jdGlvbiBueCgpe30sClJkOmZ1bmN0aW9uIFJkKCl7fSwKa1I6ZnVuY3Rpb24ga1IoKXt9
+LApUZjpmdW5jdGlvbiBUZigpe30sCmx3OmZ1bmN0aW9uIGx3KCl7fSwKb0o6ZnVuY3Rpb24gb0ooKXt9
+LAppZDpmdW5jdGlvbiBpZCgpe30sCkJ3OmZ1bmN0aW9uIEJ3KCl7fSwKbzQ6ZnVuY3Rpb24gbzQoKXt9
+LApIUzpmdW5jdGlvbiBIUygpe30sClZvOmZ1bmN0aW9uIFZvKCl7fSwKRmg6ZnVuY3Rpb24gRmgoKXt9
+LApjeDpmdW5jdGlvbiBjeCgpe30sClNiOmZ1bmN0aW9uIFNiKCl7fSwKUUY6ZnVuY3Rpb24gUUYoKXt9
+LApOaDpmdW5jdGlvbiBOaCgpe30sCkZ2OmZ1bmN0aW9uIEZ2KCl7fSwKSUI6ZnVuY3Rpb24gSUIoKXt9
+LApZbDpmdW5jdGlvbiBZbCgpe30sCm43OmZ1bmN0aW9uIG43KCl7fSwKd3o6ZnVuY3Rpb24gd3ooYSxi
+KXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY3Y6ZnVuY3Rpb24gY3YoKXt9LApDdjpmdW5jdGlvbiBDdigp
+e30sCmVhOmZ1bmN0aW9uIGVhKCl7fSwKRDA6ZnVuY3Rpb24gRDAoKXt9LApUNTpmdW5jdGlvbiBUNSgp
+e30sClhWOmZ1bmN0aW9uIFhWKCl7fSwKd0o6ZnVuY3Rpb24gd0ooKXt9LApoNDpmdW5jdGlvbiBoNCgp
+e30sCkdPOmZ1bmN0aW9uIEdPKCl7fSwKSkM6ZnVuY3Rpb24gSkMoKXt9LApicjpmdW5jdGlvbiBicigp
+e30sCnhuOmZ1bmN0aW9uIHhuKCl7fSwKVmI6ZnVuY3Rpb24gVmIoKXt9LApmSjpmdW5jdGlvbiBmSigp
+e30sCmJVOmZ1bmN0aW9uIGJVKGEpe3RoaXMuYT1hfSwKaEg6ZnVuY3Rpb24gaEgoYSxiKXt0aGlzLmE9
+YQp0aGlzLmI9Yn0sCndhOmZ1bmN0aW9uIHdhKCl7fSwKU2c6ZnVuY3Rpb24gU2coKXt9LApKSzpmdW5j
+dGlvbiBKSygpe30sCkhMOmZ1bmN0aW9uIEhMKCl7fSwKd1A6ZnVuY3Rpb24gd1AoKXt9LAp1ODpmdW5j
+dGlvbiB1OCgpe30sCno2OmZ1bmN0aW9uIHo2KCl7fSwKQ2Y6ZnVuY3Rpb24gQ2YoKXt9LApRYjpmdW5j
+dGlvbiBRYigpe30sClMwOmZ1bmN0aW9uIFMwKCl7fSwKRkE6ZnVuY3Rpb24gRkEoYSl7dGhpcy5hPWF9
+LAp6MjpmdW5jdGlvbiB6Migpe30sCnVxOmZ1bmN0aW9uIHVxKGEpe3RoaXMuYT1hfSwKQVc6ZnVuY3Rp
+b24gQVcoKXt9LApETTpmdW5jdGlvbiBETSgpe30sCk9LOmZ1bmN0aW9uIE9LKCl7fSwKZTc6ZnVuY3Rp
+b24gZTcoYSl7dGhpcy5hPWF9LAp1SDpmdW5jdGlvbiB1SCgpe30sCkJIOmZ1bmN0aW9uIEJIKCl7fSwK
+UWw6ZnVuY3Rpb24gUWwoKXt9LApHWDpmdW5jdGlvbiBHWCgpe30sClNOOmZ1bmN0aW9uIFNOKCl7fSwK
+SEQ6ZnVuY3Rpb24gSEQoKXt9LApjbDpmdW5jdGlvbiBjbCgpe30sCkV2OmZ1bmN0aW9uIEV2KCl7fSwK
+THI6ZnVuY3Rpb24gTHIoKXt9LApLUjpmdW5jdGlvbiBLUigpe30sCmV3OmZ1bmN0aW9uIGV3KCl7fSwK
+cDg6ZnVuY3Rpb24gcDgoKXt9LAppaTpmdW5jdGlvbiBpaShhKXt0aGlzLmE9YX0sCmxwOmZ1bmN0aW9u
+IGxwKCl7fSwKU1Y6ZnVuY3Rpb24gU1YoKXt9LApNazpmdW5jdGlvbiBNaygpe30sClk0OmZ1bmN0aW9u
+IFk0KCl7fSwKTm46ZnVuY3Rpb24gTm4oKXt9LApsODpmdW5jdGlvbiBsOCgpe30sCkFzOmZ1bmN0aW9u
+IEFzKCl7fSwKY1g6ZnVuY3Rpb24gY1goYSl7dGhpcy5hPWF9LApiazpmdW5jdGlvbiBiaygpe30sCldX
+OmZ1bmN0aW9uIFdXKCl7fSwKVGI6ZnVuY3Rpb24gVGIoKXt9LApJdjpmdW5jdGlvbiBJdigpe30sCkJU
+OmZ1bmN0aW9uIEJUKCl7fSwKZlg6ZnVuY3Rpb24gZlgoKXt9LApGQjpmdW5jdGlvbiBGQigpe30sCkEx
+OmZ1bmN0aW9uIEExKCl7fSwKTU46ZnVuY3Rpb24gTU4oKXt9LApYMDpmdW5jdGlvbiBYMCgpe30sCm5K
+OmZ1bmN0aW9uIG5KKCl7fSwKbXo6ZnVuY3Rpb24gbXooKXt9LAphMzpmdW5jdGlvbiBhMygpe30sCmNp
+OmZ1bmN0aW9uIGNpKCl7fSwKY246ZnVuY3Rpb24gY24oKXt9LAp3NjpmdW5jdGlvbiB3Nigpe30sCkZq
+OmZ1bmN0aW9uIEZqKCl7fSwKdkY6ZnVuY3Rpb24gdkYoKXt9LApPaTpmdW5jdGlvbiBPaSgpe30sCkNt
+OmZ1bmN0aW9uIENtKCl7fSwKQ1E6ZnVuY3Rpb24gQ1EoKXt9LApQUjpmdW5jdGlvbiBQUigpe30sCnc0
+OmZ1bmN0aW9uIHc0KCl7fSwKRjI6ZnVuY3Rpb24gRjIoKXt9LApyaDpmdW5jdGlvbiByaCgpe30sCkxP
+OmZ1bmN0aW9uIExPKCl7fSwKYjE6ZnVuY3Rpb24gYjEoKXt9LAphVDpmdW5jdGlvbiBhVCgpe30sCmk3
+OmZ1bmN0aW9uIGk3KGEpe3RoaXMuYT1hfSwKU3k6ZnVuY3Rpb24gU3koYSl7dGhpcy5hPWF9LApLUzpm
+dW5jdGlvbiBLUyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQTM6ZnVuY3Rpb24gQTMoYSxiKXt0aGlz
+LmE9YQp0aGlzLmI9Yn0sCkk0OmZ1bmN0aW9uIEk0KGEpe3RoaXMuYT1hfSwKRms6ZnVuY3Rpb24gRmso
+YSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKUk86ZnVuY3Rpb24gUk8oYSxiLGMsZCl7dmFyIF89dGhp
+cwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKZXU6ZnVuY3Rpb24gZXUoYSxiLGMsZCl7dmFyIF89
+dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKeEM6ZnVuY3Rpb24geEMoYSxiLGMsZCxlKXt2
+YXIgXz10aGlzCl8uYj1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uJHRpPWV9LAp2TjpmdW5jdGlvbiB2Tihh
+KXt0aGlzLmE9YX0sCkpROmZ1bmN0aW9uIEpRKGEpe3RoaXMuYT1hfSwKR206ZnVuY3Rpb24gR20oKXt9
+LAp2RDpmdW5jdGlvbiB2RChhKXt0aGlzLmE9YX0sClV2OmZ1bmN0aW9uIFV2KGEpe3RoaXMuYT1hfSwK
+RWc6ZnVuY3Rpb24gRWcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKbTY6ZnVuY3Rp
+b24gbTYoKXt9LApFbzpmdW5jdGlvbiBFbygpe30sCldrOmZ1bmN0aW9uIFdrKCl7fSwKY3Q6ZnVuY3Rp
+b24gY3QoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uZT1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwK
+SUE6ZnVuY3Rpb24gSUEoKXt9LApPdzpmdW5jdGlvbiBPdygpe30sClc5OmZ1bmN0aW9uIFc5KGEsYixj
+KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0tMQpfLmQ9bnVsbApfLiR0aT1jfSwKZFc6ZnVuY3Rp
+b24gZFcoYSl7dGhpcy5hPWF9LApGYjpmdW5jdGlvbiBGYigpe30sCmtGOmZ1bmN0aW9uIGtGKCl7fSwK
+bWs6ZnVuY3Rpb24gbWsoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCktvOmZ1bmN0aW9uIEtvKGEpe3Ro
+aXMuYT1hCnRoaXMuYj0hMX0sCmZtOmZ1bmN0aW9uIGZtKGEpe3RoaXMuYT1hfSwKTGU6ZnVuY3Rpb24g
+TGUoKXt9LApKVTpmdW5jdGlvbiBKVSgpe30sCnhYOmZ1bmN0aW9uIHhYKCl7fSwKdmU6ZnVuY3Rpb24g
+dmUoKXt9LApiRzpmdW5jdGlvbiBiRygpe30sCnRJOmZ1bmN0aW9uIHRJKCl7fSwKZmc6ZnVuY3Rpb24g
+ZmcoKXt9LApjVzpmdW5jdGlvbiBjVygpe30sCkhXOmZ1bmN0aW9uIEhXKCl7fSwKbEc6ZnVuY3Rpb24g
+bEcoKXt9LApxczpmdW5jdGlvbiBxcygpe30sCmNzOmZ1bmN0aW9uIGNzKCl7fSwKS0I6ZnVuY3Rpb24g
+S0IoKXt9LApLNzpmdW5jdGlvbiBLNygpe30sCnJCOmZ1bmN0aW9uIHJCKCl7fSwKZlQ6ZnVuY3Rpb24g
+ZlQoKXt9LApmNzpmdW5jdGlvbiBmNygpe30sCmJnOmZ1bmN0aW9uIGJnKCl7fSwKb0g6ZnVuY3Rpb24g
+b0goKXt9LApDRTpmdW5jdGlvbiBDRSgpe30sCmFEOmZ1bmN0aW9uIGFEKCl7fSwKWng6ZnVuY3Rpb24g
+WngoKXt9LApPWDpmdW5jdGlvbiBPWCgpe30sClVqOmZ1bmN0aW9uIFVqKCl7fSwKak06ZnVuY3Rpb24g
+ak0oKXt9LApRVjpmdW5jdGlvbiBRVigpe30sCkF3OmZ1bmN0aW9uIEF3KCl7fSwKdHI6ZnVuY3Rpb24g
+dHIoKXt9LApPMzpmdW5jdGlvbiBPMygpe30sCk92OmZ1bmN0aW9uIE92KCl7fSwKY086ZnVuY3Rpb24g
+Y08oKXt9LApZRDpmdW5jdGlvbiBZRCgpe30sCkR4OmZ1bmN0aW9uIER4KCl7fSwKWFc6ZnVuY3Rpb24g
+WFcoKXt9LApvYTpmdW5jdGlvbiBvYSgpe30sClhVOmZ1bmN0aW9uIFhVKCl7fSwKbzM6ZnVuY3Rpb24g
+bzMoKXt9LAp6djpmdW5jdGlvbiB6digpe30sCm56OmZ1bmN0aW9uIG56KCl7fX0sVT17CmpmOmZ1bmN0
+aW9uKGEpe3ZhciB0LHMscixxCmlmKGE9PW51bGwpdD1udWxsCmVsc2V7dD1ILlZNKFtdLHUuZkEpCmZv
+cihzPUouSVQodS5SLmEoYSkpO3MubSgpOyl7cj1zLmdSKHMpCnE9Si5VNihyKQpDLk5tLkEodCxuZXcg
+VS5TZShILmMocS5xKHIsImRlc2NyaXB0aW9uIikpLEguYyhxLnEociwiaHJlZiIpKSkpfX1yZXR1cm4g
+dH0sCk5kOmZ1bmN0aW9uKGEpe3ZhciB0LHMKaWYoYT09bnVsbCl0PW51bGwKZWxzZXt0PUguVk0oW10s
+dS5oaCkKZm9yKHM9Si5JVCh1LlIuYShhKSk7cy5tKCk7KUMuTm0uQSh0LFUuSmoocy5nUihzKSkpfXJl
+dHVybiB0fSwKSmo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvPSJkZXNjcmlwdGlvbiIsbj1KLlU2
+KGEpLG09SC5jKG4ucShhLG8pKSxsPUguVk0oW10sdS5hSikKZm9yKG49Si5JVCh1LlIuYShuLnEoYSwi
+ZW50cmllcyIpKSk7bi5tKCk7KXt0PW4uZ1IobikKcz1KLlU2KHQpCnI9SC5jKHMucSh0LG8pKQpxPUgu
+YyhzLnEodCwiZnVuY3Rpb24iKSkKcz1zLnEodCwibGluayIpCmlmKHM9PW51bGwpcz1udWxsCmVsc2V7
+cD1KLlU2KHMpCnM9bmV3IFUuTWwoSC5jKHAucShzLCJocmVmIikpLEguV1kocC5xKHMsImxpbmUiKSks
+SC5jKHAucShzLCJwYXRoIikpKX1DLk5tLkEobCxuZXcgVS53YihyLHEscykpfXJldHVybiBuZXcgVS55
+RChtLGwpfSwKZDI6ZnVuY3Rpb24gZDIoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8u
+Yz1jCl8uZD1kCl8uZT1lfSwKU2U6ZnVuY3Rpb24gU2UoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1s
+OmZ1bmN0aW9uIE1sKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnlEOmZ1bmN0aW9u
+IHlEKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp3YjpmdW5jdGlvbiB3YihhLGIsYyl7dGhpcy5hPWEK
+dGhpcy5iPWIKdGhpcy5jPWN9fSxCPXsKWWY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxs
+PUouVTYoYSksaz1ILmMobC5xKGEsInJlZ2lvbnMiKSksaj1ILmMobC5xKGEsIm5hdmlnYXRpb25Db250
+ZW50IikpLGk9SC5jKGwucShhLCJzb3VyY2VDb2RlIikpLGg9UC5GbCh1Lk4sdS5mNCkKZm9yKGw9Si5J
+VChKLlFNKGwucShhLCJlZGl0cyIpKSksdD11LlIscz11LmdpO2wubSgpOyl7cj1sLmdSKGwpCnE9Si5S
+RShyKQpwPUguYyhxLmdHMyhyKSkKbz1ILlZNKFtdLHMpCmZvcihxPUouSVQodC5hKHEuZ253KHIpKSk7
+cS5tKCk7KXtuPXEuZ1IocSkKbT1KLlU2KG4pCkMuTm0uQShvLG5ldyBCLmo4KEguV1kobS5xKG4sImxp
+bmUiKSksSC5jKG0ucShuLCJleHBsYW5hdGlvbiIpKSxILldZKG0ucShuLCJvZmZzZXQiKSkpKX1oLnQo
+MCxwLG8pfXJldHVybiBuZXcgQi5xcChrLGosaSxoKX0sCmo4OmZ1bmN0aW9uIGo4KGEsYixjKXt0aGlz
+LmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnFwOmZ1bmN0aW9uIHFwKGEsYixjLGQpe3ZhciBfPXRoaXMK
+Xy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApMdTpmdW5jdGlvbiBMdSgpe30sCk9TOmZ1bmN0aW9uKGEp
+e3ZhciB0CmlmKCEoYT49NjUmJmE8PTkwKSl0PWE+PTk3JiZhPD0xMjIKZWxzZSB0PSEwCnJldHVybiB0
+fSwKWXU6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hLmxlbmd0aCxzPWIrMgppZih0PHMpcmV0dXJuITEKaWYo
+IUIuT1MoQy54Qi5PMihhLGIpKSlyZXR1cm4hMQppZihDLnhCLk8yKGEsYisxKSE9PTU4KXJldHVybiEx
+CmlmKHQ9PT1zKXJldHVybiEwCnJldHVybiBDLnhCLk8yKGEscyk9PT00N319LFQ9e21ROmZ1bmN0aW9u
+IG1RKCl7fX0sTD17CkRlOmZ1bmN0aW9uKCl7Qy5CWi5CKGRvY3VtZW50LCJET01Db250ZW50TG9hZGVk
+IixuZXcgTC5lKCkpCkMub2wuQih3aW5kb3csInBvcHN0YXRlIixuZXcgTC5MKCkpfSwKa3o6ZnVuY3Rp
+b24oYSl7dmFyIHQscz11LmguYShhLnBhcmVudE5vZGUpLnF1ZXJ5U2VsZWN0b3IoIjpzY29wZSA+IHVs
+Iikscj1zLnN0eWxlLHE9IiIrQy5DRC56UShzLm9mZnNldEhlaWdodCkqMisicHgiCnIubWF4SGVpZ2h0
+PXEKcj1KLnFGKGEpCnE9ci4kdGkKdD1xLkMoIn4oMSkiKS5hKG5ldyBMLld4KHMsYSkpCnUuTS5hKG51
+bGwpClcuSkUoci5hLHIuYix0LCExLHEuYyl9LAp5WDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAs
+bz0icXVlcnlTZWxlY3RvckFsbCIsbj1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKGEpLG09dS5oCm4udG9T
+dHJpbmcKSC5EaChtLG0sIlQiLG8pCnQ9dS5VCnM9bmV3IFcud3oobi5xdWVyeVNlbGVjdG9yQWxsKCIu
+bmF2LWxpbmsiKSx0KQpzLlUocyxuZXcgTC5BTyhiKSkKSC5EaChtLG0sIlQiLG8pCnI9bmV3IFcud3oo
+bi5xdWVyeVNlbGVjdG9yQWxsKCIucmVnaW9uIiksdCkKaWYoci5nayhyKSE9PTApe3E9bi5xdWVyeVNl
+bGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKcS50b1N0cmluZwpyLlUocixuZXcgTC5IbyhxLmdldEF0
+dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHEpKS5ZKCJwYXRoIikpKSl9SC5EaChtLG0s
+IlQiLG8pCnA9bmV3IFcud3oobi5xdWVyeVNlbGVjdG9yQWxsKCIucG9zdC1saW5rIiksdCkKcC5VKHAs
+bmV3IEwuSUMoKSl9LApRNjpmdW5jdGlvbihhLGIpe3ZhciB0PXUuTgpyZXR1cm4gVy5xRChMLlE0KGEs
+YiksbnVsbCxQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYt
+OCJdLHQsdCkpfSwKdHk6ZnVuY3Rpb24oYSl7dmFyIHQ9dS5OCnJldHVybiBXLnFEKEwuUTQoYSxQLkZs
+KHQsdCkpLCJQT1NUIixQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNl
+dD1VVEYtOCJdLHQsdCkpLlc3KG5ldyBMLkwxKCksdS5yKX0sCmFLOmZ1bmN0aW9uKGEpe3ZhciB0PVAu
+aEsoYSkuZ2hZKCkucSgwLCJsaW5lIikKcmV0dXJuIHQ9PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LApH
+NjpmdW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgpLnEoMCwib2Zmc2V0IikKcmV0dXJuIHQ9PW51
+bGw/bnVsbDpILkhwKHQsbnVsbCl9LAp0MjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG49
+e30sbT11LmguYShXLnFjKGEuY3VycmVudFRhcmdldCkpCmEucHJldmVudERlZmF1bHQoKQp0PW4uYT1t
+LmdldEF0dHJpYnV0ZSgiaHJlZiIpCmlmKEouemwodCwiPyIpKXtzPUMueEIuTmoodCwwLEMueEIuT1ko
+dCwiPyIpKQpuLmE9cwpyPXN9ZWxzZSByPXQKaWYoYyE9bnVsbCl7cT0kLm5VKCkKcj1uLmE9cS5vNSgw
+LEQubnIocS50TShjKSxyKSl9cD1MLkc2KHQpCm89TC5hSyh0KQppZihwIT1udWxsKUwuYWYocixwLG8s
+YixuZXcgTC5uVChuLHAsbykpCmVsc2UgTC5hZihyLG51bGwsbnVsbCxiLG5ldyBMLkJaKG4pKX0sCnVt
+OmZ1bmN0aW9uKGEpe3JldHVybiBMLlFTKHUuVi5hKGEpKX0sClFTOmZ1bmN0aW9uKGEpe3ZhciB0PTAs
+cz1QLkZYKHUueikscj0xLHEscD1bXSxvLG4sbSxsLGsKdmFyICRhc3luYyR1bT1QLmx6KGZ1bmN0aW9u
+KGIsYyl7aWYoYj09PTEpe3E9Ywp0PXJ9d2hpbGUodHJ1ZSlzd2l0Y2godCl7Y2FzZSAwOmw9dS5oLmEo
+Vy5xYyhhLmN1cnJlbnRUYXJnZXQpKS5nZXRBdHRyaWJ1dGUoImhyZWYiKQphLnByZXZlbnREZWZhdWx0
+KCkKcj0zCnQ9NgpyZXR1cm4gUC5qUShMLnR5KGwpLCRhc3luYyR1bSkKY2FzZSA2OnUuYV8uYShKLkdy
+KFcuUHYoZG9jdW1lbnQuZGVmYXVsdFZpZXcpKSkucmVsb2FkKCkKcj0xCnQ9NQpicmVhawpjYXNlIDM6
+cj0yCms9cQpvPUguUnUoaykKbj1ILnRzKGspCkwucUooImhhbmRsZVBvc3RMaW5rQ2xpY2s6ICIrSC5k
+KG8pLG4pCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIitILmQobCkrIiAoIitILmQobykrIiku
+IikKdD01CmJyZWFrCmNhc2UgMjp0PTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2Fz
+ZSAxOnJldHVybiBQLmYzKHEscyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJHVtLHMpfSwKdlU6ZnVuY3Rp
+b24oKXt2YXIgdD1kb2N1bWVudCxzPXUuaApILkRoKHMscywiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQp0
+PW5ldyBXLnd6KHQucXVlcnlTZWxlY3RvckFsbCgiLmNvZGUiKSx1LlUpCnQuVSh0LG5ldyBMLkdIKCkp
+fSwKaFg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PXUuTgpMLlE2KGEsUC5FRihbInJlZ2lvbiIsInJlZ2lv
+biIsIm9mZnNldCIsSC5kKGIpXSx0LHQpKS5XNyhuZXcgTC5EVChhLGIsYyksdS5QKS5PQShuZXcgTC5l
+SChhKSl9LApHNzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0CmlmKCFKLnA0KGEsIi5kYXJ0Iikpe0wu
+QkUoYSxuZXcgQi5xcCgiIiwiIiwiIixDLkNNKSxkKQpMLkJYKGEsbnVsbCkKaWYoZSE9bnVsbCllLiQw
+KCkKcmV0dXJufXQ9dS5OCkwuUTYoYSxQLkVGKFsiaW5saW5lIiwidHJ1ZSJdLHQsdCkpLlc3KG5ldyBM
+Lnl1KGEsZCxiLGMsZSksdS5QKS5PQShuZXcgTC56RChhKSl9LApHZTpmdW5jdGlvbigpe3ZhciB0PSIv
+X3ByZXZpZXcvbmF2aWdhdGlvblRyZWUuanNvbiIKTC5RNih0LEMuV08pLlc3KG5ldyBMLlRXKCksdS5Q
+KS5PQShuZXcgTC54cih0KSl9LApxSjpmdW5jdGlvbihhLGIpe3ZhciB0CndpbmRvdwppZih0eXBlb2Yg
+Y29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3IoYSkKd2luZG93CnQ9SC5kKGIp
+CmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS5lcnJvcih0KX0sCnFP
+OmZ1bmN0aW9uKGEpe3ZhciB0LHM9YS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxyPUMuQ0QuelEoJC5m
+aSgpLm9mZnNldEhlaWdodCkscT13aW5kb3cuaW5uZXJIZWlnaHQscD1DLkNELnpRKCQuRFcoKS5vZmZz
+ZXRIZWlnaHQpCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuSE4oKQp0PXMuYm90dG9tCmlm
+KHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQub3MoKQppZih0PnEtKHArMTQpKUouZGgoYSkKZWxz
+ZXtxPXMudG9wCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuSigpCmlmKHE8cisxNClKLmRo
+KGEpfX0sCmZHOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmlmKGEhPW51bGwpe3Q9ZG9jdW1lbnQKcz10
+LmdldEVsZW1lbnRCeUlkKCJvIitILmQoYSkpCnI9dC5xdWVyeVNlbGVjdG9yKCIubGluZS0iK0guZChi
+KSkKaWYocyE9bnVsbCl7TC5xTyhzKQpKLmRSKHMpLkEoMCwidGFyZ2V0Iil9ZWxzZSBpZihyIT1udWxs
+KUwucU8oci5wYXJlbnRFbGVtZW50KQppZihyIT1udWxsKUouZFIodS5oLmEoci5wYXJlbnROb2RlKSku
+QSgwLCJoaWdobGlnaHQiKX1lbHNlIEwucU8oJC5EOSgpKX0sCmFmOmZ1bmN0aW9uKGEsYixjLGQsZSl7
+dmFyIHQscyxyPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpLHE9TC5hSyh3aW5kb3cubG9jYXRpb24u
+aHJlZikKaWYociE9bnVsbCl7dD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibyIrSC5kKHIpKQppZih0
+IT1udWxsKUouZFIodCkuUnooMCwidGFyZ2V0Iil9aWYocSE9bnVsbCl7cz1kb2N1bWVudC5xdWVyeVNl
+bGVjdG9yKCIubGluZS0iK0guZChxKSkKaWYocyE9bnVsbClKLmRSKHMucGFyZW50RWxlbWVudCkuUnoo
+MCwiaGlnaGxpZ2h0Iil9aWYoYT09d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lKXtMLmZHKGIsYykKZS4k
+MCgpfWVsc2UgTC5HNyhhLGIsYyxkLGUpfSwKUTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9UC5oSyhh
+KSxxPXUuTgpxPVAuRmwocSxxKQpmb3IodD1yLmdoWSgpLHQ9dC5nUHUodCksdD10Lmd3KHQpO3QubSgp
+Oyl7cz10LmdSKHQpCnEudCgwLHMuYSxzLmIpfWZvcih0PWIuZ1B1KGIpLHQ9dC5ndyh0KTt0Lm0oKTsp
+e3M9dC5nUih0KQpxLnQoMCxzLmEscy5iKX1xLnQoMCwiYXV0aFRva2VuIiwkLlVFKCkpCnJldHVybiBy
+Lm5tKDAscSkuWigwKX0sClQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbD0kLmhMKCkK
+Si5sNShsLCIiKQppZihhPT1udWxsKXt0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInAiKQp0LnRleHRD
+b250ZW50PSJTZWUgZGV0YWlscyBhYm91dCBhIHByb3Bvc2VkIGVkaXQuIgpDLkx0LnNERCh0LEguVk0o
+WyJwbGFjZWhvbGRlciJdLHUucykpCkouZGgodS5oLmEobC5hcHBlbmRDaGlsZCh0KSkpCnJldHVybn1z
+PWEuZAp0PSQublUoKQpyPXQudE0ocykKcT1hLmIKcD1kb2N1bWVudApvPXQuSFAocyxKLlQwKHAucXVl
+cnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpCm49YS5jCnQ9cC5jcmVhdGVFbGVtZW50KCJw
+IikKbT11LmguYShsLmFwcGVuZENoaWxkKHQpKQptLmFwcGVuZENoaWxkKHAuY3JlYXRlVGV4dE5vZGUo
+SC5kKHEpKyIgYXQgIitILmQobykrIjoiK0guZChuKSsiLiIpKQpKLmRoKG0pCkwuQ0MoYSxsLHIpCkwu
+RnooYSxsKX0sCkxIOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxn
+LGY9JC55UCgpCkoubDUoZiwiIikKaWYoYi5nayhiKT09PTApe3Q9ZG9jdW1lbnQKcz10LmNyZWF0ZUVs
+ZW1lbnQoInAiKQp1LmguYShmLmFwcGVuZENoaWxkKHMpKS5hcHBlbmRDaGlsZCh0LmNyZWF0ZVRleHRO
+b2RlKCJObyBwcm9wb3NlZCBlZGl0cyIpKX1lbHNlIGZvcihmPWIuZ1B1KGIpLGY9Zi5ndyhmKSx0PXUu
+aSxzPXUuUSxyPXMuQygifigxKSIpLHE9dS5NLHM9cy5jLHA9dS5oO2YubSgpOyl7bz1mLmdSKGYpCm49
+JC55UCgpCm09ZG9jdW1lbnQKbD1tLmNyZWF0ZUVsZW1lbnQoInAiKQpwLmEobi5hcHBlbmRDaGlsZChs
+KSkuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZShILmQoby5hKSsiOiIpKQpsPW0uY3JlYXRlRWxl
+bWVudCgidWwiKQprPXAuYShuLmFwcGVuZENoaWxkKGwpKQpmb3Iobz1KLklUKG8uYik7by5tKCk7KXtu
+PW8uZ1IobykKbD1tLmNyZWF0ZUVsZW1lbnQoImxpIikKaj1wLmEoay5hcHBlbmRDaGlsZChsKSkKSi5k
+UihqKS5BKDAsImVkaXQiKQpsPW0uY3JlYXRlRWxlbWVudCgiYSIpCmk9dC5hKGouYXBwZW5kQ2hpbGQo
+bCkpCmkuY2xhc3NMaXN0LmFkZCgiZWRpdC1saW5rIikKaD1uLmMKbD1ILmQoaCkKaS5zZXRBdHRyaWJ1
+dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuWSgib2Zmc2V0IiksbCkKZz1uLmEKbD1ILmQo
+ZykKaS5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuWSgibGluZSIpLGwp
+CmkuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZSgibGluZSAiK0guZChnKSkpCmw9ci5hKG5ldyBM
+LkVFKGgsZyxhKSkKcS5hKG51bGwpClcuSkUoaSwiY2xpY2siLGwsITEscykKai5hcHBlbmRDaGlsZCht
+LmNyZWF0ZVRleHROb2RlKCI6ICIrSC5kKG4uYikpKX19aWYoYylMLlQxKG51bGwpfSwKRnI6ZnVuY3Rp
+b24oYSxiLGMpe3ZhciB0LHMscj13aW5kb3cubG9jYXRpb24scT1QLmhLKChyJiZDLkV4KS5nRHIocikr
+SC5kKGEpKQpyPXUuTgpyPVAuRmwocixyKQppZihiIT1udWxsKXIudCgwLCJvZmZzZXQiLEguZChiKSkK
+aWYoYyE9bnVsbClyLnQoMCwibGluZSIsSC5kKGMpKQpyLnQoMCwiYXV0aFRva2VuIiwkLlVFKCkpCnE9
+cS5ubSgwLHIpCnI9d2luZG93Lmhpc3RvcnkKdD11LnoKcz1xLlooMCkKci50b1N0cmluZwpyLnB1c2hT
+dGF0ZShuZXcgUC5CZihbXSxbXSkuUHYoUC5GbCh0LHQpKSwiIixzKX0sCkVuOmZ1bmN0aW9uKGEpe3Zh
+ciB0PUoubShkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50LCIvIikKaWYo
+Qy54Qi5uQyhhLHQpKXJldHVybiBDLnhCLnluKGEsdC5sZW5ndGgpCmVsc2UgcmV0dXJuIGF9LApCWDpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMscj17fQpyLmE9YQphPUwuRW4oYSkKci5hPWEKJC5EOSgpLnRleHRD
+b250ZW50PWEKdD1kb2N1bWVudApzPXUuaApILkRoKHMscywiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQp0
+PW5ldyBXLnd6KHQucXVlcnlTZWxlY3RvckFsbCgiLm5hdi1wYW5lbCAubmF2LWxpbmsiKSx1LlUpCnQu
+VSh0LG5ldyBMLlZTKHIpKX0sCkJFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0iLnJlZ2lvbnMiLHM9ZG9j
+dW1lbnQscj1zLnF1ZXJ5U2VsZWN0b3IodCkscT1zLnF1ZXJ5U2VsZWN0b3IoIi5jb2RlIikKSi50SChy
+LGIuYSwkLktHKCkpCkoudEgocSxiLmIsJC5LRygpKQpMLkxIKGEsYi5kLGMpCkwudlUoKQpMLnlYKCIu
+Y29kZSIsITApCkwueVgodCwhMCl9LAp0WDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0s
+bCxrLGosaT1kb2N1bWVudCxoPWkuY3JlYXRlRWxlbWVudCgidWwiKSxnPXUuaCxmPWcuYShhLmFwcGVu
+ZENoaWxkKGgpKQpmb3IoaD1iLmxlbmd0aCx0PXUuTSxzPTA7czxiLmxlbmd0aDtiLmxlbmd0aD09PWh8
+fCgwLEgubGspKGIpLCsrcyl7cj1iW3NdCnE9aS5jcmVhdGVFbGVtZW50KCJsaSIpCnA9Zy5hKGYuYXBw
+ZW5kQ2hpbGQocSkpCnE9Si5SRShwKQppZihyLmE9PT1DLlkyKXtxLmdERChwKS5BKDAsImRpciIpCnE9
+aS5jcmVhdGVFbGVtZW50KCJzcGFuIikKbz1nLmEocC5hcHBlbmRDaGlsZChxKSkKcT1KLlJFKG8pCnEu
+Z0REKG8pLkEoMCwiYXJyb3ciKQpxLnNoZihvLCImI3gyNUJDOyIpCnE9aS5jcmVhdGVFbGVtZW50KCJz
+cGFuIikKSi5sNShnLmEocC5hcHBlbmRDaGlsZChxKSksIiYjeDFGNEMxOyIpCnAuYXBwZW5kQ2hpbGQo
+aS5jcmVhdGVUZXh0Tm9kZShyLmIpKQpMLnRYKHAsci5jKQpMLmt6KG8pfWVsc2V7cS5zaGYocCwiJiN4
+MUY0QzQ7IikKcT1pLmNyZWF0ZUVsZW1lbnQoImEiKQpuPWcuYShwLmFwcGVuZENoaWxkKHEpKQpxPUou
+UkUobikKcS5nREQobikuQSgwLCJuYXYtbGluayIpCm4uc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcu
+U3kobmV3IFcuaTcobikpLlkoIm5hbWUiKSxyLmQpCm4uc2V0QXR0cmlidXRlKCJocmVmIixyLmUpCm4u
+YXBwZW5kQ2hpbGQoaS5jcmVhdGVUZXh0Tm9kZShyLmIpKQpxPXEuZ1ZsKG4pCm09cS4kdGkKbD1tLkMo
+In4oMSkiKS5hKG5ldyBMLlREKCkpCnQuYShudWxsKQpXLkpFKHEuYSxxLmIsbCwhMSxtLmMpCms9ci5m
+CmlmKHR5cGVvZiBrIT09Im51bWJlciIpcmV0dXJuIGsub3MoKQppZihrPjApe3E9aS5jcmVhdGVFbGVt
+ZW50KCJzcGFuIikKaj1nLmEocC5hcHBlbmRDaGlsZChxKSkKSi5kUihqKS5BKDAsImVkaXQtY291bnQi
+KQpxPSIiK2srIiAiCmlmKGs9PT0xKW09ImVkaXQiCmVsc2UgbT0iZWRpdHMiCmouc2V0QXR0cmlidXRl
+KCJ0aXRsZSIscSttKQpqLmFwcGVuZENoaWxkKGkuY3JlYXRlVGV4dE5vZGUoQy5qbi5aKGspKSl9fX19
+LApGejpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1hLmEKaWYoaSE9bnVs
+bCl7dD1kb2N1bWVudApzPXQuY3JlYXRlRWxlbWVudCgicCIpCnI9dS5oCnE9ci5hKGIuYXBwZW5kQ2hp
+bGQocykpCmZvcihzPWkubGVuZ3RoLHA9dS5zLG89dS5YLG49MDtuPGkubGVuZ3RoO2kubGVuZ3RoPT09
+c3x8KDAsSC5saykoaSksKytuKXttPWlbbl0KbD10LmNyZWF0ZUVsZW1lbnQoImEiKQprPXIuYShxLmFw
+cGVuZENoaWxkKGwpKQprLmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUobS5hKSkKay5zZXRBdHRy
+aWJ1dGUoImhyZWYiLG0uYikKbD1vLmEoSC5WTShbInBvc3QtbGluayIsImJlZm9yZS1hcHBseSJdLHAp
+KQpqPUouZFIoaykKai5WMSgwKQpqLkZWKDAsbCl9fX0sCkNDOmZ1bmN0aW9uKGEzLGE0LGE1KXt2YXIg
+dCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhLGEwLGExLGEyPW51bGwKZm9yKHQ9
+YTMuZSxzPXQubGVuZ3RoLHI9dS5zLHE9dS5YLHA9dS5oLG89dS5pLG49MDtuPHQubGVuZ3RoO3QubGVu
+Z3RoPT09c3x8KDAsSC5saykodCksKytuKXttPXRbbl0KbD1kb2N1bWVudAprPWwuY3JlYXRlRWxlbWVu
+dCgicCIpCmo9cS5hKEguVk0oWyJ0cmFjZSJdLHIpKQppPUouZFIoaykKaS5WMSgwKQppLkZWKDAsaikK
+aD1hNC5hcHBlbmRDaGlsZChrKQprPWwuY3JlYXRlRWxlbWVudCgic3BhbiIpCmo9cS5hKEguVk0oWyJ0
+eXBlLWRlc2NyaXB0aW9uIl0scikpCmk9Si5kUihrKQppLlYxKDApCmkuRlYoMCxqKQprLmFwcGVuZENo
+aWxkKGwuY3JlYXRlVGV4dE5vZGUobS5hKSkKaC5hcHBlbmRDaGlsZChrKQpoLmFwcGVuZENoaWxkKGwu
+Y3JlYXRlVGV4dE5vZGUoIjoiKSkKaz1sLmNyZWF0ZUVsZW1lbnQoInVsIikKaj1xLmEoSC5WTShbInRy
+YWNlIl0scikpCmk9Si5kUihrKQppLlYxKDApCmkuRlYoMCxqKQpnPWguYXBwZW5kQ2hpbGQoaykKZm9y
+KGs9bS5iLGo9ay5sZW5ndGgsZj0wO2Y8ay5sZW5ndGg7ay5sZW5ndGg9PT1qfHwoMCxILmxrKShrKSwr
+K2Ype2U9a1tmXQpkPWwuY3JlYXRlRWxlbWVudCgibGkiKQpKLmw1KGQsIiYjeDI3NEY7ICIpCmM9cC5h
+KGcuYXBwZW5kQ2hpbGQoZCkpCmQ9bC5jcmVhdGVFbGVtZW50KCJzcGFuIikKYj1xLmEoSC5WTShbImZ1
+bmN0aW9uIl0scikpCmk9Si5kUihkKQppLlYxKDApCmkuRlYoMCxiKQpiPWUuYgpMLmtEKGQsYj09bnVs
+bD8idW5rbm93biI6YikKYy5hcHBlbmRDaGlsZChkKQphPWUuYwppZihhIT1udWxsKXtjLmFwcGVuZENo
+aWxkKGwuY3JlYXRlVGV4dE5vZGUoIiAoIikpCmEwPWEuYgpkPWwuY3JlYXRlRWxlbWVudCgiYSIpCm8u
+YShkKQpkLmFwcGVuZENoaWxkKGwuY3JlYXRlVGV4dE5vZGUoSC5kKGEuYykrIjoiK0guZChhMCkpKQph
+MT1hLmEKYj0kLm5VKCkKZC5zZXRBdHRyaWJ1dGUoImhyZWYiLGIubzUoMCxiLnE3KDAsYTUsYTEsYTIs
+YTIsYTIsYTIsYTIsYTIpKSkKZC5jbGFzc0xpc3QuYWRkKCJuYXYtbGluayIpCmMuYXBwZW5kQ2hpbGQo
+ZCkKYy5hcHBlbmRDaGlsZChsLmNyZWF0ZVRleHROb2RlKCIpIikpfWMuYXBwZW5kQ2hpbGQobC5jcmVh
+dGVUZXh0Tm9kZSgiOiAiKSkKZD1lLmEKTC5rRChjLGQ9PW51bGw/InVua25vd24iOmQpfX19LAprRDpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMscj1ILlZNKGIuc3BsaXQoIi4iKSx1LnMpLHE9Qy5ObS5ndEgociks
+cD1kb2N1bWVudAphLmFwcGVuZENoaWxkKHAuY3JlYXRlVGV4dE5vZGUocSkpCmZvcihxPUgucUMociwx
+LG51bGwsdS5OKSxxPW5ldyBILmE3KHEscS5nayhxKSxxLiR0aS5DKCJhNzxhTC5FPiIpKSx0PUouUkUo
+YSk7cS5tKCk7KXtzPXEuZAp0Lm56KGEsImJlZm9yZWVuZCIsIiYjODIwMzsuIixudWxsLG51bGwpCmEu
+YXBwZW5kQ2hpbGQocC5jcmVhdGVUZXh0Tm9kZShzKSl9fSwKZTpmdW5jdGlvbiBlKCl7fSwKVlc6ZnVu
+Y3Rpb24gVlcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKb1o6ZnVuY3Rpb24gb1oo
+KXt9LApqcjpmdW5jdGlvbiBqcigpe30sCnFsOmZ1bmN0aW9uIHFsKCl7fSwKeTg6ZnVuY3Rpb24geTgo
+KXt9LApMOmZ1bmN0aW9uIEwoKXt9LApXeDpmdW5jdGlvbiBXeChhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
+fSwKQU86ZnVuY3Rpb24gQU8oYSl7dGhpcy5hPWF9LApkTjpmdW5jdGlvbiBkTihhKXt0aGlzLmE9YX0s
+CkhvOmZ1bmN0aW9uIEhvKGEpe3RoaXMuYT1hfSwKeHo6ZnVuY3Rpb24geHooYSxiKXt0aGlzLmE9YQp0
+aGlzLmI9Yn0sCklDOmZ1bmN0aW9uIElDKCl7fSwKTDE6ZnVuY3Rpb24gTDEoKXt9LApuVDpmdW5jdGlv
+biBuVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApCWjpmdW5jdGlvbiBCWihhKXt0
+aGlzLmE9YX0sCkdIOmZ1bmN0aW9uIEdIKCl7fSwKRFQ6ZnVuY3Rpb24gRFQoYSxiLGMpe3RoaXMuYT1h
+CnRoaXMuYj1iCnRoaXMuYz1jfSwKZUg6ZnVuY3Rpb24gZUgoYSl7dGhpcy5hPWF9LAp5dTpmdW5jdGlv
+biB5dShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWV9LAp6
+RDpmdW5jdGlvbiB6RChhKXt0aGlzLmE9YX0sClRXOmZ1bmN0aW9uIFRXKCl7fSwKeHI6ZnVuY3Rpb24g
+eHIoYSl7dGhpcy5hPWF9LApFRTpmdW5jdGlvbiBFRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
+cy5jPWN9LApRTDpmdW5jdGlvbiBRTChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVlM6ZnVuY3Rpb24g
+VlMoYSl7dGhpcy5hPWF9LApURDpmdW5jdGlvbiBURCgpe30sClhBOmZ1bmN0aW9uIFhBKCl7fSwKbUs6
+ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49SC5WTShbXSx1LmZoKQpmb3IodD1KLklUKHUuUi5h
+KGEpKTt0Lm0oKTspe3M9dC5nUih0KQpyPUouVTYocykKcT1MLnAyKEguYyhyLnEocywidHlwZSIpKSkK
+cD1ILmMoci5xKHMsIm5hbWUiKSkKbz1yLnEocywic3VidHJlZSIpCm89bz09bnVsbD9udWxsOkwubUso
+bykKQy5ObS5BKG4sbmV3IEwuWloocSxwLG8sSC5jKHIucShzLCJwYXRoIikpLEguYyhyLnEocywiaHJl
+ZiIpKSxILldZKHIucShzLCJlZGl0Q291bnQiKSkpKX1yZXR1cm4gbn0sCnAyOmZ1bmN0aW9uKGEpe3N3
+aXRjaChhKXtjYXNlImRpcmVjdG9yeSI6cmV0dXJuIEMuWTIKY2FzZSJmaWxlIjpyZXR1cm4gQy5yZgpk
+ZWZhdWx0OnRocm93IEguYihQLlBWKCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlw
+ZTogIitILmQoYSkpKX19LApaWjpmdW5jdGlvbiBaWihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9
+YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sCldBOmZ1bmN0aW9uIFdBKGEpe3RoaXMuYj1h
+fSwKSVY6ZnVuY3Rpb24gSVYoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9
+ZH19LE09ewpZRjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuCmZvcih0PWIubGVuZ3RoLHM9
+MTtzPHQ7KytzKXtpZihiW3NdPT1udWxsfHxiW3MtMV0hPW51bGwpY29udGludWUKZm9yKDt0Pj0xO3Q9
+cil7cj10LTEKaWYoYltyXSE9bnVsbClicmVha31xPW5ldyBQLlJuKCIiKQpwPWErIigiCnEuYT1wCm89
+SC5xQyhiLDAsdCxILnQ2KGIpLmMpCm49by4kdGkKbj1wK25ldyBILmxKKG8sbi5DKCJxVShhTC5FKSIp
+LmEobmV3IE0uTm8oKSksbi5DKCJsSjxhTC5FLHFVPiIpKS56VigwLCIsICIpCnEuYT1uCnEuYT1uKygi
+KTogcGFydCAiKyhzLTEpKyIgd2FzIG51bGwsIGJ1dCBwYXJ0ICIrcysiIHdhcyBub3QuIikKdGhyb3cg
+SC5iKFAueFkocS5aKDApKSl9fSwKbEk6ZnVuY3Rpb24gbEkoYSl7dGhpcy5hPWF9LApNaTpmdW5jdGlv
+biBNaSgpe30sCnE3OmZ1bmN0aW9uIHE3KCl7fSwKTm86ZnVuY3Rpb24gTm8oKXt9fSxYPXsKQ0w6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89Yi54WihhKQpiLmhLKGEpCmlmKG8hPW51bGwpYT1KLktW
+KGEsby5sZW5ndGgpCnQ9dS5zCnM9SC5WTShbXSx0KQpyPUguVk0oW10sdCkKdD1hLmxlbmd0aAppZih0
+IT09MCYmYi5yNChDLnhCLldkKGEsMCkpKXtpZigwPj10KXJldHVybiBILmsoYSwwKQpDLk5tLkEocixh
+WzBdKQpxPTF9ZWxzZXtDLk5tLkEociwiIikKcT0wfWZvcihwPXE7cDx0OysrcClpZihiLnI0KEMueEIu
+V2QoYSxwKSkpe0MuTm0uQShzLEMueEIuTmooYSxxLHApKQpDLk5tLkEocixhW3BdKQpxPXArMX1pZihx
+PHQpe0MuTm0uQShzLEMueEIueW4oYSxxKSkKQy5ObS5BKHIsIiIpfXJldHVybiBuZXcgWC5XRChiLG8s
+cyxyKX0sCldEOmZ1bmN0aW9uIFdEKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPWMK
+Xy5lPWR9LApxUjpmdW5jdGlvbiBxUihhKXt0aGlzLmE9YX0sCkk3OmZ1bmN0aW9uKGEpe3JldHVybiBu
+ZXcgWC5kdihhKX0sCmR2OmZ1bmN0aW9uIGR2KGEpe3RoaXMuYT1hfX0sTz17ClJoOmZ1bmN0aW9uKCl7
+dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpPW51bGwKaWYoUC51bygpLmdGaSgpIT09ImZpbGUiKXJl
+dHVybiAkLkViKCkKdD1QLnVvKCkKaWYoIUMueEIuVGModC5nSWkodCksIi8iKSlyZXR1cm4gJC5FYigp
+CnM9UC5QaShpLDAsMCkKcj1QLnpSKGksMCwwKQpxPVAuT2UoaSwwLDAsITEpCnA9UC5sZShpLDAsMCxp
+KQpvPVAudEcoaSwwLDApCm49UC53QihpLHMpCm09cz09PSJmaWxlIgppZihxPT1udWxsKXQ9ci5sZW5n
+dGghPT0wfHxuIT1udWxsfHxtCmVsc2UgdD0hMQppZih0KXE9IiIKdD1xPT1udWxsCmw9IXQKaz1QLmth
+KCJhL2IiLDAsMyxpLHMsbCkKaj1zLmxlbmd0aD09PTAKaWYoaiYmdCYmIUMueEIubkMoaywiLyIpKWs9
+UC53RihrLCFqfHxsKQplbHNlIGs9UC54ZShrKQppZihuZXcgUC5EbihzLHIsdCYmQy54Qi5uQyhrLCIv
+LyIpPyIiOnEsbixrLHAsbykudDQoKT09PSJhXFxiIilyZXR1cm4gJC5LaygpCnJldHVybiAkLmJEKCl9
+LApPTzpmdW5jdGlvbiBPTygpe319LEU9e09GOmZ1bmN0aW9uIE9GKGEsYixjKXt0aGlzLmQ9YQp0aGlz
+LmU9Ygp0aGlzLmY9Y319LEY9e3J1OmZ1bmN0aW9uIHJ1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5kPWEK
+Xy5lPWIKXy5mPWMKXy5yPWR9fSxEPXsKUlg6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9UC51bygpCmlmKEou
+Uk0ociwkLkk2KSlyZXR1cm4gJC5GZgokLkk2PXIKaWYoJC5IaygpPT0kLkViKCkpcmV0dXJuICQuRmY9
+ci5aSSgiLiIpLlooMCkKZWxzZXt0PXIudDQoKQpzPXQubGVuZ3RoLTEKcmV0dXJuICQuRmY9cz09PTA/
+dDpDLnhCLk5qKHQsMCxzKX19LApucjpmdW5jdGlvbihhLGIpe3ZhciB0PW51bGwKcmV0dXJuICQublUo
+KS5xNygwLGEsYix0LHQsdCx0LHQsdCl9fQp2YXIgdz1bQyxILEosUCxXLFUsQixULEwsTSxYLE8sRSxG
+LERdCmh1bmtIZWxwZXJzLnNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeSh3KQp2YXIgJD17fQpILkZL
+LnByb3RvdHlwZT17fQpKLnZCLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PT1i
+fSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJuIEguZVEoYSl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiJJbnN0
+YW5jZSBvZiAnIitILmQoSC5saChhKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1Lm8uYShiKQp0aHJv
+dyBILmIoUC5scihhLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9fQpKLnlFLnByb3RvdHlwZT17Clo6
+ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBhPzUxOTAx
+ODoyMTgxNTl9LAokaWEyOjF9CkouWUUucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+bnVsbD09Yn0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIm51bGwifSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJu
+IDB9LAplNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNqKGEsdS5vLmEoYikpfSwKJGljODoxfQpK
+Lk1GLnByb3RvdHlwZT17CmdpOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKWjpmdW5jdGlvbihhKXtyZXR1
+cm4gU3RyaW5nKGEpfSwKJGl2bToxfQpKLmlDLnByb3RvdHlwZT17fQpKLmtkLnByb3RvdHlwZT17fQpK
+LmM1LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9YVskLndRKCldCmlmKHQ9PW51bGwpcmV0
+dXJuIHRoaXMubihhKQpyZXR1cm4iSmF2YVNjcmlwdCBmdW5jdGlvbiBmb3IgIitILmQoSi5BYyh0KSl9
+LAokUzpmdW5jdGlvbigpe3JldHVybntmdW5jOjEsb3B0OlssLCwsLCwsLCwsLCwsLCwsXX19LAokaUVI
+OjF9CkouamQucHJvdG90eXBlPXsKQTpmdW5jdGlvbihhLGIpe0gudDYoYSkuYy5hKGIpCmlmKCEhYS5m
+aXhlZCRsZW5ndGgpSC5WaihQLkw0KCJhZGQiKSkKYS5wdXNoKGIpfSwKVzQ6ZnVuY3Rpb24oYSxiKXt2
+YXIgdAppZighIWEuZml4ZWQkbGVuZ3RoKUguVmooUC5MNCgicmVtb3ZlQXQiKSkKdD1hLmxlbmd0aApp
+ZihiPj10KXRocm93IEguYihQLk83KGIsbnVsbCkpCnJldHVybiBhLnNwbGljZShiLDEpWzBdfSwKVUc6
+ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpILnQ2KGEpLkMoIkx5PDE+IikuYShjKQppZighIWEuZml4
+ZWQkbGVuZ3RoKUguVmooUC5MNCgiaW5zZXJ0QWxsIikpCnQ9YS5sZW5ndGgKUC53QShiLDAsdCwiaW5k
+ZXgiKQpzPWMubGVuZ3RoCnRoaXMuc2soYSx0K3MpCnI9YitzCnRoaXMuWVcoYSxyLGEubGVuZ3RoLGEs
+YikKdGhpcy52ZyhhLGIscixjKX0sCm12OmZ1bmN0aW9uKGEpe2lmKCEhYS5maXhlZCRsZW5ndGgpSC5W
+aihQLkw0KCJyZW1vdmVMYXN0IikpCmlmKGEubGVuZ3RoPT09MCl0aHJvdyBILmIoSC5IWShhLC0xKSkK
+cmV0dXJuIGEucG9wKCl9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0CkgudDYoYSkuQygiTHk8MT4iKS5h
+KGIpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC5WaihQLkw0KCJhZGRBbGwiKSkKZm9yKHQ9Si5JVChiKTt0
+Lm0oKTspYS5wdXNoKHQuZ1IodCkpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC50NihhKS5DKCJ+
+KDEpIikuYShiKQp0PWEubGVuZ3RoCmZvcihzPTA7czx0Oysrcyl7Yi4kMShhW3NdKQppZihhLmxlbmd0
+aCE9PXQpdGhyb3cgSC5iKFAuYTQoYSkpfX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILnQ2KGEp
+CnJldHVybiBuZXcgSC5sSihhLHQuSyhjKS5DKCIxKDIpIikuYShiKSx0LkMoIkA8MT4iKS5LKGMpLkMo
+ImxKPDEsMj4iKSl9LAp6VjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9bmV3IEFycmF5KGEubGVuZ3RoKQpz
+LmZpeGVkJGxlbmd0aD1BcnJheQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KXRoaXMudChzLHQsSC5kKGFb
+dF0pKQpyZXR1cm4gcy5qb2luKGIpfSwKTjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmQuYShi
+KQpILnQ2KGEpLksoZCkuQygiMSgxLDIpIikuYShjKQp0PWEubGVuZ3RoCmZvcihzPWIscj0wO3I8dDsr
+K3Ipe3M9Yy4kMihzLGFbcl0pCmlmKGEubGVuZ3RoIT09dCl0aHJvdyBILmIoUC5hNChhKSl9cmV0dXJu
+IHN9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0
+dXJuIGFbYl19LApENjpmdW5jdGlvbihhLGIsYyl7aWYoYjwwfHxiPmEubGVuZ3RoKXRocm93IEguYihQ
+LlRFKGIsMCxhLmxlbmd0aCwic3RhcnQiLG51bGwpKQppZihjPGJ8fGM+YS5sZW5ndGgpdGhyb3cgSC5i
+KFAuVEUoYyxiLGEubGVuZ3RoLCJlbmQiLG51bGwpKQppZihiPT09YylyZXR1cm4gSC5WTShbXSxILnQ2
+KGEpKQpyZXR1cm4gSC5WTShhLnNsaWNlKGIsYyksSC50NihhKSl9LApndEg6ZnVuY3Rpb24oYSl7aWYo
+YS5sZW5ndGg+MClyZXR1cm4gYVswXQp0aHJvdyBILmIoSC5XcCgpKX0sCmdyWjpmdW5jdGlvbihhKXt2
+YXIgdD1hLmxlbmd0aAppZih0PjApcmV0dXJuIGFbdC0xXQp0aHJvdyBILmIoSC5XcCgpKX0sCllXOmZ1
+bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyPUgudDYoYSkKci5DKCJMeTwxPiIpLmEoZCkKaWYoISFh
+LmltbXV0YWJsZSRsaXN0KUguVmooUC5MNCgic2V0UmFuZ2UiKSkKUC5qQihiLGMsYS5sZW5ndGgpCnQ9
+Yy1iCmlmKHQ9PT0wKXJldHVybgpQLmsxKGUsInNraXBDb3VudCIpCnIuQygiek08MT4iKS5hKGQpCnI9
+Si5VNihkKQppZihlK3Q+ci5nayhkKSl0aHJvdyBILmIoSC5hcigpKQppZihlPGIpZm9yKHM9dC0xO3M+
+PTA7LS1zKWFbYitzXT1yLnEoZCxlK3MpCmVsc2UgZm9yKHM9MDtzPHQ7KytzKWFbYitzXT1yLnEoZCxl
+K3MpfSwKdmc6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0sClZyOmZ1
+bmN0aW9uKGEsYil7dmFyIHQscwpILnQ2KGEpLkMoImEyKDEpIikuYShiKQp0PWEubGVuZ3RoCmZvcihz
+PTA7czx0Oysrcyl7aWYoSC5vVChiLiQxKGFbc10pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9PXQpdGhy
+b3cgSC5iKFAuYTQoYSkpfXJldHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD0wO3Q8
+YS5sZW5ndGg7Kyt0KWlmKEouUk0oYVt0XSxiKSlyZXR1cm4hMApyZXR1cm4hMX0sClo6ZnVuY3Rpb24o
+YSl7cmV0dXJuIFAuV0UoYSwiWyIsIl0iKX0sCmd3OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSi5tMShh
+LGEubGVuZ3RoLEgudDYoYSkuQygibTE8MT4iKSl9LApnaTpmdW5jdGlvbihhKXtyZXR1cm4gSC5lUShh
+KX0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnNrOmZ1bmN0aW9uKGEsYil7aWYoISFh
+LmZpeGVkJGxlbmd0aClILlZqKFAuTDQoInNldCBsZW5ndGgiKSkKaWYoYjwwKXRocm93IEguYihQLlRF
+KGIsMCxudWxsLCJuZXdMZW5ndGgiLG51bGwpKQphLmxlbmd0aD1ifSwKcTpmdW5jdGlvbihhLGIpe0gu
+V1koYikKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0s
+CnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKSC50NihhKS5jLmEoYykKaWYoISFhLmltbXV0YWJsZSRs
+aXN0KUguVmooUC5MNCgiaW5kZXhlZCBzZXQiKSkKaWYoIUgub2soYikpdGhyb3cgSC5iKEguSFkoYSxi
+KSkKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQphW2JdPWN9LAokaWJROjEs
+CiRpTHk6MSwKJGl6TToxfQpKLlBvLnByb3RvdHlwZT17fQpKLm0xLnByb3RvdHlwZT17CmdSOmZ1bmN0
+aW9uKGEpe3JldHVybiB0aGlzLmR9LAptOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLHI9cy5hLHE9ci5s
+ZW5ndGgKaWYocy5iIT09cSl0aHJvdyBILmIoSC5sayhyKSkKdD1zLmMKaWYodD49cSl7cy5zSShudWxs
+KQpyZXR1cm4hMX1zLnNJKHJbdF0pOysrcy5jCnJldHVybiEwfSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5k
+PXRoaXMuJHRpLmMuYShhKX0sCiRpQW46MX0KSi5xSS5wcm90b3R5cGU9ewp5dTpmdW5jdGlvbihhKXt2
+YXIgdAppZihhPj0tMjE0NzQ4MzY0OCYmYTw9MjE0NzQ4MzY0NylyZXR1cm4gYXwwCmlmKGlzRmluaXRl
+KGEpKXt0PWE8MD9NYXRoLmNlaWwoYSk6TWF0aC5mbG9vcihhKQpyZXR1cm4gdCswfXRocm93IEguYihQ
+Lkw0KCIiK2ErIi50b0ludCgpIikpfSwKelE6ZnVuY3Rpb24oYSl7aWYoYT4wKXtpZihhIT09MS8wKXJl
+dHVybiBNYXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJldHVybiAwLU1hdGgucm91bmQoMC1hKQp0
+aHJvdyBILmIoUC5MNCgiIithKyIucm91bmQoKSIpKX0sCkQ4OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
+LHEKaWYoYjwyfHxiPjM2KXRocm93IEguYihQLlRFKGIsMiwzNiwicmFkaXgiLG51bGwpKQp0PWEudG9T
+dHJpbmcoYikKaWYoQy54Qi5PMih0LHQubGVuZ3RoLTEpIT09NDEpcmV0dXJuIHQKcz0vXihbXGRhLXpd
+KykoPzpcLihbXGRhLXpdKykpP1woZVwrKFxkKylcKSQvLmV4ZWModCkKaWYocz09bnVsbClILlZqKFAu
+TDQoIlVuZXhwZWN0ZWQgdG9TdHJpbmcgcmVzdWx0OiAiK3QpKQpyPXMubGVuZ3RoCmlmKDE+PXIpcmV0
+dXJuIEguayhzLDEpCnQ9c1sxXQppZigzPj1yKXJldHVybiBILmsocywzKQpxPStzWzNdCnI9c1syXQpp
+ZihyIT1udWxsKXt0Kz1yCnEtPXIubGVuZ3RofXJldHVybiB0K0MueEIuSXgoIjAiLHEpfSwKWjpmdW5j
+dGlvbihhKXtpZihhPT09MCYmMS9hPDApcmV0dXJuIi0wLjAiCmVsc2UgcmV0dXJuIiIrYX0sCmdpOmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9YXwwCmlmKGE9PT1wKXJldHVybiA1MzY4NzA5MTEmcAp0PU1h
+dGguYWJzKGEpCnM9TWF0aC5sb2codCkvMC42OTMxNDcxODA1NTk5NDUzfDAKcj1NYXRoLnBvdygyLHMp
+CnE9dDwxP3QvcjpyL3QKcmV0dXJuIDUzNjg3MDkxMSYoKHEqOTAwNzE5OTI1NDc0MDk5MnwwKSsocSoz
+NTQyMjQzMTgxMTc2NTIxfDApKSo1OTkxOTcrcyoxMjU5fSwKelk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1h
+JWIKaWYodD09PTApcmV0dXJuIDAKaWYodD4wKXJldHVybiB0CmlmKGI8MClyZXR1cm4gdC1iCmVsc2Ug
+cmV0dXJuIHQrYn0sCndHOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT4wKXQ9dGhpcy5wMyhhLGIpCmVs
+c2V7dD1iPjMxPzMxOmIKdD1hPj50Pj4+MH1yZXR1cm4gdH0sCmJmOmZ1bmN0aW9uKGEsYil7aWYoYjww
+KXRocm93IEguYihILnRMKGIpKQpyZXR1cm4gdGhpcy5wMyhhLGIpfSwKcDM6ZnVuY3Rpb24oYSxiKXty
+ZXR1cm4gYj4zMT8wOmE+Pj5ifSwKJGlDUDoxLAokaWxmOjF9CkoudXIucHJvdG90eXBlPXskaUlmOjF9
+CkouVkEucHJvdG90eXBlPXt9CkouRHIucHJvdG90eXBlPXsKTzI6ZnVuY3Rpb24oYSxiKXtpZihiPDAp
+dGhyb3cgSC5iKEguSFkoYSxiKSkKaWYoYj49YS5sZW5ndGgpSC5WaihILkhZKGEsYikpCnJldHVybiBh
+LmNoYXJDb2RlQXQoYil9LApXZDpmdW5jdGlvbihhLGIpe2lmKGI+PWEubGVuZ3RoKXRocm93IEguYihI
+LkhZKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBu
+ZXcgSC5ORihiLGEsMCl9LApoOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJzdHJpbmciKXRocm93
+IEguYihQLkwzKGIsbnVsbCxudWxsKSkKcmV0dXJuIGErYn0sClRjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9
+Yi5sZW5ndGgscz1hLmxlbmd0aAppZih0PnMpcmV0dXJuITEKcmV0dXJuIGI9PT10aGlzLnluKGEscy10
+KX0sCmk3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMKYz1QLmpCKGIsYyxhLmxlbmd0aCkKdD1hLnN1
+YnN0cmluZygwLGIpCnM9YS5zdWJzdHJpbmcoYykKcmV0dXJuIHQrZCtzfSwKUWk6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0CmlmKCFILm9rKGMpKUguVmooSC50TChjKSkKaWYodHlwZW9mIGMhPT0ibnVtYmVyIily
+ZXR1cm4gYy5KKCkKaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxu
+dWxsLG51bGwpKQp0PWMrYi5sZW5ndGgKaWYodD5hLmxlbmd0aClyZXR1cm4hMQpyZXR1cm4gYj09PWEu
+c3Vic3RyaW5nKGMsdCl9LApuQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlFpKGEsYiwwKX0sCk5q
+OmZ1bmN0aW9uKGEsYixjKXtpZighSC5vayhiKSlILlZqKEgudEwoYikpCmlmKGM9PW51bGwpYz1hLmxl
 bmd0aAppZih0eXBlb2YgYiE9PSJudW1iZXIiKXJldHVybiBiLkooKQppZihiPDApdGhyb3cgSC5iKFAu
 TzcoYixudWxsKSkKaWYoYj5jKXRocm93IEguYihQLk83KGIsbnVsbCkpCmlmKGM+YS5sZW5ndGgpdGhy
-b3cgSC5iKFAuTzcoYyxudWxsKSkKcmV0dXJuIGEuc3Vic3RyaW5nKGIsYyl9LApHOmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIHRoaXMudyhhLGIsbnVsbCl9LApoYzpmdW5jdGlvbihhKXtyZXR1cm4gYS50b0xvd2Vy
-Q2FzZSgpfSwKYlM6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9YS50cmltKCkscD1xLmxlbmd0aAppZihw
-PT09MClyZXR1cm4gcQppZih0aGlzLlcocSwwKT09PTEzMyl7dD1KLm1tKHEsMSkKaWYodD09PXApcmV0
-dXJuIiJ9ZWxzZSB0PTAKcz1wLTEKcj10aGlzLm0ocSxzKT09PTEzMz9KLmMxKHEscyk6cAppZih0PT09
-MCYmcj09PXApcmV0dXJuIHEKcmV0dXJuIHEuc3Vic3RyaW5nKHQscil9LApJeDpmdW5jdGlvbihhLGIp
-e3ZhciB0LHMKaWYoMD49YilyZXR1cm4iIgppZihiPT09MXx8YS5sZW5ndGg9PT0wKXJldHVybiBhCmlm
-KGIhPT1iPj4+MCl0aHJvdyBILmIoQy5FcSkKZm9yKHQ9YSxzPSIiOyEwOyl7aWYoKGImMSk9PT0xKXM9
-dCtzCmI9Yj4+PjEKaWYoYj09PTApYnJlYWsKdCs9dH1yZXR1cm4gc30sClhVOmZ1bmN0aW9uKGEsYixj
-KXt2YXIgdAppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGws
-bnVsbCkpCnQ9YS5pbmRleE9mKGIsYykKcmV0dXJuIHR9LApPWTpmdW5jdGlvbihhLGIpe3JldHVybiB0
-aGlzLlhVKGEsYiwwKX0sClBrOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzCmlmKGM9PW51bGwpYz1hLmxl
-bmd0aAplbHNlIGlmKGM8MHx8Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVs
-bCxudWxsKSkKdD1iLmxlbmd0aApzPWEubGVuZ3RoCmlmKGMrdD5zKWM9cy10CnJldHVybiBhLmxhc3RJ
-bmRleE9mKGIsYyl9LApjbjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlBrKGEsYixudWxsKX0sCklz
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1hLmxlbmd0aAppZihjPnQpdGhyb3cgSC5iKFAuVEUoYywwLHQs
-bnVsbCxudWxsKSkKcmV0dXJuIEgubTIoYSxiLGMpfSwKdGc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhp
-cy5JcyhhLGIsMCl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciB0
-LHMscgpmb3IodD1hLmxlbmd0aCxzPTAscj0wO3I8dDsrK3Ipe3M9NTM2ODcwOTExJnMrYS5jaGFyQ29k
-ZUF0KHIpCnM9NTM2ODcwOTExJnMrKCg1MjQyODcmcyk8PDEwKQpzXj1zPj42fXM9NTM2ODcwOTExJnMr
-KCg2NzEwODg2MyZzKTw8MykKc149cz4+MTEKcmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8PDE1
-KX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIp
-CmlmKGI+PWEubGVuZ3RofHwhMSl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0sCiRpdlg6
-MSwKJGlxVToxfQpILnFqLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEubGVu
-Z3RofSwKcTpmdW5jdGlvbihhLGIpe3JldHVybiBDLnhCLm0odGhpcy5hLEguV1koYikpfX0KSC5iUS5w
-cm90b3R5cGU9e30KSC5hTC5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwpyZXR1
-cm4gbmV3IEguYTcodCx0LmdBKHQpLEguTGgodCkuQygiYTc8YUwuRT4iKSl9LAp6VjpmdW5jdGlvbihh
-LGIpe3ZhciB0LHMscixxPXRoaXMscD1xLmdBKHEpCmlmKGIubGVuZ3RoIT09MCl7aWYocD09PTApcmV0
-dXJuIiIKdD1ILmQocS5FKDAsMCkpCmlmKHAhPT1xLmdBKHEpKXRocm93IEguYihQLmE0KHEpKQpmb3Io
-cz10LHI9MTtyPHA7KytyKXtzPXMrYitILmQocS5FKDAscikpCmlmKHAhPT1xLmdBKHEpKXRocm93IEgu
-YihQLmE0KHEpKX1yZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c31lbHNle2ZvcihyPTAscz0iIjty
-PHA7KytyKXtzKz1ILmQocS5FKDAscikpCmlmKHAhPT1xLmdBKHEpKXRocm93IEguYihQLmE0KHEpKX1y
-ZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c319LApldjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
-LkdHKDAsSC5MaCh0aGlzKS5DKCJhMihhTC5FKSIpLmEoYikpfSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3Zh
-ciB0PUguTGgodGhpcykKcmV0dXJuIG5ldyBILmxKKHRoaXMsdC5LcShjKS5DKCIxKGFMLkUpIikuYShi
-KSx0LkMoIkA8YUwuRT4iKS5LcShjKS5DKCJsSjwxLDI+IikpfX0KSC5uSC5wcm90b3R5cGU9ewpnVUQ6
-ZnVuY3Rpb24oKXt2YXIgdD1KLkgodGhpcy5hKSxzPXRoaXMuYwppZihzPT1udWxsfHxzPnQpcmV0dXJu
-IHQKcmV0dXJuIHN9LApnQXM6ZnVuY3Rpb24oKXt2YXIgdD1KLkgodGhpcy5hKSxzPXRoaXMuYgppZihz
-PnQpcmV0dXJuIHQKcmV0dXJuIHN9LApnQTpmdW5jdGlvbihhKXt2YXIgdCxzPUouSCh0aGlzLmEpLHI9
-dGhpcy5iCmlmKHI+PXMpcmV0dXJuIDAKdD10aGlzLmMKaWYodD09bnVsbHx8dD49cylyZXR1cm4gcy1y
-CmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSE4oKQpyZXR1cm4gdC1yfSwKRTpmdW5jdGlv
-bihhLGIpe3ZhciB0LHM9dGhpcyxyPXMuZ0FzKCkrYgppZihiPj0wKXt0PXMuZ1VEKCkKaWYodHlwZW9m
-IHQhPT0ibnVtYmVyIilyZXR1cm4gSC5wWSh0KQp0PXI+PXR9ZWxzZSB0PSEwCmlmKHQpdGhyb3cgSC5i
-KFAudChiLHMsImluZGV4IixudWxsLG51bGwpKQpyZXR1cm4gSi5HQShzLmEscil9fQpILmE3LnByb3Rv
-dHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rpb24oKXt2YXIgdCxzPXRo
-aXMscj1zLmEscT1KLlU2KHIpLHA9cS5nQShyKQppZihzLmIhPT1wKXRocm93IEguYihQLmE0KHIpKQp0
-PXMuYwppZih0Pj1wKXtzLnNJKG51bGwpCnJldHVybiExfXMuc0kocS5FKHIsdCkpOysrcy5jCnJldHVy
-biEwfSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmMuYShhKX0sCiRpQW46MX0KSC5pMS5w
-cm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5MaCh0aGlzKQpyZXR1cm4gbmV3IEguTUgo
-Si5JVCh0aGlzLmEpLHRoaXMuYix0LkMoIkA8MT4iKS5LcSh0LlFbMV0pLkMoIk1IPDEsMj4iKSl9LApn
-QTpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuYSl9fQpILnh5LnByb3RvdHlwZT17JGliUToxfQpI
-Lk1ILnByb3RvdHlwZT17CkY6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5iCmlmKHMuRigpKXt0LnNJ
-KHQuYy4kMShzLmdsKCkpKQpyZXR1cm4hMH10LnNJKG51bGwpCnJldHVybiExfSwKZ2w6ZnVuY3Rpb24o
-KXtyZXR1cm4gdGhpcy5hfSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5hPXRoaXMuJHRpLlFbMV0uYShhKX19
-CkgubEoucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIEouSCh0aGlzLmEpfSwKRTpmdW5j
-dGlvbihhLGIpe3JldHVybiB0aGlzLmIuJDEoSi5HQSh0aGlzLmEsYikpfX0KSC5VNS5wcm90b3R5cGU9
-ewpna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILnZHKEouSVQodGhpcy5hKSx0aGlzLmIsdGhpcy4k
-dGkuQygidkc8MT4iKSl9fQpILnZHLnByb3RvdHlwZT17CkY6ZnVuY3Rpb24oKXt2YXIgdCxzCmZvcih0
-PXRoaXMuYSxzPXRoaXMuYjt0LkYoKTspaWYoSC5vVChzLiQxKHQuZ2woKSkpKXJldHVybiEwCnJldHVy
-biExfSwKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hLmdsKCl9fQpILlNVLnByb3RvdHlwZT17fQpI
-LlJlLnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxiLGMpe0guTGgodGhpcykuQygiUmUuRSIpLmEoYykK
-dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgYW4gdW5tb2RpZmlhYmxlIGxpc3QiKSl9fQpILncy
-LnByb3RvdHlwZT17fQpILnd2LnByb3RvdHlwZT17CmdpTzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLl9o
-YXNoQ29kZQppZih0IT1udWxsKXJldHVybiB0CnQ9NTM2ODcwOTExJjY2NDU5NypKLmhmKHRoaXMuYSkK
-dGhpcy5faGFzaENvZGU9dApyZXR1cm4gdH0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuJ1N5bWJvbCgiJytI
-LmQodGhpcy5hKSsnIiknfSwKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJldHVy
-biBiIGluc3RhbmNlb2YgSC53diYmdGhpcy5hPT1iLmF9LAokaUdEOjF9CkguUEQucHJvdG90eXBlPXt9
-CkguV1UucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sClk6ZnVuY3Rp
-b24oYSxiLGMpe3ZhciB0PUguTGgodGhpcykKdC5jLmEoYikKdC5RWzFdLmEoYykKcmV0dXJuIEguZGMo
-KX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5xNChhLEguTGgodGhpcykuQygiTjM8MSwyPiIp
-KX0sCnE0OmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwpyZXR1cm4gUC5sMChmdW5jdGlvbigpe3ZhciBz
-PWEKdmFyIHI9MCxxPTEscCxvLG4sbQpyZXR1cm4gZnVuY3Rpb24gJGFzeW5jJGdQdShjLGQpe2lmKGM9
-PT0xKXtwPWQKcj1xfXdoaWxlKHRydWUpc3dpdGNoKHIpe2Nhc2UgMDpvPXQuZ1YoKSxvPW8uZ2t6KG8p
-LG49SC5MaCh0KSxuPW4uQygiQDwxPiIpLktxKG4uUVsxXSkuQygiTjM8MSwyPiIpCmNhc2UgMjppZigh
-by5GKCkpe3I9MwpicmVha31tPW8uZ2woKQpyPTQKcmV0dXJuIG5ldyBQLk4zKG0sdC5xKDAsbSksbikK
-Y2FzZSA0OnI9MgpicmVhawpjYXNlIDM6cmV0dXJuIFAuVGgoKQpjYXNlIDE6cmV0dXJuIFAuWW0ocCl9
-fX0sYil9LAokaVowOjF9CkguTFAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-YX0sCng0OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhIT0ic3RyaW5nIilyZXR1cm4hMQppZigiX19wcm90
-b19fIj09PWEpcmV0dXJuITEKcmV0dXJuIHRoaXMuYi5oYXNPd25Qcm9wZXJ0eShhKX0sCnE6ZnVuY3Rp
-b24oYSxiKXtpZighdGhpcy54NChiKSlyZXR1cm4gbnVsbApyZXR1cm4gdGhpcy5xUChiKX0sCnFQOmZ1
-bmN0aW9uKGEpe3JldHVybiB0aGlzLmJbSC5jKGEpXX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIs
-cSxwPUguTGgodGhpcykKcC5DKCJ+KDEsMikiKS5hKGIpCnQ9dGhpcy5jCmZvcihzPXQubGVuZ3RoLHA9
-cC5RWzFdLHI9MDtyPHM7KytyKXtxPXRbcl0KYi4kMihxLHAuYSh0aGlzLnFQKHEpKSl9fSwKZ1Y6ZnVu
-Y3Rpb24oKXtyZXR1cm4gbmV3IEguWFIodGhpcyxILkxoKHRoaXMpLkMoIlhSPDE+IikpfX0KSC5YUi5w
-cm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLmMKcmV0dXJuIG5ldyBKLm0xKHQs
-dC5sZW5ndGgsSC50Nih0KS5DKCJtMTwxPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEu
-Yy5sZW5ndGh9fQpILkxJLnByb3RvdHlwZT17CmdXYTpmdW5jdGlvbigpe3ZhciB0PXRoaXMuYQpyZXR1
-cm4gdH0sCmduZDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcwppZihwLmM9PT0xKXJldHVybiBD
-LmhVCnQ9cC5kCnM9dC5sZW5ndGgtcC5lLmxlbmd0aC1wLmYKaWYocz09PTApcmV0dXJuIEMuaFUKcj1b
-XQpmb3IocT0wO3E8czsrK3Epe2lmKHE+PXQubGVuZ3RoKXJldHVybiBILmsodCxxKQpyLnB1c2godFtx
-XSl9cmV0dXJuIEoudW4ocil9LApnVm06ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9dGhp
-cwppZihsLmMhPT0wKXJldHVybiBDLldPCnQ9bC5lCnM9dC5sZW5ndGgKcj1sLmQKcT1yLmxlbmd0aC1z
-LWwuZgppZihzPT09MClyZXR1cm4gQy5XTwpwPW5ldyBILk41KHUuZW8pCmZvcihvPTA7bzxzOysrbyl7
-aWYobz49dC5sZW5ndGgpcmV0dXJuIEguayh0LG8pCm49dFtvXQptPXErbwppZihtPDB8fG0+PXIubGVu
-Z3RoKXJldHVybiBILmsocixtKQpwLlkoMCxuZXcgSC53dihuKSxyW21dKX1yZXR1cm4gbmV3IEguUEQo
-cCx1LmdGKX0sCiRpdlE6MX0KSC5Dai5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0Ckgu
-YyhhKQp0PXRoaXMuYQp0LmI9dC5iKyIkIitILmQoYSkKQy5ObS5pKHRoaXMuYixhKQpDLk5tLmkodGhp
-cy5jLGIpOysrdC5hfSwKJFM6MTN9CkguZjkucHJvdG90eXBlPXsKcVM6ZnVuY3Rpb24oYSl7dmFyIHQs
-cyxyPXRoaXMscT1uZXcgUmVnRXhwKHIuYSkuZXhlYyhhKQppZihxPT1udWxsKXJldHVybiBudWxsCnQ9
-T2JqZWN0LmNyZWF0ZShudWxsKQpzPXIuYgppZihzIT09LTEpdC5hcmd1bWVudHM9cVtzKzFdCnM9ci5j
-CmlmKHMhPT0tMSl0LmFyZ3VtZW50c0V4cHI9cVtzKzFdCnM9ci5kCmlmKHMhPT0tMSl0LmV4cHI9cVtz
-KzFdCnM9ci5lCmlmKHMhPT0tMSl0Lm1ldGhvZD1xW3MrMV0Kcz1yLmYKaWYocyE9PS0xKXQucmVjZWl2
-ZXI9cVtzKzFdCnJldHVybiB0fX0KSC5XMC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0PXRo
-aXMuYgppZih0PT1udWxsKXJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjogIitILmQodGhpcy5hKQpyZXR1
-cm4iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK3QrIicgb24gbnVsbCJ9fQpI
-LmF6LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9Ik5vU3VjaE1ldGhvZEVy
-cm9yOiBtZXRob2Qgbm90IGZvdW5kOiAnIixxPXMuYgppZihxPT1udWxsKXJldHVybiJOb1N1Y2hNZXRo
-b2RFcnJvcjogIitILmQocy5hKQp0PXMuYwppZih0PT1udWxsKXJldHVybiByK3ErIicgKCIrSC5kKHMu
-YSkrIikiCnJldHVybiByK3ErIicgb24gJyIrdCsiJyAoIitILmQocy5hKSsiKSJ9fQpILnZWLnByb3Rv
-dHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0Lmxlbmd0aD09PTA/IkVycm9y
-IjoiRXJyb3I6ICIrdH19CkguYnEucHJvdG90eXBlPXt9CkguQW0ucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7aWYodS5XLmIoYSkpaWYoYS4kdGhyb3duSnNFcnJvcj09bnVsbClhLiR0aHJvd25Kc0Vycm9y
-PXRoaXMuYQpyZXR1cm4gYX0sCiRTOjN9CkguWE8ucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIg
-dCxzPXRoaXMuYgppZihzIT1udWxsKXJldHVybiBzCnM9dGhpcy5hCnQ9cyE9PW51bGwmJnR5cGVvZiBz
-PT09Im9iamVjdCI/cy5zdGFjazpudWxsCnJldHVybiB0aGlzLmI9dD09bnVsbD8iIjp0fSwKJGlHejox
-fQpILlRwLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jb25zdHJ1Y3RvcixzPXQ9
-PW51bGw/bnVsbDp0Lm5hbWUKcmV0dXJuIkNsb3N1cmUgJyIrSC5OUShzPT1udWxsPyJ1bmtub3duIjpz
-KSsiJyJ9LAokaUVIOjEsCmdRbDpmdW5jdGlvbigpe3JldHVybiB0aGlzfSwKJEM6IiQxIiwKJFI6MSwK
-JEQ6bnVsbH0KSC5sYy5wcm90b3R5cGU9e30KSC56eC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3Zh
-ciB0PXRoaXMuJHN0YXRpY19uYW1lCmlmKHQ9PW51bGwpcmV0dXJuIkNsb3N1cmUgb2YgdW5rbm93biBz
-dGF0aWMgbWV0aG9kIgpyZXR1cm4iQ2xvc3VyZSAnIitILk5RKHQpKyInIn19CkguankucHJvdG90eXBl
-PXsKRE46ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzCmlmKGI9PW51bGwpcmV0dXJuITEKaWYodD09PWIp
-cmV0dXJuITAKaWYoIShiIGluc3RhbmNlb2YgSC5qeSkpcmV0dXJuITEKcmV0dXJuIHQuYT09PWIuYSYm
-dC5iPT09Yi5iJiZ0LmM9PT1iLmN9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmMKaWYocz09
-bnVsbCl0PUguZVEodGhpcy5hKQplbHNlIHQ9dHlwZW9mIHMhPT0ib2JqZWN0Ij9KLmhmKHMpOkguZVEo
-cykKcmV0dXJuKHReSC5lUSh0aGlzLmIpKT4+PjB9LApaOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYwpp
-Zih0PT1udWxsKXQ9dGhpcy5hCnJldHVybiJDbG9zdXJlICciK0guZCh0aGlzLmQpKyInIG9mICIrKCJJ
-bnN0YW5jZSBvZiAnIitILmQoSC5saCh0KSkrIiciKX19CkguRXEucHJvdG90eXBlPXsKWjpmdW5jdGlv
-bihhKXtyZXR1cm4iUnVudGltZUVycm9yOiAiK0guZCh0aGlzLmEpfX0KSC5rWS5wcm90b3R5cGU9ewpa
-OmZ1bmN0aW9uKGEpe3JldHVybiJBc3NlcnRpb24gZmFpbGVkOiAiK1AuaCh0aGlzLmEpfX0KSC5ONS5w
-cm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKZ1Y6ZnVuY3Rpb24oKXtyZXR1
-cm4gbmV3IEguaTUodGhpcyxILkxoKHRoaXMpLkMoImk1PDE+IikpfSwKeDQ6ZnVuY3Rpb24oYSl7dmFy
-IHQscwppZih0eXBlb2YgYT09InN0cmluZyIpe3Q9dGhpcy5iCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0
-dXJuIHRoaXMuWHUodCxhKX1lbHNle3M9dGhpcy5DWChhKQpyZXR1cm4gc319LApDWDpmdW5jdGlvbihh
-KXt2YXIgdD10aGlzLmQKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5GaCh0aGlzLkJ0KHQs
-Si5oZihhKSYweDNmZmZmZmYpLGEpPj0wfSwKcTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhp
-cyxvPW51bGwKaWYodHlwZW9mIGI9PSJzdHJpbmciKXt0PXAuYgppZih0PT1udWxsKXJldHVybiBvCnM9
-cC5qMih0LGIpCnI9cz09bnVsbD9vOnMuYgpyZXR1cm4gcn1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVy
-IiYmKGImMHgzZmZmZmZmKT09PWIpe3E9cC5jCmlmKHE9PW51bGwpcmV0dXJuIG8Kcz1wLmoyKHEsYikK
-cj1zPT1udWxsP286cy5iCnJldHVybiByfWVsc2UgcmV0dXJuIHAuYWEoYil9LAphYTpmdW5jdGlvbihh
-KXt2YXIgdCxzLHI9dGhpcy5kCmlmKHI9PW51bGwpcmV0dXJuIG51bGwKdD10aGlzLkJ0KHIsSi5oZihh
-KSYweDNmZmZmZmYpCnM9dGhpcy5GaCh0LGEpCmlmKHM8MClyZXR1cm4gbnVsbApyZXR1cm4gdFtzXS5i
-fSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPUguTGgobikKbS5jLmEo
-YikKbS5RWzFdLmEoYykKaWYodHlwZW9mIGI9PSJzdHJpbmciKXt0PW4uYgpuLkVIKHQ9PW51bGw/bi5i
-PW4ueksoKTp0LGIsYyl9ZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciImJihiJjB4M2ZmZmZmZik9PT1i
-KXtzPW4uYwpuLkVIKHM9PW51bGw/bi5jPW4ueksoKTpzLGIsYyl9ZWxzZXtyPW4uZAppZihyPT1udWxs
-KXI9bi5kPW4ueksoKQpxPUouaGYoYikmMHgzZmZmZmZmCnA9bi5CdChyLHEpCmlmKHA9PW51bGwpbi5F
-SShyLHEsW24uSG4oYixjKV0pCmVsc2V7bz1uLkZoKHAsYikKaWYobz49MClwW29dLmI9YwplbHNlIHAu
-cHVzaChuLkhuKGIsYykpfX19LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMKSC5MaChyKS5D
-KCJ+KDEsMikiKS5hKGIpCnQ9ci5lCnM9ci5yCmZvcig7dCE9bnVsbDspe2IuJDIodC5hLHQuYikKaWYo
-cyE9PXIucil0aHJvdyBILmIoUC5hNChyKSkKdD10LmN9fSwKRUg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
-LHM9dGhpcyxyPUguTGgocykKci5jLmEoYikKci5RWzFdLmEoYykKdD1zLmoyKGEsYikKaWYodD09bnVs
-bClzLkVJKGEsYixzLkhuKGIsYykpCmVsc2UgdC5iPWN9LAprczpmdW5jdGlvbigpe3RoaXMucj10aGlz
-LnIrMSY2NzEwODg2M30sCkhuOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLHI9SC5MaChzKSxxPW5l
-dyBILmRiKHIuYy5hKGEpLHIuUVsxXS5hKGIpKQppZihzLmU9PW51bGwpcy5lPXMuZj1xCmVsc2V7dD1z
-LmYKcS5kPXQKcy5mPXQuYz1xfSsrcy5hCnMua3MoKQpyZXR1cm4gcX0sCkZoOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEou
-Uk0oYVtzXS5hLGIpKXJldHVybiBzCnJldHVybi0xfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0
-aGlzKX0sCmoyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGFbYl19LApCdDpmdW5jdGlvbihhLGIpe3JldHVy
-biBhW2JdfSwKRUk6ZnVuY3Rpb24oYSxiLGMpe2FbYl09Y30sCnJuOmZ1bmN0aW9uKGEsYil7ZGVsZXRl
-IGFbYl19LApYdTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmoyKGEsYikhPW51bGx9LAp6SzpmdW5j
-dGlvbigpe3ZhciB0PSI8bm9uLWlkZW50aWZpZXIta2V5PiIscz1PYmplY3QuY3JlYXRlKG51bGwpCnRo
-aXMuRUkocyx0LHMpCnRoaXMucm4ocyx0KQpyZXR1cm4gc30sCiRpRm86MX0KSC5kYi5wcm90b3R5cGU9
-e30KSC5pNS5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmF9LApna3o6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9dGhpcy5hLHM9bmV3IEguTjYodCx0LnIsdGhpcy4kdGkuQygiTjY8MT4iKSkK
-cy5jPXQuZQpyZXR1cm4gc319CkguTjYucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
-cy5kfSwKRjpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LmEKaWYodC5iIT09cy5yKXRocm93IEguYihQ
-LmE0KHMpKQplbHNle3M9dC5jCmlmKHM9PW51bGwpe3Quc3FZKG51bGwpCnJldHVybiExfWVsc2V7dC5z
-cVkocy5hKQp0LmM9dC5jLmMKcmV0dXJuITB9fX0sCnNxWTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4k
-dGkuYy5hKGEpfSwKJGlBbjoxfQpILnIucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
-aXMuYShhKX0sCiRTOjN9CkguZEMucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhp
-cy5hKGEsYil9LAokUzozOH0KSC53Ti5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
-cy5hKEguYyhhKSl9LAokUzozN30KSC5WUi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJS
-ZWdFeHAvIit0aGlzLmErIi8iK3RoaXMuYi5mbGFnc30sCmdIYzpmdW5jdGlvbigpe3ZhciB0PXRoaXMs
-cz10LmMKaWYocyE9bnVsbClyZXR1cm4gcwpzPXQuYgpyZXR1cm4gdC5jPUgudjQodC5hLHMubXVsdGls
-aW5lLCFzLmlnbm9yZUNhc2Uscy51bmljb2RlLHMuZG90QWxsLCEwKX0sCmRkOmZ1bmN0aW9uKGEsYil7
-cmV0dXJuIG5ldyBILktXKHRoaXMsYiwwKX0sClVaOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmdI
-YygpCnMubGFzdEluZGV4PWIKdD1zLmV4ZWMoYSkKaWYodD09bnVsbClyZXR1cm4gbnVsbApyZXR1cm4g
-bmV3IEguRUsodCl9LAokaXZYOjEsCiRpd0w6MX0KSC5FSy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQKSC5XWShiKQp0PXRoaXMuYgppZihiPj10Lmxlbmd0aClyZXR1cm4gSC5rKHQsYikKcmV0
-dXJuIHRbYl19LAokaU9kOjEsCiRpaWI6MX0KSC5LVy5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7
-cmV0dXJuIG5ldyBILlBiKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19CkguUGIucHJvdG90eXBlPXsKZ2w6
-ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcyxv
-PXAuYgppZihvPT1udWxsKXJldHVybiExCnQ9cC5jCmlmKHQ8PW8ubGVuZ3RoKXtzPXAuYQpyPXMuVVoo
-byx0KQppZihyIT1udWxsKXtwLmQ9cgpvPXIuYgp0PW8uaW5kZXgKcT10K29bMF0ubGVuZ3RoCmlmKHQ9
-PT1xKXtpZihzLmIudW5pY29kZSl7bz1wLmMKdD1vKzEKcz1wLmIKaWYodDxzLmxlbmd0aCl7bz1KLnJZ
-KHMpLm0ocyxvKQppZihvPj01NTI5NiYmbzw9NTYzMTkpe289Qy54Qi5tKHMsdCkKbz1vPj01NjMyMCYm
-bzw9NTczNDN9ZWxzZSBvPSExfWVsc2Ugbz0hMX1lbHNlIG89ITEKcT0obz9xKzE6cSkrMX1wLmM9cQpy
-ZXR1cm4hMH19cC5iPXAuZD1udWxsCnJldHVybiExfSwKJGlBbjoxfQpILnRRLnByb3RvdHlwZT17CnE6
-ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGIhPT0wKUgudmgoUC5PNyhiLG51bGwpKQpyZXR1cm4gdGhp
-cy5jfSwKJGlPZDoxfQpILk5GLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEgu
-U2QodGhpcy5hLHRoaXMuYix0aGlzLmMpfX0KSC5TZC5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFy
-IHQscyxyPXRoaXMscT1yLmMscD1yLmIsbz1wLmxlbmd0aCxuPXIuYSxtPW4ubGVuZ3RoCmlmKHErbz5t
-KXtyLmQ9bnVsbApyZXR1cm4hMX10PW4uaW5kZXhPZihwLHEpCmlmKHQ8MCl7ci5jPW0rMQpyLmQ9bnVs
-bApyZXR1cm4hMX1zPXQrbwpyLmQ9bmV3IEgudFEodCxwKQpyLmM9cz09PXIuYz9zKzE6cwpyZXR1cm4h
-MH0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCiRpQW46MX0KSC5wRi5wcm90b3R5cGU9eyRp
-cEY6MSwkaUFTOjF9CkguYjAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3Ro
-fSwKJGlYajoxfQpILkRnLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCkgub2QoYixh
-LGEubGVuZ3RoKQpyZXR1cm4gYVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe0guZGooYykKSC5vZChiLGEs
-YS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkguUGcucHJvdG90eXBlPXsK
-WTpmdW5jdGlvbihhLGIsYyl7SC5XWShjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGliUTox
-LAokaWNYOjEsCiRpek06MX0KSC54ai5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQpI
-Lm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmRFLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24o
-YSxiKXtILldZKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguWkEucHJvdG90eXBl
+b3cgSC5iKFAuTzcoYyxudWxsKSkKcmV0dXJuIGEuc3Vic3RyaW5nKGIsYyl9LAp5bjpmdW5jdGlvbihh
+LGIpe3JldHVybiB0aGlzLk5qKGEsYixudWxsKX0sCmhjOmZ1bmN0aW9uKGEpe3JldHVybiBhLnRvTG93
+ZXJDYXNlKCl9LApiUzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLnRyaW0oKSxwPXEubGVuZ3RoCmlm
+KHA9PT0wKXJldHVybiBxCmlmKHRoaXMuV2QocSwwKT09PTEzMyl7dD1KLm1tKHEsMSkKaWYodD09PXAp
+cmV0dXJuIiJ9ZWxzZSB0PTAKcz1wLTEKcj10aGlzLk8yKHEscyk9PT0xMzM/Si5jMShxLHMpOnAKaWYo
+dD09PTAmJnI9PT1wKXJldHVybiBxCnJldHVybiBxLnN1YnN0cmluZyh0LHIpfSwKSXg6ZnVuY3Rpb24o
+YSxiKXt2YXIgdCxzCmlmKDA+PWIpcmV0dXJuIiIKaWYoYj09PTF8fGEubGVuZ3RoPT09MClyZXR1cm4g
+YQppZihiIT09Yj4+PjApdGhyb3cgSC5iKEMuRXEpCmZvcih0PWEscz0iIjshMDspe2lmKChiJjEpPT09
+MSlzPXQrcwpiPWI+Pj4xCmlmKGI9PT0wKWJyZWFrCnQrPXR9cmV0dXJuIHN9LApYVTpmdW5jdGlvbihh
+LGIsYyl7dmFyIHQKaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxu
+dWxsLG51bGwpKQp0PWEuaW5kZXhPZihiLGMpCnJldHVybiB0fSwKT1k6ZnVuY3Rpb24oYSxiKXtyZXR1
+cm4gdGhpcy5YVShhLGIsMCl9LApQazpmdW5jdGlvbihhLGIsYyl7dmFyIHQscwppZihjPT1udWxsKWM9
+YS5sZW5ndGgKZWxzZSBpZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3Ro
+LG51bGwsbnVsbCkpCnQ9Yi5sZW5ndGgKcz1hLmxlbmd0aAppZihjK3Q+cyljPXMtdApyZXR1cm4gYS5s
+YXN0SW5kZXhPZihiLGMpfSwKY246ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5QayhhLGIsbnVsbCl9
+LApJczpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9YS5sZW5ndGgKaWYoYz50KXRocm93IEguYihQLlRFKGMs
+MCx0LG51bGwsbnVsbCkpCnJldHVybiBILm0yKGEsYixjKX0sCnRnOmZ1bmN0aW9uKGEsYil7cmV0dXJu
+IHRoaXMuSXMoYSxiLDApfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gYX0sCmdpOmZ1bmN0aW9uKGEpe3Zh
+ciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTAscj0wO3I8dDsrK3Ipe3M9NTM2ODcwOTExJnMrYS5jaGFy
+Q29kZUF0KHIpCnM9NTM2ODcwOTExJnMrKCg1MjQyODcmcyk8PDEwKQpzXj1zPj42fXM9NTM2ODcwOTEx
+JnMrKCg2NzEwODg2MyZzKTw8MykKc149cz4+MTEKcmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8
+PDE1KX0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZ
+KGIpCmlmKGI+PWEubGVuZ3RofHwhMSl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0sCiRp
+dlg6MSwKJGlxVToxfQpILnFqLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEu
+bGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3JldHVybiBDLnhCLk8yKHRoaXMuYSxILldZKGIpKX19Ckgu
+YlEucHJvdG90eXBlPXt9CkguYUwucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwpy
+ZXR1cm4gbmV3IEguYTcodCx0LmdrKHQpLEguTGgodCkuQygiYTc8YUwuRT4iKSl9LAp6VjpmdW5jdGlv
+bihhLGIpe3ZhciB0LHMscixxPXRoaXMscD1xLmdrKHEpCmlmKGIubGVuZ3RoIT09MCl7aWYocD09PTAp
+cmV0dXJuIiIKdD1ILmQocS5XKDAsMCkpCmlmKHAhPT1xLmdrKHEpKXRocm93IEguYihQLmE0KHEpKQpm
+b3Iocz10LHI9MTtyPHA7KytyKXtzPXMrYitILmQocS5XKDAscikpCmlmKHAhPT1xLmdrKHEpKXRocm93
+IEguYihQLmE0KHEpKX1yZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c31lbHNle2ZvcihyPTAscz0i
+IjtyPHA7KytyKXtzKz1ILmQocS5XKDAscikpCmlmKHAhPT1xLmdrKHEpKXRocm93IEguYihQLmE0KHEp
+KX1yZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c319LApldjpmdW5jdGlvbihhLGIpe3JldHVybiB0
+aGlzLkdHKDAsSC5MaCh0aGlzKS5DKCJhMihhTC5FKSIpLmEoYikpfSwKRTI6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5ldyBILmxKKHRoaXMsdC5LKGMpLkMoIjEoYUwuRSkiKS5h
+KGIpLHQuQygiQDxhTC5FPiIpLksoYykuQygibEo8MSwyPiIpKX19CkgubkgucHJvdG90eXBlPXsKZ1VE
+OmZ1bmN0aW9uKCl7dmFyIHQ9Si5IKHRoaXMuYSkscz10aGlzLmMKaWYocz09bnVsbHx8cz50KXJldHVy
+biB0CnJldHVybiBzfSwKZ0FzOmZ1bmN0aW9uKCl7dmFyIHQ9Si5IKHRoaXMuYSkscz10aGlzLmIKaWYo
+cz50KXJldHVybiB0CnJldHVybiBzfSwKZ2s6ZnVuY3Rpb24oYSl7dmFyIHQscz1KLkgodGhpcy5hKSxy
+PXRoaXMuYgppZihyPj1zKXJldHVybiAwCnQ9dGhpcy5jCmlmKHQ9PW51bGx8fHQ+PXMpcmV0dXJuIHMt
+cgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkhOKCkKcmV0dXJuIHQtcn0sClc6ZnVuY3Rp
+b24oYSxiKXt2YXIgdCxzPXRoaXMscj1zLmdBcygpK2IKaWYoYj49MCl7dD1zLmdVRCgpCmlmKHR5cGVv
+ZiB0IT09Im51bWJlciIpcmV0dXJuIEgucFkodCkKdD1yPj10fWVsc2UgdD0hMAppZih0KXRocm93IEgu
+YihQLnQoYixzLCJpbmRleCIsbnVsbCxudWxsKSkKcmV0dXJuIEouR0Eocy5hLHIpfX0KSC5hNy5wcm90
+b3R5cGU9ewpnUjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5kfSwKbTpmdW5jdGlvbigpe3ZhciB0LHM9
+dGhpcyxyPXMuYSxxPUouVTYocikscD1xLmdrKHIpCmlmKHMuYiE9PXApdGhyb3cgSC5iKFAuYTQocikp
+CnQ9cy5jCmlmKHQ+PXApe3Muc0kzKG51bGwpCnJldHVybiExfXMuc0kzKHEuVyhyLHQpKTsrK3MuYwpy
+ZXR1cm4hMH0sCnNJMzpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuYy5hKGEpfSwKJGlBbjoxfQpI
+LmkxLnByb3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5ldyBI
+Lk1IKEouSVQodGhpcy5hKSx0aGlzLmIsdC5DKCJAPDE+IikuSyh0LlFbMV0pLkMoIk1IPDEsMj4iKSl9
+LApnazpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuYSl9fQpILnh5LnByb3RvdHlwZT17JGliUTox
+fQpILk1ILnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5iCmlmKHMubSgpKXt0
+LnNJMyh0LmMuJDEocy5nUihzKSkpCnJldHVybiEwfXQuc0kzKG51bGwpCnJldHVybiExfSwKZ1I6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCnNJMzpmdW5jdGlvbihhKXt0aGlzLmE9dGhpcy4kdGkuUVsx
+XS5hKGEpfX0KSC5sSi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuYSl9
+LApXOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYi4kMShKLkdBKHRoaXMuYSxiKSl9fQpILlU1LnBy
+b3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC52RyhKLklUKHRoaXMuYSksdGhpcy5i
+LHRoaXMuJHRpLkMoInZHPDE+IikpfX0KSC52Ry5wcm90b3R5cGU9ewptOmZ1bmN0aW9uKCl7dmFyIHQs
+cwpmb3IodD10aGlzLmEscz10aGlzLmI7dC5tKCk7KWlmKEgub1Qocy4kMSh0LmdSKHQpKSkpcmV0dXJu
+ITAKcmV0dXJuITF9LApnUjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ1IodCl9fQpI
+LlNVLnByb3RvdHlwZT17fQpILlJlLnByb3RvdHlwZT17CnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikK
+SC5MaCh0aGlzKS5DKCJSZS5FIikuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSBhbiB1
+bm1vZGlmaWFibGUgbGlzdCIpKX19CkgudzIucHJvdG90eXBlPXt9Ckgud3YucHJvdG90eXBlPXsKZ2k6
+ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5faGFzaENvZGUKaWYodCE9bnVsbClyZXR1cm4gdAp0PTUzNjg3
+MDkxMSY2NjQ1OTcqSi5JKHRoaXMuYSkKdGhpcy5faGFzaENvZGU9dApyZXR1cm4gdH0sClo6ZnVuY3Rp
+b24oYSl7cmV0dXJuJ1N5bWJvbCgiJytILmQodGhpcy5hKSsnIiknfSwKRE46ZnVuY3Rpb24oYSxiKXtp
+ZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2YgSC53diYmdGhpcy5hPT1iLmF9LAok
+aUdEOjF9CkguUEQucHJvdG90eXBlPXt9CkguV1UucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1
+cm4gUC5uTyh0aGlzKX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguTGgodGhpcykKdC5jLmEoYikK
+dC5RWzFdLmEoYykKcmV0dXJuIEguZGMoKX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5xNChh
+LEguTGgodGhpcykuQygiTjM8MSwyPiIpKX0sCnE0OmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwpyZXR1
+cm4gUC5sMChmdW5jdGlvbigpe3ZhciBzPWEKdmFyIHI9MCxxPTEscCxvLG4sbQpyZXR1cm4gZnVuY3Rp
+b24gJGFzeW5jJGdQdShjLGQpe2lmKGM9PT0xKXtwPWQKcj1xfXdoaWxlKHRydWUpc3dpdGNoKHIpe2Nh
+c2UgMDpvPXQuZ3YodCksbz1vLmd3KG8pLG49SC5MaCh0KSxuPW4uQygiQDwxPiIpLksobi5RWzFdKS5D
+KCJOMzwxLDI+IikKY2FzZSAyOmlmKCFvLm0oKSl7cj0zCmJyZWFrfW09by5nUihvKQpyPTQKcmV0dXJu
+IG5ldyBQLk4zKG0sdC5xKDAsbSksbikKY2FzZSA0OnI9MgpicmVhawpjYXNlIDM6cmV0dXJuIFAuVGgo
+KQpjYXNlIDE6cmV0dXJuIFAuWW0ocCl9fX0sYil9LAokaVowOjF9CkguTFAucHJvdG90eXBlPXsKZ2s6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCng0OmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJz
+dHJpbmciKXJldHVybiExCmlmKCJfX3Byb3RvX18iPT09YilyZXR1cm4hMQpyZXR1cm4gdGhpcy5iLmhh
+c093blByb3BlcnR5KGIpfSwKcTpmdW5jdGlvbihhLGIpe2lmKCF0aGlzLng0KDAsYikpcmV0dXJuIG51
+bGwKcmV0dXJuIHRoaXMuRChiKX0sCkQ6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYltILmMoYSldfSwK
+VTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9SC5MaCh0aGlzKQpwLkMoIn4oMSwyKSIpLmEoYikK
+dD10aGlzLmMKZm9yKHM9dC5sZW5ndGgscD1wLlFbMV0scj0wO3I8czsrK3Ipe3E9dFtyXQpiLiQyKHEs
+cC5hKHRoaXMuRChxKSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5YUih0aGlzLEguTGgo
+dGhpcykuQygiWFI8MT4iKSl9fQpILlhSLnByb3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
+aXMuYS5jCnJldHVybiBuZXcgSi5tMSh0LHQubGVuZ3RoLEgudDYodCkuQygibTE8MT4iKSl9LApnazpm
+dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmMubGVuZ3RofX0KSC5MSS5wcm90b3R5cGU9ewpnV2E6ZnVu
+Y3Rpb24oKXt2YXIgdD10aGlzLmEKcmV0dXJuIHR9LApnbmQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxw
+PXRoaXMKaWYocC5jPT09MSlyZXR1cm4gQy5kbgp0PXAuZApzPXQubGVuZ3RoLXAuZS5sZW5ndGgtcC5m
+CmlmKHM9PT0wKXJldHVybiBDLmRuCnI9W10KZm9yKHE9MDtxPHM7KytxKXtpZihxPj10Lmxlbmd0aCly
+ZXR1cm4gSC5rKHQscSkKci5wdXNoKHRbcV0pfXJldHVybiBKLnVuKHIpfSwKZ1ZtOmZ1bmN0aW9uKCl7
+dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMKaWYobC5jIT09MClyZXR1cm4gQy5EeAp0PWwuZQpzPXQu
+bGVuZ3RoCnI9bC5kCnE9ci5sZW5ndGgtcy1sLmYKaWYocz09PTApcmV0dXJuIEMuRHgKcD1uZXcgSC5O
+NSh1LmVvKQpmb3Iobz0wO288czsrK28pe2lmKG8+PXQubGVuZ3RoKXJldHVybiBILmsodCxvKQpuPXRb
+b10KbT1xK28KaWYobTwwfHxtPj1yLmxlbmd0aClyZXR1cm4gSC5rKHIsbSkKcC50KDAsbmV3IEgud3Yo
+biksclttXSl9cmV0dXJuIG5ldyBILlBEKHAsdS5nRil9LAokaXZROjF9CkguQ2oucHJvdG90eXBlPXsK
+JDI6ZnVuY3Rpb24oYSxiKXt2YXIgdApILmMoYSkKdD10aGlzLmEKdC5iPXQuYisiJCIrSC5kKGEpCkMu
+Tm0uQSh0aGlzLmIsYSkKQy5ObS5BKHRoaXMuYyxiKTsrK3QuYX0sCiRTOjEzfQpILmY5LnByb3RvdHlw
+ZT17CnFTOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9bmV3IFJlZ0V4cChyLmEpLmV4ZWMoYSkK
+aWYocT09bnVsbClyZXR1cm4gbnVsbAp0PU9iamVjdC5jcmVhdGUobnVsbCkKcz1yLmIKaWYocyE9PS0x
+KXQuYXJndW1lbnRzPXFbcysxXQpzPXIuYwppZihzIT09LTEpdC5hcmd1bWVudHNFeHByPXFbcysxXQpz
+PXIuZAppZihzIT09LTEpdC5leHByPXFbcysxXQpzPXIuZQppZihzIT09LTEpdC5tZXRob2Q9cVtzKzFd
+CnM9ci5mCmlmKHMhPT0tMSl0LnJlY2VpdmVyPXFbcysxXQpyZXR1cm4gdH19CkguVzAucHJvdG90eXBl
+PXsKWjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9k
+RXJyb3I6ICIrSC5kKHRoaXMuYSkKcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qgbm90IGZv
+dW5kOiAnIit0KyInIG9uIG51bGwifX0KSC5hei5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0
+LHM9dGhpcyxyPSJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5vdCBmb3VuZDogJyIscT1zLmIKaWYo
+cT09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6ICIrSC5kKHMuYSkKdD1zLmMKaWYodD09bnVs
+bClyZXR1cm4gcitxKyInICgiK0guZChzLmEpKyIpIgpyZXR1cm4gcitxKyInIG9uICciK3QrIicgKCIr
+SC5kKHMuYSkrIikifX0KSC52Vi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpy
+ZXR1cm4gdC5sZW5ndGg9PT0wPyJFcnJvciI6IkVycm9yOiAiK3R9fQpILmJxLnByb3RvdHlwZT17fQpI
+LkFtLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe2lmKHUubS5iKGEpKWlmKGEuJHRocm93bkpzRXJy
+b3I9PW51bGwpYS4kdGhyb3duSnNFcnJvcj10aGlzLmEKcmV0dXJuIGF9LAokUzo0fQpILlhPLnByb3Rv
+dHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmIKaWYocyE9bnVsbClyZXR1cm4gcwpzPXRo
+aXMuYQp0PXMhPT1udWxsJiZ0eXBlb2Ygcz09PSJvYmplY3QiP3Muc3RhY2s6bnVsbApyZXR1cm4gdGhp
+cy5iPXQ9PW51bGw/IiI6dH0sCiRpR3o6MX0KSC5UcC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3Zh
+ciB0PXRoaXMuY29uc3RydWN0b3Iscz10PT1udWxsP251bGw6dC5uYW1lCnJldHVybiJDbG9zdXJlICci
+K0guTlEocz09bnVsbD8idW5rbm93biI6cykrIicifSwKJGlFSDoxLApnUWw6ZnVuY3Rpb24oKXtyZXR1
+cm4gdGhpc30sCiRDOiIkMSIsCiRSOjEsCiREOm51bGx9CkgubGMucHJvdG90eXBlPXt9CkguengucHJv
+dG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLiRzdGF0aWNfbmFtZQppZih0PT1udWxsKXJl
+dHVybiJDbG9zdXJlIG9mIHVua25vd24gc3RhdGljIG1ldGhvZCIKcmV0dXJuIkNsb3N1cmUgJyIrSC5O
+USh0KSsiJyJ9fQpILmp5LnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZihi
+PT1udWxsKXJldHVybiExCmlmKHQ9PT1iKXJldHVybiEwCmlmKCEoYiBpbnN0YW5jZW9mIEguankpKXJl
+dHVybiExCnJldHVybiB0LmE9PT1iLmEmJnQuYj09PWIuYiYmdC5jPT09Yi5jfSwKZ2k6ZnVuY3Rpb24o
+YSl7dmFyIHQscz10aGlzLmMKaWYocz09bnVsbCl0PUguZVEodGhpcy5hKQplbHNlIHQ9dHlwZW9mIHMh
+PT0ib2JqZWN0Ij9KLkkocyk6SC5lUShzKQpyZXR1cm4odF5ILmVRKHRoaXMuYikpPj4+MH0sClo6ZnVu
+Y3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9PW51bGwpdD10aGlzLmEKcmV0dXJuIkNsb3N1cmUgJyIr
+SC5kKHRoaXMuZCkrIicgb2YgIisoIkluc3RhbmNlIG9mICciK0guZChILmxoKHQpKSsiJyIpfX0KSC5F
+cS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSdW50aW1lRXJyb3I6ICIrSC5kKHRoaXMu
+YSl9fQpILmtZLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIkFzc2VydGlvbiBmYWlsZWQ6
+ICIrUC5oKHRoaXMuYSl9fQpILk41LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LmF9LApndjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguaTUodGhpcyxILkxoKHRoaXMpLkMoImk1PDE+
+IikpfSwKeDQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7dD10aGlz
+LmIKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5YdSh0LGIpfWVsc2V7cz10aGlzLkNYKGIp
+CnJldHVybiBzfX0sCkNYOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiEx
+CnJldHVybiB0aGlzLkYodGhpcy5IKHQsSi5JKGEpJjB4M2ZmZmZmZiksYSk+PTB9LApxOmZ1bmN0aW9u
+KGEsYil7dmFyIHQscyxyLHEscD10aGlzLG89bnVsbAppZih0eXBlb2YgYj09InN0cmluZyIpe3Q9cC5i
+CmlmKHQ9PW51bGwpcmV0dXJuIG8Kcz1wLmoodCxiKQpyPXM9PW51bGw/bzpzLmIKcmV0dXJuIHJ9ZWxz
+ZSBpZih0eXBlb2YgYj09Im51bWJlciImJihiJjB4M2ZmZmZmZik9PT1iKXtxPXAuYwppZihxPT1udWxs
+KXJldHVybiBvCnM9cC5qKHEsYikKcj1zPT1udWxsP286cy5iCnJldHVybiByfWVsc2UgcmV0dXJuIHAu
+WChiKX0sClg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMuZAppZihyPT1udWxsKXJldHVybiBudWxs
+CnQ9dGhpcy5IKHIsSi5JKGEpJjB4M2ZmZmZmZikKcz10aGlzLkYodCxhKQppZihzPDApcmV0dXJuIG51
+bGwKcmV0dXJuIHRbc10uYn0sCnQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMs
+bT1ILkxoKG4pCm0uYy5hKGIpCm0uUVsxXS5hKGMpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7dD1uLmIK
+bi51KHQ9PW51bGw/bi5iPW4ubCgpOnQsYixjKX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGIm
+MHgzZmZmZmZmKT09PWIpe3M9bi5jCm4udShzPT1udWxsP24uYz1uLmwoKTpzLGIsYyl9ZWxzZXtyPW4u
+ZAppZihyPT1udWxsKXI9bi5kPW4ubCgpCnE9Si5JKGIpJjB4M2ZmZmZmZgpwPW4uSChyLHEpCmlmKHA9
+PW51bGwpbi5FKHIscSxbbi5PKGIsYyldKQplbHNle289bi5GKHAsYikKaWYobz49MClwW29dLmI9Ywpl
+bHNlIHAucHVzaChuLk8oYixjKSl9fX0sClU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwpILkxo
+KHIpLkMoIn4oMSwyKSIpLmEoYikKdD1yLmUKcz1yLnIKZm9yKDt0IT1udWxsOyl7Yi4kMih0LmEsdC5i
+KQppZihzIT09ci5yKXRocm93IEguYihQLmE0KHIpKQp0PXQuY319LAp1OmZ1bmN0aW9uKGEsYixjKXt2
+YXIgdCxzPXRoaXMscj1ILkxoKHMpCnIuYy5hKGIpCnIuUVsxXS5hKGMpCnQ9cy5qKGEsYikKaWYodD09
+bnVsbClzLkUoYSxiLHMuTyhiLGMpKQplbHNlIHQuYj1jfSwKRzpmdW5jdGlvbigpe3RoaXMucj10aGlz
+LnIrMSY2NzEwODg2M30sCk86ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1ILkxoKHMpLHE9bmV3
+IEgudmgoci5jLmEoYSksci5RWzFdLmEoYikpCmlmKHMuZT09bnVsbClzLmU9cy5mPXEKZWxzZXt0PXMu
+ZgpxLmQ9dApzLmY9dC5jPXF9KytzLmEKcy5HKCkKcmV0dXJuIHF9LApGOmZ1bmN0aW9uKGEsYil7dmFy
+IHQscwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouUk0o
+YVtzXS5hLGIpKXJldHVybiBzCnJldHVybi0xfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlz
+KX0sCmo6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVtiXX0sCkg6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVti
+XX0sCkU6ZnVuY3Rpb24oYSxiLGMpe2FbYl09Y30sClY6ZnVuY3Rpb24oYSxiKXtkZWxldGUgYVtiXX0s
+Clh1OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuaihhLGIpIT1udWxsfSwKbDpmdW5jdGlvbigpe3Zh
+ciB0PSI8bm9uLWlkZW50aWZpZXIta2V5PiIscz1PYmplY3QuY3JlYXRlKG51bGwpCnRoaXMuRShzLHQs
+cykKdGhpcy5WKHMsdCkKcmV0dXJuIHN9LAokaUZvOjF9CkgudmgucHJvdG90eXBlPXt9CkguaTUucHJv
+dG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5hfSwKZ3c6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5hLHM9bmV3IEguTjYodCx0LnIsdGhpcy4kdGkuQygiTjY8MT4iKSkKcy5jPXQuZQpyZXR1
+cm4gc319CkguTjYucHJvdG90eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0sCm06ZnVu
+Y3Rpb24oKXt2YXIgdD10aGlzLHM9dC5hCmlmKHQuYiE9PXMucil0aHJvdyBILmIoUC5hNChzKSkKZWxz
+ZXtzPXQuYwppZihzPT1udWxsKXt0LnNNKG51bGwpCnJldHVybiExfWVsc2V7dC5zTShzLmEpCnQuYz10
+LmMuYwpyZXR1cm4hMH19fSwKc006ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmMuYShhKX0sCiRp
+QW46MX0KSC5yLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEoYSl9LAokUzo0
+fQpILmRDLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYShhLGIpfSwKJFM6
+NDV9Ckgud04ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYShILmMoYSkpfSwK
+JFM6Mjh9CkguVlIucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iUmVnRXhwLyIrdGhpcy5h
+KyIvIit0aGlzLmIuZmxhZ3N9LApnSGM6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jCmlmKHMhPW51
+bGwpcmV0dXJuIHMKcz10LmIKcmV0dXJuIHQuYz1ILnY0KHQuYSxzLm11bHRpbGluZSwhcy5pZ25vcmVD
+YXNlLHMudW5pY29kZSxzLmRvdEFsbCwhMCl9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5L
+Vyh0aGlzLGIsMCl9LApVWjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5nSGMoKQpzLmxhc3RJbmRl
+eD1iCnQ9cy5leGVjKGEpCmlmKHQ9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIG5ldyBILkVLKHQpfSwK
+JGl2WDoxLAokaXdMOjF9CkguRUsucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3ZhciB0CkguV1ko
+YikKdD10aGlzLmIKaWYoYj49dC5sZW5ndGgpcmV0dXJuIEguayh0LGIpCnJldHVybiB0W2JdfSwKJGlP
+ZDoxLAokaWliOjF9CkguS1cucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlBi
+KHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19CkguUGIucHJvdG90eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuZH0sCm06ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmIKaWYobz09bnVs
+bClyZXR1cm4hMQp0PXAuYwppZih0PD1vLmxlbmd0aCl7cz1wLmEKcj1zLlVaKG8sdCkKaWYociE9bnVs
+bCl7cC5kPXIKbz1yLmIKdD1vLmluZGV4CnE9dCtvWzBdLmxlbmd0aAppZih0PT09cSl7aWYocy5iLnVu
+aWNvZGUpe289cC5jCnQ9bysxCnM9cC5iCmlmKHQ8cy5sZW5ndGgpe289Si5yWShzKS5PMihzLG8pCmlm
+KG8+PTU1Mjk2JiZvPD01NjMxOSl7bz1DLnhCLk8yKHMsdCkKbz1vPj01NjMyMCYmbzw9NTczNDN9ZWxz
+ZSBvPSExfWVsc2Ugbz0hMX1lbHNlIG89ITEKcT0obz9xKzE6cSkrMX1wLmM9cQpyZXR1cm4hMH19cC5i
+PXAuZD1udWxsCnJldHVybiExfSwKJGlBbjoxfQpILnRRLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxi
+KXtILldZKGIpCmlmKGIhPT0wKUguVmooUC5PNyhiLG51bGwpKQpyZXR1cm4gdGhpcy5jfSwKJGlPZDox
+fQpILk5GLnByb3RvdHlwZT17Cmd3OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5TZCh0aGlzLmEsdGhp
+cy5iLHRoaXMuYyl9fQpILlNkLnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcyxx
+PXIuYyxwPXIuYixvPXAubGVuZ3RoLG49ci5hLG09bi5sZW5ndGgKaWYocStvPm0pe3IuZD1udWxsCnJl
+dHVybiExfXQ9bi5pbmRleE9mKHAscSkKaWYodDwwKXtyLmM9bSsxCnIuZD1udWxsCnJldHVybiExfXM9
+dCtvCnIuZD1uZXcgSC50USh0LHApCnIuYz1zPT09ci5jP3MrMTpzCnJldHVybiEwfSwKZ1I6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMuZH0sCiRpQW46MX0KSC5XWi5wcm90b3R5cGU9eyRpV1o6MX0KSC5wRi5w
+cm90b3R5cGU9eyRpcEY6MSwkaUFTOjF9CkguYjAucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofSwKJGlYajoxfQpILkRnLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILldZ
+KGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1ko
+YikKSC5kaihjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGliUToxLAokaUx5OjEsCiRpek06
+MX0KSC5QZy5wcm90b3R5cGU9ewp0OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCkguV1koYykKSC5vZChi
+LGEsYS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGlMeToxLAokaXpNOjF9CkgueGoucHJvdG90eXBl
 PXsKcTpmdW5jdGlvbihhLGIpe0guV1koYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0K
-SC53Zi5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkK
-cmV0dXJuIGFbYl19fQpILlBxLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCkgub2Qo
-YixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguZUUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7
-cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKSC5vZChiLGEsYS5sZW5ndGgp
-CnJldHVybiBhW2JdfX0KSC5WNi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
-dGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19
-LAokaVY2OjEsCiRpbjY6MX0KSC5SRy5wcm90b3R5cGU9e30KSC5WUC5wcm90b3R5cGU9e30KSC5XQi5w
-cm90b3R5cGU9e30KSC5aRy5wcm90b3R5cGU9e30KSC5KYy5wcm90b3R5cGU9ewpDOmZ1bmN0aW9uKGEp
-e3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLHRoaXMsYSl9LApLcTpmdW5jdGlvbihhKXtyZXR1cm4g
-SC52NSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfX0KSC5FVC5wcm90b3R5cGU9e30KSC51OS5wcm90b3R5
-cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9fQpILngucHJvdG90eXBlPXt9ClAudGgucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLHM9dC5hCnQuYT1udWxsCnMuJDAoKX0s
-CiRTOjEyfQpQLmhhLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMKdGhpcy5hLmE9dS5N
-LmEoYSkKdD10aGlzLmIKcz10aGlzLmMKdC5maXJzdENoaWxkP3QucmVtb3ZlQ2hpbGQocyk6dC5hcHBl
-bmRDaGlsZChzKX0sCiRTOjIwfQpQLlZzLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQw
-KCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLkZ0LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhp
-cy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLlczLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9u
-KGEsYil7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxsKXNlbGYuc2V0VGltZW91dChILnRSKG5ldyBQLnlI
-KHRoaXMsYiksMCksYSkKZWxzZSB0aHJvdyBILmIoUC5MNCgiYHNldFRpbWVvdXQoKWAgbm90IGZvdW5k
-LiIpKX19ClAueUgucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmIuJDAoKX0sCiRDOiIkMCIs
-CiRSOjAsCiRTOjJ9ClAuaWgucHJvdG90eXBlPXsKYU06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhp
-cy4kdGkKci5DKCIxLyIpLmEoYikKdD0hdGhpcy5ifHxyLkMoImI4PDE+IikuYihiKQpzPXRoaXMuYQpp
-Zih0KXMuWGYoYikKZWxzZSBzLlgyKHIuYy5hKGIpKX0sCncwOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYo
-Yj09bnVsbCliPVAudjAoYSkKdD10aGlzLmEKaWYodGhpcy5iKXQuWkwoYSxiKQplbHNlIHQuTmsoYSxi
-KX19ClAuV00ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS4kMigwLGEpfSwK
-JFM6NDd9ClAuU1gucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuJDIoMSxuZXcgSC5i
-cShhLHUubC5hKGIpKSl9LAokQzoiJDIiLAokUjoyLAokUzoyMX0KUC5Hcy5wcm90b3R5cGU9ewokMjpm
-dW5jdGlvbihhLGIpe3RoaXMuYShILldZKGEpLGIpfSwKJFM6MjZ9ClAuRnkucHJvdG90eXBlPXsKWjpm
-dW5jdGlvbihhKXtyZXR1cm4iSXRlcmF0aW9uTWFya2VyKCIrdGhpcy5iKyIsICIrSC5kKHRoaXMuYSkr
-IikifX0KUC5HVi5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3ZhciB0PXRoaXMuYwppZih0PT1udWxs
-KXJldHVybiB0aGlzLmIKcmV0dXJuIHRoaXMuJHRpLmMuYSh0LmdsKCkpfSwKRjpmdW5jdGlvbigpe3Zh
-ciB0LHMscixxLHA9dGhpcwpmb3IoOyEwOyl7dD1wLmMKaWYodCE9bnVsbClpZih0LkYoKSlyZXR1cm4h
-MAplbHNlIHAuYz1udWxsCnM9ZnVuY3Rpb24oYSxiLGMpe3ZhciBvLG49Ygp3aGlsZSh0cnVlKXRyeXty
-ZXR1cm4gYShuLG8pfWNhdGNoKG0pe289bQpuPWN9fShwLmEsMCwxKQppZihzIGluc3RhbmNlb2YgUC5G
-eSl7cj1zLmIKaWYocj09PTIpe3Q9cC5kCmlmKHQ9PW51bGx8fHQubGVuZ3RoPT09MCl7cC5zRUMobnVs
-bCkKcmV0dXJuITF9aWYoMD49dC5sZW5ndGgpcmV0dXJuIEguayh0LC0xKQpwLmE9dC5wb3AoKQpjb250
-aW51ZX1lbHNle3Q9cy5hCmlmKHI9PT0zKXRocm93IHQKZWxzZXtxPUouSVQodCkKaWYocSBpbnN0YW5j
-ZW9mIFAuR1Ype3Q9cC5kCmlmKHQ9PW51bGwpdD1wLmQ9W10KQy5ObS5pKHQscC5hKQpwLmE9cS5hCmNv
-bnRpbnVlfWVsc2V7cC5jPXEKY29udGludWV9fX19ZWxzZXtwLnNFQyhzKQpyZXR1cm4hMH19cmV0dXJu
-ITF9LApzRUM6ZnVuY3Rpb24oYSl7dGhpcy5iPXRoaXMuJHRpLmMuYShhKX0sCiRpQW46MX0KUC5xNC5w
-cm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkdWKHRoaXMuYSgpLHRoaXMuJHRp
+SC5kRS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkK
+cmV0dXJuIGFbYl19fQpILlpBLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCkgub2Qo
+YixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19Ckgud2YucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIp
+e0guV1koYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5QcS5wcm90b3R5cGU9ewpx
+OmZ1bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmVF
+LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxi
+KXtILldZKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguVjYucHJvdG90eXBlPXsK
+Z2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKSC5v
+ZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwKJGlWNjoxLAokaW42OjF9CkguUkcucHJvdG90eXBl
+PXt9CkguVlAucHJvdG90eXBlPXt9CkguV0IucHJvdG90eXBlPXt9CkguWkcucHJvdG90eXBlPXt9Ckgu
+SmMucHJvdG90eXBlPXsKQzpmdW5jdGlvbihhKXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0aGlz
+LGEpfSwKSzpmdW5jdGlvbihhKXtyZXR1cm4gSC52NSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfX0KSC5F
+VC5wcm90b3R5cGU9e30KSC5rUy5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9
+fQpILngucHJvdG90eXBlPXt9ClAudGgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
+cy5hLHM9dC5hCnQuYT1udWxsCnMuJDAoKX0sCiRTOjE4fQpQLmhhLnByb3RvdHlwZT17CiQxOmZ1bmN0
+aW9uKGEpe3ZhciB0LHMKdGhpcy5hLmE9dS5NLmEoYSkKdD10aGlzLmIKcz10aGlzLmMKdC5maXJzdENo
+aWxkP3QucmVtb3ZlQ2hpbGQocyk6dC5hcHBlbmRDaGlsZChzKX0sCiRTOjM5fQpQLlZzLnByb3RvdHlw
+ZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLkZ0LnBy
+b3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQ
+LlczLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEsYil7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxsKXNl
+bGYuc2V0VGltZW91dChILnRSKG5ldyBQLnlIKHRoaXMsYiksMCksYSkKZWxzZSB0aHJvdyBILmIoUC5M
+NCgiYHNldFRpbWVvdXQoKWAgbm90IGZvdW5kLiIpKX19ClAueUgucHJvdG90eXBlPXsKJDA6ZnVuY3Rp
+b24oKXt0aGlzLmIuJDAoKX0sCiRDOiIkMCIsCiRSOjAsCiRTOjJ9ClAuaWgucHJvdG90eXBlPXsKYU06
+ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcy4kdGkKci5DKCIxLyIpLmEoYikKdD0hdGhpcy5ifHxy
+LkMoImI4PDE+IikuYihiKQpzPXRoaXMuYQppZih0KXMuWGYoYikKZWxzZSBzLlgyKHIuYy5hKGIpKX0s
+CncwOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYj09bnVsbCliPVAudjAoYSkKdD10aGlzLmEKaWYodGhp
+cy5iKXQuWkwoYSxiKQplbHNlIHQuTmsoYSxiKX19ClAuV00ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuYS4kMigwLGEpfSwKJFM6MTB9ClAuU1gucHJvdG90eXBlPXsKJDI6ZnVuY3Rp
+b24oYSxiKXt0aGlzLmEuJDIoMSxuZXcgSC5icShhLHUubC5hKGIpKSl9LAokQzoiJDIiLAokUjoyLAok
+Uzo0MH0KUC5Hcy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYShILldZKGEpLGIpfSwK
+JFM6NDN9ClAuRnkucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iSXRlcmF0aW9uTWFya2Vy
+KCIrdGhpcy5iKyIsICIrSC5kKHRoaXMuYSkrIikifSwKZ253OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LmF9fQpQLkdWLnByb3RvdHlwZT17CmdSOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYwppZih0PT1udWxs
+KXJldHVybiB0aGlzLmIKcmV0dXJuIHRoaXMuJHRpLmMuYSh0LmdSKHQpKX0sCm06ZnVuY3Rpb24oKXt2
+YXIgdCxzLHIscSxwPXRoaXMKZm9yKDshMDspe3Q9cC5jCmlmKHQhPW51bGwpaWYodC5tKCkpcmV0dXJu
+ITAKZWxzZSBwLmM9bnVsbApzPWZ1bmN0aW9uKGEsYixjKXt2YXIgbyxuPWIKd2hpbGUodHJ1ZSl0cnl7
+cmV0dXJuIGEobixvKX1jYXRjaChtKXtvPW0Kbj1jfX0ocC5hLDAsMSkKaWYocyBpbnN0YW5jZW9mIFAu
+Rnkpe3I9cy5iCmlmKHI9PT0yKXt0PXAuZAppZih0PT1udWxsfHx0Lmxlbmd0aD09PTApe3Auc0VDKG51
+bGwpCnJldHVybiExfWlmKDA+PXQubGVuZ3RoKXJldHVybiBILmsodCwtMSkKcC5hPXQucG9wKCkKY29u
+dGludWV9ZWxzZXt0PXMuYQppZihyPT09Myl0aHJvdyB0CmVsc2V7cT1KLklUKHQpCmlmKHEgaW5zdGFu
+Y2VvZiBQLkdWKXt0PXAuZAppZih0PT1udWxsKXQ9cC5kPVtdCkMuTm0uQSh0LHAuYSkKcC5hPXEuYQpj
+b250aW51ZX1lbHNle3AuYz1xCmNvbnRpbnVlfX19fWVsc2V7cC5zRUMocykKcmV0dXJuITB9fXJldHVy
+biExfSwKc0VDOmZ1bmN0aW9uKGEpe3RoaXMuYj10aGlzLiR0aS5jLmEoYSl9LAokaUFuOjF9ClAucTQu
+cHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkdWKHRoaXMuYSgpLHRoaXMuJHRp
 LkMoIkdWPDE+IikpfX0KUC5iOC5wcm90b3R5cGU9e30KUC5QZi5wcm90b3R5cGU9ewp3MDpmdW5jdGlv
 bihhLGIpe3ZhciB0ClAuVUkoYSwiZXJyb3IiLHUuSykKdD10aGlzLmEKaWYodC5hIT09MCl0aHJvdyBI
 LmIoUC5QVigiRnV0dXJlIGFscmVhZHkgY29tcGxldGVkIikpCnQuTmsoYSxiPT1udWxsP1AudjAoYSk6
@@ -2394,1701 +2465,2431 @@
 CnJldHVybiB0aGlzLmIuYi5idih1LmFsLmEodGhpcy5kKSxhLmEsdS55LHUuSyl9LApLdzpmdW5jdGlv
 bihhKXt2YXIgdD10aGlzLmUscz11Lnoscj11LksscT10aGlzLiR0aS5DKCIyLyIpLHA9dGhpcy5iLmIK
 aWYodS5hZy5iKHQpKXJldHVybiBxLmEocC5ycCh0LGEuYSxhLmIscyxyLHUubCkpCmVsc2UgcmV0dXJu
-IHEuYShwLmJ2KHUuRi5hKHQpLGEuYSxzLHIpKX19ClAudnMucHJvdG90eXBlPXsKU3E6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciB0LHMscixxPXRoaXMuJHRpCnEuS3EoYykuQygiMS8oMikiKS5hKGEpCnQ9JC5YMwpp
-Zih0IT09Qy5OVSl7Yy5DKCJAPDAvPiIpLktxKHEuYykuQygiMSgyKSIpLmEoYSkKaWYoYiE9bnVsbCli
-PVAuVkgoYix0KX1zPW5ldyBQLnZzKCQuWDMsYy5DKCJ2czwwPiIpKQpyPWI9PW51bGw/MTozCnRoaXMu
-eGYobmV3IFAuRmUocyxyLGEsYixxLkMoIkA8MT4iKS5LcShjKS5DKCJGZTwxLDI+IikpKQpyZXR1cm4g
-c30sClc3OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuU3EoYSxudWxsLGIpfSwKUWQ6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciB0LHM9dGhpcy4kdGkKcy5LcShjKS5DKCIxLygyKSIpLmEoYSkKdD1uZXcgUC52cygk
-LlgzLGMuQygidnM8MD4iKSkKdGhpcy54ZihuZXcgUC5GZSh0LDE5LGEsYixzLkMoIkA8MT4iKS5LcShj
-KS5DKCJGZTwxLDI+IikpKQpyZXR1cm4gdH0sCk9BOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LmJmLmEo
-bnVsbCkKdD10aGlzLiR0aQpzPSQuWDMKcj1uZXcgUC52cyhzLHQpCmlmKHMhPT1DLk5VKWE9UC5WSChh
-LHMpCnRoaXMueGYobmV3IFAuRmUociwyLG51bGwsYSx0LkMoIkA8MT4iKS5LcSh0LmMpLkMoIkZlPDEs
-Mj4iKSkpCnJldHVybiByfSwKeGY6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9cy5hCmlmKHI8PTEp
-e2EuYT11LnguYShzLmMpCnMuYz1hfWVsc2V7aWYocj09PTIpe3Q9dS5fLmEocy5jKQpyPXQuYQppZihy
-PDQpe3QueGYoYSkKcmV0dXJufXMuYT1yCnMuYz10LmN9UC5UayhudWxsLG51bGwscy5iLHUuTS5hKG5l
-dyBQLmRhKHMsYSkpKX19LApqUTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG89dGhpcyxuPXt9Cm4u
-YT1hCmlmKGE9PW51bGwpcmV0dXJuCnQ9by5hCmlmKHQ8PTEpe3M9dS54LmEoby5jKQpyPW8uYz1hCmlm
-KHMhPW51bGwpe2Zvcig7cT1yLmEscSE9bnVsbDtyPXEpO3IuYT1zfX1lbHNle2lmKHQ9PT0yKXtwPXUu
-Xy5hKG8uYykKdD1wLmEKaWYodDw0KXtwLmpRKGEpCnJldHVybn1vLmE9dApvLmM9cC5jfW4uYT1vLk44
-KGEpClAuVGsobnVsbCxudWxsLG8uYix1Lk0uYShuZXcgUC5vUShuLG8pKSl9fSwKYWg6ZnVuY3Rpb24o
-KXt2YXIgdD11LnguYSh0aGlzLmMpCnRoaXMuYz1udWxsCnJldHVybiB0aGlzLk44KHQpfSwKTjg6ZnVu
-Y3Rpb24oYSl7dmFyIHQscyxyCmZvcih0PWEscz1udWxsO3QhPW51bGw7cz10LHQ9cil7cj10LmEKdC5h
-PXN9cmV0dXJuIHN9LApISDpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1zLiR0aQpyLkMoIjEvIiku
-YShhKQppZihyLkMoImI4PDE+IikuYihhKSlpZihyLmIoYSkpUC5BOShhLHMpCmVsc2UgUC5rMyhhLHMp
-CmVsc2V7dD1zLmFoKCkKci5jLmEoYSkKcy5hPTQKcy5jPWEKUC5IWihzLHQpfX0sClgyOmZ1bmN0aW9u
-KGEpe3ZhciB0LHM9dGhpcwpzLiR0aS5jLmEoYSkKdD1zLmFoKCkKcy5hPTQKcy5jPWEKUC5IWihzLHQp
-fSwKWkw6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwp1LmwuYShiKQp0PXIuYWgoKQpzPVAuVGwo
-YSxiKQpyLmE9OApyLmM9cwpQLkhaKHIsdCl9LApYZjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9dC4k
-dGkKcy5DKCIxLyIpLmEoYSkKaWYocy5DKCJiODwxPiIpLmIoYSkpe3QuY1UoYSkKcmV0dXJufXQuYT0x
-ClAuVGsobnVsbCxudWxsLHQuYix1Lk0uYShuZXcgUC5ySCh0LGEpKSl9LApjVTpmdW5jdGlvbihhKXt2
-YXIgdD10aGlzLHM9dC4kdGkKcy5DKCJiODwxPiIpLmEoYSkKaWYocy5iKGEpKXtpZihhLmE9PT04KXt0
-LmE9MQpQLlRrKG51bGwsbnVsbCx0LmIsdS5NLmEobmV3IFAuS0YodCxhKSkpfWVsc2UgUC5BOShhLHQp
-CnJldHVybn1QLmszKGEsdCl9LApOazpmdW5jdGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVsbCxudWxs
-LHRoaXMuYix1Lk0uYShuZXcgUC5aTCh0aGlzLGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90b3R5cGU9
-ewokMDpmdW5jdGlvbigpe1AuSFoodGhpcy5hLHRoaXMuYil9LAokUzowfQpQLm9RLnByb3RvdHlwZT17
-CiQwOmZ1bmN0aW9uKCl7UC5IWih0aGlzLmIsdGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90b3R5cGU9
-ewokMTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKdC5hPTAKdC5ISChhKX0sCiRTOjEyfQpQLlU3LnBy
-b3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dS5sLmEoYikKdGhpcy5hLlpMKGEsYil9LAokMTpmdW5j
-dGlvbihhKXtyZXR1cm4gdGhpcy4kMihhLG51bGwpfSwKJEM6IiQyIiwKJEQ6ZnVuY3Rpb24oKXtyZXR1
-cm5bbnVsbF19LAokUzozMH0KUC52ci5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0
-aGlzLmIsdGhpcy5jKX0sCiRTOjB9ClAuckgucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdD10
-aGlzLmEKdC5YMih0LiR0aS5jLmEodGhpcy5iKSl9LAokUzowfQpQLktGLnByb3RvdHlwZT17CiQwOmZ1
-bmN0aW9uKCl7UC5BOSh0aGlzLmIsdGhpcy5hKX0sCiRTOjB9ClAuWkwucHJvdG90eXBlPXsKJDA6ZnVu
-Y3Rpb24oKXt0aGlzLmEuWkwodGhpcy5iLHRoaXMuYyl9LAokUzowfQpQLlJULnByb3RvdHlwZT17CiQw
-OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPW51bGwKdHJ5e3I9bi5jCm09ci5iLmIu
-enoodS5mTy5hKHIuZCksdS56KX1jYXRjaChxKXt0PUguUnUocSkKcz1ILnRzKHEpCmlmKG4uZCl7cj11
-Lm4uYShuLmEuYS5jKS5hCnA9dApwPXI9PW51bGw/cD09bnVsbDpyPT09cApyPXB9ZWxzZSByPSExCnA9
-bi5iCmlmKHIpcC5iPXUubi5hKG4uYS5hLmMpCmVsc2UgcC5iPVAuVGwodCxzKQpwLmE9ITAKcmV0dXJu
-fWlmKHUuYy5iKG0pKXtpZihtIGluc3RhbmNlb2YgUC52cyYmbS5hPj00KXtpZihtLmE9PT04KXtyPW4u
-YgpyLmI9dS5uLmEobS5jKQpyLmE9ITB9cmV0dXJufW89bi5hLmEKcj1uLmIKci5iPW0uVzcobmV3IFAu
-aloobyksdS56KQpyLmE9ITF9fSwKJFM6Mn0KUC5qWi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5hfSwKJFM6MzN9ClAucnEucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxz
-LHIscSxwLG8sbixtPXRoaXMKdHJ5e3I9bS5iCnE9ci4kdGkKcD1xLmMKbz1wLmEobS5jKQptLmEuYj1y
-LmIuYi5idihxLkMoIjIvKDEpIikuYShyLmQpLG8scS5DKCIyLyIpLHApfWNhdGNoKG4pe3Q9SC5SdShu
-KQpzPUgudHMobikKcj1tLmEKci5iPVAuVGwodCxzKQpyLmE9ITB9fSwKJFM6Mn0KUC5SVy5wcm90b3R5
-cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10aGlzCnRyeXt0PXUubi5hKGwu
-YS5hLmMpCnE9bC5jCmlmKEgub1QocS5IUih0KSkmJnEuZSE9bnVsbCl7cD1sLmIKcC5iPXEuS3codCkK
-cC5hPSExfX1jYXRjaChvKXtzPUguUnUobykKcj1ILnRzKG8pCnE9dS5uLmEobC5hLmEuYykKcD1xLmEK
-bj1zCm09bC5iCmlmKHA9PW51bGw/bj09bnVsbDpwPT09biltLmI9cQplbHNlIG0uYj1QLlRsKHMscikK
-bS5hPSEwfX0sCiRTOjJ9ClAuT00ucHJvdG90eXBlPXt9ClAucWgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rp
-b24oYSl7dmFyIHQscyxyPXRoaXMscT17fSxwPW5ldyBQLnZzKCQuWDMsdS5mSikKcS5hPTAKdD1ILkxo
-KHIpCnM9dC5DKCJ+KDEpIikuYShuZXcgUC5CNShxLHIpKQp1Lk0uYShuZXcgUC5QSShxLHApKQpXLkpF
-KHIuYSxyLmIscywhMSx0LmMpCnJldHVybiBwfX0KUC5CNS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
-KXtILkxoKHRoaXMuYikuYy5hKGEpOysrdGhpcy5hLmF9LAokUzpmdW5jdGlvbigpe3JldHVybiBILkxo
-KHRoaXMuYikuQygiYzgoMSkiKX19ClAuUEkucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmIu
-SEgodGhpcy5hLmEpfSwKJFM6MH0KUC5NTy5wcm90b3R5cGU9e30KUC5rVC5wcm90b3R5cGU9e30KUC54
-SS5wcm90b3R5cGU9e30KUC5PSC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiBILmQodGhp
-cy5hKX0sCiRpWFM6MSwKZ0lJOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYn19ClAubTAucHJvdG90eXBl
-PXskaUpCOjF9ClAucEsucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMuYSxyPXMu
-YgppZihyPT1udWxsKXRocm93IEguYihzLmEpCnQ9SC5iKHMuYSkKdC5zdGFjaz1yLlooMCkKdGhyb3cg
-dH0sCiRTOjB9ClAuSmkucHJvdG90eXBlPXsKYkg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9bnVsbAp1
-Lk0uYShhKQp0cnl7aWYoQy5OVT09PSQuWDMpe2EuJDAoKQpyZXR1cm59UC5UOChxLHEsdGhpcyxhLHUu
-SCl9Y2F0Y2gocil7dD1ILlJ1KHIpCnM9SC50cyhyKQpQLkwyKHEscSx0aGlzLHQsdS5sLmEocykpfX0s
-CkRsOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT1udWxsCmMuQygifigwKSIpLmEoYSkKYy5hKGIp
-CnRyeXtpZihDLk5VPT09JC5YMyl7YS4kMShiKQpyZXR1cm59UC55dihxLHEsdGhpcyxhLGIsdS5ILGMp
-fWNhdGNoKHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5MMihxLHEsdGhpcyx0LHUubC5hKHMpKX19LApS
-VDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5oaih0aGlzLGIuQygiMCgpIikuYShhKSxiKX0sCkdZ
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5WcCh0aGlzLHUuTS5hKGEpKX0sClB5OmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIG5ldyBQLk9SKHRoaXMsYi5DKCJ+KDApIikuYShhKSxiKX0sCnE6ZnVuY3Rpb24oYSxi
-KXtyZXR1cm4gbnVsbH0sCnp6OmZ1bmN0aW9uKGEsYil7Yi5DKCIwKCkiKS5hKGEpCmlmKCQuWDM9PT1D
-Lk5VKXJldHVybiBhLiQwKCkKcmV0dXJuIFAuVDgobnVsbCxudWxsLHRoaXMsYSxiKX0sCmJ2OmZ1bmN0
-aW9uKGEsYixjLGQpe2MuQygiQDwwPiIpLktxKGQpLkMoIjEoMikiKS5hKGEpCmQuYShiKQppZigkLlgz
-PT09Qy5OVSlyZXR1cm4gYS4kMShiKQpyZXR1cm4gUC55dihudWxsLG51bGwsdGhpcyxhLGIsYyxkKX0s
-CnJwOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXtkLkMoIkA8MD4iKS5LcShlKS5LcShmKS5DKCIxKDIsMyki
-KS5hKGEpCmUuYShiKQpmLmEoYykKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDIoYixjKQpyZXR1cm4g
-UC5ReChudWxsLG51bGwsdGhpcyxhLGIsYyxkLGUsZil9LApMajpmdW5jdGlvbihhLGIsYyxkKXtyZXR1
-cm4gYi5DKCJAPDA+IikuS3EoYykuS3EoZCkuQygiMSgyLDMpIikuYShhKX19ClAuaGoucHJvdG90eXBl
-PXsKJDA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hLnp6KHRoaXMuYix0aGlzLmMpfSwKJFM6ZnVuY3Rp
-b24oKXtyZXR1cm4gdGhpcy5jLkMoIjAoKSIpfX0KUC5WcC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigp
-e3JldHVybiB0aGlzLmEuYkgodGhpcy5iKX0sCiRTOjJ9ClAuT1IucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcy5jCnJldHVybiB0aGlzLmEuRGwodGhpcy5iLHQuYShhKSx0KX0sCiRTOmZ1
-bmN0aW9uKCl7cmV0dXJuIHRoaXMuYy5DKCJ+KDApIil9fQpQLmI2LnByb3RvdHlwZT17CmdrejpmdW5j
-dGlvbihhKXt2YXIgdD10aGlzLHM9bmV3IFAubG0odCx0LnIsSC5MaCh0KS5DKCJsbTwxPiIpKQpzLmM9
-dC5lCnJldHVybiBzfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCnRnOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscwppZih0eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIil7dD10aGlzLmIK
-aWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdS5KLmEodFtiXSkhPW51bGx9ZWxzZXtzPXRoaXMuUFIo
-YikKcmV0dXJuIHN9fSwKUFI6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJu
-ITEKcmV0dXJuIHRoaXMuREYodFt0aGlzLk4oYSldLGEpPj0wfSwKaTpmdW5jdGlvbihhLGIpe3ZhciB0
-LHMscj10aGlzCkguTGgocikuYy5hKGIpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3Rv
-X18iKXt0PXIuYgpyZXR1cm4gci5TKHQ9PW51bGw/ci5iPVAuVDIoKTp0LGIpfWVsc2UgaWYodHlwZW9m
-IGI9PSJudW1iZXIiJiYoYiYxMDczNzQxODIzKT09PWIpe3M9ci5jCnJldHVybiByLlMocz09bnVsbD9y
-LmM9UC5UMigpOnMsYil9ZWxzZSByZXR1cm4gci5CNyhiKX0sCkI3OmZ1bmN0aW9uKGEpe3ZhciB0LHMs
-cixxPXRoaXMKSC5MaChxKS5jLmEoYSkKdD1xLmQKaWYodD09bnVsbCl0PXEuZD1QLlQyKCkKcz1xLk4o
-YSkKcj10W3NdCmlmKHI9PW51bGwpdFtzXT1bcS55byhhKV0KZWxzZXtpZihxLkRGKHIsYSk+PTApcmV0
-dXJuITEKci5wdXNoKHEueW8oYSkpfXJldHVybiEwfSwKUjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMK
-aWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpcmV0dXJuIHQuSDQodC5iLGIpCmVs
-c2UgaWYodHlwZW9mIGI9PSJudW1iZXIiJiYoYiYxMDczNzQxODIzKT09PWIpcmV0dXJuIHQuSDQodC5j
-LGIpCmVsc2UgcmV0dXJuIHQucWcoYil9LApxZzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMs
-bz1wLmQKaWYobz09bnVsbClyZXR1cm4hMQp0PXAuTihhKQpzPW9bdF0Kcj1wLkRGKHMsYSkKaWYocjww
-KXJldHVybiExCnE9cy5zcGxpY2UociwxKVswXQppZigwPT09cy5sZW5ndGgpZGVsZXRlIG9bdF0KcC5H
-UyhxKQpyZXR1cm4hMH0sClM6ZnVuY3Rpb24oYSxiKXtILkxoKHRoaXMpLmMuYShiKQppZih1LkouYShh
-W2JdKSE9bnVsbClyZXR1cm4hMQphW2JdPXRoaXMueW8oYikKcmV0dXJuITB9LApINDpmdW5jdGlvbihh
-LGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuITEKdD11LkouYShhW2JdKQppZih0PT1udWxsKXJldHVy
-biExCnRoaXMuR1ModCkKZGVsZXRlIGFbYl0KcmV0dXJuITB9LApYOmZ1bmN0aW9uKCl7dGhpcy5yPTEw
-NzM3NDE4MjMmdGhpcy5yKzF9LAp5bzpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1uZXcgUC5ibihI
-LkxoKHMpLmMuYShhKSkKaWYocy5lPT1udWxsKXMuZT1zLmY9cgplbHNle3Q9cy5mCnIuYz10CnMuZj10
-LmI9cn0rK3MuYQpzLlgoKQpyZXR1cm4gcn0sCkdTOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz1hLmMs
-cj1hLmIKaWYocz09bnVsbCl0LmU9cgplbHNlIHMuYj1yCmlmKHI9PW51bGwpdC5mPXMKZWxzZSByLmM9
-czstLXQuYQp0LlgoKX0sCk46ZnVuY3Rpb24oYSl7cmV0dXJuIEouaGYoYSkmMTA3Mzc0MTgyM30sCkRG
-OmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9
-MDtzPHQ7KytzKWlmKEouUk0oYVtzXS5hLGIpKXJldHVybiBzCnJldHVybi0xfX0KUC5ibi5wcm90b3R5
-cGU9e30KUC5sbS5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0
-aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYQppZih0LmIhPT1zLnIpdGhyb3cgSC5iKFAuYTQocykpCmVsc2V7
-cz10LmMKaWYocz09bnVsbCl7dC5zaihudWxsKQpyZXR1cm4hMX1lbHNle3Quc2oodC4kdGkuYy5hKHMu
-YSkpCnQuYz10LmMuYgpyZXR1cm4hMH19fSwKc2o6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmMu
-YShhKX0sCiRpQW46MX0KUC5tVy5wcm90b3R5cGU9e30KUC5MVS5wcm90b3R5cGU9eyRpYlE6MSwkaWNY
-OjEsJGl6TToxfQpQLmxELnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguYTco
-YSx0aGlzLmdBKGEpLEgucShhKS5DKCJhNzxsRC5FPiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
-dGhpcy5xKGEsYil9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnEoYSkuQygifihsRC5FKSIpLmEo
-YikKdD10aGlzLmdBKGEpCmZvcihzPTA7czx0Oysrcyl7Yi4kMSh0aGlzLnEoYSxzKSkKaWYodCE9PXRo
-aXMuZ0EoYSkpdGhyb3cgSC5iKFAuYTQoYSkpfX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILnEo
-YSkKcmV0dXJuIG5ldyBILmxKKGEsdC5LcShjKS5DKCIxKGxELkUpIikuYShiKSx0LkMoIkA8bEQuRT4i
-KS5LcShjKS5DKCJsSjwxLDI+IikpfSwKZHU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKSC5xKGEpLkMo
-ImxELkUiKS5hKGQpClAuakIoYixjLHRoaXMuZ0EoYSkpCmZvcih0PWI7dDxjOysrdCl0aGlzLlkoYSx0
-LGQpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gUC5XRShhLCJbIiwiXSIpfX0KUC5pbC5wcm90b3R5cGU9
-e30KUC5yYS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5hCmlmKCFzLmEp
-dGhpcy5iLmErPSIsICIKcy5hPSExCnM9dGhpcy5iCnQ9cy5hKz1ILmQoYSkKcy5hPXQrIjogIgpzLmEr
-PUguZChiKX0sCiRTOjF9ClAuWWsucHJvdG90eXBlPXsKSzpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC5M
-aCh0aGlzKS5DKCJ+KFlrLkssWWsuVikiKS5hKGIpCmZvcih0PUouSVQodGhpcy5nVigpKTt0LkYoKTsp
-e3M9dC5nbCgpCmIuJDIocyx0aGlzLnEoMCxzKSl9fSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVybiBKLk0x
-KHRoaXMuZ1YoKSxuZXcgUC55USh0aGlzKSxILkxoKHRoaXMpLkMoIk4zPFlrLkssWWsuVj4iKSl9LApn
-QTpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuZ1YoKSl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBQ
-Lm5PKHRoaXMpfSwKJGlaMDoxfQpQLnlRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRo
-aXMuYSxzPUguTGgodCkKcy5DKCJZay5LIikuYShhKQpyZXR1cm4gbmV3IFAuTjMoYSx0LnEoMCxhKSxz
-LkMoIkA8WWsuSz4iKS5LcShzLkMoIllrLlYiKSkuQygiTjM8MSwyPiIpKX0sCiRTOmZ1bmN0aW9uKCl7
-cmV0dXJuIEguTGgodGhpcy5hKS5DKCJOMzxZay5LLFlrLlY+KFlrLkspIil9fQpQLktQLnByb3RvdHlw
-ZT17Clk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguTGgodGhpcykKdC5jLmEoYikKdC5RWzFdLmEoYykK
-dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIG1hcCIpKX19ClAuUG4ucHJv
-dG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmEucSgwLGIpfSwKWTpmdW5jdGlvbihh
-LGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQp0aGlzLmEuWSgwLHQuYy5hKGIpLHQuUVsxXS5hKGMpKX0sCks6
-ZnVuY3Rpb24oYSxiKXt0aGlzLmEuSygwLEguTGgodGhpcykuQygifigxLDIpIikuYShiKSl9LApnQTpm
-dW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ0EodCl9LApaOmZ1bmN0aW9uKGEpe3JldHVy
-biBKLkFjKHRoaXMuYSl9LApnUHU6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0LmdQdSh0
-KX0sCiRpWjA6MX0KUC5Hai5wcm90b3R5cGU9e30KUC5NYS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEp
-e3JldHVybiBQLldFKHRoaXMsInsiLCJ9Iil9fQpQLlZqLnByb3RvdHlwZT17JGliUToxLCRpY1g6MSwk
-aXh1OjF9ClAuWHYucHJvdG90eXBlPXsKRlY6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD1KLklUKEgu
-TGgodGhpcykuQygiY1g8MT4iKS5hKGIpKTt0LkYoKTspdGhpcy5pKDAsdC5nbCgpKX0sClo6ZnVuY3Rp
-b24oYSl7cmV0dXJuIFAuV0UodGhpcywieyIsIn0iKX0sCnpWOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1Q
-LnJqKHRoaXMsdGhpcy5yLEguTGgodGhpcykuYykKaWYoIXMuRigpKXJldHVybiIiCmlmKGI9PT0iIil7
-dD0iIgpkbyB0Kz1ILmQocy5kKQp3aGlsZShzLkYoKSl9ZWxzZXt0PUguZChzLmQpCmZvcig7cy5GKCk7
-KXQ9dCtiK0guZChzLmQpfXJldHVybiB0LmNoYXJDb2RlQXQoMCk9PTA/dDp0fSwKJGliUToxLAokaWNY
-OjEsCiRpeHU6MX0KUC5uWS5wcm90b3R5cGU9e30KUC5UQy5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5
-cGU9e30KUC51dy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmIKaWYocz09
-bnVsbClyZXR1cm4gdGhpcy5jLnEoMCxiKQplbHNlIGlmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4g
-bnVsbAplbHNle3Q9c1tiXQpyZXR1cm4gdHlwZW9mIHQ9PSJ1bmRlZmluZWQiP3RoaXMuZmIoYik6dH19
-LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5iPT1udWxsP3RoaXMuYy5hOnRoaXMuQ2YoKS5sZW5n
-dGh9LApnVjpmdW5jdGlvbigpe2lmKHRoaXMuYj09bnVsbCl7dmFyIHQ9dGhpcy5jCnJldHVybiBuZXcg
-SC5pNSh0LEguTGgodCkuQygiaTU8MT4iKSl9cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKWTpmdW5jdGlv
-bihhLGIsYyl7dmFyIHQscyxyPXRoaXMKaWYoci5iPT1udWxsKXIuYy5ZKDAsYixjKQplbHNlIGlmKHIu
-eDQoYikpe3Q9ci5iCnRbYl09YwpzPXIuYQppZihzPT1udWxsP3QhPW51bGw6cyE9PXQpc1tiXT1udWxs
-fWVsc2Ugci5YSygpLlkoMCxiLGMpfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodGhpcy5iPT1udWxsKXJldHVy
-biB0aGlzLmMueDQoYSkKcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0
-aGlzLmEsYSl9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD10aGlzCnUuY0EuYShiKQppZihw
-LmI9PW51bGwpcmV0dXJuIHAuYy5LKDAsYikKdD1wLkNmKCkKZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7
-cj10W3NdCnE9cC5iW3JdCmlmKHR5cGVvZiBxPT0idW5kZWZpbmVkIil7cT1QLlFlKHAuYVtyXSkKcC5i
-W3JdPXF9Yi4kMihyLHEpCmlmKHQhPT1wLmMpdGhyb3cgSC5iKFAuYTQocCkpfX0sCkNmOmZ1bmN0aW9u
-KCl7dmFyIHQ9dS5qLmEodGhpcy5jKQppZih0PT1udWxsKXQ9dGhpcy5jPUguVk0oT2JqZWN0LmtleXMo
-dGhpcy5hKSx1LnMpCnJldHVybiB0fSwKWEs6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG89dGhpcwpp
-ZihvLmI9PW51bGwpcmV0dXJuIG8uYwp0PVAuRmwodS5OLHUueikKcz1vLkNmKCkKZm9yKHI9MDtxPXMu
-bGVuZ3RoLHI8cTsrK3Ipe3A9c1tyXQp0LlkoMCxwLG8ucSgwLHApKX1pZihxPT09MClDLk5tLmkocyxu
-dWxsKQplbHNlIEMuTm0uc0EocywwKQpvLmE9by5iPW51bGwKcmV0dXJuIG8uYz10fSwKZmI6ZnVuY3Rp
-b24oYSl7dmFyIHQKaWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEs
-YSkpcmV0dXJuIG51bGwKdD1QLlFlKHRoaXMuYVthXSkKcmV0dXJuIHRoaXMuYlthXT10fX0KUC5pOC5w
-cm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ0EodCl9LApFOmZ1
-bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hCmlmKHQuYj09bnVsbCl0PXQuZ1YoKS5FKDAsYikKZWxzZXt0
-PXQuQ2YoKQppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILmsodCxiKQp0PXRbYl19cmV0dXJuIHR9
-LApna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCmlmKHQuYj09bnVsbCl7dD10LmdWKCkKdD10Lmdr
-eih0KX1lbHNle3Q9dC5DZigpCnQ9bmV3IEoubTEodCx0Lmxlbmd0aCxILnQ2KHQpLkMoIm0xPDE+Iikp
-fXJldHVybiB0fX0KUC5DVi5wcm90b3R5cGU9ewp5cjpmdW5jdGlvbihhLGEwLGExKXt2YXIgdCxzLHIs
-cSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYj0iSW52YWxpZCBiYXNlNjQgZW5jb2RpbmcgbGVu
-Z3RoICIKYTE9UC5qQihhMCxhMSxhLmxlbmd0aCkKdD0kLlY3KCkKZm9yKHM9YTAscj1zLHE9bnVsbCxw
-PS0xLG89LTEsbj0wO3M8YTE7cz1tKXttPXMrMQpsPUMueEIuVyhhLHMpCmlmKGw9PT0zNyl7az1tKzIK
-aWYoazw9YTEpe2o9SC5vbyhDLnhCLlcoYSxtKSkKaT1ILm9vKEMueEIuVyhhLG0rMSkpCmg9aioxNitp
+IHEuYShwLmJ2KHUuYkkuYSh0KSxhLmEscyxyKSl9fQpQLnZzLnByb3RvdHlwZT17ClNxOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgdCxzLHIscT10aGlzLiR0aQpxLksoYykuQygiMS8oMikiKS5hKGEpCnQ9JC5YMwpp
+Zih0IT09Qy5OVSl7Yy5DKCJAPDAvPiIpLksocS5jKS5DKCIxKDIpIikuYShhKQppZihiIT1udWxsKWI9
+UC5WSChiLHQpfXM9bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnI9Yj09bnVsbD8xOjMKdGhpcy54
+ZihuZXcgUC5GZShzLHIsYSxiLHEuQygiQDwxPiIpLksoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHN9
+LApXNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNxKGEsbnVsbCxiKX0sClFkOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdCxzPXRoaXMuJHRpCnMuSyhjKS5DKCIxLygyKSIpLmEoYSkKdD1uZXcgUC52cygkLlgz
+LGMuQygidnM8MD4iKSkKdGhpcy54ZihuZXcgUC5GZSh0LDE5LGEsYixzLkMoIkA8MT4iKS5LKGMpLkMo
+IkZlPDEsMj4iKSkpCnJldHVybiB0fSwKT0E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCnUuYmYuYShudWxs
+KQp0PXRoaXMuJHRpCnM9JC5YMwpyPW5ldyBQLnZzKHMsdCkKaWYocyE9PUMuTlUpYT1QLlZIKGEscykK
+dGhpcy54ZihuZXcgUC5GZShyLDIsbnVsbCxhLHQuQygiQDwxPiIpLksodC5jKS5DKCJGZTwxLDI+Iikp
+KQpyZXR1cm4gcn0sCnhmOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPXMuYQppZihyPD0xKXthLmE9
+dS54LmEocy5jKQpzLmM9YX1lbHNle2lmKHI9PT0yKXt0PXUuXy5hKHMuYykKcj10LmEKaWYocjw0KXt0
+LnhmKGEpCnJldHVybn1zLmE9cgpzLmM9dC5jfVAuVGsobnVsbCxudWxsLHMuYix1Lk0uYShuZXcgUC5k
+YShzLGEpKSl9fSwKalE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvPXRoaXMsbj17fQpuLmE9YQpp
+ZihhPT1udWxsKXJldHVybgp0PW8uYQppZih0PD0xKXtzPXUueC5hKG8uYykKcj1vLmM9YQppZihzIT1u
+dWxsKXtmb3IoO3E9ci5hLHEhPW51bGw7cj1xKTtyLmE9c319ZWxzZXtpZih0PT09Mil7cD11Ll8uYShv
+LmMpCnQ9cC5hCmlmKHQ8NCl7cC5qUShhKQpyZXR1cm59by5hPXQKby5jPXAuY31uLmE9by5OOChhKQpQ
+LlRrKG51bGwsbnVsbCxvLmIsdS5NLmEobmV3IFAub1EobixvKSkpfX0sCmFoOmZ1bmN0aW9uKCl7dmFy
+IHQ9dS54LmEodGhpcy5jKQp0aGlzLmM9bnVsbApyZXR1cm4gdGhpcy5OOCh0KX0sCk44OmZ1bmN0aW9u
+KGEpe3ZhciB0LHMscgpmb3IodD1hLHM9bnVsbDt0IT1udWxsO3M9dCx0PXIpe3I9dC5hCnQuYT1zfXJl
+dHVybiBzfSwKSEg6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9cy4kdGkKci5DKCIxLyIpLmEoYSkK
+aWYoci5DKCJiODwxPiIpLmIoYSkpaWYoci5iKGEpKVAuQTkoYSxzKQplbHNlIFAuazMoYSxzKQplbHNl
+e3Q9cy5haCgpCnIuYy5hKGEpCnMuYT00CnMuYz1hClAuSFoocyx0KX19LApYMjpmdW5jdGlvbihhKXt2
+YXIgdCxzPXRoaXMKcy4kdGkuYy5hKGEpCnQ9cy5haCgpCnMuYT00CnMuYz1hClAuSFoocyx0KX0sClpM
+OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMKdS5sLmEoYikKdD1yLmFoKCkKcz1QLlRsKGEsYikK
+ci5hPTgKci5jPXMKUC5IWihyLHQpfSwKWGY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPXQuJHRpCnMu
+QygiMS8iKS5hKGEpCmlmKHMuQygiYjg8MT4iKS5iKGEpKXt0LmNVKGEpCnJldHVybn10LmE9MQpQLlRr
+KG51bGwsbnVsbCx0LmIsdS5NLmEobmV3IFAuckgodCxhKSkpfSwKY1U6ZnVuY3Rpb24oYSl7dmFyIHQ9
+dGhpcyxzPXQuJHRpCnMuQygiYjg8MT4iKS5hKGEpCmlmKHMuYihhKSl7aWYoYS5hPT09OCl7dC5hPTEK
+UC5UayhudWxsLG51bGwsdC5iLHUuTS5hKG5ldyBQLktGKHQsYSkpKX1lbHNlIFAuQTkoYSx0KQpyZXR1
+cm59UC5rMyhhLHQpfSwKTms6ZnVuY3Rpb24oYSxiKXt0aGlzLmE9MQpQLlRrKG51bGwsbnVsbCx0aGlz
+LmIsdS5NLmEobmV3IFAuWkwodGhpcyxhLGIpKSl9LAokaWI4OjF9ClAuZGEucHJvdG90eXBlPXsKJDA6
+ZnVuY3Rpb24oKXtQLkhaKHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0KUC5vUS5wcm90b3R5cGU9ewokMDpm
+dW5jdGlvbigpe1AuSFoodGhpcy5iLHRoaXMuYS5hKX0sCiRTOjB9ClAucFYucHJvdG90eXBlPXsKJDE6
+ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnQuYT0wCnQuSEgoYSl9LAokUzoxOH0KUC5VNy5wcm90b3R5
+cGU9ewokMjpmdW5jdGlvbihhLGIpe3UubC5hKGIpCnRoaXMuYS5aTChhLGIpfSwKJDE6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuJDIoYSxudWxsKX0sCiRDOiIkMiIsCiREOmZ1bmN0aW9uKCl7cmV0dXJuW251
+bGxdfSwKJFM6MjZ9ClAudnIucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwodGhpcy5i
+LHRoaXMuYyl9LAokUzowfQpQLnJILnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5h
+CnQuWDIodC4kdGkuYy5hKHRoaXMuYikpfSwKJFM6MH0KUC5LRi5wcm90b3R5cGU9ewokMDpmdW5jdGlv
+bigpe1AuQTkodGhpcy5iLHRoaXMuYSl9LAokUzowfQpQLlpMLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
+KCl7dGhpcy5hLlpMKHRoaXMuYix0aGlzLmMpfSwKJFM6MH0KUC5SVC5wcm90b3R5cGU9ewokMDpmdW5j
+dGlvbigpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMsbT1udWxsCnRyeXtyPW4uYwptPXIuYi5iLnp6KHUu
+Zk8uYShyLmQpLHUueil9Y2F0Y2gocSl7dD1ILlJ1KHEpCnM9SC50cyhxKQppZihuLmQpe3I9dS5uLmEo
+bi5hLmEuYykuYQpwPXQKcD1yPT1udWxsP3A9PW51bGw6cj09PXAKcj1wfWVsc2Ugcj0hMQpwPW4uYgpp
+ZihyKXAuYj11Lm4uYShuLmEuYS5jKQplbHNlIHAuYj1QLlRsKHQscykKcC5hPSEwCnJldHVybn1pZih1
+LmMuYihtKSl7aWYobSBpbnN0YW5jZW9mIFAudnMmJm0uYT49NCl7aWYobS5hPT09OCl7cj1uLmIKci5i
+PXUubi5hKG0uYykKci5hPSEwfXJldHVybn1vPW4uYS5hCnI9bi5iCnIuYj1tLlc3KG5ldyBQLmpaKG8p
+LHUueikKci5hPSExfX0sCiRTOjJ9ClAualoucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
+IHRoaXMuYX0sCiRTOjMwfQpQLnJxLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEs
+cCxvLG4sbT10aGlzCnRyeXtyPW0uYgpxPXIuJHRpCnA9cS5jCm89cC5hKG0uYykKbS5hLmI9ci5iLmIu
+YnYocS5DKCIyLygxKSIpLmEoci5kKSxvLHEuQygiMi8iKSxwKX1jYXRjaChuKXt0PUguUnUobikKcz1I
+LnRzKG4pCnI9bS5hCnIuYj1QLlRsKHQscykKci5hPSEwfX0sCiRTOjJ9ClAuUlcucHJvdG90eXBlPXsK
+JDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9dGhpcwp0cnl7dD11Lm4uYShsLmEuYS5j
+KQpxPWwuYwppZihILm9UKHEuSFIodCkpJiZxLmUhPW51bGwpe3A9bC5iCnAuYj1xLkt3KHQpCnAuYT0h
+MX19Y2F0Y2gobyl7cz1ILlJ1KG8pCnI9SC50cyhvKQpxPXUubi5hKGwuYS5hLmMpCnA9cS5hCm49cwpt
+PWwuYgppZihwPT1udWxsP249PW51bGw6cD09PW4pbS5iPXEKZWxzZSBtLmI9UC5UbChzLHIpCm0uYT0h
+MH19LAokUzoyfQpQLk9NLnByb3RvdHlwZT17fQpQLnFoLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEp
+e3ZhciB0LHMscj10aGlzLHE9e30scD1uZXcgUC52cygkLlgzLHUuZkopCnEuYT0wCnQ9SC5MaChyKQpz
+PXQuQygifigxKSIpLmEobmV3IFAuQjUocSxyKSkKdS5NLmEobmV3IFAuUEkocSxwKSkKVy5KRShyLmEs
+ci5iLHMsITEsdC5jKQpyZXR1cm4gcH19ClAuQjUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC5M
+aCh0aGlzLmIpLmMuYShhKTsrK3RoaXMuYS5hfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4gSC5MaCh0aGlz
+LmIpLkMoImM4KDEpIil9fQpQLlBJLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5iLkhIKHRo
+aXMuYS5hKX0sCiRTOjB9ClAuTU8ucHJvdG90eXBlPXt9ClAua1QucHJvdG90eXBlPXt9ClAueEkucHJv
+dG90eXBlPXt9ClAuT0gucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gSC5kKHRoaXMuYSl9
+LAokaVhTOjEsCmdJSTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJ9fQpQLm0wLnByb3RvdHlwZT17JGlK
+QjoxfQpQLnBLLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLmEscj1zLmIKaWYo
+cj09bnVsbCl0aHJvdyBILmIocy5hKQp0PUguYihzLmEpCnQuc3RhY2s9ci5aKDApCnRocm93IHR9LAok
+UzowfQpQLkppLnByb3RvdHlwZT17CmJIOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPW51bGwKdS5NLmEo
+YSkKdHJ5e2lmKEMuTlU9PT0kLlgzKXthLiQwKCkKcmV0dXJufVAuVDgocSxxLHRoaXMsYSx1LkgpfWNh
+dGNoKHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5MMihxLHEsdGhpcyx0LHUubC5hKHMpKX19LApEbDpm
+dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9bnVsbApjLkMoIn4oMCkiKS5hKGEpCmMuYShiKQp0cnl7
+aWYoQy5OVT09PSQuWDMpe2EuJDEoYikKcmV0dXJufVAueXYocSxxLHRoaXMsYSxiLHUuSCxjKX1jYXRj
+aChyKXt0PUguUnUocikKcz1ILnRzKHIpClAuTDIocSxxLHRoaXMsdCx1LmwuYShzKSl9fSwKUlQ6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuaGoodGhpcyxiLkMoIjAoKSIpLmEoYSksYil9LApHWTpmdW5j
+dGlvbihhKXtyZXR1cm4gbmV3IFAuVnAodGhpcyx1Lk0uYShhKSl9LApQeTpmdW5jdGlvbihhLGIpe3Jl
+dHVybiBuZXcgUC5PUih0aGlzLGIuQygifigwKSIpLmEoYSksYil9LApxOmZ1bmN0aW9uKGEsYil7cmV0
+dXJuIG51bGx9LAp6ejpmdW5jdGlvbihhLGIpe2IuQygiMCgpIikuYShhKQppZigkLlgzPT09Qy5OVSly
+ZXR1cm4gYS4kMCgpCnJldHVybiBQLlQ4KG51bGwsbnVsbCx0aGlzLGEsYil9LApidjpmdW5jdGlvbihh
+LGIsYyxkKXtjLkMoIkA8MD4iKS5LKGQpLkMoIjEoMikiKS5hKGEpCmQuYShiKQppZigkLlgzPT09Qy5O
+VSlyZXR1cm4gYS4kMShiKQpyZXR1cm4gUC55dihudWxsLG51bGwsdGhpcyxhLGIsYyxkKX0sCnJwOmZ1
+bmN0aW9uKGEsYixjLGQsZSxmKXtkLkMoIkA8MD4iKS5LKGUpLksoZikuQygiMSgyLDMpIikuYShhKQpl
+LmEoYikKZi5hKGMpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBhLiQyKGIsYykKcmV0dXJuIFAuUXgobnVs
+bCxudWxsLHRoaXMsYSxiLGMsZCxlLGYpfSwKTGo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGIuQygi
+QDwwPiIpLksoYykuSyhkKS5DKCIxKDIsMykiKS5hKGEpfX0KUC5oai5wcm90b3R5cGU9ewokMDpmdW5j
+dGlvbigpe3JldHVybiB0aGlzLmEuenoodGhpcy5iLHRoaXMuYyl9LAokUzpmdW5jdGlvbigpe3JldHVy
+biB0aGlzLmMuQygiMCgpIil9fQpQLlZwLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7cmV0dXJuIHRo
+aXMuYS5iSCh0aGlzLmIpfSwKJFM6Mn0KUC5PUi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
+dD10aGlzLmMKcmV0dXJuIHRoaXMuYS5EbCh0aGlzLmIsdC5hKGEpLHQpfSwKJFM6ZnVuY3Rpb24oKXty
+ZXR1cm4gdGhpcy5jLkMoIn4oMCkiKX19ClAuYjYucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcyxzPW5ldyBQLmxtKHQsdC5yLEguTGgodCkuQygibG08MT4iKSkKcy5jPXQuZQpyZXR1cm4g
+c30sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciB0LHMK
+aWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3Q9dGhpcy5iCmlmKHQ9PW51bGwp
+cmV0dXJuITEKcmV0dXJuIHUuSi5hKHRbYl0pIT1udWxsfWVsc2V7cz10aGlzLlBSKGIpCnJldHVybiBz
+fX0sClBSOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiExCnJldHVybiB0
+aGlzLkRGKHRbdGhpcy5yayhhKV0sYSk+PTB9LApBOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMK
+SC5MaChyKS5jLmEoYikKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3Q9ci5i
+CnJldHVybiByLmNXKHQ9PW51bGw/ci5iPVAuVDIoKTp0LGIpfWVsc2UgaWYodHlwZW9mIGI9PSJudW1i
+ZXIiJiYoYiYxMDczNzQxODIzKT09PWIpe3M9ci5jCnJldHVybiByLmNXKHM9PW51bGw/ci5jPVAuVDIo
+KTpzLGIpfWVsc2UgcmV0dXJuIHIuQjcoMCxiKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHE9
+dGhpcwpILkxoKHEpLmMuYShiKQp0PXEuZAppZih0PT1udWxsKXQ9cS5kPVAuVDIoKQpzPXEucmsoYikK
+cj10W3NdCmlmKHI9PW51bGwpdFtzXT1bcS5kZyhiKV0KZWxzZXtpZihxLkRGKHIsYik+PTApcmV0dXJu
+ITEKci5wdXNoKHEuZGcoYikpfXJldHVybiEwfSwKUno6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzCmlm
+KHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXJldHVybiB0Lkg0KHQuYixiKQplbHNl
+IGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1iKXJldHVybiB0Lkg0KHQuYyxi
+KQplbHNlIHJldHVybiB0LnFnKDAsYil9LApxZzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhp
+cyxvPXAuZAppZihvPT1udWxsKXJldHVybiExCnQ9cC5yayhiKQpzPW9bdF0Kcj1wLkRGKHMsYikKaWYo
+cjwwKXJldHVybiExCnE9cy5zcGxpY2UociwxKVswXQppZigwPT09cy5sZW5ndGgpZGVsZXRlIG9bdF0K
+cC5HUyhxKQpyZXR1cm4hMH0sCmNXOmZ1bmN0aW9uKGEsYil7SC5MaCh0aGlzKS5jLmEoYikKaWYodS5K
+LmEoYVtiXSkhPW51bGwpcmV0dXJuITEKYVtiXT10aGlzLmRnKGIpCnJldHVybiEwfSwKSDQ6ZnVuY3Rp
+b24oYSxiKXt2YXIgdAppZihhPT1udWxsKXJldHVybiExCnQ9dS5KLmEoYVtiXSkKaWYodD09bnVsbCly
+ZXR1cm4hMQp0aGlzLkdTKHQpCmRlbGV0ZSBhW2JdCnJldHVybiEwfSwKWEE6ZnVuY3Rpb24oKXt0aGlz
+LnI9MTA3Mzc0MTgyMyZ0aGlzLnIrMX0sCmRnOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPW5ldyBQ
+LmJuKEguTGgocykuYy5hKGEpKQppZihzLmU9PW51bGwpcy5lPXMuZj1yCmVsc2V7dD1zLmYKci5jPXQK
+cy5mPXQuYj1yfSsrcy5hCnMuWEEoKQpyZXR1cm4gcn0sCkdTOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMs
+cz1hLmMscj1hLmIKaWYocz09bnVsbCl0LmU9cgplbHNlIHMuYj1yCmlmKHI9PW51bGwpdC5mPXMKZWxz
+ZSByLmM9czstLXQuYQp0LlhBKCl9LApyazpmdW5jdGlvbihhKXtyZXR1cm4gSi5JKGEpJjEwNzM3NDE4
+MjN9LApERjpmdW5jdGlvbihhLGIpe3ZhciB0LHMKaWYoYT09bnVsbClyZXR1cm4tMQp0PWEubGVuZ3Ro
+CmZvcihzPTA7czx0OysrcylpZihKLlJNKGFbc10uYSxiKSlyZXR1cm4gcwpyZXR1cm4tMX19ClAuYm4u
+cHJvdG90eXBlPXt9ClAubG0ucHJvdG90eXBlPXsKZ1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0s
+Cm06ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5hCmlmKHQuYiE9PXMucil0aHJvdyBILmIoUC5hNChz
+KSkKZWxzZXtzPXQuYwppZihzPT1udWxsKXt0LnNCYihudWxsKQpyZXR1cm4hMX1lbHNle3Quc0JiKHQu
+JHRpLmMuYShzLmEpKQp0LmM9dC5jLmIKcmV0dXJuITB9fX0sCnNCYjpmdW5jdGlvbihhKXt0aGlzLmQ9
+dGhpcy4kdGkuYy5hKGEpfSwKJGlBbjoxfQpQLm1XLnByb3RvdHlwZT17fQpQLkxVLnByb3RvdHlwZT17
+JGliUToxLCRpTHk6MSwkaXpNOjF9ClAubEQucHJvdG90eXBlPXsKZ3c6ZnVuY3Rpb24oYSl7cmV0dXJu
+IG5ldyBILmE3KGEsdGhpcy5nayhhKSxILnEoYSkuQygiYTc8bEQuRT4iKSl9LApXOmZ1bmN0aW9uKGEs
+Yil7cmV0dXJuIHRoaXMucShhLGIpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC5xKGEpLkMoIn4o
+bEQuRSkiKS5hKGIpCnQ9dGhpcy5nayhhKQpmb3Iocz0wO3M8dDsrK3Mpe2IuJDEodGhpcy5xKGEscykp
+CmlmKHQhPT10aGlzLmdrKGEpKXRocm93IEguYihQLmE0KGEpKX19LApFMjpmdW5jdGlvbihhLGIsYyl7
+dmFyIHQ9SC5xKGEpCnJldHVybiBuZXcgSC5sSihhLHQuSyhjKS5DKCIxKGxELkUpIikuYShiKSx0LkMo
+IkA8bEQuRT4iKS5LKGMpLkMoImxKPDEsMj4iKSl9LApkdTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdApI
+LnEoYSkuQygibEQuRSIpLmEoZCkKUC5qQihiLGMsdGhpcy5nayhhKSkKZm9yKHQ9Yjt0PGM7Kyt0KXRo
+aXMudChhLHQsZCl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJdIil9fQpQLmlsLnBy
+b3RvdHlwZT17fQpQLnJhLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmEK
+aWYoIXMuYSl0aGlzLmIuYSs9IiwgIgpzLmE9ITEKcz10aGlzLmIKdD1zLmErPUguZChhKQpzLmE9dCsi
+OiAiCnMuYSs9SC5kKGIpfSwKJFM6MX0KUC5Zay5wcm90b3R5cGU9ewpVOmZ1bmN0aW9uKGEsYil7dmFy
+IHQscwpILnEoYSkuQygifihZay5LLFlrLlYpIikuYShiKQpmb3IodD1KLklUKHRoaXMuZ3YoYSkpO3Qu
+bSgpOyl7cz10LmdSKHQpCmIuJDIocyx0aGlzLnEoYSxzKSl9fSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVy
+biBKLk0xKHRoaXMuZ3YoYSksbmV3IFAueVEoYSksSC5xKGEpLkMoIk4zPFlrLkssWWsuVj4iKSl9LApn
+azpmdW5jdGlvbihhKXtyZXR1cm4gSi5IKHRoaXMuZ3YoYSkpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4g
+UC5uTyhhKX0sCiRpWjA6MX0KUC55US5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LmEscz1ILnEodCkKcy5DKCJZay5LIikuYShhKQpyZXR1cm4gbmV3IFAuTjMoYSxKLng5KHQsYSkscy5D
+KCJAPFlrLks+IikuSyhzLkMoIllrLlYiKSkuQygiTjM8MSwyPiIpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0
+dXJuIEgucSh0aGlzLmEpLkMoIk4zPFlrLkssWWsuVj4oWWsuSykiKX19ClAuS1AucHJvdG90eXBlPXsK
+dDpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQp0LmMuYShiKQp0LlFbMV0uYShjKQp0aHJv
+dyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFibGUgbWFwIikpfX0KUC5Qbi5wcm90b3R5
+cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEoueDkodGhpcy5hLGIpfSwKdDpmdW5jdGlvbihhLGIs
+Yyl7dmFyIHQ9SC5MaCh0aGlzKQpKLnU5KHRoaXMuYSx0LmMuYShiKSx0LlFbMV0uYShjKSl9LApVOmZ1
+bmN0aW9uKGEsYil7Si5oRSh0aGlzLmEsSC5MaCh0aGlzKS5DKCJ+KDEsMikiKS5hKGIpKX0sCmdrOmZ1
+bmN0aW9uKGEpe3JldHVybiBKLkgodGhpcy5hKX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIEouQWModGhp
+cy5hKX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gSi5RTSh0aGlzLmEpfSwKJGlaMDoxfQpQLkdqLnBy
+b3RvdHlwZT17fQpQLk1hLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UodGhpcywi
+eyIsIn0iKX19ClAuUksucHJvdG90eXBlPXskaWJROjEsJGlMeToxLCRpeHU6MX0KUC5Ydi5wcm90b3R5
+cGU9ewpGVjpmdW5jdGlvbihhLGIpe3ZhciB0CmZvcih0PUouSVQoSC5MaCh0aGlzKS5DKCJMeTwxPiIp
+LmEoYikpO3QubSgpOyl0aGlzLkEoMCx0LmdSKHQpKX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0Uo
+dGhpcywieyIsIn0iKX0sCnpWOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1QLnJqKHRoaXMsdGhpcy5yLEgu
+TGgodGhpcykuYykKaWYoIXMubSgpKXJldHVybiIiCmlmKGI9PT0iIil7dD0iIgpkbyB0Kz1ILmQocy5k
+KQp3aGlsZShzLm0oKSl9ZWxzZXt0PUguZChzLmQpCmZvcig7cy5tKCk7KXQ9dCtiK0guZChzLmQpfXJl
+dHVybiB0LmNoYXJDb2RlQXQoMCk9PTA/dDp0fSwKJGliUToxLAokaUx5OjEsCiRpeHU6MX0KUC5uWS5w
+cm90b3R5cGU9e30KUC5Mai5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5cGU9e30KUC51dy5wcm90b3R5
+cGU9ewpxOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4gdGhpcy5j
+LnEoMCxiKQplbHNlIGlmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4gbnVsbAplbHNle3Q9c1tiXQpy
+ZXR1cm4gdHlwZW9mIHQ9PSJ1bmRlZmluZWQiP3RoaXMuZmIoYik6dH19LApnazpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5iPT1udWxsP3RoaXMuYy5hOnRoaXMuQ2YoKS5sZW5ndGh9LApndjpmdW5jdGlvbihh
+KXt2YXIgdAppZih0aGlzLmI9PW51bGwpe3Q9dGhpcy5jCnJldHVybiBuZXcgSC5pNSh0LEguTGgodCku
+QygiaTU8MT4iKSl9cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKdDpmdW5jdGlvbihhLGIsYyl7dmFyIHQs
+cyxyPXRoaXMKaWYoci5iPT1udWxsKXIuYy50KDAsYixjKQplbHNlIGlmKHIueDQoMCxiKSl7dD1yLmIK
+dFtiXT1jCnM9ci5hCmlmKHM9PW51bGw/dCE9bnVsbDpzIT09dClzW2JdPW51bGx9ZWxzZSByLlhLKCku
+dCgwLGIsYyl9LAp4NDpmdW5jdGlvbihhLGIpe2lmKHRoaXMuYj09bnVsbClyZXR1cm4gdGhpcy5jLng0
+KDAsYikKcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYil9
+LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD10aGlzCnUuVC5hKGIpCmlmKHAuYj09bnVsbCly
+ZXR1cm4gcC5jLlUoMCxiKQp0PXAuQ2YoKQpmb3Iocz0wO3M8dC5sZW5ndGg7KytzKXtyPXRbc10KcT1w
+LmJbcl0KaWYodHlwZW9mIHE9PSJ1bmRlZmluZWQiKXtxPVAuUWUocC5hW3JdKQpwLmJbcl09cX1iLiQy
+KHIscSkKaWYodCE9PXAuYyl0aHJvdyBILmIoUC5hNChwKSl9fSwKQ2Y6ZnVuY3Rpb24oKXt2YXIgdD11
+LmouYSh0aGlzLmMpCmlmKHQ9PW51bGwpdD10aGlzLmM9SC5WTShPYmplY3Qua2V5cyh0aGlzLmEpLHUu
+cykKcmV0dXJuIHR9LApYSzpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbz10aGlzCmlmKG8uYj09bnVs
+bClyZXR1cm4gby5jCnQ9UC5GbCh1Lk4sdS56KQpzPW8uQ2YoKQpmb3Iocj0wO3E9cy5sZW5ndGgscjxx
+Oysrcil7cD1zW3JdCnQudCgwLHAsby5xKDAscCkpfWlmKHE9PT0wKUMuTm0uQShzLG51bGwpCmVsc2Ug
+Qy5ObS5zayhzLDApCm8uYT1vLmI9bnVsbApyZXR1cm4gby5jPXR9LApmYjpmdW5jdGlvbihhKXt2YXIg
+dAppZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMuYSxhKSlyZXR1cm4g
+bnVsbAp0PVAuUWUodGhpcy5hW2FdKQpyZXR1cm4gdGhpcy5iW2FdPXR9fQpQLmk4LnByb3RvdHlwZT17
+CmdrOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4gdC5nayh0KX0sClc6ZnVuY3Rpb24oYSxi
+KXt2YXIgdD10aGlzLmEKaWYodC5iPT1udWxsKXQ9dC5ndih0KS5XKDAsYikKZWxzZXt0PXQuQ2YoKQpp
+ZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILmsodCxiKQp0PXRbYl19cmV0dXJuIHR9LApndzpmdW5j
+dGlvbihhKXt2YXIgdD10aGlzLmEKaWYodC5iPT1udWxsKXt0PXQuZ3YodCkKdD10Lmd3KHQpfWVsc2V7
+dD10LkNmKCkKdD1uZXcgSi5tMSh0LHQubGVuZ3RoLEgudDYodCkuQygibTE8MT4iKSl9cmV0dXJuIHR9
+fQpQLkNWLnByb3RvdHlwZT17CnlyOmZ1bmN0aW9uKGEsYTAsYTEsYTIpe3ZhciB0LHMscixxLHAsbyxu
+LG0sbCxrLGosaSxoLGcsZixlLGQsYyxiPSJJbnZhbGlkIGJhc2U2NCBlbmNvZGluZyBsZW5ndGggIgph
+Mj1QLmpCKGExLGEyLGEwLmxlbmd0aCkKdD0kLlY3KCkKZm9yKHM9YTEscj1zLHE9bnVsbCxwPS0xLG89
+LTEsbj0wO3M8YTI7cz1tKXttPXMrMQpsPUMueEIuV2QoYTAscykKaWYobD09PTM3KXtrPW0rMgppZihr
+PD1hMil7aj1ILm9vKEMueEIuV2QoYTAsbSkpCmk9SC5vbyhDLnhCLldkKGEwLG0rMSkpCmg9aioxNitp
 LShpJjI1NikKaWYoaD09PTM3KWg9LTEKbT1rfWVsc2UgaD0tMX1lbHNlIGg9bAppZigwPD1oJiZoPD0x
 Mjcpe2lmKGg8MHx8aD49dC5sZW5ndGgpcmV0dXJuIEguayh0LGgpCmc9dFtoXQppZihnPj0wKXtoPUMu
-eEIubSgiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAx
-MjM0NTY3ODkrLyIsZykKaWYoaD09PWwpY29udGludWUKbD1ofWVsc2V7aWYoZz09PS0xKXtpZihwPDAp
-e2Y9cT09bnVsbD9udWxsOnEuYS5sZW5ndGgKaWYoZj09bnVsbClmPTAKcD1mKyhzLXIpCm89c30rK24K
-aWYobD09PTYxKWNvbnRpbnVlfWw9aH1pZihnIT09LTIpe2lmKHE9PW51bGwpcT1uZXcgUC5SbigiIikK
-cS5hKz1DLnhCLncoYSxyLHMpCnEuYSs9SC5MdyhsKQpyPW0KY29udGludWV9fXRocm93IEguYihQLnJy
-KCJJbnZhbGlkIGJhc2U2NCBkYXRhIixhLHMpKX1pZihxIT1udWxsKXtmPXEuYSs9Qy54Qi53KGEscixh
-MSkKZT1mLmxlbmd0aAppZihwPj0wKVAueE0oYSxvLGExLHAsbixlKQplbHNle2Q9Qy5qbi56WShlLTEs
-NCkrMQppZihkPT09MSl0aHJvdyBILmIoUC5ycihiLGEsYTEpKQpmb3IoO2Q8NDspe2YrPSI9IgpxLmE9
-ZjsrK2R9fWY9cS5hCnJldHVybiBDLnhCLmk3KGEsYTAsYTEsZi5jaGFyQ29kZUF0KDApPT0wP2Y6Zil9
-Yz1hMS1hMAppZihwPj0wKVAueE0oYSxvLGExLHAsbixjKQplbHNle2Q9Qy5qbi56WShjLDQpCmlmKGQ9
-PT0xKXRocm93IEguYihQLnJyKGIsYSxhMSkpCmlmKGQ+MSlhPUMueEIuaTcoYSxhMSxhMSxkPT09Mj8i
-PT0iOiI9Iil9cmV0dXJuIGF9fQpQLlU4LnByb3RvdHlwZT17fQpQLlVrLnByb3RvdHlwZT17fQpQLndJ
-LnByb3RvdHlwZT17fQpQLlppLnByb3RvdHlwZT17fQpQLmJ5LnByb3RvdHlwZT17CnBXOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdAp1LmVwLmEoYykKdD1QLkJTKGIsdGhpcy5nSGUoKS5hKQpyZXR1cm4gdH0sCmdI
-ZTpmdW5jdGlvbigpe3JldHVybiBDLkEzfX0KUC5NeC5wcm90b3R5cGU9e30KUC51NS5wcm90b3R5cGU9
-ewpnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5Ra319ClAuRTMucHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24o
-YSl7dmFyIHQscyxyPVAuakIoMCxudWxsLGEubGVuZ3RoKSxxPXItMAppZihxPT09MClyZXR1cm4gbmV3
-IFVpbnQ4QXJyYXkoMCkKdD1uZXcgVWludDhBcnJheShxKjMpCnM9bmV3IFAuUncodCkKaWYocy5HeChh
-LDAscikhPT1yKXMuTzYoSi5hNihhLHItMSksMCkKcmV0dXJuIG5ldyBVaW50OEFycmF5KHQuc3ViYXJy
-YXkoMCxILnJNKDAscy5iLHQubGVuZ3RoKSkpfX0KUC5Sdy5wcm90b3R5cGU9ewpPNjpmdW5jdGlvbihh
-LGIpe3ZhciB0LHM9dGhpcyxyPXMuYyxxPXMuYixwPXErMSxvPXIubGVuZ3RoCmlmKChiJjY0NTEyKT09
-PTU2MzIwKXt0PTY1NTM2KygoYSYxMDIzKTw8MTApfGImMTAyMwpzLmI9cAppZihxPj1vKXJldHVybiBI
-LmsocixxKQpyW3FdPTI0MHx0Pj4+MTgKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguayhyLHApCnJb
-cF09MTI4fHQ+Pj4xMiY2MwpwPXMuYj1xKzEKaWYocT49bylyZXR1cm4gSC5rKHIscSkKcltxXT0xMjh8
-dD4+PjYmNjMKcy5iPXArMQppZihwPj1vKXJldHVybiBILmsocixwKQpyW3BdPTEyOHx0JjYzCnJldHVy
-biEwfWVsc2V7cy5iPXAKaWYocT49bylyZXR1cm4gSC5rKHIscSkKcltxXT0yMjR8YT4+PjEyCnE9cy5i
-PXArMQppZihwPj1vKXJldHVybiBILmsocixwKQpyW3BdPTEyOHxhPj4+NiY2MwpzLmI9cSsxCmlmKHE+
-PW8pcmV0dXJuIEguayhyLHEpCnJbcV09MTI4fGEmNjMKcmV0dXJuITF9fSwKR3g6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0LHMscixxLHAsbyxuLG09dGhpcwppZihiIT09YyYmKEMueEIubShhLGMtMSkmNjQ1MTIp
-PT09NTUyOTYpLS1jCmZvcih0PW0uYyxzPXQubGVuZ3RoLHI9YjtyPGM7KytyKXtxPUMueEIuVyhhLHIp
-CmlmKHE8PTEyNyl7cD1tLmIKaWYocD49cylicmVhawptLmI9cCsxCnRbcF09cX1lbHNlIGlmKChxJjY0
-NTEyKT09PTU1Mjk2KXtpZihtLmIrMz49cylicmVhawpvPXIrMQppZihtLk82KHEsQy54Qi5XKGEsbykp
-KXI9b31lbHNlIGlmKHE8PTIwNDcpe3A9bS5iCm49cCsxCmlmKG4+PXMpYnJlYWsKbS5iPW4KaWYocD49
-cylyZXR1cm4gSC5rKHQscCkKdFtwXT0xOTJ8cT4+PjYKbS5iPW4rMQp0W25dPTEyOHxxJjYzfWVsc2V7
-cD1tLmIKaWYocCsyPj1zKWJyZWFrCm49bS5iPXArMQppZihwPj1zKXJldHVybiBILmsodCxwKQp0W3Bd
-PTIyNHxxPj4+MTIKcD1tLmI9bisxCmlmKG4+PXMpcmV0dXJuIEguayh0LG4pCnRbbl09MTI4fHE+Pj42
-JjYzCm0uYj1wKzEKaWYocD49cylyZXR1cm4gSC5rKHQscCkKdFtwXT0xMjh8cSY2M319cmV0dXJuIHJ9
-fQpQLkdZLnByb3RvdHlwZT17CldKOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbAp1Lkwu
-YShhKQp0PVAua3koITEsYSwwLG51bGwpCmlmKHQhPW51bGwpcmV0dXJuIHQKcz1QLmpCKDAsbnVsbCxK
-LkgoYSkpCnI9UC5jUChhLDAscykKaWYocj4wKXtxPVAuSE0oYSwwLHIpCmlmKHI9PT1zKXJldHVybiBx
-CnA9bmV3IFAuUm4ocSkKbz1yCm49ITF9ZWxzZXtvPTAKcD1udWxsCm49ITB9aWYocD09bnVsbClwPW5l
-dyBQLlJuKCIiKQptPW5ldyBQLmJ6KCExLHApCm0uYz1uCm0uTUUoYSxvLHMpCmlmKG0uZT4wKXtILnZo
-KFAucnIoIlVuZmluaXNoZWQgVVRGLTggb2N0ZXQgc2VxdWVuY2UiLGEscykpCnAuYSs9SC5Mdyg2NTUz
-MykKbS5mPW0uZT1tLmQ9MH1sPXAuYQpyZXR1cm4gbC5jaGFyQ29kZUF0KDApPT0wP2w6bH19ClAuYnou
-cHJvdG90eXBlPXsKTUU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxo
-PXRoaXMsZz0iQmFkIFVURi04IGVuY29kaW5nIDB4Igp1LkwuYShhKQp0PWguZApzPWguZQpyPWguZgpo
-LmY9aC5lPWguZD0wCiRsYWJlbDAkMDpmb3IocT1KLlU2KGEpLHA9aC5iLG89YjshMDtvPWopeyRsYWJl
-bDEkMTppZihzPjApe2Rve2lmKG89PT1jKWJyZWFrICRsYWJlbDAkMApuPXEucShhLG8pCmlmKHR5cGVv
-ZiBuIT09Im51bWJlciIpcmV0dXJuIG4uek0oKQppZigobiYxOTIpIT09MTI4KXttPVAucnIoZytDLmpu
-LkQ4KG4sMTYpLGEsbykKdGhyb3cgSC5iKG0pfWVsc2V7dD0odDw8NnxuJjYzKT4+PjA7LS1zOysrb319
-d2hpbGUocz4wKQptPXItMQppZihtPDB8fG0+PTQpcmV0dXJuIEguayhDLkdiLG0pCmlmKHQ8PUMuR2Jb
-bV0pe209UC5ycigiT3ZlcmxvbmcgZW5jb2Rpbmcgb2YgMHgiK0Muam4uRDgodCwxNiksYSxvLXItMSkK
-dGhyb3cgSC5iKG0pfWlmKHQ+MTExNDExMSl7bT1QLnJyKCJDaGFyYWN0ZXIgb3V0c2lkZSB2YWxpZCBV
-bmljb2RlIHJhbmdlOiAweCIrQy5qbi5EOCh0LDE2KSxhLG8tci0xKQp0aHJvdyBILmIobSl9aWYoIWgu
-Y3x8dCE9PTY1Mjc5KXAuYSs9SC5Mdyh0KQpoLmM9ITF9Zm9yKG09bzxjO207KXtsPVAuY1AoYSxvLGMp
-CmlmKGw+MCl7aC5jPSExCms9bytsCnAuYSs9UC5ITShhLG8saykKaWYoaz09PWMpYnJlYWt9ZWxzZSBr
-PW8Kaj1rKzEKbj1xLnEoYSxrKQppZih0eXBlb2YgbiE9PSJudW1iZXIiKXJldHVybiBuLkooKQppZihu
-PDApe2k9UC5ycigiTmVnYXRpdmUgVVRGLTggY29kZSB1bml0OiAtMHgiK0Muam4uRDgoLW4sMTYpLGEs
-ai0xKQp0aHJvdyBILmIoaSl9ZWxzZXtpZigobiYyMjQpPT09MTkyKXt0PW4mMzEKcz0xCnI9MQpjb250
-aW51ZSAkbGFiZWwwJDB9aWYoKG4mMjQwKT09PTIyNCl7dD1uJjE1CnM9MgpyPTIKY29udGludWUgJGxh
-YmVsMCQwfWlmKChuJjI0OCk9PT0yNDAmJm48MjQ1KXt0PW4mNwpzPTMKcj0zCmNvbnRpbnVlICRsYWJl
-bDAkMH1pPVAucnIoZytDLmpuLkQ4KG4sMTYpLGEsai0xKQp0aHJvdyBILmIoaSl9fWJyZWFrICRsYWJl
-bDAkMH1pZihzPjApe2guZD10CmguZT1zCmguZj1yfX19ClAuV0YucHJvdG90eXBlPXsKJDI6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIKdS5mby5hKGEpCnQ9dGhpcy5iCnM9dGhpcy5hCnQuYSs9cy5hCnI9dC5h
-Kz1ILmQoYS5hKQp0LmE9cisiOiAiCnQuYSs9UC5oKGIpCnMuYT0iLCAifSwKJFM6MTl9ClAuYTIucHJv
-dG90eXBlPXt9ClAuaVAucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVy
-biExCnJldHVybiBiIGluc3RhbmNlb2YgUC5pUCYmdGhpcy5hPT09Yi5hJiYhMH0sCmdpTzpmdW5jdGlv
-bihhKXt2YXIgdD10aGlzLmEKcmV0dXJuKHReQy5qbi53Ryh0LDMwKSkmMTA3Mzc0MTgyM30sClo6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9dGhpcyxzPVAuR3EoSC50Sih0KSkscj1QLmgwKEguTlModCkpLHE9UC5oMChI
-LmpBKHQpKSxwPVAuaDAoSC5LTCh0KSksbz1QLmgwKEguY2godCkpLG49UC5oMChILkpkKHQpKSxtPVAu
-VngoSC5WYSh0KSksbD1zKyItIityKyItIitxKyIgIitwKyI6IitvKyI6IituKyIuIittCnJldHVybiBs
+eEIuTzIoIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXow
+MTIzNDU2Nzg5Ky8iLGcpCmlmKGg9PT1sKWNvbnRpbnVlCmw9aH1lbHNle2lmKGc9PT0tMSl7aWYocDww
+KXtmPXE9PW51bGw/bnVsbDpxLmEubGVuZ3RoCmlmKGY9PW51bGwpZj0wCnA9Zisocy1yKQpvPXN9Kytu
+CmlmKGw9PT02MSljb250aW51ZX1sPWh9aWYoZyE9PS0yKXtpZihxPT1udWxsKXE9bmV3IFAuUm4oIiIp
+CnEuYSs9Qy54Qi5OaihhMCxyLHMpCnEuYSs9SC5MdyhsKQpyPW0KY29udGludWV9fXRocm93IEguYihQ
+LnJyKCJJbnZhbGlkIGJhc2U2NCBkYXRhIixhMCxzKSl9aWYocSE9bnVsbCl7Zj1xLmErPUMueEIuTmoo
+YTAscixhMikKZT1mLmxlbmd0aAppZihwPj0wKVAueE0oYTAsbyxhMixwLG4sZSkKZWxzZXtkPUMuam4u
+elkoZS0xLDQpKzEKaWYoZD09PTEpdGhyb3cgSC5iKFAucnIoYixhMCxhMikpCmZvcig7ZDw0Oyl7Zis9
+Ij0iCnEuYT1mOysrZH19Zj1xLmEKcmV0dXJuIEMueEIuaTcoYTAsYTEsYTIsZi5jaGFyQ29kZUF0KDAp
+PT0wP2Y6Zil9Yz1hMi1hMQppZihwPj0wKVAueE0oYTAsbyxhMixwLG4sYykKZWxzZXtkPUMuam4uelko
+Yyw0KQppZihkPT09MSl0aHJvdyBILmIoUC5ycihiLGEwLGEyKSkKaWYoZD4xKWEwPUMueEIuaTcoYTAs
+YTIsYTIsZD09PTI/Ij09IjoiPSIpfXJldHVybiBhMH19ClAudkEucHJvdG90eXBlPXt9ClAuVWsucHJv
+dG90eXBlPXt9ClAud0kucHJvdG90eXBlPXt9ClAuWmkucHJvdG90eXBlPXt9ClAuYnkucHJvdG90eXBl
+PXsKcFc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CnUuZXAuYShjKQp0PVAuQlMoYix0aGlzLmdIZSgpLmEp
+CnJldHVybiB0fSwKZ0hlOmZ1bmN0aW9uKCl7cmV0dXJuIEMuQTN9fQpQLk14LnByb3RvdHlwZT17fQpQ
+LnU1LnByb3RvdHlwZT17CmdaRTpmdW5jdGlvbigpe3JldHVybiBDLlFrfX0KUC5FMy5wcm90b3R5cGU9
+ewpXSjpmdW5jdGlvbihhKXt2YXIgdCxzLHI9UC5qQigwLG51bGwsYS5sZW5ndGgpLHE9ci0wCmlmKHE9
+PT0wKXJldHVybiBuZXcgVWludDhBcnJheSgwKQp0PW5ldyBVaW50OEFycmF5KHEqMykKcz1uZXcgUC5S
+dyh0KQppZihzLkd4KGEsMCxyKSE9PXIpcy5PNihKLmE2KGEsci0xKSwwKQpyZXR1cm4gbmV3IFVpbnQ4
+QXJyYXkodC5zdWJhcnJheSgwLEguck0oMCxzLmIsdC5sZW5ndGgpKSl9fQpQLlJ3LnByb3RvdHlwZT17
+Ck82OmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLHI9cy5jLHE9cy5iLHA9cSsxLG89ci5sZW5ndGgK
+aWYoKGImNjQ1MTIpPT09NTYzMjApe3Q9NjU1MzYrKChhJjEwMjMpPDwxMCl8YiYxMDIzCnMuYj1wCmlm
+KHE+PW8pcmV0dXJuIEguayhyLHEpCnJbcV09MjQwfHQ+Pj4xOApxPXMuYj1wKzEKaWYocD49bylyZXR1
+cm4gSC5rKHIscCkKcltwXT0xMjh8dD4+PjEyJjYzCnA9cy5iPXErMQppZihxPj1vKXJldHVybiBILmso
+cixxKQpyW3FdPTEyOHx0Pj4+NiY2MwpzLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguayhyLHApCnJbcF09
+MTI4fHQmNjMKcmV0dXJuITB9ZWxzZXtzLmI9cAppZihxPj1vKXJldHVybiBILmsocixxKQpyW3FdPTIy
+NHxhPj4+MTIKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguayhyLHApCnJbcF09MTI4fGE+Pj42JjYz
+CnMuYj1xKzEKaWYocT49bylyZXR1cm4gSC5rKHIscSkKcltxXT0xMjh8YSY2MwpyZXR1cm4hMX19LApH
+eDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzCmlmKGIhPT1jJiYoQy54Qi5P
+MihhLGMtMSkmNjQ1MTIpPT09NTUyOTYpLS1jCmZvcih0PW0uYyxzPXQubGVuZ3RoLHI9YjtyPGM7Kyty
+KXtxPUMueEIuV2QoYSxyKQppZihxPD0xMjcpe3A9bS5iCmlmKHA+PXMpYnJlYWsKbS5iPXArMQp0W3Bd
+PXF9ZWxzZSBpZigocSY2NDUxMik9PT01NTI5Nil7aWYobS5iKzM+PXMpYnJlYWsKbz1yKzEKaWYobS5P
+NihxLEMueEIuV2QoYSxvKSkpcj1vfWVsc2UgaWYocTw9MjA0Nyl7cD1tLmIKbj1wKzEKaWYobj49cyli
+cmVhawptLmI9bgppZihwPj1zKXJldHVybiBILmsodCxwKQp0W3BdPTE5MnxxPj4+NgptLmI9bisxCnRb
+bl09MTI4fHEmNjN9ZWxzZXtwPW0uYgppZihwKzI+PXMpYnJlYWsKbj1tLmI9cCsxCmlmKHA+PXMpcmV0
+dXJuIEguayh0LHApCnRbcF09MjI0fHE+Pj4xMgpwPW0uYj1uKzEKaWYobj49cylyZXR1cm4gSC5rKHQs
+bikKdFtuXT0xMjh8cT4+PjYmNjMKbS5iPXArMQppZihwPj1zKXJldHVybiBILmsodCxwKQp0W3BdPTEy
+OHxxJjYzfX1yZXR1cm4gcn19ClAuR1kucHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
+LHEscCxvLG4sbSxsCnUuTC5hKGEpCnQ9UC5reSghMSxhLDAsbnVsbCkKaWYodCE9bnVsbClyZXR1cm4g
+dApzPVAuakIoMCxudWxsLEouSChhKSkKcj1QLmNQKGEsMCxzKQppZihyPjApe3E9UC5ITShhLDAscikK
+aWYocj09PXMpcmV0dXJuIHEKcD1uZXcgUC5SbihxKQpvPXIKbj0hMX1lbHNle289MApwPW51bGwKbj0h
+MH1pZihwPT1udWxsKXA9bmV3IFAuUm4oIiIpCm09bmV3IFAuYnooITEscCkKbS5jPW4KbS5NRShhLG8s
+cykKaWYobS5lPjApe0guVmooUC5ycigiVW5maW5pc2hlZCBVVEYtOCBvY3RldCBzZXF1ZW5jZSIsYSxz
+KSkKcC5hKz1ILkx3KDY1NTMzKQptLmY9bS5lPW0uZD0wfWw9cC5hCnJldHVybiBsLmNoYXJDb2RlQXQo
+MCk9PTA/bDpsfX0KUC5iei5wcm90b3R5cGU9ewpNRTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEs
+cCxvLG4sbSxsLGssaixpLGg9dGhpcyxnPSJCYWQgVVRGLTggZW5jb2RpbmcgMHgiCnUuTC5hKGEpCnQ9
+aC5kCnM9aC5lCnI9aC5mCmguZj1oLmU9aC5kPTAKJGxhYmVsMCQwOmZvcihxPUouVTYoYSkscD1oLmIs
+bz1iOyEwO289ail7JGxhYmVsMSQxOmlmKHM+MCl7ZG97aWYobz09PWMpYnJlYWsgJGxhYmVsMCQwCm49
+cS5xKGEsbykKaWYodHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi56TSgpCmlmKChuJjE5MikhPT0x
+Mjgpe209UC5ycihnK0Muam4uRDgobiwxNiksYSxvKQp0aHJvdyBILmIobSl9ZWxzZXt0PSh0PDw2fG4m
+NjMpPj4+MDstLXM7KytvfX13aGlsZShzPjApCm09ci0xCmlmKG08MHx8bT49NClyZXR1cm4gSC5rKEMu
+R2IsbSkKaWYodDw9Qy5HYlttXSl7bT1QLnJyKCJPdmVybG9uZyBlbmNvZGluZyBvZiAweCIrQy5qbi5E
+OCh0LDE2KSxhLG8tci0xKQp0aHJvdyBILmIobSl9aWYodD4xMTE0MTExKXttPVAucnIoIkNoYXJhY3Rl
+ciBvdXRzaWRlIHZhbGlkIFVuaWNvZGUgcmFuZ2U6IDB4IitDLmpuLkQ4KHQsMTYpLGEsby1yLTEpCnRo
+cm93IEguYihtKX1pZighaC5jfHx0IT09NjUyNzkpcC5hKz1ILkx3KHQpCmguYz0hMX1mb3IobT1vPGM7
+bTspe2w9UC5jUChhLG8sYykKaWYobD4wKXtoLmM9ITEKaz1vK2wKcC5hKz1QLkhNKGEsbyxrKQppZihr
+PT09YylicmVha31lbHNlIGs9bwpqPWsrMQpuPXEucShhLGspCmlmKHR5cGVvZiBuIT09Im51bWJlciIp
+cmV0dXJuIG4uSigpCmlmKG48MCl7aT1QLnJyKCJOZWdhdGl2ZSBVVEYtOCBjb2RlIHVuaXQ6IC0weCIr
+Qy5qbi5EOCgtbiwxNiksYSxqLTEpCnRocm93IEguYihpKX1lbHNle2lmKChuJjIyNCk9PT0xOTIpe3Q9
+biYzMQpzPTEKcj0xCmNvbnRpbnVlICRsYWJlbDAkMH1pZigobiYyNDApPT09MjI0KXt0PW4mMTUKcz0y
+CnI9Mgpjb250aW51ZSAkbGFiZWwwJDB9aWYoKG4mMjQ4KT09PTI0MCYmbjwyNDUpe3Q9biY3CnM9Mwpy
+PTMKY29udGludWUgJGxhYmVsMCQwfWk9UC5ycihnK0Muam4uRDgobiwxNiksYSxqLTEpCnRocm93IEgu
+YihpKX19YnJlYWsgJGxhYmVsMCQwfWlmKHM+MCl7aC5kPXQKaC5lPXMKaC5mPXJ9fX0KUC5XRi5wcm90
+b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgp1LmZvLmEoYSkKdD10aGlzLmIKcz10aGlz
+LmEKdC5hKz1zLmEKcj10LmErPUguZChhLmEpCnQuYT1yKyI6ICIKdC5hKz1QLmgoYikKcy5hPSIsICJ9
+LAokUzo0N30KUC5hMi5wcm90b3R5cGU9e30KUC5pUC5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIp
+e2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLmlQJiZ0aGlzLmE9PT1iLmEm
+JnRoaXMuYj09PWIuYn0sClhrOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmEKaWYoTWF0aC5hYnMo
+cyk8PTg2NGUxMyl0PSExCmVsc2UgdD0hMAppZih0KXRocm93IEguYihQLnhZKCJEYXRlVGltZSBpcyBv
+dXRzaWRlIHZhbGlkIHJhbmdlOiAiK3MpKQpQLlVJKHRoaXMuYiwiaXNVdGMiLHUueSl9LApnaTpmdW5j
+dGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuKHReQy5qbi53Ryh0LDMwKSkmMTA3Mzc0MTgyM30sClo6
+ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPVAuR3EoSC50Sih0KSkscj1QLmgwKEguTlModCkpLHE9UC5o
+MChILmpBKHQpKSxwPVAuaDAoSC5LTCh0KSksbz1QLmgwKEguY2godCkpLG49UC5oMChILkpkKHQpKSxt
+PVAuVngoSC5WYSh0KSkKaWYodC5iKXJldHVybiBzKyItIityKyItIitxKyIgIitwKyI6IitvKyI6Iitu
+KyIuIittKyJaIgplbHNlIHJldHVybiBzKyItIityKyItIitxKyIgIitwKyI6IitvKyI6IituKyIuIitt
 fX0KUC5DUC5wcm90b3R5cGU9e30KUC5YUy5wcm90b3R5cGU9ewpnSUk6ZnVuY3Rpb24oKXtyZXR1cm4g
 SC50cyh0aGlzLiR0aHJvd25Kc0Vycm9yKX19ClAuQzYucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXt2
 YXIgdD10aGlzLmEKaWYodCE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLmgodCkKcmV0
 dXJuIkFzc2VydGlvbiBmYWlsZWQifX0KUC5MSy5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVy
-biJUaHJvdyBvZiBudWxsLiJ9fQpQLkFULnByb3RvdHlwZT17CmdMOmZ1bmN0aW9uKCl7cmV0dXJuIklu
-dmFsaWQgYXJndW1lbnQiKyghdGhpcy5hPyIocykiOiIiKX0sCmd1OmZ1bmN0aW9uKCl7cmV0dXJuIiJ9
-LApaOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9dGhpcyxvPXAuYyxuPW8hPW51bGw/IiAoIitvKyIp
-IjoiIgpvPXAuZAp0PW89PW51bGw/IiI6IjogIitILmQobykKcz1wLmdMKCkrbit0CmlmKCFwLmEpcmV0
-dXJuIHMKcj1wLmd1KCkKcT1QLmgocC5iKQpyZXR1cm4gcytyKyI6ICIrcX19ClAuYkoucHJvdG90eXBl
-PXsKZ0w6ZnVuY3Rpb24oKXtyZXR1cm4iUmFuZ2VFcnJvciJ9LApndTpmdW5jdGlvbigpe3ZhciB0LHMs
-cj10aGlzLmUKaWYocj09bnVsbCl7cj10aGlzLmYKdD1yIT1udWxsPyI6IE5vdCBsZXNzIHRoYW4gb3Ig
-ZXF1YWwgdG8gIitILmQocik6IiJ9ZWxzZXtzPXRoaXMuZgppZihzPT1udWxsKXQ9IjogTm90IGdyZWF0
-ZXIgdGhhbiBvciBlcXVhbCB0byAiK0guZChyKQplbHNlIGlmKHM+cil0PSI6IE5vdCBpbiByYW5nZSAi
-K0guZChyKSsiLi4iK0guZChzKSsiLCBpbmNsdXNpdmUiCmVsc2UgdD1zPHI/IjogVmFsaWQgdmFsdWUg
-cmFuZ2UgaXMgZW1wdHkiOiI6IE9ubHkgdmFsaWQgdmFsdWUgaXMgIitILmQocil9cmV0dXJuIHR9fQpQ
-LmVZLnByb3RvdHlwZT17CmdMOmZ1bmN0aW9uKCl7cmV0dXJuIlJhbmdlRXJyb3IifSwKZ3U6ZnVuY3Rp
-b24oKXt2YXIgdCxzPUguV1kodGhpcy5iKQppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkoo
-KQppZihzPDApcmV0dXJuIjogaW5kZXggbXVzdCBub3QgYmUgbmVnYXRpdmUiCnQ9dGhpcy5mCmlmKHQ9
-PT0wKXJldHVybiI6IG5vIGluZGljZXMgYXJlIHZhbGlkIgpyZXR1cm4iOiBpbmRleCBzaG91bGQgYmUg
-bGVzcyB0aGFuICIrSC5kKHQpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZn19ClAubXAucHJv
-dG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9dGhpcyxrPXt9LGo9bmV3
-IFAuUm4oIiIpCmsuYT0iIgpmb3IodD1sLmMscz10Lmxlbmd0aCxyPTAscT0iIixwPSIiO3I8czsrK3Is
-cD0iLCAiKXtvPXRbcl0Kai5hPXErcApxPWouYSs9UC5oKG8pCmsuYT0iLCAifWwuZC5LKDAsbmV3IFAu
-V0YoayxqKSkKbj1QLmgobC5hKQptPWouWigwKQp0PSJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5v
-dCBmb3VuZDogJyIrSC5kKGwuYi5hKSsiJ1xuUmVjZWl2ZXI6ICIrbisiXG5Bcmd1bWVudHM6IFsiK20r
-Il0iCnJldHVybiB0fX0KUC51Yi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJVbnN1cHBv
-cnRlZCBvcGVyYXRpb246ICIrdGhpcy5hfX0KUC5kcy5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3Zh
-ciB0PXRoaXMuYQpyZXR1cm4gdCE9bnVsbD8iVW5pbXBsZW1lbnRlZEVycm9yOiAiK3Q6IlVuaW1wbGVt
-ZW50ZWRFcnJvciJ9fQpQLmxqLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIkJhZCBzdGF0
-ZTogIit0aGlzLmF9fQpQLlVWLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCmlm
-KHQ9PW51bGwpcmV0dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb24uIgpy
-ZXR1cm4iQ29uY3VycmVudCBtb2RpZmljYXRpb24gZHVyaW5nIGl0ZXJhdGlvbjogIitQLmgodCkrIi4i
-fX0KUC5rNS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJPdXQgb2YgTWVtb3J5In0sCmdJ
-STpmdW5jdGlvbigpe3JldHVybiBudWxsfSwKJGlYUzoxfQpQLktZLnByb3RvdHlwZT17Clo6ZnVuY3Rp
-b24oYSl7cmV0dXJuIlN0YWNrIE92ZXJmbG93In0sCmdJSTpmdW5jdGlvbigpe3JldHVybiBudWxsfSwK
-JGlYUzoxfQpQLnQ3LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0
-PT1udWxsPyJSZWFkaW5nIHN0YXRpYyB2YXJpYWJsZSBkdXJpbmcgaXRzIGluaXRpYWxpemF0aW9uIjoi
-UmVhZGluZyBzdGF0aWMgdmFyaWFibGUgJyIrdCsiJyBkdXJpbmcgaXRzIGluaXRpYWxpemF0aW9uIn19
-ClAuQ0QucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iRXhjZXB0aW9uOiAiK3RoaXMuYX19
-ClAuYUUucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGks
-aD10aGlzLmEsZz1oIT1udWxsJiYiIiE9PWg/IkZvcm1hdEV4Y2VwdGlvbjogIitILmQoaCk6IkZvcm1h
-dEV4Y2VwdGlvbiIsZj10aGlzLmMsZT10aGlzLmIKaWYodHlwZW9mIGU9PSJzdHJpbmciKXtpZihmIT1u
-dWxsKWg9ZjwwfHxmPmUubGVuZ3RoCmVsc2UgaD0hMQppZihoKWY9bnVsbAppZihmPT1udWxsKXt0PWUu
-bGVuZ3RoPjc4P0MueEIudyhlLDAsNzUpKyIuLi4iOmUKcmV0dXJuIGcrIlxuIit0fWZvcihzPTEscj0w
-LHE9ITEscD0wO3A8ZjsrK3Ape289Qy54Qi5XKGUscCkKaWYobz09PTEwKXtpZihyIT09cHx8IXEpKytz
-CnI9cCsxCnE9ITF9ZWxzZSBpZihvPT09MTMpeysrcwpyPXArMQpxPSEwfX1nPXM+MT9nKygiIChhdCBs
-aW5lICIrcysiLCBjaGFyYWN0ZXIgIisoZi1yKzEpKyIpXG4iKTpnKygiIChhdCBjaGFyYWN0ZXIgIiso
-ZisxKSsiKVxuIikKbj1lLmxlbmd0aApmb3IocD1mO3A8bjsrK3Ape289Qy54Qi5tKGUscCkKaWYobz09
-PTEwfHxvPT09MTMpe249cApicmVha319aWYobi1yPjc4KWlmKGYtcjw3NSl7bT1yKzc1Cmw9cgprPSIi
-Cmo9Ii4uLiJ9ZWxzZXtpZihuLWY8NzUpe2w9bi03NQptPW4Kaj0iIn1lbHNle2w9Zi0zNgptPWYrMzYK
-aj0iLi4uIn1rPSIuLi4ifWVsc2V7bT1uCmw9cgprPSIiCmo9IiJ9aT1DLnhCLncoZSxsLG0pCnJldHVy
-biBnK2sraStqKyJcbiIrQy54Qi5JeCgiICIsZi1sK2subGVuZ3RoKSsiXlxuIn1lbHNlIHJldHVybiBm
-IT1udWxsP2crKCIgKGF0IG9mZnNldCAiK0guZChmKSsiKSIpOmd9fQpQLkVILnByb3RvdHlwZT17fQpQ
-LklmLnByb3RvdHlwZT17fQpQLmNYLnByb3RvdHlwZT17CkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1I
-LkxoKHRoaXMpCnJldHVybiBILksxKHRoaXMsdC5LcShjKS5DKCIxKGNYLkUpIikuYShiKSx0LkMoImNY
-LkUiKSxjKX0sCmV2OmZ1bmN0aW9uKGEsYil7dmFyIHQ9SC5MaCh0aGlzKQpyZXR1cm4gbmV3IEguVTUo
-dGhpcyx0LkMoImEyKGNYLkUpIikuYShiKSx0LkMoIlU1PGNYLkU+IikpfSwKZ0E6ZnVuY3Rpb24oYSl7
-dmFyIHQscz10aGlzLmdreih0aGlzKQpmb3IodD0wO3MuRigpOykrK3QKcmV0dXJuIHR9LApnbDA6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIXRoaXMuZ2t6KHRoaXMpLkYoKX0sCmdyODpmdW5jdGlvbihhKXt2YXIgdCxz
-PXRoaXMuZ2t6KHRoaXMpCmlmKCFzLkYoKSl0aHJvdyBILmIoSC5XcCgpKQp0PXMuZ2woKQppZihzLkYo
-KSl0aHJvdyBILmIoSC5kVSgpKQpyZXR1cm4gdH0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscT0i
-aW5kZXgiClAuVUkoYixxLHUuUykKUC5rMShiLHEpCmZvcih0PXRoaXMuZ2t6KHRoaXMpLHM9MDt0LkYo
-KTspe3I9dC5nbCgpCmlmKGI9PT1zKXJldHVybiByOysrc310aHJvdyBILmIoUC50KGIsdGhpcyxxLG51
-bGwscykpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gUC5FUCh0aGlzLCIoIiwiKSIpfX0KUC5Bbi5wcm90
-b3R5cGU9e30KUC56TS5wcm90b3R5cGU9eyRpYlE6MSwkaWNYOjF9ClAuWjAucHJvdG90eXBlPXt9ClAu
-TjMucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iTWFwRW50cnkoIitILmQodGhpcy5hKSsi
-OiAiK0guZCh0aGlzLmIpKyIpIn19ClAuYzgucHJvdG90eXBlPXsKZ2lPOmZ1bmN0aW9uKGEpe3JldHVy
-biBQLk1oLnByb3RvdHlwZS5naU8uY2FsbCh0aGlzLHRoaXMpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4i
-bnVsbCJ9fQpQLmxmLnByb3RvdHlwZT17fQpQLk1oLnByb3RvdHlwZT17Y29uc3RydWN0b3I6UC5NaCwk
-aU1oOjEsCkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXM9PT1ifSwKZ2lPOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBILmVRKHRoaXMpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEgu
-bGgodGhpcykpKyInIn0sCmU3OmZ1bmN0aW9uKGEsYil7dS5vLmEoYikKdGhyb3cgSC5iKFAubHIodGhp
-cyxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfSwKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
-cy5aKHRoaXMpfX0KUC5PZC5wcm90b3R5cGU9e30KUC5pYi5wcm90b3R5cGU9eyRpT2Q6MX0KUC54dS5w
-cm90b3R5cGU9e30KUC5Hei5wcm90b3R5cGU9e30KUC5aZC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEp
-e3JldHVybiIifSwKJGlHejoxfQpQLnFVLnByb3RvdHlwZT17JGl2WDoxfQpQLlJuLnByb3RvdHlwZT17
-CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEubGVuZ3RofSwKWjpmdW5jdGlvbihhKXt2YXIgdD10
-aGlzLmEKcmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaUJMOjF9ClAuR0QucHJvdG90eXBl
-PXt9ClAubjEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1LmYuYShhKQpI
-LmMoYikKdD1KLnJZKGIpLk9ZKGIsIj0iKQppZih0PT09LTEpe2lmKGIhPT0iIilhLlkoMCxQLmt1KGIs
-MCxiLmxlbmd0aCx0aGlzLmEsITApLCIiKX1lbHNlIGlmKHQhPT0wKXtzPUMueEIudyhiLDAsdCkKcj1D
-LnhCLkcoYix0KzEpCnE9dGhpcy5hCmEuWSgwLFAua3UocywwLHMubGVuZ3RoLHEsITApLFAua3Uociww
-LHIubGVuZ3RoLHEsITApKX1yZXR1cm4gYX0sCiRTOjQxfQpQLmNTLnByb3RvdHlwZT17CiQyOmZ1bmN0
-aW9uKGEsYil7dGhyb3cgSC5iKFAucnIoIklsbGVnYWwgSVB2NCBhZGRyZXNzLCAiK2EsdGhpcy5hLGIp
-KX0sCiRTOjQzfQpQLlZDLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKFAucnIo
-IklsbGVnYWwgSVB2NiBhZGRyZXNzLCAiK2EsdGhpcy5hLGIpKX0sCiQxOmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLiQyKGEsbnVsbCl9LAokUzo0NX0KUC5KVC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIp
-e3ZhciB0CmlmKGItYT40KXRoaXMuYS4kMigiYW4gSVB2NiBwYXJ0IGNhbiBvbmx5IGNvbnRhaW4gYSBt
-YXhpbXVtIG9mIDQgaGV4IGRpZ2l0cyIsYSkKdD1QLlFBKEMueEIudyh0aGlzLmIsYSxiKSxudWxsLDE2
-KQppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkooKQppZih0PDB8fHQ+NjU1MzUpdGhpcy5h
-LiQyKCJlYWNoIHBhcnQgbXVzdCBiZSBpbiB0aGUgcmFuZ2Ugb2YgYDB4MC4uMHhGRkZGYCIsYSkKcmV0
-dXJuIHR9LAokUzo0Nn0KUC5Ebi5wcm90b3R5cGU9ewpna3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5i
-fSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYwppZih0PT1udWxsKXJldHVybiIiCmlmKEMueEIu
-bih0LCJbIikpcmV0dXJuIEMueEIudyh0LDEsdC5sZW5ndGgtMSkKcmV0dXJuIHR9LApndHA6ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuIFAud0sodGhpcy5hKQpyZXR1cm4gdH0s
-Cmd0UDpmdW5jdGlvbigpe3ZhciB0PXRoaXMuZgpyZXR1cm4gdD09bnVsbD8iIjp0fSwKZ0thOmZ1bmN0
-aW9uKCl7dmFyIHQ9dGhpcy5yCnJldHVybiB0PT1udWxsPyIiOnR9LApubTpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMscixxLHAsbyxuLG0sbD10aGlzCnUuWC5hKG51bGwpCnUuYi5hKGIpCnQ9bC5hCnM9dD09PSJm
-aWxlIgpyPWwuYgpxPWwuZApwPWwuYwppZighKHAhPW51bGwpKXA9ci5sZW5ndGghPT0wfHxxIT1udWxs
-fHxzPyIiOm51bGwKbz1sLmUKaWYoIXMpbj1wIT1udWxsJiZvLmxlbmd0aCE9PTAKZWxzZSBuPSEwCmlm
-KG4mJiFDLnhCLm4obywiLyIpKW89Ii8iK28KbT1QLmxlKG51bGwsMCwwLGIpCnJldHVybiBuZXcgUC5E
-bih0LHIscCxxLG8sbSxsLnIpfSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLngKaWYocyE9bnVs
-bClyZXR1cm4gcwp0PXRoaXMuZQppZih0Lmxlbmd0aCE9PTAmJkMueEIuVyh0LDApPT09NDcpdD1DLnhC
-LkcodCwxKQpzPXQ9PT0iIj9DLmRuOlAuQUYobmV3IEgubEooSC5WTSh0LnNwbGl0KCIvIiksdS5zKSx1
-LmRPLmEoUC5QSCgpKSx1LmRvKSx1Lk4pCnRoaXMuc282KHMpCnJldHVybiBzfSwKZ2hZOmZ1bmN0aW9u
-KCl7dmFyIHQscz10aGlzCmlmKHMuUT09bnVsbCl7dD1zLmYKcy5zUkgobmV3IFAuR2ooUC5XWCh0PT1u
-dWxsPyIiOnQpLHUuRCkpfXJldHVybiBzLlF9LApKaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAs
-bwpmb3IodD0wLHM9MDtDLnhCLlFpKGIsIi4uLyIscyk7KXtzKz0zOysrdH1yPUMueEIuY24oYSwiLyIp
-CndoaWxlKCEwKXtpZighKHI+MCYmdD4wKSlicmVhawpxPUMueEIuUGsoYSwiLyIsci0xKQppZihxPDAp
-YnJlYWsKcD1yLXEKbz1wIT09MgppZighb3x8cD09PTMpaWYoQy54Qi5tKGEscSsxKT09PTQ2KW89IW98
-fEMueEIubShhLHErMik9PT00NgplbHNlIG89ITEKZWxzZSBvPSExCmlmKG8pYnJlYWs7LS10CnI9cX1y
-ZXR1cm4gQy54Qi5pNyhhLHIrMSxudWxsLEMueEIuRyhiLHMtMyp0KSl9LApaSTpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0s
-bCxrPXRoaXMsaj1udWxsCmlmKGEuZ0ZpKCkubGVuZ3RoIT09MCl7dD1hLmdGaSgpCmlmKGEuZ2NqKCkp
-e3M9YS5na3UoKQpyPWEuZ0pmKGEpCnE9YS5neEEoKT9hLmd0cChhKTpqfWVsc2V7cT1qCnI9cQpzPSIi
-fXA9UC54ZShhLmdJaShhKSkKbz1hLmdRRCgpP2EuZ3RQKCk6an1lbHNle3Q9ay5hCmlmKGEuZ2NqKCkp
-e3M9YS5na3UoKQpyPWEuZ0pmKGEpCnE9UC53QihhLmd4QSgpP2EuZ3RwKGEpOmosdCkKcD1QLnhlKGEu
-Z0lpKGEpKQpvPWEuZ1FEKCk/YS5ndFAoKTpqfWVsc2V7cz1rLmIKcj1rLmMKcT1rLmQKaWYoYS5nSWko
-YSk9PT0iIil7cD1rLmUKbz1hLmdRRCgpP2EuZ3RQKCk6ay5mfWVsc2V7aWYoYS5ndFQoKSlwPVAueGUo
-YS5nSWkoYSkpCmVsc2V7bj1rLmUKaWYobi5sZW5ndGg9PT0wKWlmKHI9PW51bGwpcD10Lmxlbmd0aD09
-PTA/YS5nSWkoYSk6UC54ZShhLmdJaShhKSkKZWxzZSBwPVAueGUoIi8iK2EuZ0lpKGEpKQplbHNle209
-ay5KaChuLGEuZ0lpKGEpKQpsPXQubGVuZ3RoPT09MAppZighbHx8ciE9bnVsbHx8Qy54Qi5uKG4sIi8i
-KSlwPVAueGUobSkKZWxzZSBwPVAud0YobSwhbHx8ciE9bnVsbCl9fW89YS5nUUQoKT9hLmd0UCgpOmp9
-fX1yZXR1cm4gbmV3IFAuRG4odCxzLHIscSxwLG8sYS5nWjgoKT9hLmdLYSgpOmopfSwKZ2NqOmZ1bmN0
-aW9uKCl7cmV0dXJuIHRoaXMuYyE9bnVsbH0sCmd4QTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmQhPW51
-bGx9LApnUUQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mIT1udWxsfSwKZ1o4OmZ1bmN0aW9uKCl7cmV0
-dXJuIHRoaXMuciE9bnVsbH0sCmd0VDpmdW5jdGlvbigpe3JldHVybiBDLnhCLm4odGhpcy5lLCIvIil9
-LAp0NDpmdW5jdGlvbigpe3ZhciB0LHMscj10aGlzLHE9ci5hCmlmKHEhPT0iIiYmcSE9PSJmaWxlIil0
-aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIrSC5kKHEpKyIg
-VVJJIikpCnE9ci5mCmlmKChxPT1udWxsPyIiOnEpIT09IiIpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBl
-eHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIHF1ZXJ5IGNvbXBvbmVudCIpKQpxPXIu
-cgppZigocT09bnVsbD8iIjpxKSE9PSIiKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZp
-bGUgcGF0aCBmcm9tIGEgVVJJIHdpdGggYSBmcmFnbWVudCBjb21wb25lbnQiKSkKdD0kLk94KCkKaWYo
-SC5vVCh0KSlxPVAubW4ocikKZWxzZXtpZihyLmMhPW51bGwmJnIuZ0pmKHIpIT09IiIpSC52aChQLkw0
-KCJDYW5ub3QgZXh0cmFjdCBhIG5vbi1XaW5kb3dzIGZpbGUgcGF0aCBmcm9tIGEgZmlsZSBVUkkgd2l0
-aCBhbiBhdXRob3JpdHkiKSkKcz1yLmdGaigpClAua0UocywhMSkKcT1QLnZnKEMueEIubihyLmUsIi8i
-KT8iLyI6IiIscywiLyIpCnE9cS5jaGFyQ29kZUF0KDApPT0wP3E6cX1yZXR1cm4gcX0sClo6ZnVuY3Rp
-b24oYSl7dmFyIHQscyxyLHE9dGhpcyxwPXEueQppZihwPT1udWxsKXtwPXEuYQp0PXAubGVuZ3RoIT09
-MD9wKyI6IjoiIgpzPXEuYwpyPXM9PW51bGwKaWYoIXJ8fHA9PT0iZmlsZSIpe3A9dCsiLy8iCnQ9cS5i
-CmlmKHQubGVuZ3RoIT09MClwPXArdCsiQCIKaWYoIXIpcCs9cwp0PXEuZAppZih0IT1udWxsKXA9cCsi
-OiIrSC5kKHQpfWVsc2UgcD10CnArPXEuZQp0PXEuZgppZih0IT1udWxsKXA9cCsiPyIrdAp0PXEucgpp
-Zih0IT1udWxsKXA9cCsiIyIrdApwPXEueT1wLmNoYXJDb2RlQXQoMCk9PTA/cDpwfXJldHVybiBwfSwK
-RE46ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwppZihiPT1udWxsKXJldHVybiExCmlmKHI9PT1i
-KXJldHVybiEwCmlmKHUuRS5iKGIpKWlmKHIuYT09Yi5nRmkoKSlpZihyLmMhPW51bGw9PT1iLmdjaigp
-KWlmKHIuYj09Yi5na3UoKSlpZihyLmdKZihyKT09Yi5nSmYoYikpaWYoci5ndHAocik9PWIuZ3RwKGIp
-KWlmKHIuZT09PWIuZ0lpKGIpKXt0PXIuZgpzPXQ9PW51bGwKaWYoIXM9PT1iLmdRRCgpKXtpZihzKXQ9
-IiIKaWYodD09PWIuZ3RQKCkpe3Q9ci5yCnM9dD09bnVsbAppZighcz09PWIuZ1o4KCkpe2lmKHMpdD0i
-Igp0PXQ9PT1iLmdLYSgpfWVsc2UgdD0hMX1lbHNlIHQ9ITF9ZWxzZSB0PSExfWVsc2UgdD0hMQplbHNl
-IHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQpyZXR1
-cm4gdH0sCmdpTzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLnoKcmV0dXJuIHQ9PW51bGw/dGhpcy56PUMu
-eEIuZ2lPKHRoaXMuWigwKSk6dH0sCnNvNjpmdW5jdGlvbihhKXt0aGlzLng9dS5hLmEoYSl9LApzUkg6
-ZnVuY3Rpb24oYSl7dGhpcy5RPXUuZi5hKGEpfSwKJGlpRDoxLApnRmk6ZnVuY3Rpb24oKXtyZXR1cm4g
-dGhpcy5hfSwKZ0lpOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmV9fQpQLmUxLnByb3RvdHlwZT17CiQx
-OmZ1bmN0aW9uKGEpe3Rocm93IEguYihQLnJyKCJJbnZhbGlkIHBvcnQiLHRoaXMuYSx0aGlzLmIrMSkp
-fSwKJFM6MTR9ClAuTlkucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9IklsbGVnYWwgcGF0
-aCBjaGFyYWN0ZXIgIgpILmMoYSkKaWYoSi56bChhLCIvIikpaWYodGhpcy5hKXRocm93IEguYihQLnhZ
-KHQrYSkpCmVsc2UgdGhyb3cgSC5iKFAuTDQodCthKSl9LAokUzoxNH0KUC5SWi5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gUC5lUChDLlpKLGEsQy54TSwhMSl9LAokUzo0fQpQLk1FLnByb3Rv
-dHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5iLHM9dGhpcy5hCnQuYSs9cy5hCnMuYT0i
-JiIKcz10LmErPUguZChQLmVQKEMuRjMsYSxDLnhNLCEwKSkKaWYoYiE9bnVsbCYmYi5sZW5ndGghPT0w
-KXt0LmE9cysiPSIKdC5hKz1ILmQoUC5lUChDLkYzLGIsQy54TSwhMCkpfX0sCiRTOjIyfQpQLnk1LnBy
-b3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILmMoYSkKaWYoYj09bnVsbHx8dHlwZW9m
-IGI9PSJzdHJpbmciKXRoaXMuYS4kMihhLEguYyhiKSkKZWxzZSBmb3IodD1KLklUKHUuUi5hKGIpKSxz
-PXRoaXMuYTt0LkYoKTspcy4kMihhLEguYyh0LmdsKCkpKX0sCiRTOjEzfQpQLlBFLnByb3RvdHlwZT17
-CmdsUjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcyxvPW51bGwsbj1wLmMKaWYobiE9bnVsbCly
-ZXR1cm4gbgpuPXAuYgppZigwPj1uLmxlbmd0aClyZXR1cm4gSC5rKG4sMCkKdD1wLmEKbj1uWzBdKzEK
-cz1DLnhCLlhVKHQsIj8iLG4pCnI9dC5sZW5ndGgKaWYocz49MCl7cT1QLnVPKHQscysxLHIsQy5WQywh
-MSkKcj1zfWVsc2UgcT1vCnJldHVybiBwLmM9bmV3IFAucWUoImRhdGEiLG8sbyxvLFAudU8odCxuLHIs
-Qy5XZCwhMSkscSxvKX0sClo6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmIKaWYoMD49cy5sZW5ndGgp
-cmV0dXJuIEguayhzLDApCnQ9dGhpcy5hCnJldHVybiBzWzBdPT09LTE/ImRhdGE6Iit0OnR9fQpQLnEz
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVWludDhBcnJheSg5Nil9LAokUzoy
-M30KUC55SS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYQppZihhPj10Lmxl
-bmd0aClyZXR1cm4gSC5rKHQsYSkKdD10W2FdCkouQ00odCwwLDk2LGIpCnJldHVybiB0fSwKJFM6MjR9
-ClAuYzYucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmZvcih0PWIubGVu
-Z3RoLHM9YS5sZW5ndGgscj0wO3I8dDsrK3Ipe3E9Qy54Qi5XKGIscileOTYKaWYocT49cylyZXR1cm4g
-SC5rKGEscSkKYVtxXT1jfX19ClAucWQucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
-LHMscixxCmZvcih0PUMueEIuVyhiLDApLHM9Qy54Qi5XKGIsMSkscj1hLmxlbmd0aDt0PD1zOysrdCl7
-cT0odF45Nik+Pj4wCmlmKHE+PXIpcmV0dXJuIEguayhhLHEpCmFbcV09Y319fQpQLlVmLnByb3RvdHlw
-ZT17CmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlzLmM+MH0sCmd4QTpmdW5jdGlvbigpe3ZhciB0LHMK
-aWYodGhpcy5jPjApe3Q9dGhpcy5kCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCnM9
-dGhpcy5lCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIEgucFkocykKcz10KzE8cwp0PXN9ZWxz
-ZSB0PSExCnJldHVybiB0fSwKZ1FEOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5mCmlmKHR5cGVvZiB0IT09
-Im51bWJlciIpcmV0dXJuIHQuSigpCnJldHVybiB0PHRoaXMucn0sCmdaODpmdW5jdGlvbigpe3JldHVy
-biB0aGlzLnI8dGhpcy5hLmxlbmd0aH0sCmdOdzpmdW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZD
-LnhCLm4odGhpcy5hLCJmaWxlIil9LApnV1o6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NCYmQy54
-Qi5uKHRoaXMuYSwiaHR0cCIpfSwKZ1JlOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTUmJkMueEIu
-bih0aGlzLmEsImh0dHBzIil9LApndFQ6ZnVuY3Rpb24oKXtyZXR1cm4gQy54Qi5RaSh0aGlzLmEsIi8i
-LHRoaXMuZSl9LApnRmk6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMscj0icGFja2FnZSIscT1zLmIKaWYo
-cTw9MClyZXR1cm4iIgp0PXMueAppZih0IT1udWxsKXJldHVybiB0CmlmKHMuZ1daKCkpcT1zLng9Imh0
-dHAiCmVsc2UgaWYocy5nUmUoKSl7cy54PSJodHRwcyIKcT0iaHR0cHMifWVsc2UgaWYocy5nTncoKSl7
-cy54PSJmaWxlIgpxPSJmaWxlIn1lbHNlIGlmKHE9PT03JiZDLnhCLm4ocy5hLHIpKXtzLng9cgpxPXJ9
-ZWxzZXtxPUMueEIudyhzLmEsMCxxKQpzLng9cX1yZXR1cm4gcX0sCmdrdTpmdW5jdGlvbigpe3ZhciB0
-PXRoaXMuYyxzPXRoaXMuYiszCnJldHVybiB0PnM/Qy54Qi53KHRoaXMuYSxzLHQtMSk6IiJ9LApnSmY6
-ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCnJldHVybiB0PjA/Qy54Qi53KHRoaXMuYSx0LHRoaXMuZCk6
-IiJ9LApndHA6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzCmlmKHMuZ3hBKCkpe3Q9cy5kCmlmKHR5cGVv
-ZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCnJldHVybiBQLlFBKEMueEIudyhzLmEsdCsxLHMuZSks
-bnVsbCxudWxsKX1pZihzLmdXWigpKXJldHVybiA4MAppZihzLmdSZSgpKXJldHVybiA0NDMKcmV0dXJu
-IDB9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIudyh0aGlzLmEsdGhpcy5lLHRoaXMuZil9LApn
-dFA6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmYscz10aGlzLnIKaWYodHlwZW9mIHQhPT0ibnVtYmVyIily
-ZXR1cm4gdC5KKCkKcmV0dXJuIHQ8cz9DLnhCLncodGhpcy5hLHQrMSxzKToiIn0sCmdLYTpmdW5jdGlv
-bigpe3ZhciB0PXRoaXMucixzPXRoaXMuYQpyZXR1cm4gdDxzLmxlbmd0aD9DLnhCLkcocyx0KzEpOiIi
-fSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMuZSxxPXRoaXMuZixwPXRoaXMuYQppZihDLnhC
-LlFpKHAsIi8iLHIpKXtpZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLmgoKTsrK3J9aWYocj09
-cSlyZXR1cm4gQy5kbgp0PUguVk0oW10sdS5zKQpzPXIKd2hpbGUoITApe2lmKHR5cGVvZiBzIT09Im51
-bWJlciIpcmV0dXJuIHMuSigpCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIEgucFkocSkKaWYo
-IShzPHEpKWJyZWFrCmlmKEMueEIubShwLHMpPT09NDcpe0MuTm0uaSh0LEMueEIudyhwLHIscykpCnI9
-cysxfSsrc31DLk5tLmkodCxDLnhCLncocCxyLHEpKQpyZXR1cm4gUC5BRih0LHUuTil9LApnaFk6ZnVu
-Y3Rpb24oKXt2YXIgdD10aGlzLmYKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5KKCkKaWYo
-dD49dGhpcy5yKXJldHVybiBDLkNNCnJldHVybiBuZXcgUC5HaihQLldYKHRoaXMuZ3RQKCkpLHUuRCl9
-LAprWDpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuZAppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVy
-biBzLmgoKQp0PXMrMQpyZXR1cm4gdCthLmxlbmd0aD09PXRoaXMuZSYmQy54Qi5RaSh0aGlzLmEsYSx0
-KX0sCk45OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQucixyPXQuYQppZihzPj1yLmxlbmd0aClyZXR1
-cm4gdApyZXR1cm4gbmV3IFAuVWYoQy54Qi53KHIsMCxzKSx0LmIsdC5jLHQuZCx0LmUsdC5mLHMsdC54
-KX0sCm5tOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaj10aGlzLGk9bnVsbAp1
-LlguYShudWxsKQp1LmIuYShiKQp0PWouZ0ZpKCkKcz10PT09ImZpbGUiCnI9ai5jCnE9cj4wP0MueEIu
-dyhqLmEsai5iKzMscik6IiIKcD1qLmd4QSgpP2ouZ3RwKGopOmkKcj1qLmMKaWYocj4wKW89Qy54Qi53
-KGouYSxyLGouZCkKZWxzZSBvPXEubGVuZ3RoIT09MHx8cCE9bnVsbHx8cz8iIjppCnI9ai5hCm49Qy54
-Qi53KHIsai5lLGouZikKaWYoIXMpbT1vIT1udWxsJiZuLmxlbmd0aCE9PTAKZWxzZSBtPSEwCmlmKG0m
-JiFDLnhCLm4obiwiLyIpKW49Ii8iK24KbD1QLmxlKGksMCwwLGIpCm09ai5yCms9bTxyLmxlbmd0aD9D
-LnhCLkcocixtKzEpOmkKcmV0dXJuIG5ldyBQLkRuKHQscSxvLHAsbixsLGspfSwKWkk6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMubVMoUC5oSyhhKSl9LAptUzpmdW5jdGlvbihhKXtpZihhIGluc3RhbmNlb2Yg
-UC5VZilyZXR1cm4gdGhpcy51MSh0aGlzLGEpCnJldHVybiB0aGlzLnZzKCkubVMoYSl9LAp1MTpmdW5j
-dGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlPWIuYgppZihlPjApcmV0
-dXJuIGIKdD1iLmMKaWYodD4wKXtzPWEuYgppZihzPD0wKXJldHVybiBiCmlmKGEuZ053KCkpcj1iLmUh
-PWIuZgplbHNlIGlmKGEuZ1daKCkpcj0hYi5rWCgiODAiKQplbHNlIHI9IWEuZ1JlKCl8fCFiLmtYKCI0
-NDMiKQppZihyKXtxPXMrMQpwPUMueEIudyhhLmEsMCxxKStDLnhCLkcoYi5hLGUrMSkKZT1iLmQKaWYo
-dHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1cm4gZS5oKCkKbz1iLmUKaWYodHlwZW9mIG8hPT0ibnVtYmVy
-IilyZXR1cm4gby5oKCkKbj1iLmYKaWYodHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi5oKCkKcmV0
-dXJuIG5ldyBQLlVmKHAscyx0K3EsZStxLG8rcSxuK3EsYi5yK3EsYS54KX1lbHNlIHJldHVybiB0aGlz
-LnZzKCkubVMoYil9bT1iLmUKZT1iLmYKaWYobT09ZSl7dD1iLnIKaWYodHlwZW9mIGUhPT0ibnVtYmVy
-IilyZXR1cm4gZS5KKCkKaWYoZTx0KXtzPWEuZgppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBz
-LkhOKCkKcT1zLWUKcmV0dXJuIG5ldyBQLlVmKEMueEIudyhhLmEsMCxzKStDLnhCLkcoYi5hLGUpLGEu
-YixhLmMsYS5kLGEuZSxlK3EsdCtxLGEueCl9ZT1iLmEKaWYodDxlLmxlbmd0aCl7cz1hLnIKcmV0dXJu
-IG5ldyBQLlVmKEMueEIudyhhLmEsMCxzKStDLnhCLkcoZSx0KSxhLmIsYS5jLGEuZCxhLmUsYS5mLHQr
-KHMtdCksYS54KX1yZXR1cm4gYS5OOSgpfXQ9Yi5hCmlmKEMueEIuUWkodCwiLyIsbSkpe3M9YS5lCmlm
-KHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSE4oKQppZih0eXBlb2YgbSE9PSJudW1iZXIiKXJl
-dHVybiBILnBZKG0pCnE9cy1tCnA9Qy54Qi53KGEuYSwwLHMpK0MueEIuRyh0LG0pCmlmKHR5cGVvZiBl
-IT09Im51bWJlciIpcmV0dXJuIGUuaCgpCnJldHVybiBuZXcgUC5VZihwLGEuYixhLmMsYS5kLHMsZStx
-LGIucitxLGEueCl9bD1hLmUKaz1hLmYKaWYobD09ayYmYS5jPjApe2Zvcig7Qy54Qi5RaSh0LCIuLi8i
-LG0pOyl7aWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gbS5oKCkKbSs9M31pZih0eXBlb2YgbCE9
-PSJudW1iZXIiKXJldHVybiBsLkhOKCkKaWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gSC5wWSht
-KQpxPWwtbSsxCnA9Qy54Qi53KGEuYSwwLGwpKyIvIitDLnhCLkcodCxtKQppZih0eXBlb2YgZSE9PSJu
+biJUaHJvdyBvZiBudWxsLiJ9fQpQLkFULnByb3RvdHlwZT17CmdaMjpmdW5jdGlvbigpe3JldHVybiJJ
+bnZhbGlkIGFyZ3VtZW50IisoIXRoaXMuYT8iKHMpIjoiIil9LApnTjpmdW5jdGlvbigpe3JldHVybiIi
+fSwKWjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmMsbj1vIT1udWxsPyIgKCIrbysi
+KSI6IiIKbz1wLmQKdD1vPT1udWxsPyIiOiI6ICIrSC5kKG8pCnM9cC5nWjIoKStuK3QKaWYoIXAuYSly
+ZXR1cm4gcwpyPXAuZ04oKQpxPVAuaChwLmIpCnJldHVybiBzK3IrIjogIitxfX0KUC5iSi5wcm90b3R5
+cGU9ewpnWjI6ZnVuY3Rpb24oKXtyZXR1cm4iUmFuZ2VFcnJvciJ9LApnTjpmdW5jdGlvbigpe3ZhciB0
+LHMscj10aGlzLmUKaWYocj09bnVsbCl7cj10aGlzLmYKdD1yIT1udWxsPyI6IE5vdCBsZXNzIHRoYW4g
+b3IgZXF1YWwgdG8gIitILmQocik6IiJ9ZWxzZXtzPXRoaXMuZgppZihzPT1udWxsKXQ9IjogTm90IGdy
+ZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAiK0guZChyKQplbHNlIGlmKHM+cil0PSI6IE5vdCBpbiByYW5n
+ZSAiK0guZChyKSsiLi4iK0guZChzKSsiLCBpbmNsdXNpdmUiCmVsc2UgdD1zPHI/IjogVmFsaWQgdmFs
+dWUgcmFuZ2UgaXMgZW1wdHkiOiI6IE9ubHkgdmFsaWQgdmFsdWUgaXMgIitILmQocil9cmV0dXJuIHR9
+fQpQLmVZLnByb3RvdHlwZT17CmdaMjpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmdOOmZ1
+bmN0aW9uKCl7dmFyIHQscz1ILldZKHRoaXMuYikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4g
+cy5KKCkKaWYoczwwKXJldHVybiI6IGluZGV4IG11c3Qgbm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgpp
+Zih0PT09MClyZXR1cm4iOiBubyBpbmRpY2VzIGFyZSB2YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxk
+IGJlIGxlc3MgdGhhbiAiK0guZCh0KX0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLm1w
+LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMsaz17fSxq
+PW5ldyBQLlJuKCIiKQprLmE9IiIKZm9yKHQ9bC5jLHM9dC5sZW5ndGgscj0wLHE9IiIscD0iIjtyPHM7
+KytyLHA9IiwgIil7bz10W3JdCmouYT1xK3AKcT1qLmErPVAuaChvKQprLmE9IiwgIn1sLmQuVSgwLG5l
+dyBQLldGKGssaikpCm49UC5oKGwuYSkKbT1qLlooMCkKdD0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhv
+ZCBub3QgZm91bmQ6ICciK0guZChsLmIuYSkrIidcblJlY2VpdmVyOiAiK24rIlxuQXJndW1lbnRzOiBb
+IittKyJdIgpyZXR1cm4gdH19ClAudWIucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iVW5z
+dXBwb3J0ZWQgb3BlcmF0aW9uOiAiK3RoaXMuYX19ClAuZHMucHJvdG90eXBlPXsKWjpmdW5jdGlvbihh
+KXt2YXIgdD10aGlzLmEKcmV0dXJuIHQhPW51bGw/IlVuaW1wbGVtZW50ZWRFcnJvcjogIit0OiJVbmlt
+cGxlbWVudGVkRXJyb3IifX0KUC5sai5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJCYWQg
+c3RhdGU6ICIrdGhpcy5hfX0KUC5VVi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMu
+YQppZih0PT1udWxsKXJldHVybiJDb25jdXJyZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9u
+LiIKcmV0dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb246ICIrUC5oKHQp
+KyIuIn19ClAuazUucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iT3V0IG9mIE1lbW9yeSJ9
+LApnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sCiRpWFM6MX0KUC5LWS5wcm90b3R5cGU9ewpaOmZ1
+bmN0aW9uKGEpe3JldHVybiJTdGFjayBPdmVyZmxvdyJ9LApnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gbnVs
+bH0sCiRpWFM6MX0KUC50Ny5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1
+cm4gdD09bnVsbD8iUmVhZGluZyBzdGF0aWMgdmFyaWFibGUgZHVyaW5nIGl0cyBpbml0aWFsaXphdGlv
+biI6IlJlYWRpbmcgc3RhdGljIHZhcmlhYmxlICciK3QrIicgZHVyaW5nIGl0cyBpbml0aWFsaXphdGlv
+biJ9fQpQLkNELnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIkV4Y2VwdGlvbjogIit0aGlz
+LmF9fQpQLmFFLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGss
+aixpLGg9dGhpcy5hLGc9aCE9bnVsbCYmIiIhPT1oPyJGb3JtYXRFeGNlcHRpb246ICIrSC5kKGgpOiJG
+b3JtYXRFeGNlcHRpb24iLGY9dGhpcy5jLGU9dGhpcy5iCmlmKHR5cGVvZiBlPT0ic3RyaW5nIil7aWYo
+ZiE9bnVsbCloPWY8MHx8Zj5lLmxlbmd0aAplbHNlIGg9ITEKaWYoaClmPW51bGwKaWYoZj09bnVsbCl7
+dD1lLmxlbmd0aD43OD9DLnhCLk5qKGUsMCw3NSkrIi4uLiI6ZQpyZXR1cm4gZysiXG4iK3R9Zm9yKHM9
+MSxyPTAscT0hMSxwPTA7cDxmOysrcCl7bz1DLnhCLldkKGUscCkKaWYobz09PTEwKXtpZihyIT09cHx8
+IXEpKytzCnI9cCsxCnE9ITF9ZWxzZSBpZihvPT09MTMpeysrcwpyPXArMQpxPSEwfX1nPXM+MT9nKygi
+IChhdCBsaW5lICIrcysiLCBjaGFyYWN0ZXIgIisoZi1yKzEpKyIpXG4iKTpnKygiIChhdCBjaGFyYWN0
+ZXIgIisoZisxKSsiKVxuIikKbj1lLmxlbmd0aApmb3IocD1mO3A8bjsrK3Ape289Qy54Qi5PMihlLHAp
+CmlmKG89PT0xMHx8bz09PTEzKXtuPXAKYnJlYWt9fWlmKG4tcj43OClpZihmLXI8NzUpe209cis3NQps
+PXIKaz0iIgpqPSIuLi4ifWVsc2V7aWYobi1mPDc1KXtsPW4tNzUKbT1uCmo9IiJ9ZWxzZXtsPWYtMzYK
+bT1mKzM2Cmo9Ii4uLiJ9az0iLi4uIn1lbHNle209bgpsPXIKaz0iIgpqPSIifWk9Qy54Qi5OaihlLGws
+bSkKcmV0dXJuIGcraytpK2orIlxuIitDLnhCLkl4KCIgIixmLWwray5sZW5ndGgpKyJeXG4ifWVsc2Ug
+cmV0dXJuIGYhPW51bGw/ZysoIiAoYXQgb2Zmc2V0ICIrSC5kKGYpKyIpIik6Z319ClAuRUgucHJvdG90
+eXBlPXt9ClAuSWYucHJvdG90eXBlPXt9ClAuTHkucHJvdG90eXBlPXsKRTI6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0PUguTGgodGhpcykKcmV0dXJuIEguSzEodGhpcyx0LksoYykuQygiMShMeS5FKSIpLmEoYiks
+dC5DKCJMeS5FIiksYyl9LApldjpmdW5jdGlvbihhLGIpe3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5l
+dyBILlU1KHRoaXMsdC5DKCJhMihMeS5FKSIpLmEoYiksdC5DKCJVNTxMeS5FPiIpKX0sCmdrOmZ1bmN0
+aW9uKGEpe3ZhciB0LHM9dGhpcy5ndyh0aGlzKQpmb3IodD0wO3MubSgpOykrK3QKcmV0dXJuIHR9LApn
+bDA6ZnVuY3Rpb24oYSl7cmV0dXJuIXRoaXMuZ3codGhpcykubSgpfSwKZ3I4OmZ1bmN0aW9uKGEpe3Zh
+ciB0LHM9dGhpcy5ndyh0aGlzKQppZighcy5tKCkpdGhyb3cgSC5iKEguV3AoKSkKdD1zLmdSKHMpCmlm
+KHMubSgpKXRocm93IEguYihILmRVKCkpCnJldHVybiB0fSwKVzpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
+cixxPSJpbmRleCIKUC5VSShiLHEsdS5TKQpQLmsxKGIscSkKZm9yKHQ9dGhpcy5ndyh0aGlzKSxzPTA7
+dC5tKCk7KXtyPXQuZ1IodCkKaWYoYj09PXMpcmV0dXJuIHI7KytzfXRocm93IEguYihQLnQoYix0aGlz
+LHEsbnVsbCxzKSl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBQLkVQKHRoaXMsIigiLCIpIil9fQpQLkFu
+LnByb3RvdHlwZT17fQpQLnpNLnByb3RvdHlwZT17JGliUToxLCRpTHk6MX0KUC5aMC5wcm90b3R5cGU9
+e30KUC5OMy5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJNYXBFbnRyeSgiK0guZCh0aGlz
+LmEpKyI6ICIrSC5kKHRoaXMuYikrIikifSwKZ0czOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LApn
+bnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYn19ClAuYzgucHJvdG90eXBlPXsKZ2k6ZnVuY3Rpb24o
+YSl7cmV0dXJuIFAuTWgucHJvdG90eXBlLmdpLmNhbGwodGhpcyx0aGlzKX0sClo6ZnVuY3Rpb24oYSl7
+cmV0dXJuIm51bGwifX0KUC5sZi5wcm90b3R5cGU9e30KUC5NaC5wcm90b3R5cGU9e2NvbnN0cnVjdG9y
+OlAuTWgsJGlNaDoxLApETjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzPT09Yn0sCmdpOmZ1bmN0aW9u
+KGEpe3JldHVybiBILmVRKHRoaXMpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIr
+SC5kKEgubGgodGhpcykpKyInIn0sCmU3OmZ1bmN0aW9uKGEsYil7dS5vLmEoYikKdGhyb3cgSC5iKFAu
+bHIodGhpcyxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfSwKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1
+cm4gdGhpcy5aKHRoaXMpfX0KUC5PZC5wcm90b3R5cGU9e30KUC5pYi5wcm90b3R5cGU9eyRpT2Q6MX0K
+UC54dS5wcm90b3R5cGU9e30KUC5Hei5wcm90b3R5cGU9e30KUC5aZC5wcm90b3R5cGU9ewpaOmZ1bmN0
+aW9uKGEpe3JldHVybiIifSwKJGlHejoxfQpQLnFVLnByb3RvdHlwZT17JGl2WDoxfQpQLlJuLnByb3Rv
+dHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEubGVuZ3RofSwKWjpmdW5jdGlvbihhKXt2
+YXIgdD10aGlzLmEKcmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaUJMOjF9ClAuR0QucHJv
+dG90eXBlPXt9ClAubjEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1LmYu
+YShhKQpILmMoYikKdD1KLnJZKGIpLk9ZKGIsIj0iKQppZih0PT09LTEpe2lmKGIhPT0iIilKLnU5KGEs
+UC5rdShiLDAsYi5sZW5ndGgsdGhpcy5hLCEwKSwiIil9ZWxzZSBpZih0IT09MCl7cz1DLnhCLk5qKGIs
+MCx0KQpyPUMueEIueW4oYix0KzEpCnE9dGhpcy5hCkoudTkoYSxQLmt1KHMsMCxzLmxlbmd0aCxxLCEw
+KSxQLmt1KHIsMCxyLmxlbmd0aCxxLCEwKSl9cmV0dXJuIGF9LAokUzoyNH0KUC5jUy5wcm90b3R5cGU9
+ewokMjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxlZ2FsIElQdjQgYWRkcmVzcywgIith
+LHRoaXMuYSxiKSl9LAokUzo0OH0KUC5WQy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3Rocm93
+IEguYihQLnJyKCJJbGxlZ2FsIElQdjYgYWRkcmVzcywgIithLHRoaXMuYSxiKSl9LAokMTpmdW5jdGlv
+bihhKXtyZXR1cm4gdGhpcy4kMihhLG51bGwpfSwKJFM6MzF9ClAuSlQucHJvdG90eXBlPXsKJDI6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdAppZihiLWE+NCl0aGlzLmEuJDIoImFuIElQdjYgcGFydCBjYW4gb25seSBj
+b250YWluIGEgbWF4aW11bSBvZiA0IGhleCBkaWdpdHMiLGEpCnQ9UC5RQShDLnhCLk5qKHRoaXMuYixh
+LGIpLG51bGwsMTYpCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCmlmKHQ8MHx8dD42
+NTUzNSl0aGlzLmEuJDIoImVhY2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSBvZiBgMHgwLi4weEZG
+RkZgIixhKQpyZXR1cm4gdH0sCiRTOjM1fQpQLkRuLnByb3RvdHlwZT17CmdrdTpmdW5jdGlvbigpe3Jl
+dHVybiB0aGlzLmJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9PW51bGwpcmV0dXJu
+IiIKaWYoQy54Qi5uQyh0LCJbIikpcmV0dXJuIEMueEIuTmoodCwxLHQubGVuZ3RoLTEpCnJldHVybiB0
+fSwKZ3RwOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiBQLndLKHRoaXMu
+YSkKcmV0dXJuIHR9LApndFA6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5mCnJldHVybiB0PT1udWxsPyIi
+OnR9LApnS2E6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLnIKcmV0dXJuIHQ9PW51bGw/IiI6dH0sCm5tOmZ1
+bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMKdS5YLmEobnVsbCkKdS5iLmEoYikK
+dD1sLmEKcz10PT09ImZpbGUiCnI9bC5iCnE9bC5kCnA9bC5jCmlmKCEocCE9bnVsbCkpcD1yLmxlbmd0
+aCE9PTB8fHEhPW51bGx8fHM/IiI6bnVsbApvPWwuZQppZighcyluPXAhPW51bGwmJm8ubGVuZ3RoIT09
+MAplbHNlIG49ITAKaWYobiYmIUMueEIubkMobywiLyIpKW89Ii8iK28KbT1QLmxlKG51bGwsMCwwLGIp
+CnJldHVybiBuZXcgUC5Ebih0LHIscCxxLG8sbSxsLnIpfSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHQscz10
+aGlzLngKaWYocyE9bnVsbClyZXR1cm4gcwp0PXRoaXMuZQppZih0Lmxlbmd0aCE9PTAmJkMueEIuV2Qo
+dCwwKT09PTQ3KXQ9Qy54Qi55bih0LDEpCnM9dD09PSIiP0MueEQ6UC5BRihuZXcgSC5sSihILlZNKHQu
+c3BsaXQoIi8iKSx1LnMpLHUuZE8uYShQLlBIKCkpLHUuZG8pLHUuTikKdGhpcy5zbzYocykKcmV0dXJu
+IHN9LApnaFk6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMKaWYocy5RPT1udWxsKXt0PXMuZgpzLnNSSChu
+ZXcgUC5HaihQLldYKHQ9PW51bGw/IiI6dCksdS5FKSl9cmV0dXJuIHMuUX0sCkpoOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQscyxyLHEscCxvCmZvcih0PTAscz0wO0MueEIuUWkoYiwiLi4vIixzKTspe3MrPTM7Kyt0
+fXI9Qy54Qi5jbihhLCIvIikKd2hpbGUoITApe2lmKCEocj4wJiZ0PjApKWJyZWFrCnE9Qy54Qi5Qayhh
+LCIvIixyLTEpCmlmKHE8MClicmVhawpwPXItcQpvPXAhPT0yCmlmKCFvfHxwPT09MylpZihDLnhCLk8y
+KGEscSsxKT09PTQ2KW89IW98fEMueEIuTzIoYSxxKzIpPT09NDYKZWxzZSBvPSExCmVsc2Ugbz0hMQpp
+ZihvKWJyZWFrOy0tdApyPXF9cmV0dXJuIEMueEIuaTcoYSxyKzEsbnVsbCxDLnhCLnluKGIscy0zKnQp
+KX0sClpJOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLm1TKFAuaEsoYSkpfSwKbVM6ZnVuY3Rpb24oYSl7
+dmFyIHQscyxyLHEscCxvLG4sbSxsLGs9dGhpcyxqPW51bGwKaWYoYS5nRmkoKS5sZW5ndGghPT0wKXt0
+PWEuZ0ZpKCkKaWYoYS5nY2ooKSl7cz1hLmdrdSgpCnI9YS5nSmYoYSkKcT1hLmd4QSgpP2EuZ3RwKGEp
+Omp9ZWxzZXtxPWoKcj1xCnM9IiJ9cD1QLnhlKGEuZ0lpKGEpKQpvPWEuZ1FEKCk/YS5ndFAoYSk6an1l
+bHNle3Q9ay5hCmlmKGEuZ2NqKCkpe3M9YS5na3UoKQpyPWEuZ0pmKGEpCnE9UC53QihhLmd4QSgpP2Eu
+Z3RwKGEpOmosdCkKcD1QLnhlKGEuZ0lpKGEpKQpvPWEuZ1FEKCk/YS5ndFAoYSk6an1lbHNle3M9ay5i
+CnI9ay5jCnE9ay5kCmlmKGEuZ0lpKGEpPT09IiIpe3A9ay5lCm89YS5nUUQoKT9hLmd0UChhKTprLmZ9
+ZWxzZXtpZihhLmd0VCgpKXA9UC54ZShhLmdJaShhKSkKZWxzZXtuPWsuZQppZihuLmxlbmd0aD09PTAp
+aWYocj09bnVsbClwPXQubGVuZ3RoPT09MD9hLmdJaShhKTpQLnhlKGEuZ0lpKGEpKQplbHNlIHA9UC54
+ZSgiLyIrYS5nSWkoYSkpCmVsc2V7bT1rLkpoKG4sYS5nSWkoYSkpCmw9dC5sZW5ndGg9PT0wCmlmKCFs
+fHxyIT1udWxsfHxDLnhCLm5DKG4sIi8iKSlwPVAueGUobSkKZWxzZSBwPVAud0YobSwhbHx8ciE9bnVs
+bCl9fW89YS5nUUQoKT9hLmd0UChhKTpqfX19cmV0dXJuIG5ldyBQLkRuKHQscyxyLHEscCxvLGEuZ1o4
+KCk/YS5nS2EoKTpqKX0sCmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlzLmMhPW51bGx9LApneEE6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy5kIT1udWxsfSwKZ1FEOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZiE9
+bnVsbH0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnIhPW51bGx9LApndFQ6ZnVuY3Rpb24oKXty
+ZXR1cm4gQy54Qi5uQyh0aGlzLmUsIi8iKX0sCnQ0OmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMscT1y
+LmEKaWYocSE9PSIiJiZxIT09ImZpbGUiKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZp
+bGUgcGF0aCBmcm9tIGEgIitILmQocSkrIiBVUkkiKSkKcT1yLmYKaWYoKHE9PW51bGw/IiI6cSkhPT0i
+Iil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhIFVSSSB3aXRo
+IGEgcXVlcnkgY29tcG9uZW50IikpCnE9ci5yCmlmKChxPT1udWxsPyIiOnEpIT09IiIpdGhyb3cgSC5i
+KFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIGZyYWdtZW50
+IGNvbXBvbmVudCIpKQp0PSQuT3goKQppZihILm9UKHQpKXE9UC5tbihyKQplbHNle2lmKHIuYyE9bnVs
+bCYmci5nSmYocikhPT0iIilILlZqKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgbm9uLVdpbmRvd3MgZmls
+ZSBwYXRoIGZyb20gYSBmaWxlIFVSSSB3aXRoIGFuIGF1dGhvcml0eSIpKQpzPXIuZ0ZqKCkKUC5rRShz
+LCExKQpxPVAudmcoQy54Qi5uQyhyLmUsIi8iKT8iLyI6IiIscywiLyIpCnE9cS5jaGFyQ29kZUF0KDAp
+PT0wP3E6cX1yZXR1cm4gcX0sClo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhpcyxwPXEueQppZihw
+PT1udWxsKXtwPXEuYQp0PXAubGVuZ3RoIT09MD9wKyI6IjoiIgpzPXEuYwpyPXM9PW51bGwKaWYoIXJ8
+fHA9PT0iZmlsZSIpe3A9dCsiLy8iCnQ9cS5iCmlmKHQubGVuZ3RoIT09MClwPXArdCsiQCIKaWYoIXIp
+cCs9cwp0PXEuZAppZih0IT1udWxsKXA9cCsiOiIrSC5kKHQpfWVsc2UgcD10CnArPXEuZQp0PXEuZgpp
+Zih0IT1udWxsKXA9cCsiPyIrdAp0PXEucgppZih0IT1udWxsKXA9cCsiIyIrdApwPXEueT1wLmNoYXJD
+b2RlQXQoMCk9PTA/cDpwfXJldHVybiBwfSwKRE46ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwpp
+ZihiPT1udWxsKXJldHVybiExCmlmKHI9PT1iKXJldHVybiEwCmlmKHUuRi5iKGIpKWlmKHIuYT09Yi5n
+RmkoKSlpZihyLmMhPW51bGw9PT1iLmdjaigpKWlmKHIuYj09Yi5na3UoKSlpZihyLmdKZihyKT09Yi5n
+SmYoYikpaWYoci5ndHAocik9PWIuZ3RwKGIpKWlmKHIuZT09PWIuZ0lpKGIpKXt0PXIuZgpzPXQ9PW51
+bGwKaWYoIXM9PT1iLmdRRCgpKXtpZihzKXQ9IiIKaWYodD09PWIuZ3RQKGIpKXt0PXIucgpzPXQ9PW51
+bGwKaWYoIXM9PT1iLmdaOCgpKXtpZihzKXQ9IiIKdD10PT09Yi5nS2EoKX1lbHNlIHQ9ITF9ZWxzZSB0
+PSExfWVsc2UgdD0hMX1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0
+PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKcmV0dXJuIHR9LApnaTpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LnoKcmV0dXJuIHQ9PW51bGw/dGhpcy56PUMueEIuZ2kodGhpcy5aKDApKTp0fSwKc282OmZ1bmN0aW9u
+KGEpe3RoaXMueD11LmEuYShhKX0sCnNSSDpmdW5jdGlvbihhKXt0aGlzLlE9dS5mLmEoYSl9LAokaWlE
+OjEsCmdGaTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmF9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
+aXMuZX19ClAuZTEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAucnIoIkludmFs
+aWQgcG9ydCIsdGhpcy5hLHRoaXMuYisxKSl9LAokUzoxNX0KUC5OWS5wcm90b3R5cGU9ewokMTpmdW5j
+dGlvbihhKXt2YXIgdD0iSWxsZWdhbCBwYXRoIGNoYXJhY3RlciAiCkguYyhhKQppZihKLnpsKGEsIi8i
+KSlpZih0aGlzLmEpdGhyb3cgSC5iKFAueFkodCthKSkKZWxzZSB0aHJvdyBILmIoUC5MNCh0K2EpKX0s
+CiRTOjE1fQpQLlJaLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBQLmVQKEMuWkosYSxD
+LnhNLCExKX0sCiRTOjV9ClAuTUUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlz
+LmIscz10aGlzLmEKdC5hKz1zLmEKcy5hPSImIgpzPXQuYSs9SC5kKFAuZVAoQy5GMyxhLEMueE0sITAp
+KQppZihiIT1udWxsJiZiLmxlbmd0aCE9PTApe3QuYT1zKyI9Igp0LmErPUguZChQLmVQKEMuRjMsYixD
+LnhNLCEwKSl9fSwKJFM6MTZ9ClAueTUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+CkguYyhhKQppZihiPT1udWxsfHx0eXBlb2YgYj09InN0cmluZyIpdGhpcy5hLiQyKGEsSC5jKGIpKQpl
+bHNlIGZvcih0PUouSVQodS5SLmEoYikpLHM9dGhpcy5hO3QubSgpOylzLiQyKGEsSC5jKHQuZ1IodCkp
+KX0sCiRTOjEzfQpQLlBFLnByb3RvdHlwZT17CmdsUjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhp
+cyxvPW51bGwsbj1wLmMKaWYobiE9bnVsbClyZXR1cm4gbgpuPXAuYgppZigwPj1uLmxlbmd0aClyZXR1
+cm4gSC5rKG4sMCkKdD1wLmEKbj1uWzBdKzEKcz1DLnhCLlhVKHQsIj8iLG4pCnI9dC5sZW5ndGgKaWYo
+cz49MCl7cT1QLnVPKHQscysxLHIsQy5WQywhMSkKcj1zfWVsc2UgcT1vCnJldHVybiBwLmM9bmV3IFAu
+cWUoImRhdGEiLG8sbyxvLFAudU8odCxuLHIsQy5XZCwhMSkscSxvKX0sClo6ZnVuY3Rpb24oYSl7dmFy
+IHQscz10aGlzLmIKaWYoMD49cy5sZW5ndGgpcmV0dXJuIEguayhzLDApCnQ9dGhpcy5hCnJldHVybiBz
+WzBdPT09LTE/ImRhdGE6Iit0OnR9fQpQLnEzLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVy
+biBuZXcgVWludDhBcnJheSg5Nil9LAokUzoyMn0KUC55SS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihh
+LGIpe3ZhciB0PXRoaXMuYQppZihhPj10Lmxlbmd0aClyZXR1cm4gSC5rKHQsYSkKdD10W2FdCkouQ00o
+dCwwLDk2LGIpCnJldHVybiB0fSwKJFM6NDl9ClAuYzYucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0LHMscixxCmZvcih0PWIubGVuZ3RoLHM9YS5sZW5ndGgscj0wO3I8dDsrK3Ipe3E9Qy54
+Qi5XZChiLHIpXjk2CmlmKHE+PXMpcmV0dXJuIEguayhhLHEpCmFbcV09Y319fQpQLnFkLnByb3RvdHlw
+ZT17CiQzOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQpmb3IodD1DLnhCLldkKGIsMCkscz1DLnhC
+LldkKGIsMSkscj1hLmxlbmd0aDt0PD1zOysrdCl7cT0odF45Nik+Pj4wCmlmKHE+PXIpcmV0dXJuIEgu
+ayhhLHEpCmFbcV09Y319fQpQLlVmLnByb3RvdHlwZT17CmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlz
+LmM+MH0sCmd4QTpmdW5jdGlvbigpe3ZhciB0LHMKaWYodGhpcy5jPjApe3Q9dGhpcy5kCmlmKHR5cGVv
+ZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCnM9dGhpcy5lCmlmKHR5cGVvZiBzIT09Im51bWJlciIp
+cmV0dXJuIEgucFkocykKcz10KzE8cwp0PXN9ZWxzZSB0PSExCnJldHVybiB0fSwKZ1FEOmZ1bmN0aW9u
+KCl7dmFyIHQ9dGhpcy5mCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCnJldHVybiB0
+PHRoaXMucn0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnI8dGhpcy5hLmxlbmd0aH0sCmdOdzpm
+dW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZDLnhCLm5DKHRoaXMuYSwiZmlsZSIpfSwKZ1daOmZ1
+bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQmJkMueEIubkModGhpcy5hLCJodHRwIil9LApnUmU6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NSYmQy54Qi5uQyh0aGlzLmEsImh0dHBzIil9LApndFQ6ZnVu
+Y3Rpb24oKXtyZXR1cm4gQy54Qi5RaSh0aGlzLmEsIi8iLHRoaXMuZSl9LApnRmk6ZnVuY3Rpb24oKXt2
+YXIgdCxzPXRoaXMscj0icGFja2FnZSIscT1zLmIKaWYocTw9MClyZXR1cm4iIgp0PXMueAppZih0IT1u
+dWxsKXJldHVybiB0CmlmKHMuZ1daKCkpcT1zLng9Imh0dHAiCmVsc2UgaWYocy5nUmUoKSl7cy54PSJo
+dHRwcyIKcT0iaHR0cHMifWVsc2UgaWYocy5nTncoKSl7cy54PSJmaWxlIgpxPSJmaWxlIn1lbHNlIGlm
+KHE9PT03JiZDLnhCLm5DKHMuYSxyKSl7cy54PXIKcT1yfWVsc2V7cT1DLnhCLk5qKHMuYSwwLHEpCnMu
+eD1xfXJldHVybiBxfSwKZ2t1OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5jLHM9dGhpcy5iKzMKcmV0dXJu
+IHQ+cz9DLnhCLk5qKHRoaXMuYSxzLHQtMSk6IiJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5j
+CnJldHVybiB0PjA/Qy54Qi5Oaih0aGlzLmEsdCx0aGlzLmQpOiIifSwKZ3RwOmZ1bmN0aW9uKGEpe3Zh
+ciB0LHM9dGhpcwppZihzLmd4QSgpKXt0PXMuZAppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0
+LmgoKQpyZXR1cm4gUC5RQShDLnhCLk5qKHMuYSx0KzEscy5lKSxudWxsLG51bGwpfWlmKHMuZ1daKCkp
+cmV0dXJuIDgwCmlmKHMuZ1JlKCkpcmV0dXJuIDQ0MwpyZXR1cm4gMH0sCmdJaTpmdW5jdGlvbihhKXty
+ZXR1cm4gQy54Qi5Oaih0aGlzLmEsdGhpcy5lLHRoaXMuZil9LApndFA6ZnVuY3Rpb24oYSl7dmFyIHQ9
+dGhpcy5mLHM9dGhpcy5yCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCnJldHVybiB0
+PHM/Qy54Qi5Oaih0aGlzLmEsdCsxLHMpOiIifSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yLHM9
+dGhpcy5hCnJldHVybiB0PHMubGVuZ3RoP0MueEIueW4ocyx0KzEpOiIifSwKZ0ZqOmZ1bmN0aW9uKCl7
+dmFyIHQscyxyPXRoaXMuZSxxPXRoaXMuZixwPXRoaXMuYQppZihDLnhCLlFpKHAsIi8iLHIpKXtpZih0
+eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLmgoKTsrK3J9aWYocj09cSlyZXR1cm4gQy54RAp0PUgu
+Vk0oW10sdS5zKQpzPXIKd2hpbGUoITApe2lmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSigp
+CmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIEgucFkocSkKaWYoIShzPHEpKWJyZWFrCmlmKEMu
+eEIuTzIocCxzKT09PTQ3KXtDLk5tLkEodCxDLnhCLk5qKHAscixzKSkKcj1zKzF9KytzfUMuTm0uQSh0
+LEMueEIuTmoocCxyLHEpKQpyZXR1cm4gUC5BRih0LHUuTil9LApnaFk6ZnVuY3Rpb24oKXt2YXIgdD10
+aGlzLHM9dC5mCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSigpCmlmKHM+PXQucilyZXR1
+cm4gQy5XTwpyZXR1cm4gbmV3IFAuR2ooUC5XWCh0Lmd0UCh0KSksdS5FKX0sCmtYOmZ1bmN0aW9uKGEp
+e3ZhciB0LHM9dGhpcy5kCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuaCgpCnQ9cysxCnJl
+dHVybiB0K2EubGVuZ3RoPT09dGhpcy5lJiZDLnhCLlFpKHRoaXMuYSxhLHQpfSwKTjk6ZnVuY3Rpb24o
+KXt2YXIgdD10aGlzLHM9dC5yLHI9dC5hCmlmKHM+PXIubGVuZ3RoKXJldHVybiB0CnJldHVybiBuZXcg
+UC5VZihDLnhCLk5qKHIsMCxzKSx0LmIsdC5jLHQuZCx0LmUsdC5mLHMsdC54KX0sCm5tOmZ1bmN0aW9u
+KGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaj10aGlzLGk9bnVsbAp1LlguYShudWxsKQp1LmIu
+YShiKQp0PWouZ0ZpKCkKcz10PT09ImZpbGUiCnI9ai5jCnE9cj4wP0MueEIuTmooai5hLGouYiszLHIp
+OiIiCnA9ai5neEEoKT9qLmd0cChqKTppCnI9ai5jCmlmKHI+MClvPUMueEIuTmooai5hLHIsai5kKQpl
+bHNlIG89cS5sZW5ndGghPT0wfHxwIT1udWxsfHxzPyIiOmkKcj1qLmEKbj1DLnhCLk5qKHIsai5lLGou
+ZikKaWYoIXMpbT1vIT1udWxsJiZuLmxlbmd0aCE9PTAKZWxzZSBtPSEwCmlmKG0mJiFDLnhCLm5DKG4s
+Ii8iKSluPSIvIituCmw9UC5sZShpLDAsMCxiKQptPWoucgprPW08ci5sZW5ndGg/Qy54Qi55bihyLG0r
+MSk6aQpyZXR1cm4gbmV3IFAuRG4odCxxLG8scCxuLGwsayl9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4g
+dGhpcy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBQLlVmKXJldHVy
+biB0aGlzLnUxKHRoaXMsYSkKcmV0dXJuIHRoaXMudnMoKS5tUyhhKX0sCnUxOmZ1bmN0aW9uKGEsYil7
+dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGU9Yi5iCmlmKGU+MClyZXR1cm4gYgp0PWIu
+YwppZih0PjApe3M9YS5iCmlmKHM8PTApcmV0dXJuIGIKaWYoYS5nTncoKSlyPWIuZSE9Yi5mCmVsc2Ug
+aWYoYS5nV1ooKSlyPSFiLmtYKCI4MCIpCmVsc2Ugcj0hYS5nUmUoKXx8IWIua1goIjQ0MyIpCmlmKHIp
+e3E9cysxCnA9Qy54Qi5OaihhLmEsMCxxKStDLnhCLnluKGIuYSxlKzEpCmU9Yi5kCmlmKHR5cGVvZiBl
+IT09Im51bWJlciIpcmV0dXJuIGUuaCgpCm89Yi5lCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJu
+IG8uaCgpCm49Yi5mCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4uaCgpCnJldHVybiBuZXcg
+UC5VZihwLHMsdCtxLGUrcSxvK3EsbitxLGIucitxLGEueCl9ZWxzZSByZXR1cm4gdGhpcy52cygpLm1T
+KGIpfW09Yi5lCmU9Yi5mCmlmKG09PWUpe3Q9Yi5yCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJu
+IGUuSigpCmlmKGU8dCl7cz1hLmYKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCnE9
+cy1lCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLHMpK0MueEIueW4oYi5hLGUpLGEuYixhLmMs
+YS5kLGEuZSxlK3EsdCtxLGEueCl9ZT1iLmEKaWYodDxlLmxlbmd0aCl7cz1hLnIKcmV0dXJuIG5ldyBQ
+LlVmKEMueEIuTmooYS5hLDAscykrQy54Qi55bihlLHQpLGEuYixhLmMsYS5kLGEuZSxhLmYsdCsocy10
+KSxhLngpfXJldHVybiBhLk45KCl9dD1iLmEKaWYoQy54Qi5RaSh0LCIvIixtKSl7cz1hLmUKaWYodHlw
+ZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJu
+IEgucFkobSkKcT1zLW0KcD1DLnhCLk5qKGEuYSwwLHMpK0MueEIueW4odCxtKQppZih0eXBlb2YgZSE9
+PSJudW1iZXIiKXJldHVybiBlLmgoKQpyZXR1cm4gbmV3IFAuVWYocCxhLmIsYS5jLGEuZCxzLGUrcSxi
+LnIrcSxhLngpfWw9YS5lCms9YS5mCmlmKGw9PWsmJmEuYz4wKXtmb3IoO0MueEIuUWkodCwiLi4vIixt
+KTspe2lmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIG0uaCgpCm0rPTN9aWYodHlwZW9mIGwhPT0i
+bnVtYmVyIilyZXR1cm4gbC5ITigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFkobSkK
+cT1sLW0rMQpwPUMueEIuTmooYS5hLDAsbCkrIi8iK0MueEIueW4odCxtKQppZih0eXBlb2YgZSE9PSJu
 dW1iZXIiKXJldHVybiBlLmgoKQpyZXR1cm4gbmV3IFAuVWYocCxhLmIsYS5jLGEuZCxsLGUrcSxiLnIr
 cSxhLngpfWo9YS5hCmZvcihpPWw7Qy54Qi5RaShqLCIuLi8iLGkpOyl7aWYodHlwZW9mIGkhPT0ibnVt
 YmVyIilyZXR1cm4gaS5oKCkKaSs9M31oPTAKd2hpbGUoITApe2lmKHR5cGVvZiBtIT09Im51bWJlciIp
 cmV0dXJuIG0uaCgpCmc9bSszCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJuIEgucFkoZSkKaWYo
 IShnPD1lJiZDLnhCLlFpKHQsIi4uLyIsbSkpKWJyZWFrOysraAptPWd9Zj0iIgp3aGlsZSghMCl7aWYo
 dHlwZW9mIGshPT0ibnVtYmVyIilyZXR1cm4gay5vcygpCmlmKHR5cGVvZiBpIT09Im51bWJlciIpcmV0
-dXJuIEgucFkoaSkKaWYoIShrPmkpKWJyZWFrOy0tawppZihDLnhCLm0oaixrKT09PTQ3KXtpZihoPT09
-MCl7Zj0iLyIKYnJlYWt9LS1oCmY9Ii8ifX1pZihrPT09aSYmYS5iPD0wJiYhQy54Qi5RaShqLCIvIixs
-KSl7bS09aCozCmY9IiJ9cT1rLW0rZi5sZW5ndGgKcmV0dXJuIG5ldyBQLlVmKEMueEIudyhqLDAsaykr
-ZitDLnhCLkcodCxtKSxhLmIsYS5jLGEuZCxsLGUrcSxiLnIrcSxhLngpfSwKdDQ6ZnVuY3Rpb24oKXt2
-YXIgdCxzLHIscSxwPXRoaXMKaWYocC5iPj0wJiYhcC5nTncoKSl0aHJvdyBILmIoUC5MNCgiQ2Fubm90
-IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIrSC5kKHAuZ0ZpKCkpKyIgVVJJIikpCnQ9cC5mCnM9
-cC5hCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCmlmKHQ8cy5sZW5ndGgpe2lmKHQ8
-cC5yKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJIHdp
-dGggYSBxdWVyeSBjb21wb25lbnQiKSkKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmls
-ZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIGZyYWdtZW50IGNvbXBvbmVudCIpKX1yPSQuT3goKQppZihI
-Lm9UKHIpKXQ9UC5tbihwKQplbHNle3E9cC5kCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIEgu
-cFkocSkKaWYocC5jPHEpSC52aChQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIG5vbi1XaW5kb3dzIGZpbGUg
-cGF0aCBmcm9tIGEgZmlsZSBVUkkgd2l0aCBhbiBhdXRob3JpdHkiKSkKdD1DLnhCLncocyxwLmUsdCl9
-cmV0dXJuIHR9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy55CnJldHVybiB0PT1udWxsP3RoaXMu
-eT1DLnhCLmdpTyh0aGlzLmEpOnR9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEK
-aWYodGhpcz09PWIpcmV0dXJuITAKcmV0dXJuIHUuRS5iKGIpJiZ0aGlzLmE9PT1iLlooMCl9LAp2czpm
-dW5jdGlvbigpe3ZhciB0PXRoaXMscz1udWxsLHI9dC5nRmkoKSxxPXQuZ2t1KCkscD10LmM+MD90LmdK
-Zih0KTpzLG89dC5neEEoKT90Lmd0cCh0KTpzLG49dC5hLG09dC5mLGw9Qy54Qi53KG4sdC5lLG0pLGs9
-dC5yCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIG0uSigpCm09bTxrP3QuZ3RQKCk6cwpyZXR1
-cm4gbmV3IFAuRG4ocixxLHAsbyxsLG0sazxuLmxlbmd0aD90LmdLYSgpOnMpfSwKWjpmdW5jdGlvbihh
-KXtyZXR1cm4gdGhpcy5hfSwKJGlpRDoxfQpQLnFlLnByb3RvdHlwZT17fQpXLnFFLnByb3RvdHlwZT17
-fQpXLkdoLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpR2g6MX0K
-Vy5mWS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLm5CLnByb3Rv
-dHlwZT17JGluQjoxfQpXLkF6LnByb3RvdHlwZT17JGlBejoxfQpXLlFQLnByb3RvdHlwZT17JGlRUDox
-fQpXLm54LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcub0oucHJv
-dG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5pZC5wcm90b3R5cGU9e30K
-Vy5RRi5wcm90b3R5cGU9e30KVy5OaC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJp
-bmcoYSl9fQpXLklCLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIlJlY3RhbmdsZSAoIitI
-LmQoYS5sZWZ0KSsiLCAiK0guZChhLnRvcCkrIikgIitILmQoYS53aWR0aCkrIiB4ICIrSC5kKGEuaGVp
-Z2h0KX0sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gdS5xLmIoYikm
-JmEubGVmdD09Yi5sZWZ0JiZhLnRvcD09Yi50b3AmJmEud2lkdGg9PWIud2lkdGgmJmEuaGVpZ2h0PT1i
-LmhlaWdodH0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gVy5yRShKLmhmKGEubGVmdCksSi5oZihhLnRv
-cCksSi5oZihhLndpZHRoKSxKLmhmKGEuaGVpZ2h0KSl9LAokaXRuOjF9ClcubjcucHJvdG90eXBlPXsK
-Z0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy53ei5wcm90b3R5cGU9ewpnQTpmdW5jdGlv
-bihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXt2YXIgdApILldZKGIpCnQ9
-dGhpcy5hCmlmKGI8MHx8Yj49dC5sZW5ndGgpcmV0dXJuIEguayh0LGIpCnJldHVybiB0aGlzLiR0aS5j
-LmEodFtiXSl9LApZOmZ1bmN0aW9uKGEsYixjKXt0aGlzLiR0aS5jLmEoYykKdGhyb3cgSC5iKFAuTDQo
-IkNhbm5vdCBtb2RpZnkgbGlzdCIpKX19ClcuY3YucHJvdG90eXBlPXsKZ1FnOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBuZXcgVy5pNyhhKX0sCmdEOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5JNChhKX0sCnNEOmZ1
-bmN0aW9uKGEsYil7dmFyIHQKdS5YLmEoYikKdD10aGlzLmdEKGEpCnQuVjEoMCkKdC5GVigwLGIpfSwK
-WjpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhbE5hbWV9LAp0bjpmdW5jdGlvbihhKXt2YXIgdD0hIWEu
-c2Nyb2xsSW50b1ZpZXdJZk5lZWRlZAppZih0KWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZCgpCmVsc2Ug
-YS5zY3JvbGxJbnRvVmlldygpfSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEKaWYoYz09
-bnVsbCl7aWYoZD09bnVsbCl7dD0kLmx0CmlmKHQ9PW51bGwpe3Q9SC5WTShbXSx1LmspCnM9bmV3IFcu
-dkQodCkKQy5ObS5pKHQsVy5UdyhudWxsKSkKQy5ObS5pKHQsVy5CbCgpKQokLmx0PXMKZD1zfWVsc2Ug
-ZD10fXQ9JC5FVQppZih0PT1udWxsKXt0PW5ldyBXLktvKGQpCiQuRVU9dApjPXR9ZWxzZXt0LmE9ZApj
-PXR9fWVsc2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgidmFsaWRhdG9yIGNhbiBvbmx5IGJlIHBh
-c3NlZCBpZiB0cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC54bz09bnVsbCl7dD1kb2N1bWVudApz
-PXQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKQokLnhvPXMKJC5CTz1zLmNyZWF0
-ZVJhbmdlKCkKcz0kLnhvLmNyZWF0ZUVsZW1lbnQoImJhc2UiKQp1LmNSLmEocykKcy5ocmVmPXQuYmFz
-ZVVSSQokLnhvLmhlYWQuYXBwZW5kQ2hpbGQocyl9dD0kLnhvCmlmKHQuYm9keT09bnVsbCl7cz10LmNy
-ZWF0ZUVsZW1lbnQoImJvZHkiKQp0LmJvZHk9dS5ZLmEocyl9dD0kLnhvCmlmKHUuWS5iKGEpKXI9dC5i
-b2R5CmVsc2V7cj10LmNyZWF0ZUVsZW1lbnQoYS50YWdOYW1lKQokLnhvLmJvZHkuYXBwZW5kQ2hpbGQo
-cil9aWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSYm
-IUMuTm0udGcoQy5TcSxhLnRhZ05hbWUpKXskLkJPLnNlbGVjdE5vZGVDb250ZW50cyhyKQpxPSQuQk8u
-Y3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KGIpfWVsc2V7ci5pbm5lckhUTUw9YgpxPSQueG8uY3JlYXRl
-RG9jdW1lbnRGcmFnbWVudCgpCmZvcig7dD1yLmZpcnN0Q2hpbGQsdCE9bnVsbDspcS5hcHBlbmRDaGls
-ZCh0KX10PSQueG8uYm9keQppZihyPT1udWxsP3QhPW51bGw6ciE9PXQpSi5MdChyKQpjLlBuKHEpCmRv
-Y3VtZW50LmFkb3B0Tm9kZShxKQpyZXR1cm4gcX0sCkFIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gdGhp
-cy5yNihhLGIsYyxudWxsKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxiKX0sCnBrOmZ1bmN0
-aW9uKGEsYixjKXthLnRleHRDb250ZW50PW51bGwKYS5hcHBlbmRDaGlsZCh0aGlzLnI2KGEsYixudWxs
-LGMpKX0sCllDOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwpfSwKZ25zOmZ1bmN0
-aW9uKGEpe3JldHVybiBhLnRhZ05hbWV9LApnVmw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLmV1KGEs
-ImNsaWNrIiwhMSx1LlEpfSwKJGljdjoxfQpXLkN2LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
-dHVybiB1LmguYih1LkEuYShhKSl9LAokUzoyNX0KVy5lYS5wcm90b3R5cGU9eyRpZWE6MX0KVy5EMC5w
-cm90b3R5cGU9ewpPbjpmdW5jdGlvbihhLGIsYyxkKXt1LlUuYShjKQppZihjIT1udWxsKXRoaXMudihh
-LGIsYyxkKX0sCkI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLk9uKGEsYixjLG51bGwpfSwKdjpm
-dW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYS5hZGRFdmVudExpc3RlbmVyKGIsSC50Uih1LlUuYShjKSwx
-KSxkKX0sCiRpRDA6MX0KVy5UNS5wcm90b3R5cGU9eyRpVDU6MX0KVy5oNC5wcm90b3R5cGU9ewpnQTpm
-dW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmJyLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEp
-e3JldHVybiBhLmxlbmd0aH19ClcuVmIucHJvdG90eXBlPXt9ClcuZkoucHJvdG90eXBlPXsKZW86ZnVu
-Y3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEub3BlbihiLGMsITApfSwKJGlmSjoxfQpXLmJVLnByb3RvdHlw
-ZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLnNldFJlcXVlc3RIZWFkZXIoSC5jKGEpLEguYyhiKSl9
-LAokUzo5fQpXLmhILnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAKdS5wLmEo
-YSkKdD10aGlzLmEKcz10LnN0YXR1cwppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLnRCKCkK
-cj1zPj0yMDAmJnM8MzAwCnE9cz4zMDcmJnM8NDAwCnM9cnx8cz09PTB8fHM9PT0zMDR8fHEKcD10aGlz
-LmIKaWYocylwLmFNKDAsdCkKZWxzZSBwLnBtKGEpfSwKJFM6Mjd9Clcud2EucHJvdG90eXBlPXt9Clcu
-U2cucHJvdG90eXBlPXskaVNnOjF9ClcudTgucHJvdG90eXBlPXsKZ0RyOmZ1bmN0aW9uKGEpe2lmKCJv
-cmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILmQoYS5wcm90b2NvbCkrIi8vIitILmQo
-YS5ob3N0KX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpdTg6MX0KVy5PSy5wcm90
-b3R5cGU9eyRpT0s6MX0KVy5lNy5wcm90b3R5cGU9ewpncjg6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5h
-LHM9dC5jaGlsZE5vZGVzLmxlbmd0aAppZihzPT09MCl0aHJvdyBILmIoUC5QVigiTm8gZWxlbWVudHMi
-KSkKaWYocz4xKXRocm93IEguYihQLlBWKCJNb3JlIHRoYW4gb25lIGVsZW1lbnQiKSkKcmV0dXJuIHQu
-Zmlyc3RDaGlsZH0sCkZWOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKdS5laC5hKGIpCnQ9Yi5hCnM9
-dGhpcy5hCmlmKHQhPT1zKWZvcihyPXQuY2hpbGROb2Rlcy5sZW5ndGgscT0wO3E8cjsrK3Epcy5hcHBl
-bmRDaGlsZCh0LmZpcnN0Q2hpbGQpCnJldHVybn0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKdS5B
-LmEoYykKdD10aGlzLmEKcz10LmNoaWxkTm9kZXMKaWYoYjwwfHxiPj1zLmxlbmd0aClyZXR1cm4gSC5r
-KHMsYikKdC5yZXBsYWNlQ2hpbGQoYyxzW2JdKX0sCmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEu
-Y2hpbGROb2RlcwpyZXR1cm4gbmV3IFcuVzkodCx0Lmxlbmd0aCxILnEodCkuQygiVzk8R20uRT4iKSl9
-LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNoaWxkTm9kZXMubGVuZ3RofSwKcTpmdW5jdGlv
-bihhLGIpe3ZhciB0CkguV1koYikKdD10aGlzLmEuY2hpbGROb2RlcwppZihiPDB8fGI+PXQubGVuZ3Ro
-KXJldHVybiBILmsodCxiKQpyZXR1cm4gdFtiXX19ClcudUgucHJvdG90eXBlPXsKd2c6ZnVuY3Rpb24o
-YSl7dmFyIHQ9YS5wYXJlbnROb2RlCmlmKHQhPW51bGwpdC5yZW1vdmVDaGlsZChhKX0sCkQ0OmZ1bmN0
-aW9uKGEpe3ZhciB0CmZvcig7dD1hLmZpcnN0Q2hpbGQsdCE9bnVsbDspYS5yZW1vdmVDaGlsZCh0KX0s
-Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5ub2RlVmFsdWUKcmV0dXJuIHQ9PW51bGw/dGhpcy5VKGEpOnR9
-LAokaXVIOjF9ClcuQkgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwK
-cTpmdW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIo
-UC50KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7dS5B
-LmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlz
-dC4iKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsYikK
-cmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9ClcuU04ucHJvdG90eXBl
-PXt9ClcuZXcucHJvdG90eXBlPXskaWV3OjF9ClcubHAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7
-cmV0dXJuIGEubGVuZ3RofX0KVy5UYi5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIg
-dCxzCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUp
-cmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1XLlU5KCI8dGFibGU+IitILmQoYikrIjwvdGFibGU+Iixj
-LGQpCnM9ZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnMudG9TdHJpbmcKdC50b1N0cmlu
-ZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHQpKQpyZXR1cm4gc319ClcuSXYucHJvdG90eXBlPXsK
-cjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEKaWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVu
-dCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSlyZXR1cm4gdGhpcy5EVyhhLGIsYyxkKQp0PWRvY3Vt
-ZW50CnM9dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKdD1DLkllLnI2KHQuY3JlYXRlRWxlbWVudCgi
-dGFibGUiKSxiLGMsZCkKdC50b1N0cmluZwp0PW5ldyBXLmU3KHQpCnI9dC5ncjgodCkKci50b1N0cmlu
-Zwp0PW5ldyBXLmU3KHIpCnE9dC5ncjgodCkKcy50b1N0cmluZwpxLnRvU3RyaW5nCm5ldyBXLmU3KHMp
-LkZWKDAsbmV3IFcuZTcocSkpCnJldHVybiBzfX0KVy5CVC5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihh
-LGIsYyxkKXt2YXIgdCxzLHIKaWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJh
-bmdlLnByb3RvdHlwZSlyZXR1cm4gdGhpcy5EVyhhLGIsYyxkKQp0PWRvY3VtZW50CnM9dC5jcmVhdGVE
-b2N1bWVudEZyYWdtZW50KCkKdD1DLkllLnI2KHQuY3JlYXRlRWxlbWVudCgidGFibGUiKSxiLGMsZCkK
-dC50b1N0cmluZwp0PW5ldyBXLmU3KHQpCnI9dC5ncjgodCkKcy50b1N0cmluZwpyLnRvU3RyaW5nCm5l
-dyBXLmU3KHMpLkZWKDAsbmV3IFcuZTcocikpCnJldHVybiBzfX0KVy55WS5wcm90b3R5cGU9ewpwazpm
-dW5jdGlvbihhLGIsYyl7dmFyIHQscwphLnRleHRDb250ZW50PW51bGwKdD1hLmNvbnRlbnQKdC50b1N0
-cmluZwpKLmJUKHQpCnM9dGhpcy5yNihhLGIsbnVsbCxjKQphLmNvbnRlbnQuYXBwZW5kQ2hpbGQocyl9
-LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixudWxsKX0sCiRpeVk6MX0KVy53Ni5w
-cm90b3R5cGU9e30KVy5LNS5wcm90b3R5cGU9ewpnbVc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubG9jYXRp
-b259LAokaUs1OjEsCiRpdjY6MX0KVy5DbS5wcm90b3R5cGU9eyRpQ206MX0KVy5DUS5wcm90b3R5cGU9
-eyRpQ1E6MX0KVy53NC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSZWN0YW5nbGUgKCIr
-SC5kKGEubGVmdCkrIiwgIitILmQoYS50b3ApKyIpICIrSC5kKGEud2lkdGgpKyIgeCAiK0guZChhLmhl
-aWdodCl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUucS5iKGIp
-JiZhLmxlZnQ9PWIubGVmdCYmYS50b3A9PWIudG9wJiZhLndpZHRoPT1iLndpZHRoJiZhLmhlaWdodD09
-Yi5oZWlnaHR9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoSi5oZihhLmxlZnQpLEouaGYoYS50
-b3ApLEouaGYoYS53aWR0aCksSi5oZihhLmhlaWdodCkpfX0KVy5yaC5wcm90b3R5cGU9ewpnQTpmdW5j
-dGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9
-PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFb
-Yl19LApZOmZ1bmN0aW9uKGEsYixjKXt1LkEuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2ln
-biBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+
-PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaWNY
-OjEsCiRpek06MX0KVy5jZi5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscAp1
-LmVBLmEoYikKZm9yKHQ9dGhpcy5nVigpLHM9dC5sZW5ndGgscj10aGlzLmEscT0wO3E8dC5sZW5ndGg7
-dC5sZW5ndGg9PT1zfHwoMCxILmxrKSh0KSwrK3Epe3A9dFtxXQpiLiQyKHAsci5nZXRBdHRyaWJ1dGUo
-cCkpfX0sCmdWOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10aGlzLmEuYXR0cmlidXRlcyxvPUguVk0o
-W10sdS5zKQpmb3IodD1wLmxlbmd0aCxzPXUuaDkscj0wO3I8dDsrK3Ipe2lmKHI+PXAubGVuZ3RoKXJl
-dHVybiBILmsocCxyKQpxPXMuYShwW3JdKQppZihxLm5hbWVzcGFjZVVSST09bnVsbClDLk5tLmkobyxx
-Lm5hbWUpfXJldHVybiBvfX0KVy5pNy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRo
-aXMuYS5nZXRBdHRyaWJ1dGUoSC5jKGIpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5zZXRBdHRy
-aWJ1dGUoYixjKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdWKCkubGVuZ3RofX0KVy5TeS5w
-cm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5hLmdldEF0dHJpYnV0ZSgiZGF0
-YS0iK3RoaXMuTyhILmMoYikpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5hLnNldEF0dHJpYnV0
-ZSgiZGF0YS0iK3RoaXMuTyhiKSxjKX0sCks6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuSygwLG5ldyBXLktT
-KHRoaXMsdS5lQS5hKGIpKSl9LApnVjpmdW5jdGlvbigpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLmEu
-SygwLG5ldyBXLkEzKHRoaXMsdCkpCnJldHVybiB0fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-Z1YoKS5sZW5ndGh9LAprOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj1ILlZNKGEuc3BsaXQoIi0iKSx1LnMp
-CmZvcih0PTE7dDxyLmxlbmd0aDsrK3Qpe3M9clt0XQppZihzLmxlbmd0aD4wKUMuTm0uWShyLHQsc1sw
-XS50b1VwcGVyQ2FzZSgpK0ouS1YocywxKSl9cmV0dXJuIEMuTm0uelYociwiIil9LApPOmZ1bmN0aW9u
-KGEpe3ZhciB0LHMscixxLHAKZm9yKHQ9YS5sZW5ndGgscz0wLHI9IiI7czx0Oysrcyl7cT1hW3NdCnA9
-cS50b0xvd2VyQ2FzZSgpCnI9KHEhPT1wJiZzPjA/cisiLSI6cikrcH1yZXR1cm4gci5jaGFyQ29kZUF0
-KDApPT0wP3I6cn19ClcuS1MucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtpZihKLnJZKGEpLm4o
-YSwiZGF0YS0iKSl0aGlzLmIuJDIodGhpcy5hLmsoQy54Qi5HKGEsNSkpLGIpfSwKJFM6OX0KVy5BMy5w
-cm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lmKEouclkoYSkubihhLCJkYXRhLSIpKUMuTm0uaSh0
-aGlzLmIsdGhpcy5hLmsoQy54Qi5HKGEsNSkpKX0sCiRTOjl9ClcuSTQucHJvdG90eXBlPXsKUDpmdW5j
-dGlvbigpe3ZhciB0LHMscixxLHA9UC5Mcyh1Lk4pCmZvcih0PXRoaXMuYS5jbGFzc05hbWUuc3BsaXQo
-IiAiKSxzPXQubGVuZ3RoLHI9MDtyPHM7KytyKXtxPUouVDAodFtyXSkKaWYocS5sZW5ndGghPT0wKXAu
-aSgwLHEpfXJldHVybiBwfSwKcDpmdW5jdGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPXUuQy5hKGEpLnpW
-KDAsIiAiKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0aH0sClYx
-OmZ1bmN0aW9uKGEpe3RoaXMuYS5jbGFzc05hbWU9IiJ9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciB0PXRo
-aXMuYS5jbGFzc0xpc3QuY29udGFpbnMoYikKcmV0dXJuIHR9LAppOmZ1bmN0aW9uKGEsYil7dmFyIHQ9
-dGhpcy5hLmNsYXNzTGlzdCxzPXQuY29udGFpbnMoYikKdC5hZGQoYikKcmV0dXJuIXN9LApSOmZ1bmN0
-aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlzdCxzPXQuY29udGFpbnMoYikKdC5yZW1vdmUoYikK
-cmV0dXJuIHN9LApGVjpmdW5jdGlvbihhLGIpe1cuVE4odGhpcy5hLHUuWC5hKGIpKX19ClcuRmsucHJv
-dG90eXBlPXt9ClcuUk8ucHJvdG90eXBlPXt9ClcuZXUucHJvdG90eXBlPXt9ClcueEMucHJvdG90eXBl
-PXt9Clcudk4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS4kMSh1LkIuYShh
-KSl9LAokUzoyOH0KVy5KUS5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhKXt2YXIgdAppZigkLm9yLmE9
-PT0wKXtmb3IodD0wO3Q8MjYyOysrdCkkLm9yLlkoMCxDLmNtW3RdLFcucFMoKSkKZm9yKHQ9MDt0PDEy
-OysrdCkkLm9yLlkoMCxDLkJJW3RdLFcuVjQoKSl9fSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuICQuQU4o
-KS50ZygwLFcuclMoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PSQub3IucSgwLEguZChXLnJT
-KGEpKSsiOjoiK2IpCmlmKHQ9PW51bGwpdD0kLm9yLnEoMCwiKjo6IitiKQppZih0PT1udWxsKXJldHVy
-biExCnJldHVybiBILkU5KHQuJDQoYSxiLGMsdGhpcykpfSwKJGlrRjoxfQpXLkdtLnByb3RvdHlwZT17
-CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuVzkoYSx0aGlzLmdBKGEpLEgucShhKS5DKCJXOTxH
-bS5FPiIpKX19ClcudkQucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0uVnIodGhp
-cy5hLG5ldyBXLlV2KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEs
-bmV3IFcuRWcoYSxiLGMpKX0sCiRpa0Y6MX0KVy5Vdi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXty
-ZXR1cm4gdS5lLmEoYSkuaTAodGhpcy5hKX0sCiRTOjE1fQpXLkVnLnByb3RvdHlwZT17CiQxOmZ1bmN0
-aW9uKGEpe3JldHVybiB1LmUuYShhKS5FYih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzoxNX0KVy5t
-Ni5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdGhpcy5hLkZWKDAsYykK
-dD1iLmV2KDAsbmV3IFcuRW8oKSkKcz1iLmV2KDAsbmV3IFcuV2soKSkKdGhpcy5iLkZWKDAsdCkKcj10
-aGlzLmMKci5GVigwLEMuZG4pCnIuRlYoMCxzKX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEu
-dGcoMCxXLnJTKGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD10aGlzLHM9Vy5yUyhhKSxyPXQu
-YwppZihyLnRnKDAsSC5kKHMpKyI6OiIrYikpcmV0dXJuIHQuZC5EdChjKQplbHNlIGlmKHIudGcoMCwi
-Kjo6IitiKSlyZXR1cm4gdC5kLkR0KGMpCmVsc2V7cj10LmIKaWYoci50ZygwLEguZChzKSsiOjoiK2Ip
-KXJldHVybiEwCmVsc2UgaWYoci50ZygwLCIqOjoiK2IpKXJldHVybiEwCmVsc2UgaWYoci50ZygwLEgu
-ZChzKSsiOjoqIikpcmV0dXJuITAKZWxzZSBpZihyLnRnKDAsIio6OioiKSlyZXR1cm4hMH1yZXR1cm4h
-MX0sCiRpa0Y6MX0KVy5Fby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4hQy5ObS50ZyhD
-LkJJLEguYyhhKSl9LAokUzo4fQpXLldrLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBD
-Lk5tLnRnKEMuQkksSC5jKGEpKX0sCiRTOjh9ClcuY3QucHJvdG90eXBlPXsKRWI6ZnVuY3Rpb24oYSxi
-LGMpe2lmKHRoaXMuakYoYSxiLGMpKXJldHVybiEwCmlmKGI9PT0idGVtcGxhdGUiJiZjPT09IiIpcmV0
-dXJuITAKaWYoYS5nZXRBdHRyaWJ1dGUoInRlbXBsYXRlIik9PT0iIilyZXR1cm4gdGhpcy5lLnRnKDAs
-YikKcmV0dXJuITF9fQpXLklBLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiJURU1QTEFU
-RTo6IitILmQoSC5jKGEpKX0sCiRTOjR9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7dmFy
-IHQKaWYodS5ldy5iKGEpKXJldHVybiExCnQ9dS5nNy5iKGEpCmlmKHQmJlcuclMoYSk9PT0iZm9yZWln
-bk9iamVjdCIpcmV0dXJuITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEsYixj
-KXtpZihiPT09ImlzInx8Qy54Qi5uKGIsIm9uIikpcmV0dXJuITEKcmV0dXJuIHRoaXMuaTAoYSl9LAok
-aWtGOjF9ClcuVzkucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LmMrMSxyPXQu
-YgppZihzPHIpe3Quc00oSi54OSh0LmEscykpCnQuYz1zCnJldHVybiEwfXQuc00obnVsbCkKdC5jPXIK
-cmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApzTTpmdW5jdGlvbihhKXt0aGlz
-LmQ9dGhpcy4kdGkuYy5hKGEpfSwKJGlBbjoxfQpXLmRXLnByb3RvdHlwZT17CmdtVzpmdW5jdGlvbihh
-KXtyZXR1cm4gVy56WCh0aGlzLmEubG9jYXRpb24pfSwKJGlEMDoxLAokaXY2OjF9ClcuRmIucHJvdG90
-eXBlPXt9Clcua0YucHJvdG90eXBlPXt9ClcubWsucHJvdG90eXBlPXskaXkwOjF9ClcuS28ucHJvdG90
-eXBlPXsKUG46ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPW5ldyBXLmZtKHQpCnQuYj0hMQpzLiQyKGEs
-bnVsbCkKZm9yKDt0LmI7KXt0LmI9ITEKcy4kMihhLG51bGwpfX0sCkVQOmZ1bmN0aW9uKGEsYil7dmFy
-IHQ9dGhpcy5iPSEwCmlmKGIhPW51bGw/YiE9PWEucGFyZW50Tm9kZTp0KUouTHQoYSkKZWxzZSBiLnJl
-bW92ZUNoaWxkKGEpfSwKSTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89ITAsbj1udWxsLG09
-bnVsbAp0cnl7bj1KLmlnKGEpCm09bi5hLmdldEF0dHJpYnV0ZSgiaXMiKQp1LmguYShhKQp0PWZ1bmN0
-aW9uKGMpe2lmKCEoYy5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFtZWROb2RlTWFwKSlyZXR1cm4gdHJ1
-ZQppZihjLmlkPT0nbGFzdENoaWxkJ3x8Yy5uYW1lPT0nbGFzdENoaWxkJ3x8Yy5pZD09J3ByZXZpb3Vz
-U2libGluZyd8fGMubmFtZT09J3ByZXZpb3VzU2libGluZyd8fGMuaWQ9PSdjaGlsZHJlbid8fGMubmFt
-ZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZQp2YXIgbD1jLmNoaWxkTm9kZXMKaWYoYy5sYXN0Q2hpbGQm
-JmMubGFzdENoaWxkIT09bFtsLmxlbmd0aC0xXSlyZXR1cm4gdHJ1ZQppZihjLmNoaWxkcmVuKWlmKCEo
-Yy5jaGlsZHJlbiBpbnN0YW5jZW9mIEhUTUxDb2xsZWN0aW9ufHxjLmNoaWxkcmVuIGluc3RhbmNlb2Yg
-Tm9kZUxpc3QpKXJldHVybiB0cnVlCnZhciBrPTAKaWYoYy5jaGlsZHJlbilrPWMuY2hpbGRyZW4ubGVu
-Z3RoCmZvcih2YXIgaj0wO2o8aztqKyspe3ZhciBpPWMuY2hpbGRyZW5bal0KaWYoaS5pZD09J2F0dHJp
-YnV0ZXMnfHxpLm5hbWU9PSdhdHRyaWJ1dGVzJ3x8aS5pZD09J2xhc3RDaGlsZCd8fGkubmFtZT09J2xh
-c3RDaGlsZCd8fGkuaWQ9PSdwcmV2aW91c1NpYmxpbmcnfHxpLm5hbWU9PSdwcmV2aW91c1NpYmxpbmcn
-fHxpLmlkPT0nY2hpbGRyZW4nfHxpLm5hbWU9PSdjaGlsZHJlbicpcmV0dXJuIHRydWV9cmV0dXJuIGZh
-bHNlfShhKQpvPUgub1QodCk/ITA6IShhLmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXAp
-fWNhdGNoKHEpe0guUnUocSl9cz0iZWxlbWVudCB1bnByaW50YWJsZSIKdHJ5e3M9Si5BYyhhKX1jYXRj
-aChxKXtILlJ1KHEpfXRyeXtyPVcuclMoYSkKdGhpcy5rUih1LmguYShhKSxiLG8scyxyLHUuRy5hKG4p
-LEguYyhtKSl9Y2F0Y2gocSl7aWYoSC5SdShxKSBpbnN0YW5jZW9mIFAuQVQpdGhyb3cgcQplbHNle3Ro
-aXMuRVAoYSxiKQp3aW5kb3cKcD0iUmVtb3ZpbmcgY29ycnVwdGVkIGVsZW1lbnQgIitILmQocykKaWYo
-dHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocCl9fX0sCmtSOmZ1
-bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMKaWYoYyl7bi5FUChhLGIp
-CndpbmRvdwp0PSJSZW1vdmluZyBlbGVtZW50IGR1ZSB0byBjb3JydXB0ZWQgYXR0cmlidXRlcyBvbiA8
-IitkKyI+IgppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fybih0
-KQpyZXR1cm59aWYoIW4uYS5pMChhKSl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxv
-d2VkIGVsZW1lbnQgPCIrSC5kKGUpKyI+IGZyb20gIitILmQoYikKaWYodHlwZW9mIGNvbnNvbGUhPSJ1
-bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4odCkKcmV0dXJufWlmKGchPW51bGwpaWYoIW4uYS5F
-YihhLCJpcyIsZykpe24uRVAoYSxiKQp3aW5kb3cKdD0iUmVtb3ZpbmcgZGlzYWxsb3dlZCB0eXBlIGV4
-dGVuc2lvbiA8IitILmQoZSkrJyBpcz0iJytnKyciPicKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmlu
-ZWQiKXdpbmRvdy5jb25zb2xlLndhcm4odCkKcmV0dXJufXQ9Zi5nVigpCnM9SC5WTSh0LnNsaWNlKDAp
-LEgudDYodCkuQygiamQ8MT4iKSkKZm9yKHI9Zi5nVigpLmxlbmd0aC0xLHQ9Zi5hO3I+PTA7LS1yKXtp
-ZihyPj1zLmxlbmd0aClyZXR1cm4gSC5rKHMscikKcT1zW3JdCnA9bi5hCm89Si5jSChxKQpILmMocSkK
-aWYoIXAuRWIoYSxvLHQuZ2V0QXR0cmlidXRlKHEpKSl7d2luZG93CnA9IlJlbW92aW5nIGRpc2FsbG93
-ZWQgYXR0cmlidXRlIDwiK0guZChlKSsiICIrcSsnPSInK0guZCh0LmdldEF0dHJpYnV0ZShxKSkrJyI+
-JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKQp0LnJl
-bW92ZUF0dHJpYnV0ZShxKX19aWYodS5hVy5iKGEpKW4uUG4oYS5jb250ZW50KX0sCiRpb246MX0KVy5m
-bS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMuYQpzd2l0
-Y2goYS5ub2RlVHlwZSl7Y2FzZSAxOm4uSTQoYSxiKQpicmVhawpjYXNlIDg6Y2FzZSAxMTpjYXNlIDM6
-Y2FzZSA0OmJyZWFrCmRlZmF1bHQ6bi5FUChhLGIpfXQ9YS5sYXN0Q2hpbGQKZm9yKHI9dS5BO251bGwh
-PXQ7KXtzPW51bGwKdHJ5e3M9dC5wcmV2aW91c1NpYmxpbmcKaWYocyE9bnVsbCl7cT1zLm5leHRTaWJs
-aW5nCnA9dApwPXE9PW51bGw/cCE9bnVsbDpxIT09cApxPXB9ZWxzZSBxPSExCmlmKHEpe3E9UC5QVigi
-Q29ycnVwdCBIVE1MIikKdGhyb3cgSC5iKHEpfX1jYXRjaChvKXtILlJ1KG8pCnE9ci5hKHQpCm4uYj0h
-MApwPXEucGFyZW50Tm9kZQpwPWE9PW51bGw/cCE9bnVsbDphIT09cAppZihwKXtwPXEucGFyZW50Tm9k
-ZQppZihwIT1udWxsKXAucmVtb3ZlQ2hpbGQocSl9ZWxzZSBhLnJlbW92ZUNoaWxkKHEpCnQ9bnVsbApz
-PWEubGFzdENoaWxkfWlmKHQhPW51bGwpdGhpcy4kMih0LGEpCnQ9c319LAokUzozOX0KVy5MZS5wcm90
-b3R5cGU9e30KVy5LNy5wcm90b3R5cGU9e30KVy5yQi5wcm90b3R5cGU9e30KVy5YVy5wcm90b3R5cGU9
-e30KVy5vYS5wcm90b3R5cGU9e30KUC5pSi5wcm90b3R5cGU9ewpWSDpmdW5jdGlvbihhKXt2YXIgdCxz
-PXRoaXMuYSxyPXMubGVuZ3RoCmZvcih0PTA7dDxyOysrdClpZihzW3RdPT09YSlyZXR1cm4gdApDLk5t
-LmkocyxhKQpDLk5tLmkodGhpcy5iLG51bGwpCnJldHVybiByfSwKUHY6ZnVuY3Rpb24oYSl7dmFyIHQs
-cyxyLHE9dGhpcyxwPXt9CmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoSC5yUShhKSlyZXR1cm4gYQppZih0
-eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlm
-KGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBuZXcgRGF0ZShhLmEpCmlmKHUuZnYuYihhKSl0aHJvdyBI
-LmIoUC5uKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIFJlZ0V4cCIpKQppZih1LmM4LmIoYSkpcmV0dXJuIGEK
-aWYodS5kLmIoYSkpcmV0dXJuIGEKaWYodS5JLmIoYSkpcmV0dXJuIGEKdD11LmRELmIoYSl8fCExCmlm
-KHQpcmV0dXJuIGEKaWYodS5HLmIoYSkpe3M9cS5WSChhKQp0PXEuYgppZihzPj10Lmxlbmd0aClyZXR1
-cm4gSC5rKHQscykKcj1wLmE9dFtzXQppZihyIT1udWxsKXJldHVybiByCnI9e30KcC5hPXIKQy5ObS5Z
-KHQscyxyKQphLksoMCxuZXcgUC5qZyhwLHEpKQpyZXR1cm4gcC5hfWlmKHUuai5iKGEpKXtzPXEuVkgo
-YSkKcD1xLmIKaWYocz49cC5sZW5ndGgpcmV0dXJuIEguayhwLHMpCnI9cFtzXQppZihyIT1udWxsKXJl
-dHVybiByCnJldHVybiBxLmVrKGEscyl9aWYodS5lSC5iKGEpKXtzPXEuVkgoYSkKdD1xLmIKaWYocz49
-dC5sZW5ndGgpcmV0dXJuIEguayh0LHMpCnI9cC5iPXRbc10KaWYociE9bnVsbClyZXR1cm4gcgpyPXt9
-CnAuYj1yCkMuTm0uWSh0LHMscikKcS5pbShhLG5ldyBQLlRhKHAscSkpCnJldHVybiBwLmJ9dGhyb3cg
-SC5iKFAubigic3RydWN0dXJlZCBjbG9uZSBvZiBvdGhlciB0eXBlIikpfSwKZWs6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzPUouVTYoYSkscj1zLmdBKGEpLHE9bmV3IEFycmF5KHIpCkMuTm0uWSh0aGlzLmIsYixx
-KQpmb3IodD0wO3Q8cjsrK3QpQy5ObS5ZKHEsdCx0aGlzLlB2KHMucShhLHQpKSkKcmV0dXJuIHF9fQpQ
-LmpnLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLmFbYV09dGhpcy5iLlB2KGIpfSwK
-JFM6MX0KUC5UYS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS5iW2FdPXRoaXMuYi5Q
-dihiKX0sCiRTOjF9ClAuQmYucHJvdG90eXBlPXsKaW06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1
-LmI4LmEoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSkscz10Lmxlbmd0aCxyPTA7cjxzOysrcil7cT10W3Jd
-CmIuJDIocSxhW3FdKX19fQpQLkFzLnByb3RvdHlwZT17ClQ6ZnVuY3Rpb24oYSl7dmFyIHQKSC5jKGEp
-CnQ9JC5oRygpLmIKaWYodHlwZW9mIGEhPSJzdHJpbmciKUgudmgoSC5JKGEpKQppZih0LnRlc3QoYSkp
-cmV0dXJuIGEKdGhyb3cgSC5iKFAuTDMoYSwidmFsdWUiLCJOb3QgYSB2YWxpZCBjbGFzcyB0b2tlbiIp
-KX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuUCgpLnpWKDAsIiAiKX0sCmdrejpmdW5jdGlvbihh
-KXt2YXIgdD10aGlzLlAoKQpyZXR1cm4gUC5yaih0LHQucixILkxoKHQpLmMpfSwKZ0E6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMuUCgpLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3RoaXMuVChiKQpyZXR1cm4gdGhp
-cy5QKCkudGcoMCxiKX0sCmk6ZnVuY3Rpb24oYSxiKXt0aGlzLlQoYikKcmV0dXJuIEguRTkodGhpcy5P
-UyhuZXcgUC5HRShiKSkpfSwKUjpmdW5jdGlvbihhLGIpe3ZhciB0LHMKdGhpcy5UKGIpCnQ9dGhpcy5Q
-KCkKcz10LlIoMCxiKQp0aGlzLnAodCkKcmV0dXJuIHN9LApGVjpmdW5jdGlvbihhLGIpe3RoaXMuT1Mo
-bmV3IFAuTjcodGhpcyx1LlguYShiKSkpfSwKVjE6ZnVuY3Rpb24oYSl7dGhpcy5PUyhuZXcgUC51USgp
-KX0sCk9TOmZ1bmN0aW9uKGEpe3ZhciB0LHMKdS5iVS5hKGEpCnQ9dGhpcy5QKCkKcz1hLiQxKHQpCnRo
-aXMucCh0KQpyZXR1cm4gc319ClAuR0UucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUu
-Qy5hKGEpLmkoMCx0aGlzLmEpfSwKJFM6MzJ9ClAuTjcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
-dmFyIHQ9dGhpcy5iLHM9SC50Nih0KQpyZXR1cm4gdS5DLmEoYSkuRlYoMCxuZXcgSC5sSih0LHMuQygi
-cVUoMSkiKS5hKHRoaXMuYS5ndU0oKSkscy5DKCJsSjwxLHFVPiIpKSl9LAokUzoxNn0KUC51US5wcm90
-b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LkMuYShhKQppZihhLmE+MCl7YS5iPWEuYz1hLmQ9YS5lPWEu
-Zj1udWxsCmEuYT0wCmEuWCgpfXJldHVybiBudWxsfSwKJFM6MTZ9ClAuaEYucHJvdG90eXBlPXskaWhG
-OjF9ClAuUEMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5aLmEoYSkKdD1mdW5jdGlv
-bihiLGMsZCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGIoYyxkLHRoaXMsQXJyYXkucHJvdG90eXBl
-LnNsaWNlLmFwcGx5KGFyZ3VtZW50cykpfX0oUC5SNCxhLCExKQpQLkRtKHQsJC53USgpLGEpCnJldHVy
-biB0fSwKJFM6M30KUC5tdC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IHRoaXMu
-YShhKX0sCiRTOjN9ClAuTnoucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLnI3
-KGEpfSwKJFM6MzR9ClAubnAucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLlR6
-KGEsdS5hbSl9LAokUzozNX0KUC5VdC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3
-IFAuRTQoYSl9LAokUzozNn0KUC5FNC5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9m
-IGIhPSJzdHJpbmciJiZ0eXBlb2YgYiE9Im51bWJlciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlz
-IG5vdCBhIFN0cmluZyBvciBudW0iKSkKcmV0dXJuIFAuTDcodGhpcy5hW2JdKX0sClk6ZnVuY3Rpb24o
-YSxiLGMpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIiYmdHlwZW9mIGIhPSJudW1iZXIiKXRocm93IEguYihQ
-LnhZKCJwcm9wZXJ0eSBpcyBub3QgYSBTdHJpbmcgb3IgbnVtIikpCnRoaXMuYVtiXT1QLndZKGMpfSwK
-RE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2YgUC5F
-NCYmdGhpcy5hPT09Yi5hfSwKWjpmdW5jdGlvbihhKXt2YXIgdCxzCnRyeXt0PVN0cmluZyh0aGlzLmEp
-CnJldHVybiB0fWNhdGNoKHMpe0guUnUocykKdD10aGlzLnhiKDApCnJldHVybiB0fX0sClY3OmZ1bmN0
-aW9uKGEsYil7dmFyIHQscz10aGlzLmEKaWYoYj09bnVsbCl0PW51bGwKZWxzZXt0PUgudDYoYikKdD1Q
-LkNIKG5ldyBILmxKKGIsdC5DKCJAKDEpIikuYShQLmlHKCkpLHQuQygibEo8MSxAPiIpKSwhMCx1Lnop
-fXJldHVybiBQLkw3KHNbYV0uYXBwbHkocyx0KSl9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIDB9fQpQ
-LnI3LnByb3RvdHlwZT17fQpQLlR6LnByb3RvdHlwZT17CmNQOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMs
-cz1hPDB8fGE+PXQuZ0EodCkKaWYocyl0aHJvdyBILmIoUC5URShhLDAsdC5nQSh0KSxudWxsLG51bGwp
-KX0sCnE6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYj09Im51bWJlciImJmI9PT1DLmpuLnl1KGIpKXRo
-aXMuY1AoSC5XWShiKSkKcmV0dXJuIHRoaXMuJHRpLmMuYSh0aGlzLlVyKDAsYikpfSwKWTpmdW5jdGlv
-bihhLGIsYyl7dmFyIHQKdGhpcy4kdGkuYy5hKGMpCnQ9Qy5qbi55dShiKQppZihiPT09dCl0aGlzLmNQ
-KGIpCnRoaXMuZTQoMCxiLGMpfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLmxlbmd0aAppZih0
-eXBlb2YgdD09PSJudW1iZXIiJiZ0Pj4+MD09PXQpcmV0dXJuIHQKdGhyb3cgSC5iKFAuUFYoIkJhZCBK
-c0FycmF5IGxlbmd0aCIpKX0sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9ClAuY28ucHJvdG90eXBlPXt9
-ClAubmQucHJvdG90eXBlPXskaW5kOjF9ClAuS2UucHJvdG90eXBlPXsKUDpmdW5jdGlvbigpe3ZhciB0
-LHMscixxLHA9dGhpcy5hLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSxvPVAuTHModS5OKQppZihwPT1udWxs
-KXJldHVybiBvCmZvcih0PXAuc3BsaXQoIiAiKSxzPXQubGVuZ3RoLHI9MDtyPHM7KytyKXtxPUouVDAo
-dFtyXSkKaWYocS5sZW5ndGghPT0wKW8uaSgwLHEpfXJldHVybiBvfSwKcDpmdW5jdGlvbihhKXt0aGlz
-LmEuc2V0QXR0cmlidXRlKCJjbGFzcyIsYS56VigwLCIgIikpfX0KUC5kNS5wcm90b3R5cGU9ewpnRDpm
-dW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuS2UoYSl9LApzaGY6ZnVuY3Rpb24oYSxiKXt0aGlzLllDKGEs
-Yil9LApyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG8KaWYoZD09bnVsbCl7dD1ILlZN
-KFtdLHUuaykKZD1uZXcgVy52RCh0KQpDLk5tLmkodCxXLlR3KG51bGwpKQpDLk5tLmkodCxXLkJsKCkp
-CkMuTm0uaSh0LG5ldyBXLk93KCkpfWM9bmV3IFcuS28oZCkKcz0nPHN2ZyB2ZXJzaW9uPSIxLjEiPicr
-SC5kKGIpKyI8L3N2Zz4iCnQ9ZG9jdW1lbnQKcj10LmJvZHkKcT0ociYmQy5SWSkuQUgocixzLGMpCnA9
-dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKcS50b1N0cmluZwp0PW5ldyBXLmU3KHEpCm89dC5ncjgo
-dCkKZm9yKDt0PW8uZmlyc3RDaGlsZCx0IT1udWxsOylwLmFwcGVuZENoaWxkKHQpCnJldHVybiBwfSwK
-Z1ZsOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5ldShhLCJjbGljayIsITEsdS5RKX0sCiRpZDU6MX0K
-UC5uNi5wcm90b3R5cGU9eyRpYlE6MSwkaWNYOjEsJGl6TToxLCRpQVM6MX0KVS5kMi5wcm90b3R5cGU9
-e30KVS5TZS5wcm90b3R5cGU9e30KVS51Ri5wcm90b3R5cGU9e30KVS5NbC5wcm90b3R5cGU9e30KVS55
-RC5wcm90b3R5cGU9e30KVS53Yi5wcm90b3R5cGU9e30KQi5qOC5wcm90b3R5cGU9e30KQi5xcC5wcm90
-b3R5cGU9e30KVC5tUS5wcm90b3R5cGU9e30KTC5lLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxLHAsbyxuCnUuQi5hKGEpCnQ9d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lCnM9TC5HNih3
-aW5kb3cubG9jYXRpb24uaHJlZikKcj1MLmFLKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpMLkdlKCkKaWYo
-dCE9PSIvIiYmdCE9PUouVDAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVu
-dCkpTC5HNyh0LHMsciwhMCxuZXcgTC5WVyh0LHMscikpCnE9ZG9jdW1lbnQKcD1KLnFGKHEucXVlcnlT
-ZWxlY3RvcigiLmFwcGx5LW1pZ3JhdGlvbiIpKQpvPXAuJHRpCm49by5DKCJ+KDEpIikuYShuZXcgTC5v
-WigpKQp1Lk0uYShudWxsKQpXLkpFKHAuYSxwLmIsbiwhMSxvLmMpCnE9Si5xRihxLnF1ZXJ5U2VsZWN0
-b3IoIi5yZXJ1bi1taWdyYXRpb24iKSkKbz1xLiR0aQpXLkpFKHEuYSxxLmIsby5DKCJ+KDEpIikuYShu
-ZXcgTC55OCgpKSwhMSxvLmMpfSwKJFM6MTd9CkwuVlcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtM
-LkZyKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjB9Ckwub1oucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7dS5WLmEoYSkKaWYoSC5vVCh3aW5kb3cuY29uZmlybSgiVGhpcyB3aWxsIGFwcGx5IHRoZSBj
-aGFuZ2VzIHlvdSd2ZSBwcmV2aWV3ZWQgdG8geW91ciB3b3JraW5nIGRpcmVjdG9yeS4gSXQgaXMgcmVj
-b21tZW5kZWQgeW91IGNvbW1pdCBhbnkgY2hhbmdlcyB5b3UgbWFkZSBiZWZvcmUgZG9pbmcgdGhpcy4i
-KSkpTC50eSgiL2FwcGx5LW1pZ3JhdGlvbiIpLlc3KG5ldyBMLmpyKCksdS5QKS5PQShuZXcgTC5xbCgp
-KX0sCiRTOjV9CkwuanIucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5yLmEoYSkKdD1k
-b2N1bWVudC5ib2R5CnQuY2xhc3NMaXN0LnJlbW92ZSgicHJvcG9zZWQiKQp0LmNsYXNzTGlzdC5hZGQo
-ImFwcGxpZWQiKX0sCiRTOjd9CkwucWwucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtMLnFKKCJh
-cHBseSBtaWdyYXRpb24gZXJyb3I6ICIrSC5kKGEpLGIpCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGFw
-cGx5IG1pZ3JhdGlvbiAoIitILmQoYSkrIikuIil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpMLnk4LnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnhuKHUuVi5hKGEpKX0sCnhuOmZ1bmN0
-aW9uKGEpe3ZhciB0PTAscz1QLkZYKHUuUCkscj0xLHEscD1bXSxvLG4sbSxsCnZhciAkYXN5bmMkJDE9
-UC5seihmdW5jdGlvbihiLGMpe2lmKGI9PT0xKXtxPWMKdD1yfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nh
-c2UgMDpyPTMKZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCJyZXJ1bm5pbmciKQp0PTYKcmV0dXJu
-IFAualEoTC50eSgiL3JlcnVuLW1pZ3JhdGlvbiIpLCRhc3luYyQkMSkKY2FzZSA2OndpbmRvdy5sb2Nh
-dGlvbi5yZWxvYWQoKQpwLnB1c2goNSkKdD00CmJyZWFrCmNhc2UgMzpyPTIKbD1xCm89SC5SdShsKQpu
-PUgudHMobCkKTC5xSigicmVydW4gbWlncmF0aW9uOiAiK0guZChvKSxuKQp3aW5kb3cuYWxlcnQoIkZh
-aWxlZCB0byByZXJ1biBtaWdyYXRpb246ICIrSC5kKG8pKyIuIikKcC5wdXNoKDUpCnQ9NApicmVhawpj
-YXNlIDI6cD1bMV0KY2FzZSA0OnI9MQpkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoInJlcnVu
-bmluZyIpCnQ9cC5wb3AoKQpicmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxzKQpjYXNlIDE6cmV0
-dXJuIFAuZjMocSxzKX19KQpyZXR1cm4gUC5ESSgkYXN5bmMkJDEscyl9LAokUzo0MH0KTC5MLnByb3Rv
-dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LkIuYShhKQp0PXdpbmRvdy5sb2NhdGlvbi5w
-YXRobmFtZQpzPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpCnI9TC5hSyh3aW5kb3cubG9jYXRpb24u
-aHJlZikKaWYodC5sZW5ndGg+MSlMLkc3KHQscyxyLCExLG51bGwpCmVsc2V7TC5CRSh0LG5ldyBCLnFw
-KCIiLCIiLCIiLEMueEQpLCEwKQpMLkJYKCImbmJzcDsiLG51bGwpfX0sCiRTOjE3fQpMLld4LnByb3Rv
-dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPSJjb2xsYXBzZWQiCnUuVi5hKGEpCnQ9dGhp
-cy5hCnM9Si5SRSh0KQpyPXRoaXMuYgppZighcy5nRCh0KS50ZygwLHEpKXtzLmdEKHQpLmkoMCxxKQpK
-LmRSKHIpLmkoMCxxKX1lbHNle3MuZ0QodCkuUigwLHEpCkouZFIocikuUigwLHEpfX0sCiRTOjV9Ckwu
-QU8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5xRih1LmguYShhKSkscz10LiR0aSxy
-PXMuQygifigxKSIpLmEobmV3IEwuZE4odGhpcy5hKSkKdS5NLmEobnVsbCkKVy5KRSh0LmEsdC5iLHIs
-ITEscy5jKX0sCiRTOjZ9CkwuZE4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5WLmEo
-YSkKdD1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKdC50b1N0cmluZwpM
-LnQyKGEsdGhpcy5hLHQuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcodCkpLk8o
-InBhdGgiKSkpfSwKJFM6NX0KTC5Iby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIK
-dS5oLmEoYSkKdD1KLnFGKGEpCnM9dC4kdGkKcj1zLkMoIn4oMSkiKS5hKG5ldyBMLnh6KGEsdGhpcy5h
-KSkKdS5NLmEobnVsbCkKVy5KRSh0LmEsdC5iLHIsITEscy5jKX0sCiRTOjZ9CkwueHoucHJvdG90eXBl
-PXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscz1udWxsCnUuVi5hKGEpCnQ9dGhpcy5hCkwuaFgodGhpcy5i
-LFAuUUEodC5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyh0KSkuTygib2Zmc2V0
-IikpLHMscyksUC5RQSh0LmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHQpKS5P
-KCJsaW5lIikpLHMscykpfSwKJFM6NX0KTC5JQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
-dD1KLnFGKHUuaC5hKGEpKSxzPXQuJHRpCnMuQygifigxKSIpLmEoTC5IMCgpKQp1Lk0uYShudWxsKQpX
-LkpFKHQuYSx0LmIsTC5IMCgpLCExLHMuYyl9LAokUzo2fQpMLkwxLnByb3RvdHlwZT17CiQxOmZ1bmN0
-aW9uKGEpe3ZhciB0CnUuci5hKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMClyZXR1cm4gYQplbHNlIHRo
-cm93IEguYigiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo0Mn0KTC5uVC5w
-cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLmEsdGhpcy5iLHRoaXMuYyl9LAokUzow
-fQpMLkJaLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7TC5Gcih0aGlzLmEuYSxudWxsLG51bGwpfSwK
-JFM6MH0KTC5HSC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LmguYShhKQokLnpCKCkudG9TdHJp
-bmcKdS52LmEoJC5vdygpLnEoMCwiaGxqcyIpKS5WNygiaGlnaGxpZ2h0QmxvY2siLFthXSl9LAokUzo2
-fQpMLkRULnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0CnUuci5hKGEpCnQ9YS5zdGF0dXMK
-aWYodD09PTIwMCl7TC5UMShVLnl1KEMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxudWxsKSkpCkwuRnIo
-dGhpcy5hLHRoaXMuYix0aGlzLmMpCkwueVgoIi5lZGl0LXBhbmVsIC5wYW5lbC1jb250ZW50IiwhMSl9
-ZWxzZSB3aW5kb3cuYWxlcnQoIlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2YgIitILmQodCkpfSwKJFM6
-N30KTC5lSC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wucUooImxvYWRSZWdpb25FeHBsYW5h
-dGlvbjogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK0guZCh0aGlzLmEp
-KyIgKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwKJFI6MiwKJFM6MX0KTC56RC5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcwp1LnIuYShhKQp0PWEuc3RhdHVzCmlmKHQ9PT0yMDAp
-e3M9ci5hCkwuQkUocyxCLllmKHUuYi5hKEMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxudWxsKSkpLHIu
-YikKdD1yLmMKTC5mRyh0LHIuZCkKTC5CWChDLnhCLnRnKHMsIj8iKT9DLnhCLncocywwLEMueEIuT1ko
-cywiPyIpKTpzLHQpCnQ9ci5lCmlmKHQhPW51bGwpdC4kMCgpfWVsc2Ugd2luZG93LmFsZXJ0KCJSZXF1
-ZXN0IGZhaWxlZDsgc3RhdHVzIG9mICIrSC5kKHQpKX0sCiRTOjd9CkwuT0UucHJvdG90eXBlPXsKJDI6
-ZnVuY3Rpb24oYSxiKXtMLnFKKCJsb2FkRmlsZTogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3Vs
-ZCBub3QgbG9hZCAiK3RoaXMuYSsiICgiK0guZChhKSsiKS4iKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjF9
-CkwuVFcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCnUuci5hKGEpCnQ9YS5zdGF0
-dXMKaWYodD09PTIwMCl7cz1DLkN0LnBXKDAsYS5yZXNwb25zZVRleHQsbnVsbCkKcj1kb2N1bWVudC5x
-dWVyeVNlbGVjdG9yKCIubmF2LXRyZWUiKQpKLmw1KHIsIiIpCkwudFgocixMLm1LKHMpKX1lbHNlIHdp
-bmRvdy5hbGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpMLnhy
-LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZE5hdmlnYXRpb25UcmVlOiAiK0gu
-ZChhKSxiKQp3aW5kb3cuYWxlcnQoIkNvdWxkIG5vdCBsb2FkICIrdGhpcy5hKyIgKCIrSC5kKGEpKyIp
-LiIpfSwKJEM6IiQyIiwKJFI6MiwKJFM6MX0KTC5FRS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2
-YXIgdCxzCnUuVi5hKGEpCnQ9dGhpcy5hCnM9dGhpcy5iCkwuYWYod2luZG93LmxvY2F0aW9uLnBhdGhu
-YW1lLHQscywhMCxuZXcgTC5RTCh0LHMpKQpMLmhYKHRoaXMuYyx0LHMpfSwKJFM6NX0KTC5RTC5wcm90
-b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHRoaXMuYSx0
-aGlzLmIpfSwKJFM6MH0KTC5WUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzPSJzZWxl
-Y3RlZC1maWxlIgp1LmguYShhKQphLnRvU3RyaW5nCnQ9Si5SRShhKQppZihhLmdldEF0dHJpYnV0ZSgi
-ZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGEpKS5PKCJuYW1lIikpPT09dGhpcy5hLmEpdC5nRChhKS5p
-KDAscykKZWxzZSB0LmdEKGEpLlIoMCxzKX0sCiRTOjZ9CkwuVEQucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7cmV0dXJuIEwudDIodS5WLmEoYSksITAsbnVsbCl9LAokUzoxOH0KTC5YQS5wcm90b3R5cGU9
-ewpFYjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuITB9LAppMDpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCiRp
-a0Y6MX0KTC5aWi5wcm90b3R5cGU9e30KTC5POS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLmJ9fQpNLmxJLnByb3RvdHlwZT17CldPOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1udWxsCk0u
-WUYoImFic29sdXRlIixILlZNKFtiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSx1LnMpKQp0
-PXRoaXMuYQp0PXQuWXIoYik+MCYmIXQuaEsoYikKaWYodClyZXR1cm4gYgp0PUQuUlgoKQpyZXR1cm4g
-dGhpcy5xNygwLHQsYixzLHMscyxzLHMscyl9LAp0TTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9WC5DTChh
-LHRoaXMuYSkKci5JVigpCnQ9ci5kCnM9dC5sZW5ndGgKaWYocz09PTApe3Q9ci5iCnJldHVybiB0PT1u
-dWxsPyIuIjp0fWlmKHM9PT0xKXt0PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6dH1pZigwPj1zKXJldHVy
-biBILmsodCwtMSkKdC5wb3AoKQpDLk5tLm12KHIuZSkKci5JVigpCnJldHVybiByLlooMCl9LApxNzpm
-dW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSl7dmFyIHQ9SC5WTShbYixjLGQsZSxmLGcsaCxpXSx1LnMp
-Ck0uWUYoImpvaW4iLHQpCnJldHVybiB0aGlzLklQKG5ldyBILlU1KHQsdS5iQi5hKG5ldyBNLk1pKCkp
-LHUuY2MpKX0sCklQOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbAp1LlguYShhKQpmb3Io
-dD1hLiR0aSxzPXQuQygiYTIoY1guRSkiKS5hKG5ldyBNLnE3KCkpLHI9YS5na3ooYSksdD1uZXcgSC52
-RyhyLHMsdC5DKCJ2RzxjWC5FPiIpKSxzPXRoaXMuYSxxPSExLHA9ITEsbz0iIjt0LkYoKTspe249ci5n
-bCgpCmlmKHMuaEsobikmJnApe209WC5DTChuLHMpCmw9by5jaGFyQ29kZUF0KDApPT0wP286bwpvPUMu
-eEIudyhsLDAscy5TcChsLCEwKSkKbS5iPW8KaWYocy5kcyhvKSlDLk5tLlkobS5lLDAscy5nbUkoKSkK
-bz1tLlooMCl9ZWxzZSBpZihzLllyKG4pPjApe3A9IXMuaEsobikKbz1ILmQobil9ZWxzZXtpZighKG4u
-bGVuZ3RoPjAmJnMuVWQoblswXSkpKWlmKHEpbys9cy5nbUkoKQpvKz1ILmQobil9cT1zLmRzKG4pfXJl
-dHVybiBvLmNoYXJDb2RlQXQoMCk9PTA/bzpvfSwKbzU6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoIXRoaXMu
-eTMoYSkpcmV0dXJuIGEKdD1YLkNMKGEsdGhpcy5hKQp0LnJSKCkKcmV0dXJuIHQuWigwKX0sCnkzOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrCmEudG9TdHJpbmcKdD10aGlzLmEKcz10Llly
-KGEpCmlmKHMhPT0wKXtpZih0PT09JC5LaygpKWZvcihyPTA7cjxzOysrcilpZihDLnhCLlcoYSxyKT09
-PTQ3KXJldHVybiEwCnE9cwpwPTQ3fWVsc2V7cT0wCnA9bnVsbH1mb3Iobz1uZXcgSC5xaihhKS5hLG49
-by5sZW5ndGgscj1xLG09bnVsbDtyPG47KytyLG09cCxwPWwpe2w9Qy54Qi5tKG8scikKaWYodC5yNChs
-KSl7aWYodD09PSQuS2soKSYmbD09PTQ3KXJldHVybiEwCmlmKHAhPW51bGwmJnQucjQocCkpcmV0dXJu
-ITAKaWYocD09PTQ2KWs9bT09bnVsbHx8bT09PTQ2fHx0LnI0KG0pCmVsc2Ugaz0hMQppZihrKXJldHVy
-biEwfX1pZihwPT1udWxsKXJldHVybiEwCmlmKHQucjQocCkpcmV0dXJuITAKaWYocD09PTQ2KXQ9bT09
-bnVsbHx8dC5yNChtKXx8bT09PTQ2CmVsc2UgdD0hMQppZih0KXJldHVybiEwCnJldHVybiExfSwKSFA6
-ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89dGhpcyxuPSdVbmFibGUgdG8gZmluZCBhIHBhdGgg
-dG8gIicKYj1vLldPKDAsYikKdD1vLmEKaWYodC5ZcihiKTw9MCYmdC5ZcihhKT4wKXJldHVybiBvLm81
-KGEpCmlmKHQuWXIoYSk8PTB8fHQuaEsoYSkpYT1vLldPKDAsYSkKaWYodC5ZcihhKTw9MCYmdC5Zcihi
-KT4wKXRocm93IEguYihYLkk3KG4rSC5kKGEpKyciIGZyb20gIicrSC5kKGIpKyciLicpKQpzPVguQ0wo
-Yix0KQpzLnJSKCkKcj1YLkNMKGEsdCkKci5yUigpCnE9cy5kCmlmKHEubGVuZ3RoPjAmJkouUk0ocVsw
-XSwiLiIpKXJldHVybiByLlooMCkKcT1zLmIKcD1yLmIKaWYocSE9cClxPXE9PW51bGx8fHA9PW51bGx8
-fCF0Lk5jKHEscCkKZWxzZSBxPSExCmlmKHEpcmV0dXJuIHIuWigwKQp3aGlsZSghMCl7cT1zLmQKaWYo
-cS5sZW5ndGg+MCl7cD1yLmQKcT1wLmxlbmd0aD4wJiZ0Lk5jKHFbMF0scFswXSl9ZWxzZSBxPSExCmlm
-KCFxKWJyZWFrCkMuTm0uVzQocy5kLDApCkMuTm0uVzQocy5lLDEpCkMuTm0uVzQoci5kLDApCkMuTm0u
-VzQoci5lLDEpfXE9cy5kCmlmKHEubGVuZ3RoPjAmJkouUk0ocVswXSwiLi4iKSl0aHJvdyBILmIoWC5J
-NyhuK0guZChhKSsnIiBmcm9tICInK0guZChiKSsnIi4nKSkKcT11Lk4KQy5ObS5VRyhyLmQsMCxQLk84
-KHMuZC5sZW5ndGgsIi4uIixxKSkKQy5ObS5ZKHIuZSwwLCIiKQpDLk5tLlVHKHIuZSwxLFAuTzgocy5k
-Lmxlbmd0aCx0LmdtSSgpLHEpKQp0PXIuZApxPXQubGVuZ3RoCmlmKHE9PT0wKXJldHVybiIuIgppZihx
-PjEmJkouUk0oQy5ObS5ncloodCksIi4iKSl7dD1yLmQKaWYoMD49dC5sZW5ndGgpcmV0dXJuIEguayh0
-LC0xKQp0LnBvcCgpCnQ9ci5lCkMuTm0ubXYodCkKQy5ObS5tdih0KQpDLk5tLmkodCwiIil9ci5iPSIi
-CnIuSVYoKQpyZXR1cm4gci5aKDApfX0KTS5NaS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1
-cm4gSC5jKGEpIT1udWxsfSwKJFM6OH0KTS5xNy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1
-cm4gSC5jKGEpIT09IiJ9LAokUzo4fQpNLk5vLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe0guYyhh
-KQpyZXR1cm4gYT09bnVsbD8ibnVsbCI6JyInK2ErJyInfSwKJFM6NH0KQi5MdS5wcm90b3R5cGU9ewp4
-WjpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuWXIoYSkKaWYocz4wKXJldHVybiBKLmxkKGEsMCxzKQpp
-Zih0aGlzLmhLKGEpKXtpZigwPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsMCkKdD1hWzBdfWVsc2UgdD1u
-dWxsCnJldHVybiB0fSwKTmM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09Yn19ClguV0QucHJvdG90eXBl
-PXsKSVY6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcwp3aGlsZSghMCl7dD1yLmQKaWYoISh0Lmxlbmd0
-aCE9PTAmJkouUk0oQy5ObS5ncloodCksIiIpKSlicmVhawp0PXIuZAppZigwPj10Lmxlbmd0aClyZXR1
-cm4gSC5rKHQsLTEpCnQucG9wKCkKQy5ObS5tdihyLmUpfXQ9ci5lCnM9dC5sZW5ndGgKaWYocz4wKUMu
-Tm0uWSh0LHMtMSwiIil9LApyUjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuLG09dGhpcyxsPUgu
-Vk0oW10sdS5zKQpmb3IodD1tLmQscz10Lmxlbmd0aCxyPTAscT0wO3E8dC5sZW5ndGg7dC5sZW5ndGg9
-PT1zfHwoMCxILmxrKSh0KSwrK3Epe3A9dFtxXQpvPUouaWEocCkKaWYoIShvLkROKHAsIi4iKXx8by5E
-TihwLCIiKSkpaWYoby5ETihwLCIuLiIpKWlmKGwubGVuZ3RoPjApbC5wb3AoKQplbHNlICsrcgplbHNl
-IEMuTm0uaShsLHApfWlmKG0uYj09bnVsbClDLk5tLlVHKGwsMCxQLk84KHIsIi4uIix1Lk4pKQppZihs
-Lmxlbmd0aD09PTAmJm0uYj09bnVsbClDLk5tLmkobCwiLiIpCm49UC5kSChsLmxlbmd0aCxuZXcgWC5x
-UihtKSwhMCx1Lk4pCnQ9bS5iCnQ9dCE9bnVsbCYmbC5sZW5ndGg+MCYmbS5hLmRzKHQpP20uYS5nbUko
-KToiIgpILnQ2KG4pLmMuYSh0KQppZighIW4uZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgiaW5zZXJ0Iikp
-Cm4uc3BsaWNlKDAsMCx0KQptLnNuSihsKQptLnNQaChuKQp0PW0uYgppZih0IT1udWxsJiZtLmE9PT0k
-LktrKCkpe3QudG9TdHJpbmcKbS5iPUgueXModCwiLyIsIlxcIil9bS5JVigpfSwKWjpmdW5jdGlvbihh
-KXt2YXIgdCxzLHI9dGhpcyxxPXIuYgpxPXEhPW51bGw/cToiIgpmb3IodD0wO3Q8ci5kLmxlbmd0aDsr
-K3Qpe3M9ci5lCmlmKHQ+PXMubGVuZ3RoKXJldHVybiBILmsocyx0KQpzPXErSC5kKHNbdF0pCnE9ci5k
-CmlmKHQ+PXEubGVuZ3RoKXJldHVybiBILmsocSx0KQpxPXMrSC5kKHFbdF0pfXErPUguZChDLk5tLmdy
-WihyLmUpKQpyZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sCnNuSjpmdW5jdGlvbihhKXt0aGlz
-LmQ9dS5hLmEoYSl9LApzUGg6ZnVuY3Rpb24oYSl7dGhpcy5lPXUuYS5hKGEpfX0KWC5xUi5wcm90b3R5
-cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmEuZ21JKCl9LAokUzo0NH0KWC5kdi5wcm90
-b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJQYXRoRXhjZXB0aW9uOiAiK3RoaXMuYX19Ck8uekwu
-cHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nb2ModGhpcyl9fQpFLk9GLnByb3Rv
-dHlwZT17ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEp
-e3JldHVybiBhPT09NDd9LApkczpmdW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aApyZXR1cm4gdCE9PTAm
-JkMueEIubShhLHQtMSkhPT00N30sClNwOmZ1bmN0aW9uKGEsYil7aWYoYS5sZW5ndGghPT0wJiZDLnhC
-LlcoYSwwKT09PTQ3KXJldHVybiAxCnJldHVybiAwfSwKWXI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-U3AoYSwhMSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4hMX0sCmdvYzpmdW5jdGlvbigpe3JldHVybiJw
-b3NpeCJ9LApnbUk6ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9fQpGLnJ1LnByb3RvdHlwZT17ClVkOmZ1bmN0
-aW9uKGEpe3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3JldHVybiBhPT09NDd9
-LApkczpmdW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4hMQppZihDLnhCLm0o
-YSx0LTEpIT09NDcpcmV0dXJuITAKcmV0dXJuIEMueEIuVGMoYSwiOi8vIikmJnRoaXMuWXIoYSk9PT10
-fSwKU3A6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPWEubGVuZ3RoCmlmKHA9PT0wKXJldHVybiAw
-CmlmKEMueEIuVyhhLDApPT09NDcpcmV0dXJuIDEKZm9yKHQ9MDt0PHA7Kyt0KXtzPUMueEIuVyhhLHQp
-CmlmKHM9PT00NylyZXR1cm4gMAppZihzPT09NTgpe2lmKHQ9PT0wKXJldHVybiAwCnI9Qy54Qi5YVShh
-LCIvIixDLnhCLlFpKGEsIi8vIix0KzEpP3QrMzp0KQppZihyPD0wKXJldHVybiBwCmlmKCFifHxwPHIr
-MylyZXR1cm4gcgppZighQy54Qi5uKGEsImZpbGU6Ly8iKSlyZXR1cm4gcgppZighQi5ZdShhLHIrMSkp
-cmV0dXJuIHIKcT1yKzMKcmV0dXJuIHA9PT1xP3E6cis0fX1yZXR1cm4gMH0sCllyOmZ1bmN0aW9uKGEp
-e3JldHVybiB0aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RoIT09MCYm
-Qy54Qi5XKGEsMCk9PT00N30sCmdvYzpmdW5jdGlvbigpe3JldHVybiJ1cmwifSwKZ21JOmZ1bmN0aW9u
-KCl7cmV0dXJuIi8ifX0KTC5JVi5wcm90b3R5cGU9ewpVZDpmdW5jdGlvbihhKXtyZXR1cm4gQy54Qi50
-ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3fHxhPT09OTJ9LApkczpmdW5jdGlv
-bihhKXt2YXIgdD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4hMQp0PUMueEIubShhLHQtMSkKcmV0dXJu
-ISh0PT09NDd8fHQ9PT05Mil9LApTcDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1hLmxlbmd0aAppZihy
-PT09MClyZXR1cm4gMAp0PUMueEIuVyhhLDApCmlmKHQ9PT00NylyZXR1cm4gMQppZih0PT09OTIpe2lm
-KHI8Mnx8Qy54Qi5XKGEsMSkhPT05MilyZXR1cm4gMQpzPUMueEIuWFUoYSwiXFwiLDIpCmlmKHM+MCl7
-cz1DLnhCLlhVKGEsIlxcIixzKzEpCmlmKHM+MClyZXR1cm4gc31yZXR1cm4gcn1pZihyPDMpcmV0dXJu
-IDAKaWYoIUIuT1ModCkpcmV0dXJuIDAKaWYoQy54Qi5XKGEsMSkhPT01OClyZXR1cm4gMApyPUMueEIu
-VyhhLDIpCmlmKCEocj09PTQ3fHxyPT09OTIpKXJldHVybiAwCnJldHVybiAzfSwKWXI6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ZcihhKT09
-PTF9LApPdDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PT1iKXJldHVybiEwCmlmKGE9PT00NylyZXR1
-cm4gYj09PTkyCmlmKGE9PT05MilyZXR1cm4gYj09PTQ3CmlmKChhXmIpIT09MzIpcmV0dXJuITEKdD1h
-fDMyCnJldHVybiB0Pj05NyYmdDw9MTIyfSwKTmM6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKaWYoYT09
-YilyZXR1cm4hMAp0PWEubGVuZ3RoCmlmKHQhPT1iLmxlbmd0aClyZXR1cm4hMQpmb3Iocz1KLnJZKGIp
-LHI9MDtyPHQ7KytyKWlmKCF0aGlzLk90KEMueEIuVyhhLHIpLHMuVyhiLHIpKSlyZXR1cm4hMQpyZXR1
-cm4hMH0sCmdvYzpmdW5jdGlvbigpe3JldHVybiJ3aW5kb3dzIn0sCmdtSTpmdW5jdGlvbigpe3JldHVy
-biJcXCJ9fTsoZnVuY3Rpb24gYWxpYXNlcygpe3ZhciB0PUoudkIucHJvdG90eXBlCnQuVT10LloKdC5T
-aj10LmU3CnQ9Si5NRi5wcm90b3R5cGUKdC50PXQuWgp0PVAuY1gucHJvdG90eXBlCnQuR0c9dC5ldgp0
-PVAuTWgucHJvdG90eXBlCnQueGI9dC5aCnQ9Vy5jdi5wcm90b3R5cGUKdC5EVz10LnI2CnQ9Vy5tNi5w
-cm90b3R5cGUKdC5qRj10LkViCnQ9UC5FNC5wcm90b3R5cGUKdC5Vcj10LnEKdC5lND10Lll9KSgpOyhm
-dW5jdGlvbiBpbnN0YWxsVGVhck9mZnMoKXt2YXIgdD1odW5rSGVscGVycy5fc3RhdGljXzEscz1odW5r
-SGVscGVycy5fc3RhdGljXzAscj1odW5rSGVscGVycy5pbnN0YWxsSW5zdGFuY2VUZWFyT2ZmLHE9aHVu
-a0hlbHBlcnMuaW5zdGFsbFN0YXRpY1RlYXJPZmYscD1odW5rSGVscGVycy5faW5zdGFuY2VfMXUKdChQ
-LCJFWCIsIlpWIiwxMCkKdChQLCJ5dCIsIm9BIiwxMCkKdChQLCJxVyIsIkJ6IiwxMCkKcyhQLCJWOSIs
-ImVOIiwyKQpyKFAuUGYucHJvdG90eXBlLCJnWUoiLDAsMSxudWxsLFsiJDIiLCIkMSJdLFsidzAiLCJw
-bSJdLDI5LDApCnQoUCwiUEgiLCJNdCIsNCkKcShXLCJwUyIsNCxudWxsLFsiJDQiXSxbInlXIl0sMTEs
-MCkKcShXLCJWNCIsNCxudWxsLFsiJDQiXSxbIlFXIl0sMTEsMCkKcChQLkFzLnByb3RvdHlwZSwiZ3VN
-IiwiVCIsNCkKdChQLCJpRyIsIndZIiwzKQp0KFAsIncwIiwiTDciLDMxKQp0KEwsIkgwIiwidW0iLDE4
-KX0pKCk7KGZ1bmN0aW9uIGluaGVyaXRhbmNlKCl7dmFyIHQ9aHVua0hlbHBlcnMubWl4aW4scz1odW5r
-SGVscGVycy5pbmhlcml0LHI9aHVua0hlbHBlcnMuaW5oZXJpdE1hbnkKcyhQLk1oLG51bGwpCnIoUC5N
-aCxbSC5GSyxKLnZCLEoubTEsUC5uWSxQLmNYLEguYTcsUC5BbixILlNVLEguUmUsSC53dixQLlBuLEgu
-V1UsSC5MSSxILlRwLEguZjksUC5YUyxILmJxLEguWE8sUC5ZayxILmRiLEguTjYsSC5WUixILkVLLEgu
-UGIsSC50USxILlNkLEguSmMsSC5FVCxQLlczLFAuaWgsUC5GeSxQLkdWLFAuYjgsUC5QZixQLkZlLFAu
-dnMsUC5PTSxQLnFoLFAuTU8sUC5rVCxQLnhJLFAuT0gsUC5tMCxQLlh2LFAuYm4sUC5sbSxQLmxELFAu
-S1AsUC5NYSxQLlRDLFAuVWssUC5SdyxQLmJ6LFAuYTIsUC5pUCxQLmxmLFAuazUsUC5LWSxQLkNELFAu
-YUUsUC5FSCxQLnpNLFAuWjAsUC5OMyxQLmM4LFAuT2QsUC5pYixQLkd6LFAuWmQsUC5xVSxQLlJuLFAu
-R0QsUC5EbixQLlBFLFAuVWYsVy5pZCxXLkZrLFcuSlEsVy5HbSxXLnZELFcubTYsVy5PdyxXLlc5LFcu
-ZFcsVy5GYixXLmtGLFcubWssVy5LbyxQLmlKLFAuRTQsUC5uNixVLmQyLFUuU2UsVS51RixVLk1sLFUu
-eUQsVS53YixCLmo4LEIucXAsVC5tUSxMLlhBLEwuWlosTC5POSxNLmxJLE8uekwsWC5XRCxYLmR2XSkK
-cihKLnZCLFtKLnlFLEouWUUsSi5NRixKLmpkLEoucUksSi5EcixILnBGLFcuRDAsVy5BeixXLkxlLFcu
-TmgsVy5JQixXLm43LFcuZWEsVy5icixXLlNnLFcudTgsVy5LNyxXLlhXLFAuaEZdKQpyKEouTUYsW0ou
-aUMsSi5rZCxKLmM1XSkKcyhKLlBvLEouamQpCnIoSi5xSSxbSi51cixKLlZBXSkKcyhQLkxVLFAublkp
-CnIoUC5MVSxbSC53MixXLnd6LFcuZTddKQpzKEgucWosSC53MikKcihQLmNYLFtILmJRLEguaTEsSC5V
-NSxILlhSLFAubVcsSC5ORl0pCnIoSC5iUSxbSC5hTCxILmk1LFAueHVdKQpyKEguYUwsW0gubkgsSC5s
-SixQLmk4XSkKcyhILnh5LEguaTEpCnIoUC5BbixbSC5NSCxILnZHXSkKcyhQLlJVLFAuUG4pCnMoUC5H
-aixQLlJVKQpzKEguUEQsUC5HaikKcyhILkxQLEguV1UpCnIoSC5UcCxbSC5DaixILkFtLEgubGMsSC5y
-LEguZEMsSC53TixQLnRoLFAuaGEsUC5WcyxQLkZ0LFAueUgsUC5XTSxQLlNYLFAuR3MsUC5kYSxQLm9R
-LFAucFYsUC5VNyxQLnZyLFAuckgsUC5LRixQLlpMLFAuUlQsUC5qWixQLnJxLFAuUlcsUC5CNSxQLlBJ
-LFAucEssUC5oaixQLlZwLFAuT1IsUC5yYSxQLnlRLFAuV0YsUC5uMSxQLmNTLFAuVkMsUC5KVCxQLmUx
-LFAuTlksUC5SWixQLk1FLFAueTUsUC5xMyxQLnlJLFAuYzYsUC5xZCxXLkN2LFcuYlUsVy5oSCxXLktT
-LFcuQTMsVy52TixXLlV2LFcuRWcsVy5FbyxXLldrLFcuSUEsVy5mbSxQLmpnLFAuVGEsUC5HRSxQLk43
-LFAudVEsUC5QQyxQLm10LFAuTnosUC5ucCxQLlV0LEwuZSxMLlZXLEwub1osTC5qcixMLnFsLEwueTgs
-TC5MLEwuV3gsTC5BTyxMLmROLEwuSG8sTC54eixMLklDLEwuTDEsTC5uVCxMLkJaLEwuR0gsTC5EVCxM
-LmVILEwuekQsTC5PRSxMLlRXLEwueHIsTC5FRSxMLlFMLEwuVlMsTC5URCxNLk1pLE0ucTcsTS5ObyxY
-LnFSXSkKcihQLlhTLFtILlcwLEguYXosSC52VixILkVxLFAuQzYsSC51OSxQLkxLLFAuQVQsUC5tcCxQ
-LnViLFAuZHMsUC5saixQLlVWLFAudDddKQpyKEgubGMsW0guengsSC5qeV0pCnMoSC5rWSxQLkM2KQpz
-KFAuaWwsUC5ZaykKcihQLmlsLFtILk41LFAudXcsVy5jZixXLlN5XSkKcihQLm1XLFtILktXLFAucTRd
-KQpzKEguYjAsSC5wRikKcihILmIwLFtILlJHLEguV0JdKQpzKEguVlAsSC5SRykKcyhILkRnLEguVlAp
-CnMoSC5aRyxILldCKQpzKEguUGcsSC5aRykKcihILlBnLFtILnhqLEguZEUsSC5aQSxILndmLEguUHEs
-SC5lRSxILlY2XSkKcyhILngsSC51OSkKcyhQLlpmLFAuUGYpCnMoUC5KaSxQLm0wKQpzKFAuYjYsUC5Y
-dikKcyhQLlZqLFAuVEMpCnIoUC5VayxbUC5DVixQLlppLFAuYnldKQpzKFAud0ksUC5rVCkKcihQLndJ
-LFtQLlU4LFAuTXgsUC5FMyxQLkdZXSkKcyhQLnU1LFAuWmkpCnIoUC5sZixbUC5DUCxQLklmXSkKcihQ
-LkFULFtQLmJKLFAuZVldKQpzKFAucWUsUC5EbikKcihXLkQwLFtXLnVILFcud2EsVy5LNSxXLkNtXSkK
-cihXLnVILFtXLmN2LFcubngsVy5RRixXLkNRXSkKcihXLmN2LFtXLnFFLFAuZDVdKQpyKFcucUUsW1cu
-R2gsVy5mWSxXLm5CLFcuUVAsVy5oNCxXLlNOLFcubHAsVy5UYixXLkl2LFcuQlQsVy55WV0pCnMoVy5v
-SixXLkxlKQpzKFcuVDUsVy5BeikKcyhXLlZiLFcuUUYpCnMoVy5mSixXLndhKQpyKFcuZWEsW1cudzYs
-Vy5ld10pCnMoVy5PSyxXLnc2KQpzKFcuckIsVy5LNykKcyhXLkJILFcuckIpCnMoVy53NCxXLklCKQpz
-KFcub2EsVy5YVykKcyhXLnJoLFcub2EpCnMoVy5pNyxXLmNmKQpzKFAuQXMsUC5WaikKcihQLkFzLFtX
-Lkk0LFAuS2VdKQpzKFcuUk8sUC5xaCkKcyhXLmV1LFcuUk8pCnMoVy54QyxQLk1PKQpzKFcuY3QsVy5t
-NikKcyhQLkJmLFAuaUopCnIoUC5FNCxbUC5yNyxQLmNvXSkKcyhQLlR6LFAuY28pCnMoUC5uZCxQLmQ1
-KQpzKEIuTHUsTy56TCkKcihCLkx1LFtFLk9GLEYucnUsTC5JVl0pCnQoSC53MixILlJlKQp0KEguUkcs
-UC5sRCkKdChILlZQLEguU1UpCnQoSC5XQixQLmxEKQp0KEguWkcsSC5TVSkKdChQLm5ZLFAubEQpCnQo
-UC5UQyxQLk1hKQp0KFAuUlUsUC5LUCkKdChXLkxlLFcuaWQpCnQoVy5LNyxQLmxEKQp0KFcuckIsVy5H
-bSkKdChXLlhXLFAubEQpCnQoVy5vYSxXLkdtKQp0KFAuY28sUC5sRCl9KSgpCnZhciB2PXt0eXBlVW5p
-dmVyc2U6e2VDOm5ldyBNYXAoKSx0Ujp7fSxlVDp7fSx0UFY6e30sc0VBOltdfSxtYW5nbGVkR2xvYmFs
-TmFtZXM6e0lmOiJpbnQiLENQOiJkb3VibGUiLGxmOiJudW0iLHFVOiJTdHJpbmciLGEyOiJib29sIixj
-ODoiTnVsbCIsek06Ikxpc3QifSxtYW5nbGVkTmFtZXM6e30sZ2V0VHlwZUZyb21OYW1lOmdldEdsb2Jh
-bEZyb21OYW1lLG1ldGFkYXRhOltdLHR5cGVzOlsiYzgoKSIsImM4KEAsQCkiLCJ+KCkiLCJAKEApIiwi
-cVUocVUpIiwiYzgoT0spIiwiYzgoY3YpIiwiYzgoZkopIiwiYTIocVUpIiwiYzgocVUscVUpIiwifih+
-KCkpIiwiYTIoY3YscVUscVUsSlEpIiwiYzgoQCkiLCJjOChxVSxAKSIsImM4KHFVKSIsImEyKGtGKSIs
-In4oeHU8cVU+KSIsImM4KGVhKSIsIn4oT0spIiwiYzgoR0QsQCkiLCJjOCh+KCkpIiwiYzgoQCxHeiki
-LCJ+KHFVLHFVKSIsIm42KElmKSIsIm42KEAsQCkiLCJhMih1SCkiLCJjOChJZixAKSIsImM4KGV3KSIs
-IkAoZWEpIiwifihNaFtHel0pIiwiYzgoQFtHel0pIiwiTWgoQCkiLCJhMih4dTxxVT4pIiwidnM8QD4o
-QCkiLCJyNyhAKSIsIlR6PEA+KEApIiwiRTQoQCkiLCJAKHFVKSIsIkAoQCxxVSkiLCJ+KHVILHVIKSIs
-ImI4PGM4PihPSykiLCJaMDxxVSxxVT4oWjA8cVUscVU+LHFVKSIsImZKKGZKKSIsIn4ocVUsSWYpIiwi
-cVUoSWYpIiwifihxVVtAXSkiLCJJZihJZixJZikiLCJ+KEApIl0saW50ZXJjZXB0b3JzQnlUYWc6bnVs
-bCxsZWFmVGFnczpudWxsLGFycmF5UnRpOnR5cGVvZiBTeW1ib2w9PSJmdW5jdGlvbiImJnR5cGVvZiBT
-eW1ib2woKT09InN5bWJvbCI/U3ltYm9sKCIkdGkiKToiJHRpIn0KSC54Yih2LnR5cGVVbml2ZXJzZSxK
-U09OLnBhcnNlKCd7ImM1IjoiTUYiLCJpQyI6Ik1GIiwia2QiOiJNRiIsInJ4IjoiZWEiLCJlNSI6ImVh
-IiwiWTAiOiJkNSIsInRwIjoiZDUiLCJHOCI6ImV3IiwiTXIiOiJxRSIsImVMIjoicUUiLCJJMCI6InVI
-IiwiaHMiOiJ1SCIsIlhnIjoiUUYiLCJ5YyI6Ik9LIiwieTQiOiJ3NiIsImFQIjoiQ20iLCJ4YyI6Im54
-Iiwia0oiOiJueCIsInpVIjoiRGciLCJkZiI6InBGIiwieUUiOnsiYTIiOltdfSwiWUUiOnsiYzgiOltd
-fSwiTUYiOnsidm0iOltdLCJFSCI6W119LCJqZCI6eyJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsi
-MSJdfSwiUG8iOnsiamQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwibTEi
-OnsiQW4iOlsiMSJdfSwicUkiOnsiQ1AiOltdLCJsZiI6W119LCJ1ciI6eyJJZiI6W10sIkNQIjpbXSwi
-bGYiOltdfSwiVkEiOnsiQ1AiOltdLCJsZiI6W119LCJEciI6eyJxVSI6W10sInZYIjpbXX0sInFqIjp7
-IlJlIjpbIklmIl0sImxEIjpbIklmIl0sInpNIjpbIklmIl0sImJRIjpbIklmIl0sImNYIjpbIklmIl0s
-ImxELkUiOiJJZiIsIlJlLkUiOiJJZiJ9LCJiUSI6eyJjWCI6WyIxIl19LCJhTCI6eyJiUSI6WyIxIl0s
-ImNYIjpbIjEiXX0sIm5IIjp7ImFMIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl0sImFMLkUiOiIx
-IiwiY1guRSI6IjEifSwiYTciOnsiQW4iOlsiMSJdfSwiaTEiOnsiY1giOlsiMiJdLCJjWC5FIjoiMiJ9
-LCJ4eSI6eyJpMSI6WyIxIiwiMiJdLCJiUSI6WyIyIl0sImNYIjpbIjIiXSwiY1guRSI6IjIifSwiTUgi
-OnsiQW4iOlsiMiJdfSwibEoiOnsiYUwiOlsiMiJdLCJiUSI6WyIyIl0sImNYIjpbIjIiXSwiYUwuRSI6
-IjIiLCJjWC5FIjoiMiJ9LCJVNSI6eyJjWCI6WyIxIl0sImNYLkUiOiIxIn0sInZHIjp7IkFuIjpbIjEi
-XX0sIncyIjp7IlJlIjpbIjEiXSwibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsi
-MSJdfSwid3YiOnsiR0QiOltdfSwiUEQiOnsiR2oiOlsiMSIsIjIiXSwiUlUiOlsiMSIsIjIiXSwiUG4i
-OlsiMSIsIjIiXSwiS1AiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIldVIjp7IlowIjpbIjEiLCIy
-Il19LCJMUCI6eyJXVSI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiWFIiOnsiY1giOlsiMSJdLCJj
-WC5FIjoiMSJ9LCJMSSI6eyJ2USI6W119LCJXMCI6eyJYUyI6W119LCJheiI6eyJYUyI6W119LCJ2ViI6
-eyJYUyI6W119LCJYTyI6eyJHeiI6W119LCJUcCI6eyJFSCI6W119LCJsYyI6eyJFSCI6W119LCJ6eCI6
-eyJFSCI6W119LCJqeSI6eyJFSCI6W119LCJFcSI6eyJYUyI6W119LCJrWSI6eyJYUyI6W119LCJONSI6
-eyJGbyI6WyIxIiwiMiJdLCJZayI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdLCJZay5LIjoiMSIsIllr
-LlYiOiIyIn0sImk1Ijp7ImJRIjpbIjEiXSwiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJONiI6eyJBbiI6
-WyIxIl19LCJWUiI6eyJ3TCI6W10sInZYIjpbXX0sIkVLIjp7ImliIjpbXSwiT2QiOltdfSwiS1ciOnsi
-Y1giOlsiaWIiXSwiY1guRSI6ImliIn0sIlBiIjp7IkFuIjpbImliIl19LCJ0USI6eyJPZCI6W119LCJO
-RiI6eyJjWCI6WyJPZCJdLCJjWC5FIjoiT2QifSwiU2QiOnsiQW4iOlsiT2QiXX0sInBGIjp7IkFTIjpb
-XX0sImIwIjp7IlhqIjpbIkAiXSwicEYiOltdLCJBUyI6W119LCJEZyI6eyJsRCI6WyJDUCJdLCJYaiI6
-WyJAIl0sInpNIjpbIkNQIl0sInBGIjpbXSwiYlEiOlsiQ1AiXSwiU1UiOlsiQ1AiXSwiQVMiOltdLCJj
-WCI6WyJDUCJdLCJsRC5FIjoiQ1AifSwiUGciOnsibEQiOlsiSWYiXSwiek0iOlsiSWYiXSwiWGoiOlsi
-QCJdLCJwRiI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sIkFTIjpbXSwiY1giOlsiSWYiXX0sInhq
-Ijp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwicEYiOltdLCJiUSI6WyJJZiJdLCJT
-VSI6WyJJZiJdLCJBUyI6W10sImNYIjpbIklmIl0sImxELkUiOiJJZiJ9LCJkRSI6eyJsRCI6WyJJZiJd
-LCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYiXSwiU1UiOlsiSWYiXSwiQVMi
-OltdLCJjWCI6WyJJZiJdLCJsRC5FIjoiSWYifSwiWkEiOnsibEQiOlsiSWYiXSwiek0iOlsiSWYiXSwi
-WGoiOlsiQCJdLCJwRiI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sIkFTIjpbXSwiY1giOlsiSWYi
-XSwibEQuRSI6IklmIn0sIndmIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwicEYi
-OltdLCJiUSI6WyJJZiJdLCJTVSI6WyJJZiJdLCJBUyI6W10sImNYIjpbIklmIl0sImxELkUiOiJJZiJ9
-LCJQcSI6eyJsRCI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYi
-XSwiU1UiOlsiSWYiXSwiQVMiOltdLCJjWCI6WyJJZiJdLCJsRC5FIjoiSWYifSwiZUUiOnsibEQiOlsi
-SWYiXSwiek0iOlsiSWYiXSwiWGoiOlsiQCJdLCJwRiI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0s
-IkFTIjpbXSwiY1giOlsiSWYiXSwibEQuRSI6IklmIn0sIlY2Ijp7Im42IjpbXSwibEQiOlsiSWYiXSwi
-ek0iOlsiSWYiXSwiWGoiOlsiQCJdLCJwRiI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sIkFTIjpb
-XSwiY1giOlsiSWYiXSwibEQuRSI6IklmIn0sInU5Ijp7IlhTIjpbXX0sIngiOnsiWFMiOltdfSwiR1Yi
-OnsiQW4iOlsiMSJdfSwicTQiOnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJaZiI6eyJQZiI6WyIxIl19
-LCJ2cyI6eyJiOCI6WyIxIl19LCJPSCI6eyJYUyI6W119LCJtMCI6eyJKQiI6W119LCJKaSI6eyJKQiI6
-W119LCJiNiI6eyJYdiI6WyIxIl0sInh1IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJsbSI6
-eyJBbiI6WyIxIl19LCJtVyI6eyJjWCI6WyIxIl19LCJMVSI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwi
-YlEiOlsiMSJdLCJjWCI6WyIxIl19LCJpbCI6eyJZayI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwi
-WWsiOnsiWjAiOlsiMSIsIjIiXX0sIlBuIjp7IlowIjpbIjEiLCIyIl19LCJHaiI6eyJSVSI6WyIxIiwi
-MiJdLCJQbiI6WyIxIiwiMiJdLCJLUCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiVmoiOnsiTWEi
-OlsiMSJdLCJ4dSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiWHYiOnsieHUiOlsiMSJdLCJi
-USI6WyIxIl0sImNYIjpbIjEiXX0sInV3Ijp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwi
-WWsuSyI6InFVIiwiWWsuViI6IkAifSwiaTgiOnsiYUwiOlsicVUiXSwiYlEiOlsicVUiXSwiY1giOlsi
-cVUiXSwiYUwuRSI6InFVIiwiY1guRSI6InFVIn0sIkNWIjp7IlVrIjpbInpNPElmPiIsInFVIl0sIlVr
-LlMiOiJ6TTxJZj4ifSwiVTgiOnsid0kiOlsiek08SWY+IiwicVUiXX0sIlppIjp7IlVrIjpbInFVIiwi
-ek08SWY+Il19LCJieSI6eyJVayI6WyJNaCIsInFVIl0sIlVrLlMiOiJNaCJ9LCJNeCI6eyJ3SSI6WyJx
-VSIsIk1oIl19LCJ1NSI6eyJVayI6WyJxVSIsInpNPElmPiJdLCJVay5TIjoicVUifSwiRTMiOnsid0ki
-OlsicVUiLCJ6TTxJZj4iXX0sIkdZIjp7IndJIjpbInpNPElmPiIsInFVIl19LCJDUCI6eyJsZiI6W119
-LCJDNiI6eyJYUyI6W119LCJMSyI6eyJYUyI6W119LCJBVCI6eyJYUyI6W119LCJiSiI6eyJYUyI6W119
-LCJlWSI6eyJYUyI6W119LCJtcCI6eyJYUyI6W119LCJ1YiI6eyJYUyI6W119LCJkcyI6eyJYUyI6W119
-LCJsaiI6eyJYUyI6W119LCJVViI6eyJYUyI6W119LCJrNSI6eyJYUyI6W119LCJLWSI6eyJYUyI6W119
-LCJ0NyI6eyJYUyI6W119LCJJZiI6eyJsZiI6W119LCJ6TSI6eyJiUSI6WyIxIl0sImNYIjpbIjEiXX0s
-ImliIjp7Ik9kIjpbXX0sInh1Ijp7ImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiWmQiOnsiR3oiOltdfSwi
-cVUiOnsidlgiOltdfSwiUm4iOnsiQkwiOltdfSwiRG4iOnsiaUQiOltdfSwiVWYiOnsiaUQiOltdfSwi
-cWUiOnsiaUQiOltdfSwicUUiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkdoIjp7ImN2IjpbXSwi
-dUgiOltdLCJEMCI6W119LCJmWSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwibkIiOnsiY3YiOltd
-LCJ1SCI6W10sIkQwIjpbXX0sIlFQIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJueCI6eyJ1SCI6
-W10sIkQwIjpbXX0sIlFGIjp7InVIIjpbXSwiRDAiOltdfSwiSUIiOnsidG4iOlsibGYiXX0sInd6Ijp7
-ImxEIjpbIjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXSwibEQuRSI6IjEifSwiY3Yi
-OnsidUgiOltdLCJEMCI6W119LCJUNSI6eyJBeiI6W119LCJoNCI6eyJjdiI6W10sInVIIjpbXSwiRDAi
-OltdfSwiVmIiOnsidUgiOltdLCJEMCI6W119LCJmSiI6eyJEMCI6W119LCJ3YSI6eyJEMCI6W119LCJP
-SyI6eyJlYSI6W119LCJlNyI6eyJsRCI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJiUSI6WyJ1SCJdLCJjWCI6
-WyJ1SCJdLCJsRC5FIjoidUgifSwidUgiOnsiRDAiOltdfSwiQkgiOnsiR20iOlsidUgiXSwibEQiOlsi
-dUgiXSwiek0iOlsidUgiXSwiWGoiOlsidUgiXSwiYlEiOlsidUgiXSwiY1giOlsidUgiXSwiR20uRSI6
-InVIIiwibEQuRSI6InVIIn0sIlNOIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJldyI6eyJlYSI6
-W119LCJscCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiVGIiOnsiY3YiOltdLCJ1SCI6W10sIkQw
-IjpbXX0sIkl2Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJCVCI6eyJjdiI6W10sInVIIjpbXSwi
-RDAiOltdfSwieVkiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sInc2Ijp7ImVhIjpbXX0sIks1Ijp7
-InY2IjpbXSwiRDAiOltdfSwiQ20iOnsiRDAiOltdfSwiQ1EiOnsidUgiOltdLCJEMCI6W119LCJ3NCI6
-eyJ0biI6WyJsZiJdfSwicmgiOnsiR20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsidUgiXSwiWGoi
-OlsidUgiXSwiYlEiOlsidUgiXSwiY1giOlsidUgiXSwiR20uRSI6InVIIiwibEQuRSI6InVIIn0sImNm
-Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdfSwiaTciOnsiWWsiOlsicVUiLCJxVSJd
-LCJaMCI6WyJxVSIsInFVIl0sIllrLksiOiJxVSIsIllrLlYiOiJxVSJ9LCJTeSI6eyJZayI6WyJxVSIs
-InFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsuSyI6InFVIiwiWWsuViI6InFVIn0sIkk0Ijp7Ik1hIjpb
-InFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl19LCJSTyI6eyJxaCI6WyIxIl19
-LCJldSI6eyJSTyI6WyIxIl0sInFoIjpbIjEiXX0sInhDIjp7Ik1PIjpbIjEiXX0sIkpRIjp7ImtGIjpb
-XX0sInZEIjp7ImtGIjpbXX0sIm02Ijp7ImtGIjpbXX0sImN0Ijp7ImtGIjpbXX0sIk93Ijp7ImtGIjpb
-XX0sIlc5Ijp7IkFuIjpbIjEiXX0sImRXIjp7InY2IjpbXSwiRDAiOltdfSwibWsiOnsieTAiOltdfSwi
-S28iOnsib24iOltdfSwiQXMiOnsiTWEiOlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwiY1gi
-OlsicVUiXX0sInI3Ijp7IkU0IjpbXX0sIlR6Ijp7ImxEIjpbIjEiXSwiek0iOlsiMSJdLCJiUSI6WyIx
-Il0sIkU0IjpbXSwiY1giOlsiMSJdLCJsRC5FIjoiMSJ9LCJuZCI6eyJkNSI6W10sImN2IjpbXSwidUgi
-OltdLCJEMCI6W119LCJLZSI6eyJNYSI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJjWCI6
-WyJxVSJdfSwiZDUiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm42Ijp7InpNIjpbIklmIl0sImJR
-IjpbIklmIl0sIkFTIjpbXSwiY1giOlsiSWYiXX0sIlhBIjp7ImtGIjpbXX0sIk9GIjp7Ikx1IjpbXX0s
-InJ1Ijp7Ikx1IjpbXX0sIklWIjp7Ikx1IjpbXX19JykpCkguRkYodi50eXBlVW5pdmVyc2UsSlNPTi5w
-YXJzZSgneyJiUSI6MSwidzIiOjEsIk1PIjoxLCJrVCI6MiwibVciOjEsIkxVIjoxLCJpbCI6MiwiVmoi
-OjEsIm5ZIjoxLCJUQyI6MSwiY28iOjF9JykpCnZhciB1PShmdW5jdGlvbiBydGlpKCl7dmFyIHQ9SC5O
-MApyZXR1cm57aTp0KCJHaCIpLG46dCgiT0giKSxjUjp0KCJuQiIpLGQ6dCgiQXoiKSxZOnQoIlFQIiks
-Z0Y6dCgiUEQ8R0QsQD4iKSxndzp0KCJiUTxAPiIpLGg6dCgiY3YiKSxXOnQoIlhTIiksQjp0KCJlYSIp
-LGFTOnQoIkQwIiksYzg6dCgiVDUiKSxaOnQoIkVIIiksYVE6dCgiYjg8Yzg+IiksYzp0KCJiODxAPiIp
-LHI6dCgiZkoiKSxJOnQoIlNnIiksbzp0KCJ2USIpLGVoOnQoImNYPHVIPiIpLFg6dCgiY1g8cVU+Iiks
-Ujp0KCJjWDxAPiIpLGZBOnQoImpkPFNlPiIpLHU6dCgiamQ8ajg+IiksYlA6dCgiamQ8dUY+IiksZmg6
-dCgiamQ8Wlo+Iiksazp0KCJqZDxrRj4iKSxzOnQoImpkPHFVPiIpLGhoOnQoImpkPHlEPiIpLGFKOnQo
-ImpkPHdiPiIpLG06dCgiamQ8QD4iKSx0OnQoImpkPElmPiIpLGVIOnQoInZtIiksZzp0KCJjNSIpLGFV
-OnQoIlhqPEA+IiksYW06dCgiVHo8QD4iKSxlbzp0KCJONTxHRCxAPiIpLHY6dCgiRTQiKSxkejp0KCJo
-RiIpLGE6dCgiek08cVU+Iiksajp0KCJ6TTxAPiIpLEw6dCgiek08SWY+IiksYV86dCgidTgiKSxmOnQo
-IlowPHFVLHFVPiIpLGI6dCgiWjA8cVUsQD4iKSxHOnQoIlowPEAsQD4iKSxkdjp0KCJsSjxxVSxxVT4i
-KSxkbzp0KCJsSjxxVSxAPiIpLFY6dCgiT0siKSxkRDp0KCJwRiIpLGJtOnQoIlY2IiksQTp0KCJ1SCIp
-LGU6dCgia0YiKSxQOnQoImM4IiksSzp0KCJNaCIpLHA6dCgiZXciKSxxOnQoInRuPGxmPiIpLGZ2OnQo
-IndMIiksYXY6dCgiSmMiKSxldzp0KCJuZCIpLEM6dCgieHU8cVU+IiksbDp0KCJHeiIpLE46dCgicVUi
-KSxkRzp0KCJxVShxVSkiKSxnNzp0KCJkNSIpLGZvOnQoIkdEIiksYVc6dCgieVkiKSx3OnQoIkFTIiks
-Z2M6dCgibjYiKSxhazp0KCJrZCIpLEQ6dCgiR2o8cVUscVU+IiksRTp0KCJpRCIpLGNjOnQoIlU1PHFV
-PiIpLGc0OnQoIks1IiksY2k6dCgidjYiKSxnMjp0KCJDbSIpLGJqOnQoIlpmPGZKPiIpLGg5OnQoIkNR
-IiksYWM6dCgiZTciKSxROnQoImV1PE9LPiIpLFQ6dCgid3o8Y3Y+IikseDp0KCJGZTxALEA+IiksYW86
-dCgidnM8Zko+IiksXzp0KCJ2czxAPiIpLGZKOnQoInZzPElmPiIpLE86dCgiSlEiKSxKOnQoImJuIiks
-eTp0KCJhMiIpLGFsOnQoImEyKE1oKSIpLGJCOnQoImEyKHFVKSIpLGJmOnQoImEyKEApIiksZ1I6dCgi
-Q1AiKSx6OnQoIkAiKSxmTzp0KCJAKCkiKSxVOnQoIkAoZWEpIiksRjp0KCJAKE1oKSIpLGVwOnQoIkAo
-TWgsTWgpIiksYWc6dCgiQChNaCxHeikiKSxiVTp0KCJAKHh1PHFVPikiKSxkTzp0KCJAKHFVKSIpLGI4
-OnQoIkAoQCxAKSIpLFM6dCgiSWYiKSxkaTp0KCJsZiIpLEg6dCgifiIpLE06dCgifigpIiksYW46dCgi
-fihldykiKSxlQTp0KCJ+KHFVLHFVKSIpLGNBOnQoIn4ocVUsQCkiKX19KSgpOyhmdW5jdGlvbiBjb25z
-dGFudHMoKXt2YXIgdD1odW5rSGVscGVycy5tYWtlQ29uc3RMaXN0CkMuUlk9Vy5RUC5wcm90b3R5cGUK
-Qy5CWj1XLlZiLnByb3RvdHlwZQpDLkR0PVcuZkoucHJvdG90eXBlCkMuT2s9Si52Qi5wcm90b3R5cGUK
-Qy5ObT1KLmpkLnByb3RvdHlwZQpDLmpuPUoudXIucHJvdG90eXBlCkMuak49Si5ZRS5wcm90b3R5cGUK
-Qy5DRD1KLnFJLnByb3RvdHlwZQpDLnhCPUouRHIucHJvdG90eXBlCkMuREc9Si5jNS5wcm90b3R5cGUK
-Qy5FeD1XLnU4LnByb3RvdHlwZQpDLkx0PVcuU04ucHJvdG90eXBlCkMuWlE9Si5pQy5wcm90b3R5cGUK
-Qy5JZT1XLlRiLnByb3RvdHlwZQpDLnZCPUoua2QucHJvdG90eXBlCkMub2w9Vy5LNS5wcm90b3R5cGUK
-Qy55OD1uZXcgUC5VOCgpCkMuaDk9bmV3IFAuQ1YoKQpDLndiPWZ1bmN0aW9uIGdldFRhZ0ZhbGxiYWNr
-KG8pIHsKICB2YXIgcyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTsKICByZXR1cm4g
-cy5zdWJzdHJpbmcoOCwgcy5sZW5ndGggLSAxKTsKfQpDLk80PWZ1bmN0aW9uKCkgewogIHZhciB0b1N0
-cmluZ0Z1bmN0aW9uID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWco
-bykgewogICAgdmFyIHMgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJz
-dHJpbmcoOCwgcy5sZW5ndGggLSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3Qs
-IHRhZykgewogICAgaWYgKC9eSFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZh
-ciBuYW1lID0gdG9TdHJpbmdGdW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJb
-b2JqZWN0IE9iamVjdF0iKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAg
-ICB9CiAgfQogIGZ1bmN0aW9uIGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykg
-ewogICAgaWYgKHNlbGYuSFRNTEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQp
-IHJldHVybiAiSFRNTEVsZW1lbnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcp
-OwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRv
-dyA9PSAidW5kZWZpbmVkIikgcmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09
-ICJ1bmRlZmluZWQiKSByZXR1cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWdd
-OwogICAgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAg
-IHJldHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3Io
-dGFnKSB7IHJldHVybiBudWxsOyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0g
-Im9iamVjdCI7CiAgcmV0dXJuIHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzog
-aXNCcm93c2VyID8gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAg
-IHByb3RvdHlwZUZvclRhZzogcHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3Jp
-bWluYXRvciB9Owp9CkMuZGs9ZnVuY3Rpb24oZ2V0VGFnRmFsbGJhY2spIHsKICByZXR1cm4gZnVuY3Rp
-b24oaG9va3MpIHsKICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9ICJvYmplY3QiKSByZXR1cm4gaG9v
-a3M7CiAgICB2YXIgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50OwogICAgaWYgKHVhLmluZGV4T2YoIkR1
-bXBSZW5kZXJUcmVlIikgPj0gMCkgcmV0dXJuIGhvb2tzOwogICAgaWYgKHVhLmluZGV4T2YoIkNocm9t
-ZSIpID49IDApIHsKICAgICAgZnVuY3Rpb24gY29uZmlybShwKSB7CiAgICAgICAgcmV0dXJuIHR5cGVv
-ZiB3aW5kb3cgPT0gIm9iamVjdCIgJiYgd2luZG93W3BdICYmIHdpbmRvd1twXS5uYW1lID09IHA7CiAg
-ICAgIH0KICAgICAgaWYgKGNvbmZpcm0oIldpbmRvdyIpICYmIGNvbmZpcm0oIkhUTUxFbGVtZW50Iikp
-IHJldHVybiBob29rczsKICAgIH0KICAgIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZhbGxiYWNrOwogIH07
-Cn0KQy5ZcT1mdW5jdGlvbihob29rcykgewogIGlmICh0eXBlb2YgZGFydEV4cGVyaW1lbnRhbEZpeHVw
-R2V0VGFnICE9ICJmdW5jdGlvbiIpIHJldHVybiBob29rczsKICBob29rcy5nZXRUYWcgPSBkYXJ0RXhw
-ZXJpbWVudGFsRml4dXBHZXRUYWcoaG9va3MuZ2V0VGFnKTsKfQpDLktVPWZ1bmN0aW9uKGhvb2tzKSB7
-CiAgdmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3Mu
-cHJvdG90eXBlRm9yVGFnOwogIGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBn
-ZXRUYWcobyk7CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJz
-aW9uKSByZXR1cm4gIiFEb2N1bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9
-CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsK
-ICAgIGlmICh0YWcgPT0gIkRvY3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBl
-Rm9yVGFnKHRhZyk7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3Rv
-dHlwZUZvclRhZyA9IHByb3RvdHlwZUZvclRhZ0ZpeGVkOwp9CkMueGk9ZnVuY3Rpb24oaG9va3MpIHsK
-ICB2YXIgdXNlckFnZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51
-c2VyQWdlbnQgOiAiIjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIkZpcmVmb3giKSA9PSAtMSkgcmV0
-dXJuIGhvb2tzOwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewog
-ICAgIkJlZm9yZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJv
-YXJkIiwKICAgICJHZW9HZW9sb2NhdGlvbiI6ICJHZW9sb2NhdGlvbiIsCiAgICAiTG9jYXRpb24iOiAi
-IUxvY2F0aW9uIiwKICAgICJXb3JrZXJNZXNzYWdlRXZlbnQiOiAiTWVzc2FnZUV2ZW50IiwKICAgICJY
-TUxEb2N1bWVudCI6ICIhRG9jdW1lbnQifTsKICBmdW5jdGlvbiBnZXRUYWdGaXJlZm94KG8pIHsKICAg
-IHZhciB0YWcgPSBnZXRUYWcobyk7CiAgICByZXR1cm4gcXVpY2tNYXBbdGFnXSB8fCB0YWc7CiAgfQog
-IGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpcmVmb3g7Cn0KQy5pNz1mdW5jdGlvbihob29rcykgewogIHZh
-ciB1c2VyQWdlbnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJB
-Z2VudCA6ICIiOwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiVHJpZGVudC8iKSA9PSAtMSkgcmV0dXJu
+dXJuIEgucFkoaSkKaWYoIShrPmkpKWJyZWFrOy0tawppZihDLnhCLk8yKGosayk9PT00Nyl7aWYoaD09
+PTApe2Y9Ii8iCmJyZWFrfS0taApmPSIvIn19aWYoaz09PWkmJmEuYjw9MCYmIUMueEIuUWkoaiwiLyIs
+bCkpe20tPWgqMwpmPSIifXE9ay1tK2YubGVuZ3RoCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGosMCxr
+KStmK0MueEIueW4odCxtKSxhLmIsYS5jLGEuZCxsLGUrcSxiLnIrcSxhLngpfSwKdDQ6ZnVuY3Rpb24o
+KXt2YXIgdCxzLHIscSxwPXRoaXMKaWYocC5iPj0wJiYhcC5nTncoKSl0aHJvdyBILmIoUC5MNCgiQ2Fu
+bm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIrSC5kKHAuZ0ZpKCkpKyIgVVJJIikpCnQ9cC5m
+CnM9cC5hCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCmlmKHQ8cy5sZW5ndGgpe2lm
+KHQ8cC5yKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJ
+IHdpdGggYSBxdWVyeSBjb21wb25lbnQiKSkKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEg
+ZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIGZyYWdtZW50IGNvbXBvbmVudCIpKX1yPSQuT3goKQpp
+ZihILm9UKHIpKXQ9UC5tbihwKQplbHNle3E9cC5kCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJu
+IEgucFkocSkKaWYocC5jPHEpSC5WaihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIG5vbi1XaW5kb3dzIGZp
+bGUgcGF0aCBmcm9tIGEgZmlsZSBVUkkgd2l0aCBhbiBhdXRob3JpdHkiKSkKdD1DLnhCLk5qKHMscC5l
+LHQpfXJldHVybiB0fSwKZ2k6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy55CnJldHVybiB0PT1udWxsP3Ro
+aXMueT1DLnhCLmdpKHRoaXMuYSk6dH0sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4h
+MQppZih0aGlzPT09YilyZXR1cm4hMApyZXR1cm4gdS5GLmIoYikmJnRoaXMuYT09PWIuWigwKX0sCnZz
+OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPW51bGwscj10LmdGaSgpLHE9dC5na3UoKSxwPXQuYz4wP3Qu
+Z0pmKHQpOnMsbz10Lmd4QSgpP3QuZ3RwKHQpOnMsbj10LmEsbT10LmYsbD1DLnhCLk5qKG4sdC5lLG0p
+LGs9dC5yCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIG0uSigpCm09bTxrP3QuZ3RQKHQpOnMK
+cmV0dXJuIG5ldyBQLkRuKHIscSxwLG8sbCxtLGs8bi5sZW5ndGg/dC5nS2EoKTpzKX0sClo6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMuYX0sCiRpaUQ6MX0KUC5xZS5wcm90b3R5cGU9e30KVy5xRS5wcm90b3R5
+cGU9e30KVy5ZZS5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLkdo
+LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpR2g6MX0KVy5mWS5w
+cm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLm5CLnByb3RvdHlwZT17
+JGluQjoxfQpXLkF6LnByb3RvdHlwZT17JGlBejoxfQpXLlBVLnByb3RvdHlwZT17CmdudzpmdW5jdGlv
+bihhKXtyZXR1cm4gYS52YWx1ZX19ClcuUVAucHJvdG90eXBlPXskaVFQOjF9ClcuSUYucHJvdG90eXBl
+PXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5ueC5wcm90b3R5cGU9ewpnazpmdW5j
+dGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLlJkLnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXty
+ZXR1cm4gYS52YWx1ZX19Clcua1IucHJvdG90eXBlPXt9ClcuVGYucHJvdG90eXBlPXsKZ2s6ZnVuY3Rp
+b24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5sdy5wcm90b3R5cGU9eyRpbHc6MX0KVy5vSi5wcm90b3R5
+cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmlkLnByb3RvdHlwZT17fQpXLkJ3
+LnByb3RvdHlwZT17fQpXLm80LnByb3RvdHlwZT17fQpXLkhTLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9u
+KGEpe3JldHVybiBhLmxlbmd0aH19ClcuVm8ucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVy
+biBhLnZhbHVlfX0KVy5GaC5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
+fQpXLmN4LnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcuU2IucHJv
+dG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3Jl
+dHVybiBhW0guV1koYildfX0KVy5RRi5wcm90b3R5cGU9e30KVy5OaC5wcm90b3R5cGU9ewpaOmZ1bmN0
+aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLkZ2LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5s
+ZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVu
+Y3Rpb24oYSxiLGMpe0guV1koYikKdS5xLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24g
+ZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1h
+Lmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeTox
+LAokaXpNOjF9ClcuSUIucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iUmVjdGFuZ2xlICgi
+K0guZChhLmxlZnQpKyIsICIrSC5kKGEudG9wKSsiKSAiK0guZCh0aGlzLmdQKGEpKSsiIHggIitILmQo
+dGhpcy5nTChhKSl9LApETjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGI9PW51bGwpcmV0dXJuITEKaWYo
+dS5xLmIoYikpaWYoYS5sZWZ0PT1iLmxlZnQpaWYoYS50b3A9PWIudG9wKXt0PUouUkUoYikKdD10aGlz
+LmdQKGEpPT10LmdQKGIpJiZ0aGlzLmdMKGEpPT10LmdMKGIpfWVsc2UgdD0hMQplbHNlIHQ9ITEKZWxz
+ZSB0PSExCnJldHVybiB0fSwKZ2k6ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoSi5JKGEubGVmdCksSi5J
+KGEudG9wKSxKLkkodGhpcy5nUChhKSksSi5JKHRoaXMuZ0woYSkpKX0sCmdMOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmhlaWdodH0sCmdQOmZ1bmN0aW9uKGEpe3JldHVybiBhLndpZHRofSwKJGl0bjoxfQpXLlls
+LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxi
+KXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxu
+dWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKSC5jKGMpCnRo
+cm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwK
+VzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBh
+W2JdfSwKJGliUToxLAokaVhqOjEsCiRpTHk6MSwKJGl6TToxfQpXLm43LnByb3RvdHlwZT17CmdrOmZ1
+bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19
+Clcud3oucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1
+bmN0aW9uKGEsYil7dmFyIHQKSC5XWShiKQp0PXRoaXMuYQppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVy
+biBILmsodCxiKQpyZXR1cm4gdGhpcy4kdGkuYy5hKHRbYl0pfSwKdDpmdW5jdGlvbihhLGIsYyl7SC5X
+WShiKQp0aGlzLiR0aS5jLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgbGlzdCIpKX19
+ClcuY3YucHJvdG90eXBlPXsKZ1FnOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5pNyhhKX0sCmdERDpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuSTQoYSl9LApzREQ6ZnVuY3Rpb24oYSxiKXt2YXIgdAp1Llgu
+YShiKQp0PXRoaXMuZ0REKGEpCnQuVjEoMCkKdC5GVigwLGIpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4g
+YS5sb2NhbE5hbWV9LAp0bjpmdW5jdGlvbihhKXt2YXIgdD0hIWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRl
+ZAppZih0KWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZCgpCmVsc2UgYS5zY3JvbGxJbnRvVmlldygpfSwK
+bno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzPXRoaXMucjYoYSxjLGQsZSkKc3dpdGNoKGIudG9M
+b3dlckNhc2UoKSl7Y2FzZSJiZWZvcmViZWdpbiI6YS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShzLGEp
+CmJyZWFrCmNhc2UiYWZ0ZXJiZWdpbiI6dD1hLmNoaWxkTm9kZXMKYS5pbnNlcnRCZWZvcmUocyx0Lmxl
+bmd0aD4wP3RbMF06bnVsbCkKYnJlYWsKY2FzZSJiZWZvcmVlbmQiOmEuYXBwZW5kQ2hpbGQocykKYnJl
+YWsKY2FzZSJhZnRlcmVuZCI6YS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShzLGEubmV4dFNpYmxpbmcp
+CmJyZWFrCmRlZmF1bHQ6SC5WaihQLnhZKCJJbnZhbGlkIHBvc2l0aW9uICIrYikpfX0sCnI2OmZ1bmN0
+aW9uKGEsYixjLGQpe3ZhciB0LHMscixxCmlmKGM9PW51bGwpe2lmKGQ9PW51bGwpe3Q9JC5sdAppZih0
+PT1udWxsKXt0PUguVk0oW10sdS51KQpzPW5ldyBXLnZEKHQpCkMuTm0uQSh0LFcuVHcobnVsbCkpCkMu
+Tm0uQSh0LFcuQmwoKSkKJC5sdD1zCmQ9c31lbHNlIGQ9dH10PSQuRVUKaWYodD09bnVsbCl7dD1uZXcg
+Vy5LbyhkKQokLkVVPXQKYz10fWVsc2V7dC5hPWQKYz10fX1lbHNlIGlmKGQhPW51bGwpdGhyb3cgSC5i
+KFAueFkoInZhbGlkYXRvciBjYW4gb25seSBiZSBwYXNzZWQgaWYgdHJlZVNhbml0aXplciBpcyBudWxs
+IikpCmlmKCQueG89PW51bGwpe3Q9ZG9jdW1lbnQKcz10LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxE
+b2N1bWVudCgiIikKJC54bz1zCiQuQk89cy5jcmVhdGVSYW5nZSgpCnM9JC54by5jcmVhdGVFbGVtZW50
+KCJiYXNlIikKdS5jUi5hKHMpCnMuaHJlZj10LmJhc2VVUkkKJC54by5oZWFkLmFwcGVuZENoaWxkKHMp
+fXQ9JC54bwppZih0LmJvZHk9PW51bGwpe3M9dC5jcmVhdGVFbGVtZW50KCJib2R5IikKdC5ib2R5PXUu
+ay5hKHMpfXQ9JC54bwppZih1LmsuYihhKSlyPXQuYm9keQplbHNle3I9dC5jcmVhdGVFbGVtZW50KGEu
+dGFnTmFtZSkKJC54by5ib2R5LmFwcGVuZENoaWxkKHIpfWlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21l
+bnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUmJiFDLk5tLnRnKEMuU3EsYS50YWdOYW1lKSl7JC5C
+Ty5zZWxlY3ROb2RlQ29udGVudHMocikKcT0kLkJPLmNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudChiKX1l
+bHNle3IuaW5uZXJIVE1MPWIKcT0kLnhvLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpmb3IoO3Q9ci5m
+aXJzdENoaWxkLHQhPW51bGw7KXEuYXBwZW5kQ2hpbGQodCl9dD0kLnhvLmJvZHkKaWYocj09bnVsbD90
+IT1udWxsOnIhPT10KUouTHQocikKYy5QbihxKQpkb2N1bWVudC5hZG9wdE5vZGUocSkKcmV0dXJuIHF9
+LApBSDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIHRoaXMucjYoYSxiLGMsbnVsbCl9LApzaGY6ZnVuY3Rp
+b24oYSxiKXt0aGlzLllDKGEsYil9LApwazpmdW5jdGlvbihhLGIsYyl7YS50ZXh0Q29udGVudD1udWxs
+CmEuYXBwZW5kQ2hpbGQodGhpcy5yNihhLGIsbnVsbCxjKSl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVy
+biB0aGlzLnBrKGEsYixudWxsKX0sCmduczpmdW5jdGlvbihhKXtyZXR1cm4gYS50YWdOYW1lfSwKZ1Zs
+OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5ldShhLCJjbGljayIsITEsdS5RKX0sCiRpY3Y6MX0KVy5D
+di5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5oLmIodS5BLmEoYSkpfSwKJFM6MjV9
+ClcuZWEucHJvdG90eXBlPXskaWVhOjF9ClcuRDAucHJvdG90eXBlPXsKT246ZnVuY3Rpb24oYSxiLGMs
+ZCl7dS5lNi5hKGMpCmlmKGMhPW51bGwpdGhpcy52MChhLGIsYyxkKX0sCkI6ZnVuY3Rpb24oYSxiLGMp
+e3JldHVybiB0aGlzLk9uKGEsYixjLG51bGwpfSwKdjA6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEu
+YWRkRXZlbnRMaXN0ZW5lcihiLEgudFIodS5lNi5hKGMpLDEpLGQpfSwKJGlEMDoxfQpXLlQ1LnByb3Rv
+dHlwZT17JGlUNToxfQpXLlhWLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0
+aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cg
+SC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMp
+e0guV1koYikKdS5PLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBp
+bW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1
+cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjEsCiRp
+WFY6MX0KVy53Si5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmg0
+LnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuR08ucHJvdG90eXBl
+PXskaUdPOjF9ClcuSkMucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0K
+Vy5ici5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLnhuLnByb3Rv
+dHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZ
+KGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51
+bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5BLmEoYykKdGhyb3cg
+SC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1
+bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19
+LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9ClcuVmIucHJvdG90eXBlPXt9ClcuZkoucHJv
+dG90eXBlPXsKZW86ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEub3BlbihiLGMsITApfSwKJGlmSjox
+fQpXLmJVLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLnNldFJlcXVlc3RIZWFkZXIo
+SC5jKGEpLEguYyhiKSl9LAokUzoxMn0KVy5oSC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
+dCxzLHIscSxwCnUucC5hKGEpCnQ9dGhpcy5hCnM9dC5zdGF0dXMKaWYodHlwZW9mIHMhPT0ibnVtYmVy
+IilyZXR1cm4gcy50QigpCnI9cz49MjAwJiZzPDMwMApxPXM+MzA3JiZzPDQwMApzPXJ8fHM9PT0wfHxz
+PT09MzA0fHxxCnA9dGhpcy5iCmlmKHMpcC5hTSgwLHQpCmVsc2UgcC5wbShhKX0sCiRTOjI3fQpXLndh
+LnByb3RvdHlwZT17fQpXLlNnLnByb3RvdHlwZT17JGlTZzoxfQpXLkpLLnByb3RvdHlwZT17Cmdudzpm
+dW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gYS53ZWJraXRF
+bnRyaWVzfX0KVy5ITC5wcm90b3R5cGU9ewpnRzM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEua2V5fX0KVy53
+UC5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9fQpXLnU4LnByb3RvdHlw
+ZT17CmdEcjpmdW5jdGlvbihhKXtpZigib3JpZ2luIiBpbiBhKXJldHVybiBhLm9yaWdpbgpyZXR1cm4g
+SC5kKGEucHJvdG9jb2wpKyIvLyIrSC5kKGEuaG9zdCl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJp
+bmcoYSl9LAokaXU4OjF9ClcuejYucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVu
+Z3RofX0KVy5DZi5wcm90b3R5cGU9eyRpQ2Y6MX0KVy5RYi5wcm90b3R5cGU9ewpnbnc6ZnVuY3Rpb24o
+YSl7cmV0dXJuIGEudmFsdWV9fQpXLlMwLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+UC5tUihhLmdldChILmMoYikpKX0sClU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnUuVC5hKGIpCnQ9YS5l
+bnRyaWVzKCkKZm9yKDshMDspe3M9dC5uZXh0KCkKaWYocy5kb25lKXJldHVybgpiLiQyKHMudmFsdWVb
+MF0sUC5tUihzLnZhbHVlWzFdKSl9fSwKZ3Y6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5WTShbXSx1LnMpCnRo
+aXMuVShhLG5ldyBXLkZBKHQpKQpyZXR1cm4gdH0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLnNpemV9
+LAp0OmZ1bmN0aW9uKGEsYixjKXt0aHJvdyBILmIoUC5MNCgiTm90IHN1cHBvcnRlZCIpKX0sCiRpWjA6
+MX0KVy5GQS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3JldHVybiBDLk5tLkEodGhpcy5hLGEp
+fSwKJFM6OH0KVy56Mi5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIFAubVIoYS5nZXQo
+SC5jKGIpKSl9LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp1LlQuYShiKQp0PWEuZW50cmllcygpCmZv
+cig7ITA7KXtzPXQubmV4dCgpCmlmKHMuZG9uZSlyZXR1cm4KYi4kMihzLnZhbHVlWzBdLFAubVIocy52
+YWx1ZVsxXSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLlUoYSxuZXcg
+Vy51cSh0KSkKcmV0dXJuIHR9LApnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5zaXplfSwKdDpmdW5jdGlv
+bihhLGIsYyl7dGhyb3cgSC5iKFAuTDQoIk5vdCBzdXBwb3J0ZWQiKSl9LAokaVowOjF9ClcudXEucHJv
+dG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy5ObS5BKHRoaXMuYSxhKX0sCiRTOjh9Clcu
+QVcucHJvdG90eXBlPXskaUFXOjF9ClcuRE0ucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0
+aCl0aHJvdyBILmIoUC50KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKdDpmdW5jdGlv
+bihhLGIsYyl7SC5XWShiKQp1LmNJLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxl
+bWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxl
+bmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAok
+aXpNOjF9ClcuT0sucHJvdG90eXBlPXskaU9LOjF9ClcuZTcucHJvdG90eXBlPXsKZ3I4OmZ1bmN0aW9u
+KGEpe3ZhciB0PXRoaXMuYSxzPXQuY2hpbGROb2Rlcy5sZW5ndGgKaWYocz09PTApdGhyb3cgSC5iKFAu
+UFYoIk5vIGVsZW1lbnRzIikpCmlmKHM+MSl0aHJvdyBILmIoUC5QVigiTW9yZSB0aGFuIG9uZSBlbGVt
+ZW50IikpCnJldHVybiB0LmZpcnN0Q2hpbGR9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxCnUu
+ZWguYShiKQp0PWIuYQpzPXRoaXMuYQppZih0IT09cylmb3Iocj10LmNoaWxkTm9kZXMubGVuZ3RoLHE9
+MDtxPHI7KytxKXMuYXBwZW5kQ2hpbGQodC5maXJzdENoaWxkKQpyZXR1cm59LAp0OmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdApILldZKGIpCnQ9dGhpcy5hCnQucmVwbGFjZUNoaWxkKHUuQS5hKGMpLEMudDUucSh0
+LmNoaWxkTm9kZXMsYikpfSwKZ3c6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLmNoaWxkTm9kZXMKcmV0
+dXJuIG5ldyBXLlc5KHQsdC5sZW5ndGgsSC5xKHQpLkMoIlc5PEdtLkU+IikpfSwKZ2s6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuYS5jaGlsZE5vZGVzLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIp
+CnJldHVybiBDLnQ1LnEodGhpcy5hLmNoaWxkTm9kZXMsYil9fQpXLnVILnByb3RvdHlwZT17CndnOmZ1
+bmN0aW9uKGEpe3ZhciB0PWEucGFyZW50Tm9kZQppZih0IT1udWxsKXQucmVtb3ZlQ2hpbGQoYSl9LApE
+NDpmdW5jdGlvbihhKXt2YXIgdApmb3IoO3Q9YS5maXJzdENoaWxkLHQhPW51bGw7KWEucmVtb3ZlQ2hp
+bGQodCl9LApaOmZ1bmN0aW9uKGEpe3ZhciB0PWEubm9kZVZhbHVlCnJldHVybiB0PT1udWxsP3RoaXMu
+VChhKTp0fSwKJGl1SDoxfQpXLkJILnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxl
+bmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhy
+b3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxi
+LGMpe0guV1koYikKdS5BLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBv
+ZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aCly
+ZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9
+ClcuUWwucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5HWC5wcm90
+b3R5cGU9ewpnbnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9fQpXLlNOLnByb3RvdHlwZT17fQpX
+LkhELnByb3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX19ClcuY2wucHJvdG90
+eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKJGljbDoxfQpXLkV2LnByb3RvdHlw
+ZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIp
+CmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwp
+KQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5oZS5hKGMpCnRocm93IEgu
+YihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5j
+dGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBhW2JdfSwK
+JGliUToxLAokaVhqOjEsCiRpTHk6MSwKJGl6TToxfQpXLkxyLnByb3RvdHlwZT17CmdudzpmdW5jdGlv
+bihhKXtyZXR1cm4gYS52YWx1ZX19ClcuS1IucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVy
+biBhLnZhbHVlfX0KVy5ldy5wcm90b3R5cGU9eyRpZXc6MX0KVy5wOC5wcm90b3R5cGU9ewpxOmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIFAubVIoYS5nZXQoSC5jKGIpKSl9LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cwp1LlQuYShiKQp0PWEuZW50cmllcygpCmZvcig7ITA7KXtzPXQubmV4dCgpCmlmKHMuZG9uZSlyZXR1
+cm4KYi4kMihzLnZhbHVlWzBdLFAubVIocy52YWx1ZVsxXSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0
+PUguVk0oW10sdS5zKQp0aGlzLlUoYSxuZXcgVy5paSh0KSkKcmV0dXJuIHR9LApnazpmdW5jdGlvbihh
+KXtyZXR1cm4gYS5zaXplfSwKdDpmdW5jdGlvbihhLGIsYyl7dGhyb3cgSC5iKFAuTDQoIk5vdCBzdXBw
+b3J0ZWQiKSl9LAokaVowOjF9ClcuaWkucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+Qy5ObS5BKHRoaXMuYSxhKX0sCiRTOjh9ClcubHAucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofSwKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5TVi5wcm90b3R5
+cGU9eyRpU1Y6MX0KVy5Nay5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
+LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEgu
+YihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0OmZ1bmN0aW9uKGEsYixjKXtI
+LldZKGIpCnUuZlkuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGlt
+bXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVy
+biBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaUx5OjEsCiRpek06MX0KVy5Z
+NC5wcm90b3R5cGU9eyRpWTQ6MX0KVy5Obi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4g
+YS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3Ro
+KXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0OmZ1bmN0aW9u
+KGEsYixjKXtILldZKGIpCnUuZjcuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVt
+ZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVu
+Z3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaUx5OjEsCiRp
+ek06MX0KVy5sOC5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LAokaWw4
+OjF9ClcuQXMucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3JldHVybiBhLmdldEl0ZW0oSC5jKGIp
+KX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe2Euc2V0SXRlbShiLGMpfSwKVTpmdW5jdGlvbihhLGIpe3ZhciB0
+LHMKdS5XLmEoYikKZm9yKHQ9MDshMDsrK3Qpe3M9YS5rZXkodCkKaWYocz09bnVsbClyZXR1cm4KYi4k
+MihzLGEuZ2V0SXRlbShzKSl9fSwKZ3Y6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5WTShbXSx1LnMpCnRoaXMu
+VShhLG5ldyBXLmNYKHQpKQpyZXR1cm4gdH0sCmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0s
+CiRpWjA6MX0KVy5jWC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3JldHVybiBDLk5tLkEodGhp
+cy5hLGEpfSwKJFM6MTZ9ClcuYmsucHJvdG90eXBlPXsKZ0czOmZ1bmN0aW9uKGEpe3JldHVybiBhLmtl
+eX19ClcuV1cucHJvdG90eXBlPXskaVdXOjF9ClcuVGIucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxi
+LGMsZCl7dmFyIHQscwppZigiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2Uu
+cHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEsYixjLGQpCnQ9Vy5VOSgiPHRhYmxlPiIrSC5kKGIpKyI8
+L3RhYmxlPiIsYyxkKQpzPWRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpzLnRvU3RyaW5n
+CnQudG9TdHJpbmcKbmV3IFcuZTcocykuRlYoMCxuZXcgVy5lNyh0KSkKcmV0dXJuIHN9fQpXLkl2LnBy
+b3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxCmlmKCJjcmVhdGVDb250ZXh0
+dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMs
+ZCkKdD1kb2N1bWVudApzPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNyZWF0
+ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4KHQp
+CnIudG9TdHJpbmcKdD1uZXcgVy5lNyhyKQpxPXQuZ3I4KHQpCnMudG9TdHJpbmcKcS50b1N0cmluZwpu
+ZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHEpKQpyZXR1cm4gc319ClcuQlQucHJvdG90eXBlPXsKcjY6
+ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGlu
+IHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1kb2N1bWVudApz
+PXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNyZWF0ZUVsZW1lbnQoInRhYmxl
+IiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4KHQpCnMudG9TdHJpbmcKci50
+b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHIpKQpyZXR1cm4gc319ClcuZlgucHJvdG90
+eXBlPXsKcGs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKYS50ZXh0Q29udGVudD1udWxsCnQ9YS5jb250
+ZW50CnQudG9TdHJpbmcKSi5iVCh0KQpzPXRoaXMucjYoYSxiLG51bGwsYykKYS5jb250ZW50LmFwcGVu
+ZENoaWxkKHMpfSwKWUM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5wayhhLGIsbnVsbCl9LAokaWZY
+OjF9ClcuRkIucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KVy5BMS5w
+cm90b3R5cGU9eyRpQTE6MX0KVy5NTi5wcm90b3R5cGU9eyRpTU46MX0KVy5YMC5wcm90b3R5cGU9ewpn
+azpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihi
+Pj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0
+dXJuIGFbYl19LAp0OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCnUuYzcuYShjKQp0aHJvdyBILmIoUC5M
+NCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24o
+YSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6
+MSwKJGlYajoxLAokaUx5OjEsCiRpek06MX0KVy5uSi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXty
+ZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEu
+bGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0OmZ1
+bmN0aW9uKGEsYixjKXtILldZKGIpCnUuYTAuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2ln
+biBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+
+PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaUx5
+OjEsCiRpek06MX0KVy5tei5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
+fQpXLmEzLnByb3RvdHlwZT17JGlhMzoxfQpXLmNpLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5s
+ZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVu
+Y3Rpb24oYSxiLGMpe0guV1koYikKdS5hSy5hKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWdu
+IGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49
+YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpTHk6
+MSwKJGl6TToxfQpXLmNuLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19
+ClcudzYucHJvdG90eXBlPXt9ClcuRmoucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gU3Ry
+aW5nKGEpfX0KVy52Ri5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpX
+Lk9pLnByb3RvdHlwZT17CmdtVzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhdGlvbn0sCiRpT2k6MSwK
+JGl2NjoxfQpXLkNtLnByb3RvdHlwZT17JGlDbToxfQpXLkNRLnByb3RvdHlwZT17CmdudzpmdW5jdGlv
+bihhKXtyZXR1cm4gYS52YWx1ZX0sCiRpQ1E6MX0KVy5QUi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihh
+KXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+
+PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LAp0
+OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCnUuZzUuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFz
+c2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPDB8
+fGI+PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAok
+aUx5OjEsCiRpek06MX0KVy53NC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSZWN0YW5n
+bGUgKCIrSC5kKGEubGVmdCkrIiwgIitILmQoYS50b3ApKyIpICIrSC5kKGEud2lkdGgpKyIgeCAiK0gu
+ZChhLmhlaWdodCl9LApETjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGI9PW51bGwpcmV0dXJuITEKaWYo
+dS5xLmIoYikpaWYoYS5sZWZ0PT1iLmxlZnQpaWYoYS50b3A9PWIudG9wKXt0PUouUkUoYikKdD1hLndp
+ZHRoPT10LmdQKGIpJiZhLmhlaWdodD09dC5nTChiKX1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0h
+MQpyZXR1cm4gdH0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiBXLnJFKEouSShhLmxlZnQpLEouSShhLnRv
+cCksSi5JKGEud2lkdGgpLEouSShhLmhlaWdodCkpfSwKZ0w6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuaGVp
+Z2h0fSwKZ1A6ZnVuY3Rpb24oYSl7cmV0dXJuIGEud2lkdGh9fQpXLkYyLnByb3RvdHlwZT17CmdrOmZ1
+bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4w
+IT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4g
+YVtiXX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5kUC5hKGMpCnRocm93IEguYihQLkw0KCJD
+YW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIp
+e2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAok
+aVhqOjEsCiRpTHk6MSwKJGl6TToxfQpXLnJoLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVy
+biBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5n
+dGgpdGhyb3cgSC5iKFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sCnQ6ZnVuY3Rp
+b24oYSxiLGMpe0guV1koYikKdS5BLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxl
+bWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxl
+bmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAok
+aXpNOjF9ClcuTE8ucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpm
+dW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50
+KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKdDpmdW5jdGlvbihhLGIsYyl7SC5XWShi
+KQp1LmdmLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFi
+bGUgTGlzdC4iKSl9LApXOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5r
+KGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9ClcuYjEucHJv
+dG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gu
+V1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50KGIsYSxudWxsLG51bGws
+bnVsbCkpCnJldHVybiBhW2JdfSwKdDpmdW5jdGlvbihhLGIsYyl7SC5XWShiKQp1LmduLmEoYykKdGhy
+b3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApX
+OmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsYikKcmV0dXJuIGFb
+Yl19LAokaWJROjEsCiRpWGo6MSwKJGlMeToxLAokaXpNOjF9ClcuYVQucHJvdG90eXBlPXsKVTpmdW5j
+dGlvbihhLGIpe3ZhciB0LHMscixxLHAKdS5XLmEoYikKZm9yKHQ9dGhpcy5ndih0aGlzKSxzPXQubGVu
+Z3RoLHI9dGhpcy5hLHE9MDtxPHQubGVuZ3RoO3QubGVuZ3RoPT09c3x8KDAsSC5saykodCksKytxKXtw
+PXRbcV0KYi4kMihwLHIuZ2V0QXR0cmlidXRlKHApKX19LApndjpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
+cSxwPXRoaXMuYS5hdHRyaWJ1dGVzLG89SC5WTShbXSx1LnMpCmZvcih0PXAubGVuZ3RoLHM9dS5oOSxy
+PTA7cjx0Oysrcil7aWYocj49cC5sZW5ndGgpcmV0dXJuIEguayhwLHIpCnE9cy5hKHBbcl0pCmlmKHEu
+bmFtZXNwYWNlVVJJPT1udWxsKUMuTm0uQShvLHEubmFtZSl9cmV0dXJuIG99fQpXLmk3LnByb3RvdHlw
+ZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLmdldEF0dHJpYnV0ZShILmMoYikpfSwKdDpm
+dW5jdGlvbihhLGIsYyl7dGhpcy5hLnNldEF0dHJpYnV0ZShiLGMpfSwKZ2s6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuZ3YodGhpcykubGVuZ3RofX0KVy5TeS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIHRoaXMuYS5hLmdldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuWShILmMoYikpKX0sCnQ6ZnVu
+Y3Rpb24oYSxiLGMpe3RoaXMuYS5hLnNldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuWShiKSxjKX0sClU6
+ZnVuY3Rpb24oYSxiKXt0aGlzLmEuVSgwLG5ldyBXLktTKHRoaXMsdS5XLmEoYikpKX0sCmd2OmZ1bmN0
+aW9uKGEpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLmEuVSgwLG5ldyBXLkEzKHRoaXMsdCkpCnJldHVy
+biB0fSwKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ3YodGhpcykubGVuZ3RofSwKeHE6ZnVuY3Rp
+b24oYSl7dmFyIHQscyxyPUguVk0oYS5zcGxpdCgiLSIpLHUucykKZm9yKHQ9MTt0PHIubGVuZ3RoOysr
+dCl7cz1yW3RdCmlmKHMubGVuZ3RoPjApQy5ObS50KHIsdCxzWzBdLnRvVXBwZXJDYXNlKCkrSi5LVihz
+LDEpKX1yZXR1cm4gQy5ObS56VihyLCIiKX0sClk6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscApmb3Io
+dD1hLmxlbmd0aCxzPTAscj0iIjtzPHQ7KytzKXtxPWFbc10KcD1xLnRvTG93ZXJDYXNlKCkKcj0ocSE9
+PXAmJnM+MD9yKyItIjpyKStwfXJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfX0KVy5LUy5wcm90
+b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lmKEouclkoYSkubkMoYSwiZGF0YS0iKSl0aGlzLmIuJDIo
+dGhpcy5hLnhxKEMueEIueW4oYSw1KSksYil9LAokUzoxMn0KVy5BMy5wcm90b3R5cGU9ewokMjpmdW5j
+dGlvbihhLGIpe2lmKEouclkoYSkubkMoYSwiZGF0YS0iKSlDLk5tLkEodGhpcy5iLHRoaXMuYS54cShD
+LnhCLnluKGEsNSkpKX0sCiRTOjEyfQpXLkk0LnByb3RvdHlwZT17CkRHOmZ1bmN0aW9uKCl7dmFyIHQs
+cyxyLHEscD1QLkxzKHUuTikKZm9yKHQ9dGhpcy5hLmNsYXNzTmFtZS5zcGxpdCgiICIpLHM9dC5sZW5n
+dGgscj0wO3I8czsrK3Ipe3E9Si5UMCh0W3JdKQppZihxLmxlbmd0aCE9PTApcC5BKDAscSl9cmV0dXJu
+IHB9LApwNTpmdW5jdGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPXUuQy5hKGEpLnpWKDAsIiAiKX0sCmdr
+OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0aH0sClYxOmZ1bmN0aW9uKGEp
+e3RoaXMuYS5jbGFzc05hbWU9IiJ9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYS5jbGFzc0xp
+c3QuY29udGFpbnMoYikKcmV0dXJuIHR9LApBOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNz
+TGlzdCxzPXQuY29udGFpbnMoYikKdC5hZGQoYikKcmV0dXJuIXN9LApSejpmdW5jdGlvbihhLGIpe3Zh
+ciB0PXRoaXMuYS5jbGFzc0xpc3Qscz10LmNvbnRhaW5zKGIpCnQucmVtb3ZlKGIpCnJldHVybiBzfSwK
+RlY6ZnVuY3Rpb24oYSxiKXtXLlROKHRoaXMuYSx1LlguYShiKSl9fQpXLkZrLnByb3RvdHlwZT17fQpX
+LlJPLnByb3RvdHlwZT17fQpXLmV1LnByb3RvdHlwZT17fQpXLnhDLnByb3RvdHlwZT17fQpXLnZOLnBy
+b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuJDEodS5CLmEoYSkpfSwKJFM6Mjl9
+ClcuSlEucHJvdG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoJC5vci5hPT09MCl7Zm9yKHQ9
+MDt0PDI2MjsrK3QpJC5vci50KDAsQy5jbVt0XSxXLnBTKCkpCmZvcih0PTA7dDwxMjsrK3QpJC5vci50
+KDAsQy5CSVt0XSxXLlY0KCkpfX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiAkLkFOKCkudGcoMCxXLnJT
+KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0kLm9yLnEoMCxILmQoVy5yUyhhKSkrIjo6Iiti
+KQppZih0PT1udWxsKXQ9JC5vci5xKDAsIio6OiIrYikKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4g
+SC5FOSh0LiQ0KGEsYixjLHRoaXMpKX0sCiRpa0Y6MX0KVy5HbS5wcm90b3R5cGU9ewpndzpmdW5jdGlv
+bihhKXtyZXR1cm4gbmV3IFcuVzkoYSx0aGlzLmdrKGEpLEgucShhKS5DKCJXOTxHbS5FPiIpKX19Clcu
+dkQucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0uVnIodGhpcy5hLG5ldyBXLlV2
+KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3IFcuRWcoYSxi
+LGMpKX0sCiRpa0Y6MX0KVy5Vdi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5lLmEo
+YSkuaTAodGhpcy5hKX0sCiRTOjE3fQpXLkVnLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVy
+biB1LmUuYShhKS5FYih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzoxN30KVy5tNi5wcm90b3R5cGU9
+ewpDWTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdGhpcy5hLkZWKDAsYykKdD1iLmV2KDAsbmV3
+IFcuRW8oKSkKcz1iLmV2KDAsbmV3IFcuV2soKSkKdGhpcy5iLkZWKDAsdCkKcj10aGlzLmMKci5GVigw
+LEMueEQpCnIuRlYoMCxzKX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEudGcoMCxXLnJTKGEp
+KX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD10aGlzLHM9Vy5yUyhhKSxyPXQuYwppZihyLnRnKDAs
+SC5kKHMpKyI6OiIrYikpcmV0dXJuIHQuZC5EdChjKQplbHNlIGlmKHIudGcoMCwiKjo6IitiKSlyZXR1
+cm4gdC5kLkR0KGMpCmVsc2V7cj10LmIKaWYoci50ZygwLEguZChzKSsiOjoiK2IpKXJldHVybiEwCmVs
+c2UgaWYoci50ZygwLCIqOjoiK2IpKXJldHVybiEwCmVsc2UgaWYoci50ZygwLEguZChzKSsiOjoqIikp
+cmV0dXJuITAKZWxzZSBpZihyLnRnKDAsIio6OioiKSlyZXR1cm4hMH1yZXR1cm4hMX0sCiRpa0Y6MX0K
+Vy5Fby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4hQy5ObS50ZyhDLkJJLEguYyhhKSl9
+LAokUzo5fQpXLldrLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBDLk5tLnRnKEMuQkks
+SC5jKGEpKX0sCiRTOjl9ClcuY3QucHJvdG90eXBlPXsKRWI6ZnVuY3Rpb24oYSxiLGMpe2lmKHRoaXMu
+akYoYSxiLGMpKXJldHVybiEwCmlmKGI9PT0idGVtcGxhdGUiJiZjPT09IiIpcmV0dXJuITAKaWYoYS5n
+ZXRBdHRyaWJ1dGUoInRlbXBsYXRlIik9PT0iIilyZXR1cm4gdGhpcy5lLnRnKDAsYikKcmV0dXJuITF9
+fQpXLklBLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiJURU1QTEFURTo6IitILmQoSC5j
+KGEpKX0sCiRTOjV9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYodS5ldy5i
+KGEpKXJldHVybiExCnQ9dS5nNy5iKGEpCmlmKHQmJlcuclMoYSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0
+dXJuITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEsYixjKXtpZihiPT09Imlz
+Inx8Qy54Qi5uQyhiLCJvbiIpKXJldHVybiExCnJldHVybiB0aGlzLmkwKGEpfSwKJGlrRjoxfQpXLlc5
+LnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jKzEscj10LmIKaWYoczxyKXt0
+LnNwKEoueDkodC5hLHMpKQp0LmM9cwpyZXR1cm4hMH10LnNwKG51bGwpCnQuYz1yCnJldHVybiExfSwK
+Z1I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZH0sCnNwOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0
+aS5jLmEoYSl9LAokaUFuOjF9ClcuZFcucHJvdG90eXBlPXsKZ21XOmZ1bmN0aW9uKGEpe3JldHVybiBX
+LnpYKHRoaXMuYS5sb2NhdGlvbil9LAokaUQwOjEsCiRpdjY6MX0KVy5GYi5wcm90b3R5cGU9e30KVy5r
+Ri5wcm90b3R5cGU9e30KVy5tay5wcm90b3R5cGU9eyRpV1E6MX0KVy5Lby5wcm90b3R5cGU9ewpQbjpm
+dW5jdGlvbihhKXt2YXIgdD10aGlzLHM9bmV3IFcuZm0odCkKdC5iPSExCnMuJDIoYSxudWxsKQpmb3Io
+O3QuYjspe3QuYj0hMQpzLiQyKGEsbnVsbCl9fSwKRVA6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmI9
+ITAKaWYoYiE9bnVsbD9iIT09YS5wYXJlbnROb2RlOnQpSi5MdChhKQplbHNlIGIucmVtb3ZlQ2hpbGQo
+YSl9LApJNDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz0hMCxuPW51bGwsbT1udWxsCnRyeXtu
+PUouaWcoYSkKbT1uLmEuZ2V0QXR0cmlidXRlKCJpcyIpCnUuaC5hKGEpCnQ9ZnVuY3Rpb24oYyl7aWYo
+IShjLmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApKXJldHVybiB0cnVlCmlmKGMuaWQ9
+PSdsYXN0Q2hpbGQnfHxjLm5hbWU9PSdsYXN0Q2hpbGQnfHxjLmlkPT0ncHJldmlvdXNTaWJsaW5nJ3x8
+Yy5uYW1lPT0ncHJldmlvdXNTaWJsaW5nJ3x8Yy5pZD09J2NoaWxkcmVuJ3x8Yy5uYW1lPT0nY2hpbGRy
+ZW4nKXJldHVybiB0cnVlCnZhciBsPWMuY2hpbGROb2RlcwppZihjLmxhc3RDaGlsZCYmYy5sYXN0Q2hp
+bGQhPT1sW2wubGVuZ3RoLTFdKXJldHVybiB0cnVlCmlmKGMuY2hpbGRyZW4paWYoIShjLmNoaWxkcmVu
+IGluc3RhbmNlb2YgSFRNTENvbGxlY3Rpb258fGMuY2hpbGRyZW4gaW5zdGFuY2VvZiBOb2RlTGlzdCkp
+cmV0dXJuIHRydWUKdmFyIGs9MAppZihjLmNoaWxkcmVuKWs9Yy5jaGlsZHJlbi5sZW5ndGgKZm9yKHZh
+ciBqPTA7ajxrO2orKyl7dmFyIGk9Yy5jaGlsZHJlbltqXQppZihpLmlkPT0nYXR0cmlidXRlcyd8fGku
+bmFtZT09J2F0dHJpYnV0ZXMnfHxpLmlkPT0nbGFzdENoaWxkJ3x8aS5uYW1lPT0nbGFzdENoaWxkJ3x8
+aS5pZD09J3ByZXZpb3VzU2libGluZyd8fGkubmFtZT09J3ByZXZpb3VzU2libGluZyd8fGkuaWQ9PSdj
+aGlsZHJlbid8fGkubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZX1yZXR1cm4gZmFsc2V9KGEpCm89
+SC5vVCh0KT8hMDohKGEuYXR0cmlidXRlcyBpbnN0YW5jZW9mIE5hbWVkTm9kZU1hcCl9Y2F0Y2gocSl7
+SC5SdShxKX1zPSJlbGVtZW50IHVucHJpbnRhYmxlIgp0cnl7cz1KLkFjKGEpfWNhdGNoKHEpe0guUnUo
+cSl9dHJ5e3I9Vy5yUyhhKQp0aGlzLmtSKHUuaC5hKGEpLGIsbyxzLHIsdS5HLmEobiksSC5jKG0pKX1j
+YXRjaChxKXtpZihILlJ1KHEpIGluc3RhbmNlb2YgUC5BVCl0aHJvdyBxCmVsc2V7dGhpcy5FUChhLGIp
+CndpbmRvdwpwPSJSZW1vdmluZyBjb3JydXB0ZWQgZWxlbWVudCAiK0guZChzKQppZih0eXBlb2YgY29u
+c29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKX19fSwKa1I6ZnVuY3Rpb24oYSxi
+LGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG49dGhpcwppZihjKXtuLkVQKGEsYikKd2luZG93CnQ9
+IlJlbW92aW5nIGVsZW1lbnQgZHVlIHRvIGNvcnJ1cHRlZCBhdHRyaWJ1dGVzIG9uIDwiK2QrIj4iCmlm
+KHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKHQpCnJldHVybn1p
+Zighbi5hLmkwKGEpKXtuLkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5nIGRpc2FsbG93ZWQgZWxlbWVu
+dCA8IitILmQoZSkrIj4gZnJvbSAiK0guZChiKQppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIp
+d2luZG93LmNvbnNvbGUud2Fybih0KQpyZXR1cm59aWYoZyE9bnVsbClpZighbi5hLkViKGEsImlzIixn
+KSl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2VkIHR5cGUgZXh0ZW5zaW9uIDwi
+K0guZChlKSsnIGlzPSInK2crJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93
+LmNvbnNvbGUud2Fybih0KQpyZXR1cm59dD1mLmd2KGYpCnM9SC5WTSh0LnNsaWNlKDApLEgudDYodCku
+QygiamQ8MT4iKSkKZm9yKHI9Zi5ndihmKS5sZW5ndGgtMSx0PWYuYTtyPj0wOy0tcil7aWYocj49cy5s
+ZW5ndGgpcmV0dXJuIEguayhzLHIpCnE9c1tyXQpwPW4uYQpvPUouY0gocSkKSC5jKHEpCmlmKCFwLkVi
+KGEsbyx0LmdldEF0dHJpYnV0ZShxKSkpe3dpbmRvdwpwPSJSZW1vdmluZyBkaXNhbGxvd2VkIGF0dHJp
+YnV0ZSA8IitILmQoZSkrIiAiK3ErJz0iJytILmQodC5nZXRBdHRyaWJ1dGUocSkpKyciPicKaWYodHlw
+ZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocCkKdC5yZW1vdmVBdHRy
+aWJ1dGUocSl9fWlmKHUuYVcuYihhKSluLlBuKGEuY29udGVudCl9LAokaW9uOjF9ClcuZm0ucHJvdG90
+eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbj10aGlzLmEKc3dpdGNoKGEubm9k
+ZVR5cGUpe2Nhc2UgMTpuLkk0KGEsYikKYnJlYWsKY2FzZSA4OmNhc2UgMTE6Y2FzZSAzOmNhc2UgNDpi
+cmVhawpkZWZhdWx0Om4uRVAoYSxiKX10PWEubGFzdENoaWxkCmZvcihyPXUuQTtudWxsIT10Oyl7cz1u
+dWxsCnRyeXtzPXQucHJldmlvdXNTaWJsaW5nCmlmKHMhPW51bGwpe3E9cy5uZXh0U2libGluZwpwPXQK
+cD1xPT1udWxsP3AhPW51bGw6cSE9PXAKcT1wfWVsc2UgcT0hMQppZihxKXtxPVAuUFYoIkNvcnJ1cHQg
+SFRNTCIpCnRocm93IEguYihxKX19Y2F0Y2gobyl7SC5SdShvKQpxPXIuYSh0KQpuLmI9ITAKcD1xLnBh
+cmVudE5vZGUKcD1hPT1udWxsP3AhPW51bGw6YSE9PXAKaWYocCl7cD1xLnBhcmVudE5vZGUKaWYocCE9
+bnVsbClwLnJlbW92ZUNoaWxkKHEpfWVsc2UgYS5yZW1vdmVDaGlsZChxKQp0PW51bGwKcz1hLmxhc3RD
+aGlsZH1pZih0IT1udWxsKXRoaXMuJDIodCxhKQp0PXN9fSwKJFM6NDF9ClcuTGUucHJvdG90eXBlPXt9
+ClcuSlUucHJvdG90eXBlPXt9ClcueFgucHJvdG90eXBlPXt9ClcudmUucHJvdG90eXBlPXt9ClcuYkcu
+cHJvdG90eXBlPXt9ClcudEkucHJvdG90eXBlPXt9ClcuZmcucHJvdG90eXBlPXt9ClcuY1cucHJvdG90
+eXBlPXt9ClcuSFcucHJvdG90eXBlPXt9ClcubEcucHJvdG90eXBlPXt9ClcucXMucHJvdG90eXBlPXt9
+ClcuY3MucHJvdG90eXBlPXt9ClcuS0IucHJvdG90eXBlPXt9ClcuSzcucHJvdG90eXBlPXt9ClcuckIu
+cHJvdG90eXBlPXt9ClcuZlQucHJvdG90eXBlPXt9ClcuZjcucHJvdG90eXBlPXt9ClcuYmcucHJvdG90
+eXBlPXt9Clcub0gucHJvdG90eXBlPXt9ClcuQ0UucHJvdG90eXBlPXt9ClcuYUQucHJvdG90eXBlPXt9
+ClcuWngucHJvdG90eXBlPXt9ClcuT1gucHJvdG90eXBlPXt9ClcuVWoucHJvdG90eXBlPXt9Clcuak0u
+cHJvdG90eXBlPXt9ClcuUVYucHJvdG90eXBlPXt9ClcuQXcucHJvdG90eXBlPXt9ClcudHIucHJvdG90
+eXBlPXt9ClcuTzMucHJvdG90eXBlPXt9ClcuT3YucHJvdG90eXBlPXt9ClcuY08ucHJvdG90eXBlPXt9
+ClcuWUQucHJvdG90eXBlPXt9ClcuRHgucHJvdG90eXBlPXt9ClcuWFcucHJvdG90eXBlPXt9Clcub2Eu
+cHJvdG90eXBlPXt9ClcuWFUucHJvdG90eXBlPXt9ClcubzMucHJvdG90eXBlPXt9ClcuenYucHJvdG90
+eXBlPXt9ClcubnoucHJvdG90eXBlPXt9ClAuaTYucHJvdG90eXBlPXsKVkg6ZnVuY3Rpb24oYSl7dmFy
+IHQscz10aGlzLmEscj1zLmxlbmd0aApmb3IodD0wO3Q8cjsrK3QpaWYoc1t0XT09PWEpcmV0dXJuIHQK
+Qy5ObS5BKHMsYSkKQy5ObS5BKHRoaXMuYixudWxsKQpyZXR1cm4gcn0sClB2OmZ1bmN0aW9uKGEpe3Zh
+ciB0LHMscixxPXRoaXMscD17fQppZihhPT1udWxsKXJldHVybiBhCmlmKEguclEoYSkpcmV0dXJuIGEK
+aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4g
+YQppZihhIGluc3RhbmNlb2YgUC5pUClyZXR1cm4gbmV3IERhdGUoYS5hKQppZih1LmZ2LmIoYSkpdGhy
+b3cgSC5iKFAubigic3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAiKSkKaWYodS5PLmIoYSkpcmV0dXJu
+IGEKaWYodS5kLmIoYSkpcmV0dXJuIGEKaWYodS5iWC5iKGEpKXJldHVybiBhCmlmKHUuSS5iKGEpKXJl
+dHVybiBhCmlmKHUuYlouYihhKXx8dS5kRC5iKGEpfHx1LmJLLmIoYSkpcmV0dXJuIGEKaWYodS5HLmIo
+YSkpe3Q9cS5WSChhKQpzPXEuYgppZih0Pj1zLmxlbmd0aClyZXR1cm4gSC5rKHMsdCkKcj1wLmE9c1t0
+XQppZihyIT1udWxsKXJldHVybiByCnI9e30KcC5hPXIKQy5ObS50KHMsdCxyKQpKLmhFKGEsbmV3IFAu
+amcocCxxKSkKcmV0dXJuIHAuYX1pZih1LmouYihhKSl7dD1xLlZIKGEpCnA9cS5iCmlmKHQ+PXAubGVu
+Z3RoKXJldHVybiBILmsocCx0KQpyPXBbdF0KaWYociE9bnVsbClyZXR1cm4gcgpyZXR1cm4gcS5layhh
+LHQpfWlmKHUuZUguYihhKSl7dD1xLlZIKGEpCnM9cS5iCmlmKHQ+PXMubGVuZ3RoKXJldHVybiBILmso
+cyx0KQpyPXAuYj1zW3RdCmlmKHIhPW51bGwpcmV0dXJuIHIKcj17fQpwLmI9cgpDLk5tLnQocyx0LHIp
+CnEuaW0oYSxuZXcgUC5UYShwLHEpKQpyZXR1cm4gcC5ifXRocm93IEguYihQLm4oInN0cnVjdHVyZWQg
+Y2xvbmUgb2Ygb3RoZXIgdHlwZSIpKX0sCmVrOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1KLlU2KGEpLHI9
+cy5nayhhKSxxPW5ldyBBcnJheShyKQpDLk5tLnQodGhpcy5iLGIscSkKZm9yKHQ9MDt0PHI7Kyt0KUMu
+Tm0udChxLHQsdGhpcy5QdihzLnEoYSx0KSkpCnJldHVybiBxfX0KUC5qZy5wcm90b3R5cGU9ewokMjpm
+dW5jdGlvbihhLGIpe3RoaXMuYS5hW2FdPXRoaXMuYi5QdihiKX0sCiRTOjF9ClAuVGEucHJvdG90eXBl
+PXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuYlthXT10aGlzLmIuUHYoYil9LAokUzoxfQpQLmFKLnBy
+b3RvdHlwZT17ClZIOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5hLHI9cy5sZW5ndGgKZm9yKHQ9MDt0
+PHI7Kyt0KWlmKHNbdF09PT1hKXJldHVybiB0CkMuTm0uQShzLGEpCkMuTm0uQSh0aGlzLmIsbnVsbCkK
+cmV0dXJuIHJ9LApQdjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz10aGlzLGo9e30K
+aWYoYT09bnVsbClyZXR1cm4gYQppZihILnJRKGEpKXJldHVybiBhCmlmKHR5cGVvZiBhPT0ibnVtYmVy
+IilyZXR1cm4gYQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIERh
+dGUpe3Q9YS5nZXRUaW1lKCkKcz1uZXcgUC5pUCh0LCEwKQpzLlhrKHQsITApCnJldHVybiBzfWlmKGEg
+aW5zdGFuY2VvZiBSZWdFeHApdGhyb3cgSC5iKFAubigic3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAi
+KSkKaWYodHlwZW9mIFByb21pc2UhPSJ1bmRlZmluZWQiJiZhIGluc3RhbmNlb2YgUHJvbWlzZSlyZXR1
+cm4gUC5VOChhLHUueikKcj1PYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkKaWYocj09PU9iamVjdC5wcm90
+b3R5cGV8fHI9PT1udWxsKXtxPWsuVkgoYSkKcz1rLmIKaWYocT49cy5sZW5ndGgpcmV0dXJuIEguayhz
+LHEpCnA9ai5hPXNbcV0KaWYocCE9bnVsbClyZXR1cm4gcApvPXUuegpwPVAuRmwobyxvKQpqLmE9cApD
+Lk5tLnQocyxxLHApCmsuSHAoYSxuZXcgUC5LNShqLGspKQpyZXR1cm4gai5hfWlmKGEgaW5zdGFuY2Vv
+ZiBBcnJheSl7bj1hCnE9ay5WSChuKQpzPWsuYgppZihxPj1zLmxlbmd0aClyZXR1cm4gSC5rKHMscSkK
+cD1zW3FdCmlmKHAhPW51bGwpcmV0dXJuIHAKbz1KLlU2KG4pCm09by5nayhuKQpDLk5tLnQocyxxLG4p
+CmZvcihsPTA7bDxtOysrbClvLnQobixsLGsuUHYoby5xKG4sbCkpKQpyZXR1cm4gbn1yZXR1cm4gYX19
+ClAuSzUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEuYSxzPXRoaXMuYi5Q
+dihiKQpKLnU5KHQsYSxzKQpyZXR1cm4gc30sCiRTOjMzfQpQLkJmLnByb3RvdHlwZT17CmltOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscyxyLHEKdS5ZLmEoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSkscz10Lmxlbmd0
+aCxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxhW3FdKX19fQpQLnpnLnByb3RvdHlwZT17CkhwOmZ1
+bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKdS5ZLmEoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSkscz10Lmxl
+bmd0aCxyPTA7cjx0Lmxlbmd0aDt0Lmxlbmd0aD09PXN8fCgwLEgubGspKHQpLCsrcil7cT10W3JdCmIu
+JDIocSxhW3FdKX19fQpQLmRNLnByb3RvdHlwZT17ClM6ZnVuY3Rpb24oYSl7dmFyIHQKSC5jKGEpCnQ9
+JC5FZSgpLmIKaWYodHlwZW9mIGEhPSJzdHJpbmciKUguVmooSC50TChhKSkKaWYodC50ZXN0KGEpKXJl
+dHVybiBhCnRocm93IEguYihQLkwzKGEsInZhbHVlIiwiTm90IGEgdmFsaWQgY2xhc3MgdG9rZW4iKSl9
+LApaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLkRHKCkuelYoMCwiICIpfSwKZ3c6ZnVuY3Rpb24oYSl7
+dmFyIHQ9dGhpcy5ERygpCnJldHVybiBQLnJqKHQsdC5yLEguTGgodCkuYyl9LApnazpmdW5jdGlvbihh
+KXtyZXR1cm4gdGhpcy5ERygpLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3RoaXMuUyhiKQpyZXR1cm4gdGhp
+cy5ERygpLnRnKDAsYil9LApBOmZ1bmN0aW9uKGEsYil7dGhpcy5TKGIpCnJldHVybiBILkU5KHRoaXMu
+T1MoMCxuZXcgUC5HRShiKSkpfSwKUno6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnRoaXMuUyhiKQp0PXRo
+aXMuREcoKQpzPXQuUnooMCxiKQp0aGlzLnA1KHQpCnJldHVybiBzfSwKRlY6ZnVuY3Rpb24oYSxiKXt0
+aGlzLk9TKDAsbmV3IFAuTjcodGhpcyx1LlguYShiKSkpfSwKVjE6ZnVuY3Rpb24oYSl7dGhpcy5PUygw
+LG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCnUuYlUuYShiKQp0PXRoaXMuREco
+KQpzPWIuJDEodCkKdGhpcy5wNSh0KQpyZXR1cm4gc319ClAuR0UucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHUuQy5hKGEpLkEoMCx0aGlzLmEpfSwKJFM6MzR9ClAuTjcucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5iLHM9SC50Nih0KQpyZXR1cm4gdS5DLmEoYSkuRlYoMCxu
+ZXcgSC5sSih0LHMuQygicVUoMSkiKS5hKHRoaXMuYS5ndU0oKSkscy5DKCJsSjwxLHFVPiIpKSl9LAok
+UzoxNH0KUC51US5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LkMuYShhKQppZihhLmE+MCl7YS5i
+PWEuYz1hLmQ9YS5lPWEuZj1udWxsCmEuYT0wCmEuWEEoKX1yZXR1cm4gbnVsbH0sCiRTOjE0fQpQLlcy
+LnByb3RvdHlwZT17CmdHMzpmdW5jdGlvbihhKXtyZXR1cm4gYS5rZXl9fQpQLmUzLnByb3RvdHlwZT17
+CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuemcoW10sW10pLlB2KGEudmFsdWUpfX0KUC5oRi5w
+cm90b3R5cGU9eyRpaEY6MX0KUC5CVi5wcm90b3R5cGU9ewpnRzM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
+a2V5fSwKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KUC5QQy5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXt2YXIgdAp1LlouYShhKQp0PWZ1bmN0aW9uKGIsYyxkKXtyZXR1cm4gZnVuY3Rpb24o
+KXtyZXR1cm4gYihjLGQsdGhpcyxBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoYXJndW1lbnRzKSl9
+fShQLlI0LGEsITEpClAuRG0odCwkLndRKCksYSkKcmV0dXJuIHR9LAokUzo0fQpQLm10LnByb3RvdHlw
+ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgdGhpcy5hKGEpfSwKJFM6NH0KUC5Oei5wcm90b3R5
+cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAucjcoYSl9LAokUzozNn0KUC5ucC5wcm90b3R5
+cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVHooYSx1LmFtKX0sCiRTOjM3fQpQLlV0LnBy
+b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5FNChhKX0sCiRTOjM4fQpQLkU0LnBy
+b3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0i
+bnVtYmVyIil0aHJvdyBILmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQpy
+ZXR1cm4gUC5MNyh0aGlzLmFbYl0pfSwKdDpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJzdHJp
+bmciJiZ0eXBlb2YgYiE9Im51bWJlciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBhIFN0
+cmluZyBvciBudW0iKSkKdGhpcy5hW2JdPVAud1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51
+bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LApaOmZ1bmN0
+aW9uKGEpe3ZhciB0LHMKdHJ5e3Q9U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShz
+KQp0PXRoaXMueGIoMCkKcmV0dXJuIHR9fSwKVjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQpp
+ZihiPT1udWxsKXQ9bnVsbAplbHNle3Q9SC50NihiKQp0PVAuQ0gobmV3IEgubEooYix0LkMoIkAoMSki
+KS5hKFAuaUcoKSksdC5DKCJsSjwxLEA+IikpLCEwLHUueil9cmV0dXJuIFAuTDcoc1thXS5hcHBseShz
+LHQpKX0sCmdpOmZ1bmN0aW9uKGEpe3JldHVybiAwfX0KUC5yNy5wcm90b3R5cGU9e30KUC5Uei5wcm90
+b3R5cGU9ewpjUDpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9YTwwfHxhPj10LmdrKHQpCmlmKHMpdGhy
+b3cgSC5iKFAuVEUoYSwwLHQuZ2sodCksbnVsbCxudWxsKSl9LApxOmZ1bmN0aW9uKGEsYil7aWYodHlw
+ZW9mIGI9PSJudW1iZXIiJiZiPT09Qy5qbi55dShiKSl0aGlzLmNQKEguV1koYikpCnJldHVybiB0aGlz
+LiR0aS5jLmEodGhpcy5VcigwLGIpKX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuJHRpLmMuYShjKQpp
+Zih0eXBlb2YgYj09Im51bWJlciImJmI9PT1DLkNELnl1KGIpKXRoaXMuY1AoSC5XWShiKSkKdGhpcy5l
+NCgwLGIsYyl9LApnazpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEubGVuZ3RoCmlmKHR5cGVvZiB0PT09
+Im51bWJlciImJnQ+Pj4wPT09dClyZXR1cm4gdAp0aHJvdyBILmIoUC5QVigiQmFkIEpzQXJyYXkgbGVu
+Z3RoIikpfSwKJGliUToxLAokaUx5OjEsCiRpek06MX0KUC5jby5wcm90b3R5cGU9e30KUC52Sy5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmFNKDAsdGhpcy5iLkMoIjAvIikuYShh
+KSl9LAokUzoxMH0KUC5wVS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLnBt
+KGEpfSwKJFM6MTB9ClAuSU4ucHJvdG90eXBlPXt9ClAudG4ucHJvdG90eXBlPXt9ClAudWoucHJvdG90
+eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZhbHVlfX0KUC54MC5wcm90b3R5cGU9ewpnbnc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIGEudmFsdWV9LAokaXgwOjF9ClAucTYucHJvdG90eXBlPXsKZ2s6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAh
+PT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBh
+LmdldEl0ZW0oYil9LAp0OmZ1bmN0aW9uKGEsYixjKXtILldZKGIpCnUuYkcuYShjKQp0aHJvdyBILmIo
+UC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rp
+b24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LAokaWJROjEsCiRpTHk6MSwKJGl6TToxfQpQLnVQLnBy
+b3RvdHlwZT17CmdudzpmdW5jdGlvbihhKXtyZXR1cm4gYS52YWx1ZX0sCiRpdVA6MX0KUC5MWi5wcm90
+b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5X
+WShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxu
+dWxsKSkKcmV0dXJuIGEuZ2V0SXRlbShiKX0sCnQ6ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKdS5jay5h
+KGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3Qu
+IikpfSwKVzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnEoYSxiKX0sCiRpYlE6MSwKJGlMeToxLAok
+aXpNOjF9ClAuRUQucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KUC5u
+ZC5wcm90b3R5cGU9eyRpbmQ6MX0KUC5LcS5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4g
+YS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3Ro
+KXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGEuZ2V0SXRlbShiKX0sCnQ6
+ZnVuY3Rpb24oYSxiLGMpe0guV1koYikKSC5jKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWdu
+IGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKVzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
+LnEoYSxiKX0sCiRpYlE6MSwKJGlMeToxLAokaXpNOjF9ClAuS2UucHJvdG90eXBlPXsKREc6ZnVuY3Rp
+b24oKXt2YXIgdCxzLHIscSxwPXRoaXMuYS5nZXRBdHRyaWJ1dGUoImNsYXNzIiksbz1QLkxzKHUuTikK
+aWYocD09bnVsbClyZXR1cm4gbwpmb3IodD1wLnNwbGl0KCIgIikscz10Lmxlbmd0aCxyPTA7cjxzOysr
+cil7cT1KLlQwKHRbcl0pCmlmKHEubGVuZ3RoIT09MClvLkEoMCxxKX1yZXR1cm4gb30sCnA1OmZ1bmN0
+aW9uKGEpe3RoaXMuYS5zZXRBdHRyaWJ1dGUoImNsYXNzIixhLnpWKDAsIiAiKSl9fQpQLmQ1LnByb3Rv
+dHlwZT17CmdERDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuS2UoYSl9LApzaGY6ZnVuY3Rpb24oYSxi
+KXt0aGlzLllDKGEsYil9LApyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG8KaWYoZD09
+bnVsbCl7dD1ILlZNKFtdLHUudSkKZD1uZXcgVy52RCh0KQpDLk5tLkEodCxXLlR3KG51bGwpKQpDLk5t
+LkEodCxXLkJsKCkpCkMuTm0uQSh0LG5ldyBXLk93KCkpfWM9bmV3IFcuS28oZCkKcz0nPHN2ZyB2ZXJz
+aW9uPSIxLjEiPicrSC5kKGIpKyI8L3N2Zz4iCnQ9ZG9jdW1lbnQKcj10LmJvZHkKcT0ociYmQy5SWSku
+QUgocixzLGMpCnA9dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKcS50b1N0cmluZwp0PW5ldyBXLmU3
+KHEpCm89dC5ncjgodCkKZm9yKDt0PW8uZmlyc3RDaGlsZCx0IT1udWxsOylwLmFwcGVuZENoaWxkKHQp
+CnJldHVybiBwfSwKbno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGlu
+dm9rZSBpbnNlcnRBZGphY2VudEh0bWwgb24gU1ZHLiIpKX0sCmdWbDpmdW5jdGlvbihhKXtyZXR1cm4g
+bmV3IFcuZXUoYSwiY2xpY2siLCExLHUuUSl9LAokaWQ1OjF9ClAuelkucHJvdG90eXBlPXskaXpZOjF9
+ClAuTkMucHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlv
+bihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50KGIsYSxu
+dWxsLG51bGwsbnVsbCkpCnJldHVybiBhLmdldEl0ZW0oYil9LAp0OmZ1bmN0aW9uKGEsYixjKXtILldZ
+KGIpCnUuY00uYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0
+YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LAokaWJROjEs
+CiRpTHk6MSwKJGl6TToxfQpQLmZVLnByb3RvdHlwZT17fQpQLkdDLnByb3RvdHlwZT17fQpQLmpHLnBy
+b3RvdHlwZT17fQpQLmpTLnByb3RvdHlwZT17fQpQLnhXLnByb3RvdHlwZT17fQpQLmRTLnByb3RvdHlw
+ZT17fQpQLndqLnByb3RvdHlwZT17fQpQLk1ZLnByb3RvdHlwZT17fQpQLm42LnByb3RvdHlwZT17JGli
+UToxLCRpTHk6MSwkaXpNOjEsJGlBUzoxfQpQLnIyLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmxlbmd0aH19ClAuck8ucHJvdG90eXBlPXsKZ253OmZ1bmN0aW9uKGEpe3JldHVybiBhLnZh
+bHVlfX0KUC5EWC5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIFAubVIoYS5nZXQoSC5j
+KGIpKSl9LApVOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp1LlQuYShiKQp0PWEuZW50cmllcygpCmZvcig7
+ITA7KXtzPXQubmV4dCgpCmlmKHMuZG9uZSlyZXR1cm4KYi4kMihzLnZhbHVlWzBdLFAubVIocy52YWx1
+ZVsxXSkpfX0sCmd2OmZ1bmN0aW9uKGEpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlzLlUoYSxuZXcgUC5x
+Zih0KSkKcmV0dXJuIHR9LApnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5zaXplfSwKdDpmdW5jdGlvbihh
+LGIsYyl7dGhyb3cgSC5iKFAuTDQoIk5vdCBzdXBwb3J0ZWQiKSl9LAokaVowOjF9ClAucWYucHJvdG90
+eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy5ObS5BKHRoaXMuYSxhKX0sCiRTOjh9ClAuZm8u
+cHJvdG90eXBlPXsKZ2s6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KUC5WOC5wcm90b3R5cGU9
+e30KUC5Hbi5wcm90b3R5cGU9ewpnazpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpQLlUzLnBy
+b3RvdHlwZT17fQpQLkZuLnByb3RvdHlwZT17CmdrOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0s
+CnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5i
+KFAudChiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gUC5tUihhLml0ZW0oYikpfSwKdDpmdW5jdGlv
+bihhLGIsYyl7SC5XWShiKQp1LkcuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVt
+ZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sClc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEs
+Yil9LAokaWJROjEsCiRpTHk6MSwKJGl6TToxfQpQLm1vLnByb3RvdHlwZT17fQpQLktnLnByb3RvdHlw
+ZT17fQpVLmQyLnByb3RvdHlwZT17fQpVLlNlLnByb3RvdHlwZT17fQpVLk1sLnByb3RvdHlwZT17fQpV
+LnlELnByb3RvdHlwZT17CmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ifX0KVS53Yi5wcm90b3R5
+cGU9e30KQi5qOC5wcm90b3R5cGU9e30KQi5xcC5wcm90b3R5cGU9e30KVC5tUS5wcm90b3R5cGU9e30K
+TC5lLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuCnUuQi5hKGEpCnQ9
+d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lCnM9TC5HNih3aW5kb3cubG9jYXRpb24uaHJlZikKcj1MLmFL
+KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpMLkdlKCkKaWYodCE9PSIvIiYmdCE9PUouVDAoZG9jdW1lbnQu
+cXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpTC5HNyh0LHMsciwhMCxuZXcgTC5WVyh0
+LHMscikpCnE9ZG9jdW1lbnQKcD1KLnFGKHEucXVlcnlTZWxlY3RvcigiLmFwcGx5LW1pZ3JhdGlvbiIp
+KQpvPXAuJHRpCm49by5DKCJ+KDEpIikuYShuZXcgTC5vWigpKQp1Lk0uYShudWxsKQpXLkpFKHAuYSxw
+LmIsbiwhMSxvLmMpCnE9Si5xRihxLnF1ZXJ5U2VsZWN0b3IoIi5yZXJ1bi1taWdyYXRpb24iKSkKbz1x
+LiR0aQpXLkpFKHEuYSxxLmIsby5DKCJ+KDEpIikuYShuZXcgTC55OCgpKSwhMSxvLmMpfSwKJFM6MjB9
+CkwuVlcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0s
+CiRTOjB9Ckwub1oucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dS5WLmEoYSkKaWYoSC5vVCh3aW5k
+b3cuY29uZmlybSgiVGhpcyB3aWxsIGFwcGx5IHRoZSBjaGFuZ2VzIHlvdSd2ZSBwcmV2aWV3ZWQgdG8g
+eW91ciB3b3JraW5nIGRpcmVjdG9yeS4gSXQgaXMgcmVjb21tZW5kZWQgeW91IGNvbW1pdCBhbnkgY2hh
+bmdlcyB5b3UgbWFkZSBiZWZvcmUgZG9pbmcgdGhpcy4iKSkpTC50eSgiL2FwcGx5LW1pZ3JhdGlvbiIp
+Llc3KG5ldyBMLmpyKCksdS5QKS5PQShuZXcgTC5xbCgpKX0sCiRTOjZ9CkwuanIucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5yLmEoYSkKdD1kb2N1bWVudC5ib2R5CnQuY2xhc3NMaXN0LnJl
+bW92ZSgicHJvcG9zZWQiKQp0LmNsYXNzTGlzdC5hZGQoImFwcGxpZWQiKX0sCiRTOjd9CkwucWwucHJv
+dG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtMLnFKKCJhcHBseSBtaWdyYXRpb24gZXJyb3I6ICIrSC5k
+KGEpLGIpCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGFwcGx5IG1pZ3JhdGlvbiAoIitILmQoYSkrIiku
+Iil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpMLnk4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLnhuKHUuVi5hKGEpKX0sCnhuOmZ1bmN0aW9uKGEpe3ZhciB0PTAscz1QLkZYKHUuUCks
+cj0xLHEscD1bXSxvLG4sbSxsCnZhciAkYXN5bmMkJDE9UC5seihmdW5jdGlvbihiLGMpe2lmKGI9PT0x
+KXtxPWMKdD1yfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nhc2UgMDpyPTMKZG9jdW1lbnQuYm9keS5jbGFz
+c0xpc3QuYWRkKCJyZXJ1bm5pbmciKQp0PTYKcmV0dXJuIFAualEoTC50eSgiL3JlcnVuLW1pZ3JhdGlv
+biIpLCRhc3luYyQkMSkKY2FzZSA2OndpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKQpwLnB1c2goNSkKdD00
+CmJyZWFrCmNhc2UgMzpyPTIKbD1xCm89SC5SdShsKQpuPUgudHMobCkKTC5xSigicmVydW4gbWlncmF0
+aW9uOiAiK0guZChvKSxuKQp3aW5kb3cuYWxlcnQoIkZhaWxlZCB0byByZXJ1biBtaWdyYXRpb246ICIr
+SC5kKG8pKyIuIikKcC5wdXNoKDUpCnQ9NApicmVhawpjYXNlIDI6cD1bMV0KY2FzZSA0OnI9MQpkb2N1
+bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoInJlcnVubmluZyIpCnQ9cC5wb3AoKQpicmVhawpjYXNl
+IDU6cmV0dXJuIFAueUMobnVsbCxzKQpjYXNlIDE6cmV0dXJuIFAuZjMocSxzKX19KQpyZXR1cm4gUC5E
+SSgkYXN5bmMkJDEscyl9LAokUzo0Mn0KTC5MLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0
+LHMscgp1LkIuYShhKQp0PXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZQpzPUwuRzYod2luZG93LmxvY2F0
+aW9uLmhyZWYpCnI9TC5hSyh3aW5kb3cubG9jYXRpb24uaHJlZikKaWYodC5sZW5ndGg+MSlMLkc3KHQs
+cyxyLCExLG51bGwpCmVsc2V7TC5CRSh0LG5ldyBCLnFwKCIiLCIiLCIiLEMuQ00pLCEwKQpMLkJYKCIm
+bmJzcDsiLG51bGwpfX0sCiRTOjIwfQpMLld4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0
+LHMscixxPSJjb2xsYXBzZWQiCnUuVi5hKGEpCnQ9dGhpcy5hCnM9Si5SRSh0KQpyPXRoaXMuYgppZigh
+cy5nREQodCkudGcoMCxxKSl7cy5nREQodCkuQSgwLHEpCkouZFIocikuQSgwLHEpfWVsc2V7cy5nREQo
+dCkuUnooMCxxKQpKLmRSKHIpLlJ6KDAscSl9fSwKJFM6Nn0KTC5BTy5wcm90b3R5cGU9ewokMTpmdW5j
+dGlvbihhKXt2YXIgdD1KLnFGKHUuaC5hKGEpKSxzPXQuJHRpLHI9cy5DKCJ+KDEpIikuYShuZXcgTC5k
+Tih0aGlzLmEpKQp1Lk0uYShudWxsKQpXLkpFKHQuYSx0LmIsciwhMSxzLmMpfSwKJFM6M30KTC5kTi5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdAp1LlYuYShhKQp0PWRvY3VtZW50LnF1ZXJ5U2Vs
+ZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0iKQp0LnRvU3RyaW5nCkwudDIoYSx0aGlzLmEsdC5nZXRBdHRy
+aWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyh0KSkuWSgicGF0aCIpKSl9LAokUzo2fQpMLkhv
+LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LmguYShhKQp0PUoucUYoYSkKcz10
+LiR0aQpyPXMuQygifigxKSIpLmEobmV3IEwueHooYSx0aGlzLmEpKQp1Lk0uYShudWxsKQpXLkpFKHQu
+YSx0LmIsciwhMSxzLmMpfSwKJFM6M30KTC54ei5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
+dCxzPW51bGwKdS5WLmEoYSkKdD10aGlzLmEKTC5oWCh0aGlzLmIsUC5RQSh0LmdldEF0dHJpYnV0ZSgi
+ZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHQpKS5ZKCJvZmZzZXQiKSkscyxzKSxQLlFBKHQuZ2V0QXR0
+cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcodCkpLlkoImxpbmUiKSkscyxzKSl9LAokUzo2
+fQpMLklDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PUoucUYodS5oLmEoYSkpLHM9dC4k
+dGkKcy5DKCJ+KDEpIikuYShMLkgwKCkpCnUuTS5hKG51bGwpClcuSkUodC5hLHQuYixMLkgwKCksITEs
+cy5jKX0sCiRTOjN9CkwuTDEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5yLmEoYSkK
+dD1hLnN0YXR1cwppZih0PT09MjAwKXJldHVybiBhCmVsc2UgdGhyb3cgSC5iKCJSZXF1ZXN0IGZhaWxl
+ZDsgc3RhdHVzIG9mICIrSC5kKHQpKX0sCiRTOjQ0fQpMLm5ULnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
+KCl7TC5Gcih0aGlzLmEuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjB9CkwuQloucHJvdG90eXBlPXsKJDA6
+ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYS5hLG51bGwsbnVsbCl9LAokUzowfQpMLkdILnByb3RvdHlwZT17
+CiQxOmZ1bmN0aW9uKGEpe3UuaC5hKGEpCiQuekIoKS50b1N0cmluZwp1LncuYSgkLm93KCkucSgwLCJo
+bGpzIikpLlY3KCJoaWdobGlnaHRCbG9jayIsW2FdKX0sCiRTOjN9CkwuRFQucHJvdG90eXBlPXsKJDE6
+ZnVuY3Rpb24oYSl7dmFyIHQscwp1LnIuYShhKQp0PWEuc3RhdHVzCmlmKHQ9PT0yMDApe3Q9Qy5DdC5w
+VygwLGEucmVzcG9uc2VUZXh0LG51bGwpCnM9Si5VNih0KQpMLlQxKG5ldyBVLmQyKFUuamYocy5xKHQs
+ImVkaXRzIikpLEguYyhzLnEodCwiZXhwbGFuYXRpb24iKSksSC5XWShzLnEodCwibGluZSIpKSxILmMo
+cy5xKHQsInBhdGgiKSksVS5OZChzLnEodCwidHJhY2VzIikpKSkKTC5Gcih0aGlzLmEsdGhpcy5iLHRo
+aXMuYykKTC55WCgiLmVkaXQtcGFuZWwgLnBhbmVsLWNvbnRlbnQiLCExKX1lbHNlIHdpbmRvdy5hbGVy
+dCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpMLmVILnByb3RvdHlw
+ZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZFJlZ2lvbkV4cGxhbmF0aW9uOiAiK0guZChhKSxi
+KQp3aW5kb3cuYWxlcnQoIkNvdWxkIG5vdCBsb2FkICIrSC5kKHRoaXMuYSkrIiAoIitILmQoYSkrIiku
+Iil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpMLnl1LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
+ciB0LHMscj10aGlzCnUuci5hKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMCl7cz1yLmEKTC5CRShzLEIu
+WWYodS5iLmEoQy5DdC5wVygwLGEucmVzcG9uc2VUZXh0LG51bGwpKSksci5iKQp0PXIuYwpMLmZHKHQs
+ci5kKQpMLkJYKEMueEIudGcocywiPyIpP0MueEIuTmoocywwLEMueEIuT1kocywiPyIpKTpzLHQpCnQ9
+ci5lCmlmKHQhPW51bGwpdC4kMCgpfWVsc2Ugd2luZG93LmFsZXJ0KCJSZXF1ZXN0IGZhaWxlZDsgc3Rh
+dHVzIG9mICIrSC5kKHQpKX0sCiRTOjd9CkwuekQucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtM
+LnFKKCJsb2FkRmlsZTogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK3Ro
+aXMuYSsiICgiK0guZChhKSsiKS4iKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjF9CkwuVFcucHJvdG90eXBl
+PXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCnUuci5hKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMCl7
+cz1DLkN0LnBXKDAsYS5yZXNwb25zZVRleHQsbnVsbCkKcj1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIu
+bmF2LXRyZWUiKQpKLmw1KHIsIiIpCkwudFgocixMLm1LKHMpKX1lbHNlIHdpbmRvdy5hbGVydCgiUmVx
+dWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpMLnhyLnByb3RvdHlwZT17CiQy
+OmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZE5hdmlnYXRpb25UcmVlOiAiK0guZChhKSxiKQp3aW5kb3cu
+YWxlcnQoIkNvdWxkIG5vdCBsb2FkICIrdGhpcy5hKyIgKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwK
+JFI6MiwKJFM6MX0KTC5FRS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzCnUuVi5hKGEp
+CnQ9dGhpcy5hCnM9dGhpcy5iCkwuYWYod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHQscywhMCxuZXcg
+TC5RTCh0LHMpKQpMLmhYKHRoaXMuYyx0LHMpfSwKJFM6Nn0KTC5RTC5wcm90b3R5cGU9ewokMDpmdW5j
+dGlvbigpe0wuRnIod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0K
+TC5WUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzPSJzZWxlY3RlZC1maWxlIgp1Lmgu
+YShhKQphLnRvU3RyaW5nCnQ9Si5SRShhKQppZihhLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5
+KG5ldyBXLmk3KGEpKS5ZKCJuYW1lIikpPT09dGhpcy5hLmEpdC5nREQoYSkuQSgwLHMpCmVsc2UgdC5n
+REQoYSkuUnooMCxzKX0sCiRTOjN9CkwuVEQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEwudDIodS5WLmEoYSksITAsbnVsbCl9LAokUzoyMX0KTC5YQS5wcm90b3R5cGU9ewpFYjpmdW5jdGlv
+bihhLGIsYyl7cmV0dXJuITB9LAppMDpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCiRpa0Y6MX0KTC5aWi5w
+cm90b3R5cGU9e30KTC5XQS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpN
+LmxJLnByb3RvdHlwZT17CldPOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1udWxsCk0uWUYoImFic29sdXRl
+IixILlZNKFtiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSx1LnMpKQp0PXRoaXMuYQp0PXQu
+WXIoYik+MCYmIXQuaEsoYikKaWYodClyZXR1cm4gYgp0PUQuUlgoKQpyZXR1cm4gdGhpcy5xNygwLHQs
+YixzLHMscyxzLHMscyl9LAp0TTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9WC5DTChhLHRoaXMuYSkKci5J
+VigpCnQ9ci5kCnM9dC5sZW5ndGgKaWYocz09PTApe3Q9ci5iCnJldHVybiB0PT1udWxsPyIuIjp0fWlm
+KHM9PT0xKXt0PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6dH1pZigwPj1zKXJldHVybiBILmsodCwtMSkK
+dC5wb3AoKQpDLk5tLm12KHIuZSkKci5JVigpCnJldHVybiByLlooMCl9LApxNzpmdW5jdGlvbihhLGIs
+YyxkLGUsZixnLGgsaSl7dmFyIHQ9SC5WTShbYixjLGQsZSxmLGcsaCxpXSx1LnMpCk0uWUYoImpvaW4i
+LHQpCnJldHVybiB0aGlzLklQKG5ldyBILlU1KHQsdS5iQi5hKG5ldyBNLk1pKCkpLHUuY2MpKX0sCklQ
+OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbAp1LlguYShhKQpmb3IodD1hLiR0aSxzPXQu
+QygiYTIoTHkuRSkiKS5hKG5ldyBNLnE3KCkpLHI9YS5ndyhhKSx0PW5ldyBILnZHKHIscyx0LkMoInZH
+PEx5LkU+IikpLHM9dGhpcy5hLHE9ITEscD0hMSxvPSIiO3QubSgpOyl7bj1yLmdSKHIpCmlmKHMuaEso
+bikmJnApe209WC5DTChuLHMpCmw9by5jaGFyQ29kZUF0KDApPT0wP286bwpvPUMueEIuTmoobCwwLHMu
+U3AobCwhMCkpCm0uYj1vCmlmKHMuZHMobykpQy5ObS50KG0uZSwwLHMuZ21JKCkpCm89bS5aKDApfWVs
+c2UgaWYocy5ZcihuKT4wKXtwPSFzLmhLKG4pCm89SC5kKG4pfWVsc2V7aWYoIShuLmxlbmd0aD4wJiZz
+LlVkKG5bMF0pKSlpZihxKW8rPXMuZ21JKCkKbys9SC5kKG4pfXE9cy5kcyhuKX1yZXR1cm4gby5jaGFy
+Q29kZUF0KDApPT0wP286b30sCm81OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoIXRoaXMueTMoYikpcmV0
+dXJuIGIKdD1YLkNMKGIsdGhpcy5hKQp0LnJSKDApCnJldHVybiB0LlooMCl9LAp5MzpmdW5jdGlvbihh
+KXt2YXIgdCxzLHIscSxwLG8sbixtLGwsawphLnRvU3RyaW5nCnQ9dGhpcy5hCnM9dC5ZcihhKQppZihz
+IT09MCl7aWYodD09PSQuS2soKSlmb3Iocj0wO3I8czsrK3IpaWYoQy54Qi5XZChhLHIpPT09NDcpcmV0
+dXJuITAKcT1zCnA9NDd9ZWxzZXtxPTAKcD1udWxsfWZvcihvPW5ldyBILnFqKGEpLmEsbj1vLmxlbmd0
+aCxyPXEsbT1udWxsO3I8bjsrK3IsbT1wLHA9bCl7bD1DLnhCLk8yKG8scikKaWYodC5yNChsKSl7aWYo
+dD09PSQuS2soKSYmbD09PTQ3KXJldHVybiEwCmlmKHAhPW51bGwmJnQucjQocCkpcmV0dXJuITAKaWYo
+cD09PTQ2KWs9bT09bnVsbHx8bT09PTQ2fHx0LnI0KG0pCmVsc2Ugaz0hMQppZihrKXJldHVybiEwfX1p
+ZihwPT1udWxsKXJldHVybiEwCmlmKHQucjQocCkpcmV0dXJuITAKaWYocD09PTQ2KXQ9bT09bnVsbHx8
+dC5yNChtKXx8bT09PTQ2CmVsc2UgdD0hMQppZih0KXJldHVybiEwCnJldHVybiExfSwKSFA6ZnVuY3Rp
+b24oYSxiKXt2YXIgdCxzLHIscSxwLG89dGhpcyxuPSdVbmFibGUgdG8gZmluZCBhIHBhdGggdG8gIicK
+Yj1vLldPKDAsYikKdD1vLmEKaWYodC5ZcihiKTw9MCYmdC5ZcihhKT4wKXJldHVybiBvLm81KDAsYSkK
+aWYodC5ZcihhKTw9MHx8dC5oSyhhKSlhPW8uV08oMCxhKQppZih0LllyKGEpPD0wJiZ0LllyKGIpPjAp
+dGhyb3cgSC5iKFguSTcobitILmQoYSkrJyIgZnJvbSAiJytILmQoYikrJyIuJykpCnM9WC5DTChiLHQp
+CnMuclIoMCkKcj1YLkNMKGEsdCkKci5yUigwKQpxPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0s
+Ii4iKSlyZXR1cm4gci5aKDApCnE9cy5iCnA9ci5iCmlmKHEhPXApcT1xPT1udWxsfHxwPT1udWxsfHwh
+dC5OYyhxLHApCmVsc2UgcT0hMQppZihxKXJldHVybiByLlooMCkKd2hpbGUoITApe3E9cy5kCmlmKHEu
+bGVuZ3RoPjApe3A9ci5kCnE9cC5sZW5ndGg+MCYmdC5OYyhxWzBdLHBbMF0pfWVsc2UgcT0hMQppZigh
+cSlicmVhawpDLk5tLlc0KHMuZCwwKQpDLk5tLlc0KHMuZSwxKQpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0
+KHIuZSwxKX1xPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0sIi4uIikpdGhyb3cgSC5iKFguSTco
+bitILmQoYSkrJyIgZnJvbSAiJytILmQoYikrJyIuJykpCnE9dS5OCkMuTm0uVUcoci5kLDAsUC5POChz
+LmQubGVuZ3RoLCIuLiIscSkpCkMuTm0udChyLmUsMCwiIikKQy5ObS5VRyhyLmUsMSxQLk84KHMuZC5s
+ZW5ndGgsdC5nbUkoKSxxKSkKdD1yLmQKcT10Lmxlbmd0aAppZihxPT09MClyZXR1cm4iLiIKaWYocT4x
+JiZKLlJNKEMuTm0uZ3JaKHQpLCIuIikpe3Q9ci5kCmlmKDA+PXQubGVuZ3RoKXJldHVybiBILmsodCwt
+MSkKdC5wb3AoKQp0PXIuZQpDLk5tLm12KHQpCkMuTm0ubXYodCkKQy5ObS5BKHQsIiIpfXIuYj0iIgpy
+LklWKCkKcmV0dXJuIHIuWigwKX19Ck0uTWkucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEguYyhhKSE9bnVsbH0sCiRTOjl9Ck0ucTcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEguYyhhKSE9PSIifSwKJFM6OX0KTS5Oby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtILmMoYSkK
+cmV0dXJuIGE9PW51bGw/Im51bGwiOiciJythKyciJ30sCiRTOjV9CkIuTHUucHJvdG90eXBlPXsKeFo6
+ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLllyKGEpCmlmKHM+MClyZXR1cm4gSi5sZChhLDAscykKaWYo
+dGhpcy5oSyhhKSl7aWYoMD49YS5sZW5ndGgpcmV0dXJuIEguayhhLDApCnQ9YVswXX1lbHNlIHQ9bnVs
+bApyZXR1cm4gdH0sCk5jOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PWJ9fQpYLldELnByb3RvdHlwZT17
+CklWOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMKd2hpbGUoITApe3Q9ci5kCmlmKCEodC5sZW5ndGgh
+PT0wJiZKLlJNKEMuTm0uZ3JaKHQpLCIiKSkpYnJlYWsKdD1yLmQKaWYoMD49dC5sZW5ndGgpcmV0dXJu
+IEguayh0LC0xKQp0LnBvcCgpCkMuTm0ubXYoci5lKX10PXIuZQpzPXQubGVuZ3RoCmlmKHM+MClDLk5t
+LnQodCxzLTEsIiIpfSwKclI6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzLGw9SC5W
+TShbXSx1LnMpCmZvcih0PW0uZCxzPXQubGVuZ3RoLHI9MCxxPTA7cTx0Lmxlbmd0aDt0Lmxlbmd0aD09
+PXN8fCgwLEgubGspKHQpLCsrcSl7cD10W3FdCm89Si5pYShwKQppZighKG8uRE4ocCwiLiIpfHxvLkRO
+KHAsIiIpKSlpZihvLkROKHAsIi4uIikpaWYobC5sZW5ndGg+MClsLnBvcCgpCmVsc2UgKytyCmVsc2Ug
+Qy5ObS5BKGwscCl9aWYobS5iPT1udWxsKUMuTm0uVUcobCwwLFAuTzgociwiLi4iLHUuTikpCmlmKGwu
+bGVuZ3RoPT09MCYmbS5iPT1udWxsKUMuTm0uQShsLCIuIikKbj1QLmRIKGwubGVuZ3RoLG5ldyBYLnFS
+KG0pLCEwLHUuTikKdD1tLmIKdD10IT1udWxsJiZsLmxlbmd0aD4wJiZtLmEuZHModCk/bS5hLmdtSSgp
+OiIiCkgudDYobikuYy5hKHQpCmlmKCEhbi5maXhlZCRsZW5ndGgpSC5WaihQLkw0KCJpbnNlcnQiKSkK
+bi5zcGxpY2UoMCwwLHQpCm0uc25KKGwpCm0uc1BoKG4pCnQ9bS5iCmlmKHQhPW51bGwmJm0uYT09PSQu
+S2soKSl7dC50b1N0cmluZwptLmI9SC55cyh0LCIvIiwiXFwiKX1tLklWKCl9LApaOmZ1bmN0aW9uKGEp
+e3ZhciB0LHMscj10aGlzLHE9ci5iCnE9cSE9bnVsbD9xOiIiCmZvcih0PTA7dDxyLmQubGVuZ3RoOysr
+dCl7cz1yLmUKaWYodD49cy5sZW5ndGgpcmV0dXJuIEguayhzLHQpCnM9cStILmQoc1t0XSkKcT1yLmQK
+aWYodD49cS5sZW5ndGgpcmV0dXJuIEguayhxLHQpCnE9cytILmQocVt0XSl9cSs9SC5kKEMuTm0uZ3Ja
+KHIuZSkpCnJldHVybiBxLmNoYXJDb2RlQXQoMCk9PTA/cTpxfSwKc25KOmZ1bmN0aW9uKGEpe3RoaXMu
+ZD11LmEuYShhKX0sCnNQaDpmdW5jdGlvbihhKXt0aGlzLmU9dS5hLmEoYSl9fQpYLnFSLnByb3RvdHlw
+ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYS5nbUkoKX0sCiRTOjQ2fQpYLmR2LnByb3Rv
+dHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIlBhdGhFeGNlcHRpb246ICIrdGhpcy5hfX0KTy5PTy5w
+cm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdvYyh0aGlzKX19CkUuT0YucHJvdG90
+eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIudGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7
+cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9uKGEpe3ZhciB0PWEubGVuZ3RoCnJldHVybiB0IT09MCYm
+Qy54Qi5PMihhLHQtMSkhPT00N30sClNwOmZ1bmN0aW9uKGEsYil7aWYoYS5sZW5ndGghPT0wJiZDLnhC
+LldkKGEsMCk9PT00NylyZXR1cm4gMQpyZXR1cm4gMH0sCllyOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuITF9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4i
+cG9zaXgifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIi8ifX0KRi5ydS5wcm90b3R5cGU9ewpVZDpmdW5j
+dGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3
+fSwKZHM6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgKaWYodD09PTApcmV0dXJuITEKaWYoQy54Qi5P
+MihhLHQtMSkhPT00NylyZXR1cm4hMApyZXR1cm4gQy54Qi5UYyhhLCI6Ly8iKSYmdGhpcy5ZcihhKT09
+PXR9LApTcDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9YS5sZW5ndGgKaWYocD09PTApcmV0dXJu
+IDAKaWYoQy54Qi5XZChhLDApPT09NDcpcmV0dXJuIDEKZm9yKHQ9MDt0PHA7Kyt0KXtzPUMueEIuV2Qo
+YSx0KQppZihzPT09NDcpcmV0dXJuIDAKaWYocz09PTU4KXtpZih0PT09MClyZXR1cm4gMApyPUMueEIu
+WFUoYSwiLyIsQy54Qi5RaShhLCIvLyIsdCsxKT90KzM6dCkKaWYocjw9MClyZXR1cm4gcAppZighYnx8
+cDxyKzMpcmV0dXJuIHIKaWYoIUMueEIubkMoYSwiZmlsZTovLyIpKXJldHVybiByCmlmKCFCLll1KGEs
+cisxKSlyZXR1cm4gcgpxPXIrMwpyZXR1cm4gcD09PXE/cTpyKzR9fXJldHVybiAwfSwKWXI6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGgh
+PT0wJiZDLnhCLldkKGEsMCk9PT00N30sCmdvYzpmdW5jdGlvbigpe3JldHVybiJ1cmwifSwKZ21JOmZ1
+bmN0aW9uKCl7cmV0dXJuIi8ifX0KTC5JVi5wcm90b3R5cGU9ewpVZDpmdW5jdGlvbihhKXtyZXR1cm4g
+Qy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3fHxhPT09OTJ9LApkczpm
+dW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4hMQp0PUMueEIuTzIoYSx0LTEp
+CnJldHVybiEodD09PTQ3fHx0PT09OTIpfSwKU3A6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9YS5sZW5n
+dGgKaWYocj09PTApcmV0dXJuIDAKdD1DLnhCLldkKGEsMCkKaWYodD09PTQ3KXJldHVybiAxCmlmKHQ9
+PT05Mil7aWYocjwyfHxDLnhCLldkKGEsMSkhPT05MilyZXR1cm4gMQpzPUMueEIuWFUoYSwiXFwiLDIp
+CmlmKHM+MCl7cz1DLnhCLlhVKGEsIlxcIixzKzEpCmlmKHM+MClyZXR1cm4gc31yZXR1cm4gcn1pZihy
+PDMpcmV0dXJuIDAKaWYoIUIuT1ModCkpcmV0dXJuIDAKaWYoQy54Qi5XZChhLDEpIT09NTgpcmV0dXJu
+IDAKcj1DLnhCLldkKGEsMikKaWYoIShyPT09NDd8fHI9PT05MikpcmV0dXJuIDAKcmV0dXJuIDN9LApZ
+cjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLllyKGEpPT09MX0sCk90OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT09PWIpcmV0dXJuITAKaWYo
+YT09PTQ3KXJldHVybiBiPT09OTIKaWYoYT09PTkyKXJldHVybiBiPT09NDcKaWYoKGFeYikhPT0zMily
+ZXR1cm4hMQp0PWF8MzIKcmV0dXJuIHQ+PTk3JiZ0PD0xMjJ9LApOYzpmdW5jdGlvbihhLGIpe3ZhciB0
+LHMscgppZihhPT1iKXJldHVybiEwCnQ9YS5sZW5ndGgKaWYodCE9PWIubGVuZ3RoKXJldHVybiExCmZv
+cihzPUouclkoYikscj0wO3I8dDsrK3IpaWYoIXRoaXMuT3QoQy54Qi5XZChhLHIpLHMuV2QoYixyKSkp
+cmV0dXJuITEKcmV0dXJuITB9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4id2luZG93cyJ9LApnbUk6ZnVu
+Y3Rpb24oKXtyZXR1cm4iXFwifX07KGZ1bmN0aW9uIGFsaWFzZXMoKXt2YXIgdD1KLnZCLnByb3RvdHlw
+ZQp0LlQ9dC5aCnQuU2o9dC5lNwp0PUouTUYucHJvdG90eXBlCnQubj10LloKdD1QLkx5LnByb3RvdHlw
+ZQp0LkdHPXQuZXYKdD1QLk1oLnByb3RvdHlwZQp0LnhiPXQuWgp0PVcuY3YucHJvdG90eXBlCnQuRFc9
+dC5yNgp0PVcubTYucHJvdG90eXBlCnQuakY9dC5FYgp0PVAuRTQucHJvdG90eXBlCnQuVXI9dC5xCnQu
+ZTQ9dC50fSkoKTsoZnVuY3Rpb24gaW5zdGFsbFRlYXJPZmZzKCl7dmFyIHQ9aHVua0hlbHBlcnMuX3N0
+YXRpY18xLHM9aHVua0hlbHBlcnMuX3N0YXRpY18wLHI9aHVua0hlbHBlcnMuaW5zdGFsbEluc3RhbmNl
+VGVhck9mZixxPWh1bmtIZWxwZXJzLmluc3RhbGxTdGF0aWNUZWFyT2ZmLHA9aHVua0hlbHBlcnMuX2lu
+c3RhbmNlXzF1CnQoUCwiRVgiLCJaViIsMTEpCnQoUCwieXQiLCJxRyIsMTEpCnQoUCwicVciLCJCeiIs
+MTEpCnMoUCwiVjkiLCJlTiIsMikKcihQLlBmLnByb3RvdHlwZSwiZ1lKIiwwLDEsbnVsbCxbIiQyIiwi
+JDEiXSxbIncwIiwicG0iXSwyMywwKQp0KFAsIlBIIiwiTXQiLDUpCnEoVywicFMiLDQsbnVsbCxbIiQ0
+Il0sWyJVdyJdLDE5LDApCnEoVywiVjQiLDQsbnVsbCxbIiQ0Il0sWyJuWiJdLDE5LDApCnAoUC5kTS5w
+cm90b3R5cGUsImd1TSIsIlMiLDUpCnQoUCwiaUciLCJ3WSIsNCkKdChQLCJ3MCIsIkw3IiwzMikKdChM
+LCJIMCIsInVtIiwyMSl9KSgpOyhmdW5jdGlvbiBpbmhlcml0YW5jZSgpe3ZhciB0PWh1bmtIZWxwZXJz
+Lm1peGluLHM9aHVua0hlbHBlcnMuaW5oZXJpdCxyPWh1bmtIZWxwZXJzLmluaGVyaXRNYW55CnMoUC5N
+aCxudWxsKQpyKFAuTWgsW0guRkssSi52QixKLm0xLFAublksUC5MeSxILmE3LFAuQW4sSC5TVSxILlJl
+LEgud3YsUC5QbixILldVLEguTEksSC5UcCxILmY5LFAuWFMsSC5icSxILlhPLFAuWWssSC52aCxILk42
+LEguVlIsSC5FSyxILlBiLEgudFEsSC5TZCxILkpjLEguRVQsUC5XMyxQLmloLFAuRnksUC5HVixQLmI4
+LFAuUGYsUC5GZSxQLnZzLFAuT00sUC5xaCxQLk1PLFAua1QsUC54SSxQLk9ILFAubTAsUC5YdixQLmJu
+LFAubG0sUC5sRCxQLktQLFAuTWEsUC5MaixQLlVrLFAuUncsUC5ieixQLmEyLFAuaVAsUC5sZixQLms1
+LFAuS1ksUC5DRCxQLmFFLFAuRUgsUC56TSxQLlowLFAuTjMsUC5jOCxQLk9kLFAuaWIsUC5HeixQLlpk
+LFAucVUsUC5SbixQLkdELFAuRG4sUC5QRSxQLlVmLFcuaWQsVy5GayxXLkpRLFcuR20sVy52RCxXLm02
+LFcuT3csVy5XOSxXLmRXLFcuRmIsVy5rRixXLm1rLFcuS28sUC5pNixQLmFKLFAuRTQsUC5JTixQLm42
+LFUuZDIsVS5TZSxVLk1sLFUueUQsVS53YixCLmo4LEIucXAsVC5tUSxMLlhBLEwuWlosTC5XQSxNLmxJ
+LE8uT08sWC5XRCxYLmR2XSkKcihKLnZCLFtKLnlFLEouWUUsSi5NRixKLmpkLEoucUksSi5EcixILlda
+LEgucEYsVy5EMCxXLlllLFcuQXosVy5QVSxXLkJ3LFcubzQsVy5sdyxXLkxlLFcuU2IsVy5OaCxXLkpV
+LFcuSUIsVy52ZSxXLm43LFcuZWEsVy50SSxXLkdPLFcuSkMsVy5icixXLmNXLFcuU2csVy51OCxXLno2
+LFcubEcsVy5xcyxXLkFXLFcuY3MsVy5LNyxXLmNsLFcuZlQsVy5iZyxXLlk0LFcuYUQsVy5sOCxXLk9Y
+LFcuV1csVy5VaixXLm16LFcuYTMsVy50cixXLmNuLFcuRmosVy5PdixXLllELFcuWFcsVy5YVSxXLnp2
+LFAuVzIsUC5oRixQLkJWLFAudWosUC54MCxQLmZVLFAudVAsUC5qRyxQLkVELFAueFcsUC56WSxQLndq
+LFAucjIsUC5yTyxQLlUzLFAubW9dKQpyKEouTUYsW0ouaUMsSi5rZCxKLmM1XSkKcyhKLlBvLEouamQp
+CnIoSi5xSSxbSi51cixKLlZBXSkKcyhQLkxVLFAublkpCnIoUC5MVSxbSC53MixXLnd6LFcuZTddKQpz
+KEgucWosSC53MikKcihQLkx5LFtILmJRLEguaTEsSC5VNSxILlhSLFAubVcsSC5ORl0pCnIoSC5iUSxb
+SC5hTCxILmk1LFAueHVdKQpyKEguYUwsW0gubkgsSC5sSixQLmk4XSkKcyhILnh5LEguaTEpCnIoUC5B
+bixbSC5NSCxILnZHXSkKcyhQLlJVLFAuUG4pCnMoUC5HaixQLlJVKQpzKEguUEQsUC5HaikKcyhILkxQ
+LEguV1UpCnIoSC5UcCxbSC5DaixILkFtLEgubGMsSC5yLEguZEMsSC53TixQLnRoLFAuaGEsUC5WcyxQ
+LkZ0LFAueUgsUC5XTSxQLlNYLFAuR3MsUC5kYSxQLm9RLFAucFYsUC5VNyxQLnZyLFAuckgsUC5LRixQ
+LlpMLFAuUlQsUC5qWixQLnJxLFAuUlcsUC5CNSxQLlBJLFAucEssUC5oaixQLlZwLFAuT1IsUC5yYSxQ
+LnlRLFAuV0YsUC5uMSxQLmNTLFAuVkMsUC5KVCxQLmUxLFAuTlksUC5SWixQLk1FLFAueTUsUC5xMyxQ
+LnlJLFAuYzYsUC5xZCxXLkN2LFcuYlUsVy5oSCxXLkZBLFcudXEsVy5paSxXLmNYLFcuS1MsVy5BMyxX
+LnZOLFcuVXYsVy5FZyxXLkVvLFcuV2ssVy5JQSxXLmZtLFAuamcsUC5UYSxQLks1LFAuR0UsUC5ONyxQ
+LnVRLFAuUEMsUC5tdCxQLk56LFAubnAsUC5VdCxQLnZLLFAucFUsUC5xZixMLmUsTC5WVyxMLm9aLEwu
+anIsTC5xbCxMLnk4LEwuTCxMLld4LEwuQU8sTC5kTixMLkhvLEwueHosTC5JQyxMLkwxLEwublQsTC5C
+WixMLkdILEwuRFQsTC5lSCxMLnl1LEwuekQsTC5UVyxMLnhyLEwuRUUsTC5RTCxMLlZTLEwuVEQsTS5N
+aSxNLnE3LE0uTm8sWC5xUl0pCnIoUC5YUyxbSC5XMCxILmF6LEgudlYsSC5FcSxQLkM2LEgua1MsUC5M
+SyxQLkFULFAubXAsUC51YixQLmRzLFAubGosUC5VVixQLnQ3XSkKcihILmxjLFtILnp4LEguanldKQpz
+KEgua1ksUC5DNikKcyhQLmlsLFAuWWspCnIoUC5pbCxbSC5ONSxQLnV3LFcuYVQsVy5TeV0pCnIoUC5t
+VyxbSC5LVyxQLnE0XSkKcyhILmIwLEgucEYpCnIoSC5iMCxbSC5SRyxILldCXSkKcyhILlZQLEguUkcp
+CnMoSC5EZyxILlZQKQpzKEguWkcsSC5XQikKcyhILlBnLEguWkcpCnIoSC5QZyxbSC54aixILmRFLEgu
+WkEsSC53ZixILlBxLEguZUUsSC5WNl0pCnMoSC54LEgua1MpCnMoUC5aZixQLlBmKQpzKFAuSmksUC5t
+MCkKcyhQLmI2LFAuWHYpCnMoUC5SSyxQLkxqKQpyKFAuVWssW1AuQ1YsUC5aaSxQLmJ5XSkKcyhQLndJ
+LFAua1QpCnIoUC53SSxbUC52QSxQLk14LFAuRTMsUC5HWV0pCnMoUC51NSxQLlppKQpyKFAubGYsW1Au
+Q1AsUC5JZl0pCnIoUC5BVCxbUC5iSixQLmVZXSkKcyhQLnFlLFAuRG4pCnIoVy5EMCxbVy51SCxXLndK
+LFcud2EsVy5DZixXLkxyLFcuU1YsVy5vSCxXLkExLFcuTU4sVy5RVixXLnZGLFcuT2ksVy5DbSxQLmZv
+LFAuVjhdKQpyKFcudUgsW1cuY3YsVy5ueCxXLlFGLFcuQ1FdKQpyKFcuY3YsW1cucUUsUC5kNV0pCnIo
+Vy5xRSxbVy5HaCxXLmZZLFcubkIsVy5RUCxXLklGLFcuY3gsVy5oNCxXLkpLLFcud1AsVy5RYixXLlFs
+LFcuR1gsVy5TTixXLkhELFcuS1IsVy5scCxXLlRiLFcuSXYsVy5CVCxXLmZYLFcuRkJdKQpyKFcuQncs
+W1cuUmQsVy5rUixXLkhTLFcuRmhdKQpzKFcuVGYsVy5vNCkKcyhXLm9KLFcuTGUpCnMoVy5WbyxXLmtS
+KQpzKFcueFgsVy5KVSkKcyhXLkZ2LFcueFgpCnMoVy5iRyxXLnZlKQpzKFcuWWwsVy5iRykKcyhXLlQ1
+LFcuQXopCnMoVy5mZyxXLnRJKQpzKFcuWFYsVy5mZykKcyhXLkhXLFcuY1cpCnMoVy54bixXLkhXKQpz
+KFcuVmIsVy5RRikKcyhXLmZKLFcud2EpCnIoVy5lYSxbVy53NixXLmV3LFcuYmtdKQpyKFcudzYsW1cu
+SEwsVy5PS10pCnMoVy5TMCxXLmxHKQpzKFcuejIsVy5xcykKcyhXLktCLFcuY3MpCnMoVy5ETSxXLktC
+KQpzKFcuckIsVy5LNykKcyhXLkJILFcuckIpCnMoVy5mNyxXLmZUKQpzKFcuRXYsVy5mNykKcyhXLnA4
+LFcuYmcpCnMoVy5DRSxXLm9IKQpzKFcuTWssVy5DRSkKcyhXLlp4LFcuYUQpCnMoVy5ObixXLlp4KQpz
+KFcuQXMsVy5PWCkKcyhXLmpNLFcuVWopCnMoVy5YMCxXLmpNKQpzKFcuQXcsVy5RVikKcyhXLm5KLFcu
+QXcpCnMoVy5PMyxXLnRyKQpzKFcuY2ksVy5PMykKcyhXLmNPLFcuT3YpCnMoVy5QUixXLmNPKQpzKFcu
+dzQsVy5JQikKcyhXLkR4LFcuWUQpCnMoVy5GMixXLkR4KQpzKFcub2EsVy5YVykKcyhXLnJoLFcub2Ep
+CnMoVy5vMyxXLlhVKQpzKFcuTE8sVy5vMykKcyhXLm56LFcuenYpCnMoVy5iMSxXLm56KQpzKFcuaTcs
+Vy5hVCkKcyhQLmRNLFAuUkspCnIoUC5kTSxbVy5JNCxQLktlXSkKcyhXLlJPLFAucWgpCnMoVy5ldSxX
+LlJPKQpzKFcueEMsUC5NTykKcyhXLmN0LFcubTYpCnMoUC5CZixQLmk2KQpzKFAuemcsUC5hSikKcyhQ
+LmUzLFAuVzIpCnIoUC5FNCxbUC5yNyxQLmNvXSkKcyhQLlR6LFAuY28pCnMoUC50bixQLklOKQpzKFAu
+R0MsUC5mVSkKcyhQLnE2LFAuR0MpCnMoUC5qUyxQLmpHKQpzKFAuTFosUC5qUykKcyhQLm5kLFAuZDUp
+CnMoUC5kUyxQLnhXKQpzKFAuS3EsUC5kUykKcyhQLk1ZLFAud2opCnMoUC5OQyxQLk1ZKQpzKFAuRFgs
+UC5VMykKcyhQLkduLFAuVjgpCnMoUC5LZyxQLm1vKQpzKFAuRm4sUC5LZykKcyhCLkx1LE8uT08pCnIo
+Qi5MdSxbRS5PRixGLnJ1LEwuSVZdKQp0KEgudzIsSC5SZSkKdChILlJHLFAubEQpCnQoSC5WUCxILlNV
+KQp0KEguV0IsUC5sRCkKdChILlpHLEguU1UpCnQoUC5uWSxQLmxEKQp0KFAuTGosUC5NYSkKdChQLlJV
+LFAuS1ApCnQoVy5MZSxXLmlkKQp0KFcuSlUsUC5sRCkKdChXLnhYLFcuR20pCnQoVy52ZSxQLmxEKQp0
+KFcuYkcsVy5HbSkKdChXLnRJLFAubEQpCnQoVy5mZyxXLkdtKQp0KFcuY1csUC5sRCkKdChXLkhXLFcu
+R20pCnQoVy5sRyxQLllrKQp0KFcucXMsUC5ZaykKdChXLmNzLFAubEQpCnQoVy5LQixXLkdtKQp0KFcu
+SzcsUC5sRCkKdChXLnJCLFcuR20pCnQoVy5mVCxQLmxEKQp0KFcuZjcsVy5HbSkKdChXLmJnLFAuWWsp
+CnQoVy5vSCxQLmxEKQp0KFcuQ0UsVy5HbSkKdChXLmFELFAubEQpCnQoVy5aeCxXLkdtKQp0KFcuT1gs
+UC5ZaykKdChXLlVqLFAubEQpCnQoVy5qTSxXLkdtKQp0KFcuUVYsUC5sRCkKdChXLkF3LFcuR20pCnQo
+Vy50cixQLmxEKQp0KFcuTzMsVy5HbSkKdChXLk92LFAubEQpCnQoVy5jTyxXLkdtKQp0KFcuWUQsUC5s
+RCkKdChXLkR4LFcuR20pCnQoVy5YVyxQLmxEKQp0KFcub2EsVy5HbSkKdChXLlhVLFAubEQpCnQoVy5v
+MyxXLkdtKQp0KFcuenYsUC5sRCkKdChXLm56LFcuR20pCnQoUC5jbyxQLmxEKQp0KFAuZlUsUC5sRCkK
+dChQLkdDLFcuR20pCnQoUC5qRyxQLmxEKQp0KFAualMsVy5HbSkKdChQLnhXLFAubEQpCnQoUC5kUyxX
+LkdtKQp0KFAud2osUC5sRCkKdChQLk1ZLFcuR20pCnQoUC5VMyxQLllrKQp0KFAubW8sUC5sRCkKdChQ
+LktnLFcuR20pfSkoKQp2YXIgdj17dHlwZVVuaXZlcnNlOntlQzpuZXcgTWFwKCksdFI6e30sZVQ6e30s
+dFBWOnt9LHNFQTpbXX0sbWFuZ2xlZEdsb2JhbE5hbWVzOntJZjoiaW50IixDUDoiZG91YmxlIixsZjoi
+bnVtIixxVToiU3RyaW5nIixhMjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJMaXN0In0sbWFuZ2xlZE5hbWVz
+Ont9LGdldFR5cGVGcm9tTmFtZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRhZGF0YTpbXSx0eXBlczpbImM4
+KCkiLCJjOChALEApIiwifigpIiwiYzgoY3YpIiwiQChAKSIsInFVKHFVKSIsImM4KE9LKSIsImM4KGZK
+KSIsIn4ocVUsQCkiLCJhMihxVSkiLCJ+KEApIiwifih+KCkpIiwiYzgocVUscVUpIiwiYzgocVUsQCki
+LCJ+KHh1PHFVPikiLCJjOChxVSkiLCJ+KHFVLHFVKSIsImEyKGtGKSIsImM4KEApIiwiYTIoY3YscVUs
+cVUsSlEpIiwiYzgoZWEpIiwifihPSykiLCJuNihJZikiLCJ+KE1oW0d6XSkiLCJaMDxxVSxxVT4oWjA8
+cVUscVU+LHFVKSIsImEyKHVIKSIsImM4KEBbR3pdKSIsImM4KGV3KSIsIkAocVUpIiwiQChlYSkiLCJ2
+czxAPihAKSIsIn4ocVVbQF0pIiwiTWgoQCkiLCJAKEAsQCkiLCJhMih4dTxxVT4pIiwiSWYoSWYsSWYp
+IiwicjcoQCkiLCJUejxAPihAKSIsIkU0KEApIiwiYzgofigpKSIsImM4KEAsR3opIiwifih1SCx1SCki
+LCJiODxjOD4oT0spIiwiYzgoSWYsQCkiLCJmSihmSikiLCJAKEAscVUpIiwicVUoSWYpIiwiYzgoR0Qs
+QCkiLCJ+KHFVLElmKSIsIm42KEAsQCkiXSxpbnRlcmNlcHRvcnNCeVRhZzpudWxsLGxlYWZUYWdzOm51
+bGwsYXJyYXlSdGk6dHlwZW9mIFN5bWJvbD09ImZ1bmN0aW9uIiYmdHlwZW9mIFN5bWJvbCgpPT0ic3lt
+Ym9sIj9TeW1ib2woIiR0aSIpOiIkdGkifQpILnhiKHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3si
+YzUiOiJNRiIsImlDIjoiTUYiLCJrZCI6Ik1GIiwicngiOiJlYSIsImU1IjoiZWEiLCJXSyI6IlY4Iiwi
+YzAiOiJEMCIsImZ5IjoiRDAiLCJjZyI6IkQwIiwiWTAiOiJkNSIsInRwIjoiZDUiLCJHOCI6ImV3Iiwi
+TXIiOiJxRSIsImVMIjoicUUiLCJJMCI6InVIIiwiaHMiOiJ1SCIsIlhnIjoiUUYiLCJ5YyI6Ik9LIiwi
+ajYiOiJNTiIsInk0IjoidzYiLCJhUCI6IkNtIiwieGMiOiJueCIsImtKIjoibngiLCJqNyI6IndhIiwi
+UUgiOiJ4biIsIkg2IjoibHciLCJ6QyI6IldXIiwielUiOiJEZyIsImRmIjoicEYiLCJ5RSI6eyJhMiI6
+W119LCJZRSI6eyJjOCI6W119LCJNRiI6eyJ2bSI6W10sIkVIIjpbXX0sImpkIjp7InpNIjpbIjEiXSwi
+YlEiOlsiMSJdLCJMeSI6WyIxIl19LCJQbyI6eyJqZCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJd
+LCJMeSI6WyIxIl19LCJtMSI6eyJBbiI6WyIxIl19LCJxSSI6eyJDUCI6W10sImxmIjpbXX0sInVyIjp7
+IklmIjpbXSwiQ1AiOltdLCJsZiI6W119LCJWQSI6eyJDUCI6W10sImxmIjpbXX0sIkRyIjp7InFVIjpb
+XSwidlgiOltdfSwicWoiOnsiUmUiOlsiSWYiXSwibEQiOlsiSWYiXSwiek0iOlsiSWYiXSwiYlEiOlsi
+SWYiXSwiTHkiOlsiSWYiXSwibEQuRSI6IklmIiwiUmUuRSI6IklmIn0sImJRIjp7Ikx5IjpbIjEiXX0s
+ImFMIjp7ImJRIjpbIjEiXSwiTHkiOlsiMSJdfSwibkgiOnsiYUwiOlsiMSJdLCJiUSI6WyIxIl0sIkx5
+IjpbIjEiXSwiYUwuRSI6IjEiLCJMeS5FIjoiMSJ9LCJhNyI6eyJBbiI6WyIxIl19LCJpMSI6eyJMeSI6
+WyIyIl0sIkx5LkUiOiIyIn0sInh5Ijp7ImkxIjpbIjEiLCIyIl0sImJRIjpbIjIiXSwiTHkiOlsiMiJd
+LCJMeS5FIjoiMiJ9LCJNSCI6eyJBbiI6WyIyIl19LCJsSiI6eyJhTCI6WyIyIl0sImJRIjpbIjIiXSwi
+THkiOlsiMiJdLCJhTC5FIjoiMiIsIkx5LkUiOiIyIn0sIlU1Ijp7Ikx5IjpbIjEiXSwiTHkuRSI6IjEi
+fSwidkciOnsiQW4iOlsiMSJdfSwidzIiOnsiUmUiOlsiMSJdLCJsRCI6WyIxIl0sInpNIjpbIjEiXSwi
+YlEiOlsiMSJdLCJMeSI6WyIxIl19LCJ3diI6eyJHRCI6W119LCJQRCI6eyJHaiI6WyIxIiwiMiJdLCJS
+VSI6WyIxIiwiMiJdLCJQbiI6WyIxIiwiMiJdLCJLUCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwi
+V1UiOnsiWjAiOlsiMSIsIjIiXX0sIkxQIjp7IldVIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJY
+UiI6eyJMeSI6WyIxIl0sIkx5LkUiOiIxIn0sIkxJIjp7InZRIjpbXX0sIlcwIjp7IlhTIjpbXX0sImF6
+Ijp7IlhTIjpbXX0sInZWIjp7IlhTIjpbXX0sIlhPIjp7Ikd6IjpbXX0sIlRwIjp7IkVIIjpbXX0sImxj
+Ijp7IkVIIjpbXX0sInp4Ijp7IkVIIjpbXX0sImp5Ijp7IkVIIjpbXX0sIkVxIjp7IlhTIjpbXX0sImtZ
+Ijp7IlhTIjpbXX0sIk41Ijp7IkZvIjpbIjEiLCIyIl0sIllrIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIy
+Il0sIllrLksiOiIxIiwiWWsuViI6IjIifSwiaTUiOnsiYlEiOlsiMSJdLCJMeSI6WyIxIl0sIkx5LkUi
+OiIxIn0sIk42Ijp7IkFuIjpbIjEiXX0sIlZSIjp7IndMIjpbXSwidlgiOltdfSwiRUsiOnsiaWIiOltd
+LCJPZCI6W119LCJLVyI6eyJMeSI6WyJpYiJdLCJMeS5FIjoiaWIifSwiUGIiOnsiQW4iOlsiaWIiXX0s
+InRRIjp7Ik9kIjpbXX0sIk5GIjp7Ikx5IjpbIk9kIl0sIkx5LkUiOiJPZCJ9LCJTZCI6eyJBbiI6WyJP
+ZCJdfSwicEYiOnsiQVMiOltdfSwiYjAiOnsiWGoiOlsiQCJdLCJwRiI6W10sIkFTIjpbXX0sIkRnIjp7
+ImxEIjpbIkNQIl0sIlhqIjpbIkAiXSwiek0iOlsiQ1AiXSwicEYiOltdLCJiUSI6WyJDUCJdLCJTVSI6
+WyJDUCJdLCJBUyI6W10sIkx5IjpbIkNQIl0sImxELkUiOiJDUCJ9LCJQZyI6eyJsRCI6WyJJZiJdLCJ6
+TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYiXSwiU1UiOlsiSWYiXSwiQVMiOltd
+LCJMeSI6WyJJZiJdfSwieGoiOnsibEQiOlsiSWYiXSwiek0iOlsiSWYiXSwiWGoiOlsiQCJdLCJwRiI6
+W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sIkFTIjpbXSwiTHkiOlsiSWYiXSwibEQuRSI6IklmIn0s
+ImRFIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwicEYiOltdLCJiUSI6WyJJZiJd
+LCJTVSI6WyJJZiJdLCJBUyI6W10sIkx5IjpbIklmIl0sImxELkUiOiJJZiJ9LCJaQSI6eyJsRCI6WyJJ
+ZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYiXSwiU1UiOlsiSWYiXSwi
+QVMiOltdLCJMeSI6WyJJZiJdLCJsRC5FIjoiSWYifSwid2YiOnsibEQiOlsiSWYiXSwiek0iOlsiSWYi
+XSwiWGoiOlsiQCJdLCJwRiI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sIkFTIjpbXSwiTHkiOlsi
+SWYiXSwibEQuRSI6IklmIn0sIlBxIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwi
+cEYiOltdLCJiUSI6WyJJZiJdLCJTVSI6WyJJZiJdLCJBUyI6W10sIkx5IjpbIklmIl0sImxELkUiOiJJ
+ZiJ9LCJlRSI6eyJsRCI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsi
+SWYiXSwiU1UiOlsiSWYiXSwiQVMiOltdLCJMeSI6WyJJZiJdLCJsRC5FIjoiSWYifSwiVjYiOnsibjYi
+OltdLCJsRCI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sInBGIjpbXSwiYlEiOlsiSWYiXSwi
+U1UiOlsiSWYiXSwiQVMiOltdLCJMeSI6WyJJZiJdLCJsRC5FIjoiSWYifSwia1MiOnsiWFMiOltdfSwi
+eCI6eyJYUyI6W119LCJHViI6eyJBbiI6WyIxIl19LCJxNCI6eyJMeSI6WyIxIl0sIkx5LkUiOiIxIn0s
+IlpmIjp7IlBmIjpbIjEiXX0sInZzIjp7ImI4IjpbIjEiXX0sIk9IIjp7IlhTIjpbXX0sIm0wIjp7IkpC
+IjpbXX0sIkppIjp7IkpCIjpbXX0sImI2Ijp7Ilh2IjpbIjEiXSwieHUiOlsiMSJdLCJiUSI6WyIxIl0s
+Ikx5IjpbIjEiXX0sImxtIjp7IkFuIjpbIjEiXX0sIm1XIjp7Ikx5IjpbIjEiXX0sIkxVIjp7ImxEIjpb
+IjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0sIkx5IjpbIjEiXX0sImlsIjp7IllrIjpbIjEiLCIyIl0s
+IlowIjpbIjEiLCIyIl19LCJZayI6eyJaMCI6WyIxIiwiMiJdfSwiUG4iOnsiWjAiOlsiMSIsIjIiXX0s
+IkdqIjp7IlJVIjpbIjEiLCIyIl0sIlBuIjpbIjEiLCIyIl0sIktQIjpbIjEiLCIyIl0sIlowIjpbIjEi
+LCIyIl19LCJSSyI6eyJNYSI6WyIxIl0sInh1IjpbIjEiXSwiYlEiOlsiMSJdLCJMeSI6WyIxIl19LCJY
+diI6eyJ4dSI6WyIxIl0sImJRIjpbIjEiXSwiTHkiOlsiMSJdfSwidXciOnsiWWsiOlsicVUiLCJAIl0s
+IlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUiLCJZay5WIjoiQCJ9LCJpOCI6eyJhTCI6WyJxVSJdLCJi
+USI6WyJxVSJdLCJMeSI6WyJxVSJdLCJhTC5FIjoicVUiLCJMeS5FIjoicVUifSwiQ1YiOnsiVWsiOlsi
+ek08SWY+IiwicVUiXSwiVWsuUyI6InpNPElmPiJ9LCJ2QSI6eyJ3SSI6WyJ6TTxJZj4iLCJxVSJdfSwi
+WmkiOnsiVWsiOlsicVUiLCJ6TTxJZj4iXX0sImJ5Ijp7IlVrIjpbIk1oIiwicVUiXSwiVWsuUyI6Ik1o
+In0sIk14Ijp7IndJIjpbInFVIiwiTWgiXX0sInU1Ijp7IlVrIjpbInFVIiwiek08SWY+Il0sIlVrLlMi
+OiJxVSJ9LCJFMyI6eyJ3SSI6WyJxVSIsInpNPElmPiJdfSwiR1kiOnsid0kiOlsiek08SWY+IiwicVUi
+XX0sIkNQIjp7ImxmIjpbXX0sIkM2Ijp7IlhTIjpbXX0sIkxLIjp7IlhTIjpbXX0sIkFUIjp7IlhTIjpb
+XX0sImJKIjp7IlhTIjpbXX0sImVZIjp7IlhTIjpbXX0sIm1wIjp7IlhTIjpbXX0sInViIjp7IlhTIjpb
+XX0sImRzIjp7IlhTIjpbXX0sImxqIjp7IlhTIjpbXX0sIlVWIjp7IlhTIjpbXX0sIms1Ijp7IlhTIjpb
+XX0sIktZIjp7IlhTIjpbXX0sInQ3Ijp7IlhTIjpbXX0sIklmIjp7ImxmIjpbXX0sInpNIjp7ImJRIjpb
+IjEiXSwiTHkiOlsiMSJdfSwiaWIiOnsiT2QiOltdfSwieHUiOnsiYlEiOlsiMSJdLCJMeSI6WyIxIl19
+LCJaZCI6eyJHeiI6W119LCJxVSI6eyJ2WCI6W119LCJSbiI6eyJCTCI6W119LCJEbiI6eyJpRCI6W119
+LCJVZiI6eyJpRCI6W119LCJxZSI6eyJpRCI6W119LCJxRSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltd
+fSwiR2giOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sImZZIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6
+W119LCJuQiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiUVAiOnsiY3YiOltdLCJ1SCI6W10sIkQw
+IjpbXX0sIklGIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJueCI6eyJ1SCI6W10sIkQwIjpbXX0s
+ImN4Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJRRiI6eyJ1SCI6W10sIkQwIjpbXX0sIkZ2Ijp7
+IkdtIjpbInRuPGxmPiJdLCJsRCI6WyJ0bjxsZj4iXSwiWGoiOlsidG48bGY+Il0sInpNIjpbInRuPGxm
+PiJdLCJiUSI6WyJ0bjxsZj4iXSwiTHkiOlsidG48bGY+Il0sIkdtLkUiOiJ0bjxsZj4iLCJsRC5FIjoi
+dG48bGY+In0sIklCIjp7InRuIjpbImxmIl19LCJZbCI6eyJHbSI6WyJxVSJdLCJsRCI6WyJxVSJdLCJ6
+TSI6WyJxVSJdLCJYaiI6WyJxVSJdLCJiUSI6WyJxVSJdLCJMeSI6WyJxVSJdLCJHbS5FIjoicVUiLCJs
+RC5FIjoicVUifSwid3oiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiTHkiOlsiMSJd
+LCJsRC5FIjoiMSJ9LCJjdiI6eyJ1SCI6W10sIkQwIjpbXX0sIlQ1Ijp7IkF6IjpbXX0sIlhWIjp7Ikdt
+IjpbIlQ1Il0sImxEIjpbIlQ1Il0sIlhqIjpbIlQ1Il0sInpNIjpbIlQ1Il0sImJRIjpbIlQ1Il0sIkx5
+IjpbIlQ1Il0sIkdtLkUiOiJUNSIsImxELkUiOiJUNSJ9LCJ3SiI6eyJEMCI6W119LCJoNCI6eyJjdiI6
+W10sInVIIjpbXSwiRDAiOltdfSwieG4iOnsiR20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsidUgi
+XSwiWGoiOlsidUgiXSwiYlEiOlsidUgiXSwiTHkiOlsidUgiXSwiR20uRSI6InVIIiwibEQuRSI6InVI
+In0sIlZiIjp7InVIIjpbXSwiRDAiOltdfSwiZkoiOnsiRDAiOltdfSwid2EiOnsiRDAiOltdfSwiSksi
+OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkhMIjp7ImVhIjpbXX0sIndQIjp7ImN2IjpbXSwidUgi
+OltdLCJEMCI6W119LCJDZiI6eyJEMCI6W119LCJRYiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwi
+UzAiOnsiWWsiOlsicVUiLCJAIl0sIlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUiLCJZay5WIjoiQCJ9
+LCJ6MiI6eyJZayI6WyJxVSIsIkAiXSwiWjAiOlsicVUiLCJAIl0sIllrLksiOiJxVSIsIllrLlYiOiJA
+In0sIkRNIjp7IkdtIjpbIkFXIl0sImxEIjpbIkFXIl0sIlhqIjpbIkFXIl0sInpNIjpbIkFXIl0sImJR
+IjpbIkFXIl0sIkx5IjpbIkFXIl0sIkdtLkUiOiJBVyIsImxELkUiOiJBVyJ9LCJPSyI6eyJlYSI6W119
+LCJlNyI6eyJsRCI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJiUSI6WyJ1SCJdLCJMeSI6WyJ1SCJdLCJsRC5F
+IjoidUgifSwidUgiOnsiRDAiOltdfSwiQkgiOnsiR20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsi
+dUgiXSwiWGoiOlsidUgiXSwiYlEiOlsidUgiXSwiTHkiOlsidUgiXSwiR20uRSI6InVIIiwibEQuRSI6
+InVIIn0sIlFsIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJHWCI6eyJjdiI6W10sInVIIjpbXSwi
+RDAiOltdfSwiU04iOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkhEIjp7ImN2IjpbXSwidUgiOltd
+LCJEMCI6W119LCJFdiI6eyJHbSI6WyJjbCJdLCJsRCI6WyJjbCJdLCJ6TSI6WyJjbCJdLCJYaiI6WyJj
+bCJdLCJiUSI6WyJjbCJdLCJMeSI6WyJjbCJdLCJHbS5FIjoiY2wiLCJsRC5FIjoiY2wifSwiTHIiOnsi
+RDAiOltdfSwiS1IiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sImV3Ijp7ImVhIjpbXX0sInA4Ijp7
+IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsuViI6IkAifSwibHAi
+OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlNWIjp7IkQwIjpbXX0sIk1rIjp7IkdtIjpbIlNWIl0s
+ImxEIjpbIlNWIl0sInpNIjpbIlNWIl0sIlhqIjpbIlNWIl0sIkQwIjpbXSwiYlEiOlsiU1YiXSwiTHki
+OlsiU1YiXSwiR20uRSI6IlNWIiwibEQuRSI6IlNWIn0sIk5uIjp7IkdtIjpbIlk0Il0sImxEIjpbIlk0
+Il0sInpNIjpbIlk0Il0sIlhqIjpbIlk0Il0sImJRIjpbIlk0Il0sIkx5IjpbIlk0Il0sIkdtLkUiOiJZ
+NCIsImxELkUiOiJZNCJ9LCJBcyI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsu
+SyI6InFVIiwiWWsuViI6InFVIn0sImJrIjp7ImVhIjpbXX0sIlRiIjp7ImN2IjpbXSwidUgiOltdLCJE
+MCI6W119LCJJdiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiQlQiOnsiY3YiOltdLCJ1SCI6W10s
+IkQwIjpbXX0sImZYIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJGQiI6eyJjdiI6W10sInVIIjpb
+XSwiRDAiOltdfSwiQTEiOnsiRDAiOltdfSwiTU4iOnsiRDAiOltdfSwiWDAiOnsiR20iOlsiTU4iXSwi
+bEQiOlsiTU4iXSwiWGoiOlsiTU4iXSwiek0iOlsiTU4iXSwiYlEiOlsiTU4iXSwiTHkiOlsiTU4iXSwi
+R20uRSI6Ik1OIiwibEQuRSI6Ik1OIn0sIm5KIjp7IkdtIjpbIkExIl0sImxEIjpbIkExIl0sIlhqIjpb
+IkExIl0sInpNIjpbIkExIl0sIkQwIjpbXSwiYlEiOlsiQTEiXSwiTHkiOlsiQTEiXSwiR20uRSI6IkEx
+IiwibEQuRSI6IkExIn0sImNpIjp7IkdtIjpbImEzIl0sImxEIjpbImEzIl0sInpNIjpbImEzIl0sIlhq
+IjpbImEzIl0sImJRIjpbImEzIl0sIkx5IjpbImEzIl0sIkdtLkUiOiJhMyIsImxELkUiOiJhMyJ9LCJ3
+NiI6eyJlYSI6W119LCJ2RiI6eyJEMCI6W119LCJPaSI6eyJ2NiI6W10sIkQwIjpbXX0sIkNtIjp7IkQw
+IjpbXX0sIkNRIjp7InVIIjpbXSwiRDAiOltdfSwiUFIiOnsiR20iOlsibHciXSwibEQiOlsibHciXSwi
+ek0iOlsibHciXSwiWGoiOlsibHciXSwiYlEiOlsibHciXSwiTHkiOlsibHciXSwiR20uRSI6Imx3Iiwi
+bEQuRSI6Imx3In0sInc0Ijp7InRuIjpbImxmIl19LCJGMiI6eyJHbSI6WyJHTyJdLCJsRCI6WyJHTyJd
+LCJYaiI6WyJHTyJdLCJ6TSI6WyJHTyJdLCJiUSI6WyJHTyJdLCJMeSI6WyJHTyJdLCJHbS5FIjoiR08i
+LCJsRC5FIjoiR08ifSwicmgiOnsiR20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsidUgiXSwiWGoi
+OlsidUgiXSwiYlEiOlsidUgiXSwiTHkiOlsidUgiXSwiR20uRSI6InVIIiwibEQuRSI6InVIIn0sIkxP
+Ijp7IkdtIjpbImw4Il0sImxEIjpbImw4Il0sInpNIjpbImw4Il0sIlhqIjpbImw4Il0sImJRIjpbImw4
+Il0sIkx5IjpbImw4Il0sIkdtLkUiOiJsOCIsImxELkUiOiJsOCJ9LCJiMSI6eyJHbSI6WyJXVyJdLCJs
+RCI6WyJXVyJdLCJYaiI6WyJXVyJdLCJ6TSI6WyJXVyJdLCJiUSI6WyJXVyJdLCJMeSI6WyJXVyJdLCJH
+bS5FIjoiV1ciLCJsRC5FIjoiV1cifSwiYVQiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFV
+Il19LCJpNyI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsuSyI6InFVIiwiWWsu
+ViI6InFVIn0sIlN5Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUi
+LCJZay5WIjoicVUifSwiSTQiOnsiTWEiOlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwiTHki
+OlsicVUiXX0sIlJPIjp7InFoIjpbIjEiXX0sImV1Ijp7IlJPIjpbIjEiXSwicWgiOlsiMSJdfSwieEMi
+OnsiTU8iOlsiMSJdfSwiSlEiOnsia0YiOltdfSwidkQiOnsia0YiOltdfSwibTYiOnsia0YiOltdfSwi
+Y3QiOnsia0YiOltdfSwiT3ciOnsia0YiOltdfSwiVzkiOnsiQW4iOlsiMSJdfSwiZFciOnsidjYiOltd
+LCJEMCI6W119LCJtayI6eyJXUSI6W119LCJLbyI6eyJvbiI6W119LCJkTSI6eyJNYSI6WyJxVSJdLCJ4
+dSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJMeSI6WyJxVSJdfSwicjciOnsiRTQiOltdfSwiVHoiOnsibEQi
+OlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiRTQiOltdLCJMeSI6WyIxIl0sImxELkUiOiIxIn0s
+InE2Ijp7IkdtIjpbIngwIl0sImxEIjpbIngwIl0sInpNIjpbIngwIl0sImJRIjpbIngwIl0sIkx5Ijpb
+IngwIl0sIkdtLkUiOiJ4MCIsImxELkUiOiJ4MCJ9LCJMWiI6eyJHbSI6WyJ1UCJdLCJsRCI6WyJ1UCJd
+LCJ6TSI6WyJ1UCJdLCJiUSI6WyJ1UCJdLCJMeSI6WyJ1UCJdLCJHbS5FIjoidVAiLCJsRC5FIjoidVAi
+fSwibmQiOnsiZDUiOltdLCJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiS3EiOnsiR20iOlsicVUiXSwi
+bEQiOlsicVUiXSwiek0iOlsicVUiXSwiYlEiOlsicVUiXSwiTHkiOlsicVUiXSwiR20uRSI6InFVIiwi
+bEQuRSI6InFVIn0sIktlIjp7Ik1hIjpbInFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sIkx5Ijpb
+InFVIl19LCJkNSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiTkMiOnsiR20iOlsielkiXSwibEQi
+OlsielkiXSwiek0iOlsielkiXSwiYlEiOlsielkiXSwiTHkiOlsielkiXSwiR20uRSI6InpZIiwibEQu
+RSI6InpZIn0sIm42Ijp7InpNIjpbIklmIl0sImJRIjpbIklmIl0sIkFTIjpbXSwiTHkiOlsiSWYiXX0s
+IkRYIjp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsuViI6IkAi
+fSwiZm8iOnsiRDAiOltdfSwiVjgiOnsiRDAiOltdfSwiR24iOnsiRDAiOltdfSwiRm4iOnsiR20iOlsi
+WjA8QCxAPiJdLCJsRCI6WyJaMDxALEA+Il0sInpNIjpbIlowPEAsQD4iXSwiYlEiOlsiWjA8QCxAPiJd
+LCJMeSI6WyJaMDxALEA+Il0sIkdtLkUiOiJaMDxALEA+IiwibEQuRSI6IlowPEAsQD4ifSwiWEEiOnsi
+a0YiOltdfSwiT0YiOnsiTHUiOltdfSwicnUiOnsiTHUiOltdfSwiSVYiOnsiTHUiOltdfX0nKSkKSC5G
+Rih2LnR5cGVVbml2ZXJzZSxKU09OLnBhcnNlKCd7ImJRIjoxLCJ3MiI6MSwiTU8iOjEsImtUIjoyLCJt
+VyI6MSwiTFUiOjEsImlsIjoyLCJSSyI6MSwiblkiOjEsIkxqIjoxLCJjbyI6MSwiSU4iOjF9JykpCnZh
+ciB1PShmdW5jdGlvbiBydGlpKCl7dmFyIHQ9SC5EUApyZXR1cm57aTp0KCJHaCIpLG46dCgiT0giKSxj
+Ujp0KCJuQiIpLGQ6dCgiQXoiKSxrOnQoIlFQIiksZ0Y6dCgiUEQ8R0QsQD4iKSxnNTp0KCJsdyIpLGd3
+OnQoImJRPEA+IiksaDp0KCJjdiIpLG06dCgiWFMiKSxCOnQoImVhIiksYVM6dCgiRDAiKSxPOnQoIlQ1
+IiksYlg6dCgiWFYiKSxaOnQoIkVIIiksYVE6dCgiYjg8Yzg+IiksYzp0KCJiODxAPiIpLGRQOnQoIkdP
+Iikscjp0KCJmSiIpLEk6dCgiU2ciKSxvOnQoInZRIiksZWg6dCgiTHk8dUg+IiksWDp0KCJMeTxxVT4i
+KSxSOnQoIkx5PEA+IiksZkE6dCgiamQ8U2U+IiksZ2k6dCgiamQ8ajg+IiksZmg6dCgiamQ8Wlo+Iiks
+dTp0KCJqZDxrRj4iKSxzOnQoImpkPHFVPiIpLGhoOnQoImpkPHlEPiIpLGFKOnQoImpkPHdiPiIpLHY6
+dCgiamQ8QD4iKSx0OnQoImpkPElmPiIpLGVIOnQoInZtIiksZzp0KCJjNSIpLGFVOnQoIlhqPEA+Iiks
+YW06dCgiVHo8QD4iKSxlbzp0KCJONTxHRCxAPiIpLHc6dCgiRTQiKSxkejp0KCJoRiIpLGJHOnQoIngw
+IiksZjQ6dCgiek08ajg+IiksYTp0KCJ6TTxxVT4iKSxqOnQoInpNPEA+IiksTDp0KCJ6TTxJZj4iKSxh
+Xzp0KCJ1OCIpLGY6dCgiWjA8cVUscVU+IiksYjp0KCJaMDxxVSxAPiIpLEc6dCgiWjA8QCxAPiIpLGR2
+OnQoImxKPHFVLHFVPiIpLGRvOnQoImxKPHFVLEA+IiksYks6dCgiQ2YiKSxjSTp0KCJBVyIpLFY6dCgi
+T0siKSxiWjp0KCJXWiIpLGREOnQoInBGIiksYm06dCgiVjYiKSxBOnQoInVIIiksZTp0KCJrRiIpLFA6
+dCgiYzgiKSxjazp0KCJ1UCIpLEs6dCgiTWgiKSxoZTp0KCJjbCIpLHA6dCgiZXciKSxxOnQoInRuPGxm
+PiIpLGZ2OnQoIndMIiksYXY6dCgiSmMiKSxldzp0KCJuZCIpLEM6dCgieHU8cVU+IiksZlk6dCgiU1Yi
+KSxmNzp0KCJZNCIpLGdmOnQoImw4IiksbDp0KCJHeiIpLE46dCgicVUiKSxkRzp0KCJxVShxVSkiKSxn
+bjp0KCJXVyIpLGc3OnQoImQ1IiksZm86dCgiR0QiKSxhVzp0KCJmWCIpLGEwOnQoIkExIiksYzc6dCgi
+TU4iKSxhSzp0KCJhMyIpLGNNOnQoInpZIiksRDp0KCJBUyIpLGdjOnQoIm42IiksYWs6dCgia2QiKSxF
+OnQoIkdqPHFVLHFVPiIpLEY6dCgiaUQiKSxjYzp0KCJVNTxxVT4iKSxnNDp0KCJPaSIpLGNpOnQoInY2
+IiksZzI6dCgiQ20iKSxiajp0KCJaZjxmSj4iKSxoOTp0KCJDUSIpLGFjOnQoImU3IiksUTp0KCJldTxP
+Sz4iKSxVOnQoInd6PGN2PiIpLHg6dCgiRmU8QCxAPiIpLGFvOnQoInZzPGZKPiIpLF86dCgidnM8QD4i
+KSxmSjp0KCJ2czxJZj4iKSxjcjp0KCJKUSIpLEo6dCgiYm4iKSx5OnQoImEyIiksYWw6dCgiYTIoTWgp
+IiksYkI6dCgiYTIocVUpIiksYmY6dCgiYTIoQCkiKSxnUjp0KCJDUCIpLHo6dCgiQCIpLGZPOnQoIkAo
+KSIpLGU2OnQoIkAoZWEpIiksYkk6dCgiQChNaCkiKSxlcDp0KCJAKE1oLE1oKSIpLGFnOnQoIkAoTWgs
+R3opIiksYlU6dCgiQCh4dTxxVT4pIiksZE86dCgiQChxVSkiKSxZOnQoIkAoQCxAKSIpLFM6dCgiSWYi
+KSxkaTp0KCJsZiIpLEg6dCgifiIpLE06dCgifigpIiksYW46dCgifihldykiKSxXOnQoIn4ocVUscVUp
+IiksVDp0KCJ+KHFVLEApIil9fSkoKTsoZnVuY3Rpb24gY29uc3RhbnRzKCl7dmFyIHQ9aHVua0hlbHBl
+cnMubWFrZUNvbnN0TGlzdApDLlJZPVcuUVAucHJvdG90eXBlCkMuQlo9Vy5WYi5wcm90b3R5cGUKQy5E
+dD1XLmZKLnByb3RvdHlwZQpDLk9rPUoudkIucHJvdG90eXBlCkMuTm09Si5qZC5wcm90b3R5cGUKQy5q
+bj1KLnVyLnByb3RvdHlwZQpDLmpOPUouWUUucHJvdG90eXBlCkMuQ0Q9Si5xSS5wcm90b3R5cGUKQy54
+Qj1KLkRyLnByb3RvdHlwZQpDLkRHPUouYzUucHJvdG90eXBlCkMuRXg9Vy51OC5wcm90b3R5cGUKQy50
+NT1XLkJILnByb3RvdHlwZQpDLkx0PVcuU04ucHJvdG90eXBlCkMuWlE9Si5pQy5wcm90b3R5cGUKQy5J
+ZT1XLlRiLnByb3RvdHlwZQpDLnZCPUoua2QucHJvdG90eXBlCkMub2w9Vy5PaS5wcm90b3R5cGUKQy55
+OD1uZXcgUC52QSgpCkMuaDk9bmV3IFAuQ1YoKQpDLndiPWZ1bmN0aW9uIGdldFRhZ0ZhbGxiYWNrKG8p
+IHsKICB2YXIgcyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTsKICByZXR1cm4gcy5z
+dWJzdHJpbmcoOCwgcy5sZW5ndGggLSAxKTsKfQpDLk80PWZ1bmN0aW9uKCkgewogIHZhciB0b1N0cmlu
+Z0Z1bmN0aW9uID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWcobykg
+ewogICAgdmFyIHMgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJzdHJp
+bmcoOCwgcy5sZW5ndGggLSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRh
+ZykgewogICAgaWYgKC9eSFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZhciBu
+YW1lID0gdG9TdHJpbmdGdW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJbb2Jq
+ZWN0IE9iamVjdF0iKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAgICB9
+CiAgfQogIGZ1bmN0aW9uIGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykgewog
+ICAgaWYgKHNlbGYuSFRNTEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHJl
+dHVybiAiSFRNTEVsZW1lbnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcpOwog
+IH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRvdyA9
+PSAidW5kZWZpbmVkIikgcmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09ICJ1
+bmRlZmluZWQiKSByZXR1cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwog
+ICAgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAgIHJl
+dHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3IodGFn
+KSB7IHJldHVybiBudWxsOyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9i
+amVjdCI7CiAgcmV0dXJuIHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzogaXNC
+cm93c2VyID8gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAgIHBy
+b3RvdHlwZUZvclRhZzogcHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3JpbWlu
+YXRvciB9Owp9CkMuZGs9ZnVuY3Rpb24oZ2V0VGFnRmFsbGJhY2spIHsKICByZXR1cm4gZnVuY3Rpb24o
+aG9va3MpIHsKICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9ICJvYmplY3QiKSByZXR1cm4gaG9va3M7
+CiAgICB2YXIgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50OwogICAgaWYgKHVhLmluZGV4T2YoIkR1bXBS
+ZW5kZXJUcmVlIikgPj0gMCkgcmV0dXJuIGhvb2tzOwogICAgaWYgKHVhLmluZGV4T2YoIkNocm9tZSIp
+ID49IDApIHsKICAgICAgZnVuY3Rpb24gY29uZmlybShwKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiB3
+aW5kb3cgPT0gIm9iamVjdCIgJiYgd2luZG93W3BdICYmIHdpbmRvd1twXS5uYW1lID09IHA7CiAgICAg
+IH0KICAgICAgaWYgKGNvbmZpcm0oIldpbmRvdyIpICYmIGNvbmZpcm0oIkhUTUxFbGVtZW50IikpIHJl
+dHVybiBob29rczsKICAgIH0KICAgIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZhbGxiYWNrOwogIH07Cn0K
+Qy5ZcT1mdW5jdGlvbihob29rcykgewogIGlmICh0eXBlb2YgZGFydEV4cGVyaW1lbnRhbEZpeHVwR2V0
+VGFnICE9ICJmdW5jdGlvbiIpIHJldHVybiBob29rczsKICBob29rcy5nZXRUYWcgPSBkYXJ0RXhwZXJp
+bWVudGFsRml4dXBHZXRUYWcoaG9va3MuZ2V0VGFnKTsKfQpDLktVPWZ1bmN0aW9uKGhvb2tzKSB7CiAg
+dmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3MucHJv
+dG90eXBlRm9yVGFnOwogIGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBnZXRU
+YWcobyk7CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJzaW9u
+KSByZXR1cm4gIiFEb2N1bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9CiAg
+ICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsKICAg
+IGlmICh0YWcgPT0gIkRvY3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBlRm9y
+VGFnKHRhZyk7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3RvdHlw
+ZUZvclRhZyA9IHByb3RvdHlwZUZvclRhZ0ZpeGVkOwp9CkMueGk9ZnVuY3Rpb24oaG9va3MpIHsKICB2
+YXIgdXNlckFnZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51c2Vy
+QWdlbnQgOiAiIjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIkZpcmVmb3giKSA9PSAtMSkgcmV0dXJu
 IGhvb2tzOwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAg
 IkJlZm9yZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJk
-IiwKICAgICJIVE1MRERFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJIVE1MRFRFbGVtZW50Ijog
-IkhUTUxFbGVtZW50IiwKICAgICJIVE1MUGhyYXNlRWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAi
-UG9zaXRpb24iOiAiR2VvcG9zaXRpb24iCiAgfTsKICBmdW5jdGlvbiBnZXRUYWdJRShvKSB7CiAgICB2
-YXIgdGFnID0gZ2V0VGFnKG8pOwogICAgdmFyIG5ld1RhZyA9IHF1aWNrTWFwW3RhZ107CiAgICBpZiAo
-bmV3VGFnKSByZXR1cm4gbmV3VGFnOwogICAgaWYgKHRhZyA9PSAiT2JqZWN0IikgewogICAgICBpZiAo
-d2luZG93LkRhdGFWaWV3ICYmIChvIGluc3RhbmNlb2Ygd2luZG93LkRhdGFWaWV3KSkgcmV0dXJuICJE
-YXRhVmlldyI7CiAgICB9CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JU
-YWdJRSh0YWcpIHsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKGNvbnN0
-cnVjdG9yID09IG51bGwpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlw
-ZTsKICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnSUU7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0g
-cHJvdG90eXBlRm9yVGFnSUU7Cn0KQy5mUT1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0K
-CkMuQ3Q9bmV3IFAuYnkoKQpDLkVxPW5ldyBQLms1KCkKQy54TT1uZXcgUC51NSgpCkMuUWs9bmV3IFAu
-RTMoKQpDLk5VPW5ldyBQLkppKCkKQy5wZD1uZXcgUC5aZCgpCkMuQTM9bmV3IFAuTXgobnVsbCkKQy5H
-Yj1ILlZNKHQoWzEyNywyMDQ3LDY1NTM1LDExMTQxMTFdKSx1LnQpCkMuYWs9SC5WTSh0KFswLDAsMzI3
-NzYsMzM3OTIsMSwxMDI0MCwwLDBdKSx1LnQpCkMuY209SC5WTSh0KFsiKjo6Y2xhc3MiLCIqOjpkaXIi
-LCIqOjpkcmFnZ2FibGUiLCIqOjpoaWRkZW4iLCIqOjppZCIsIio6OmluZXJ0IiwiKjo6aXRlbXByb3Ai
-LCIqOjppdGVtcmVmIiwiKjo6aXRlbXNjb3BlIiwiKjo6bGFuZyIsIio6OnNwZWxsY2hlY2siLCIqOjp0
-aXRsZSIsIio6OnRyYW5zbGF0ZSIsIkE6OmFjY2Vzc2tleSIsIkE6OmNvb3JkcyIsIkE6OmhyZWZsYW5n
-IiwiQTo6bmFtZSIsIkE6OnNoYXBlIiwiQTo6dGFiaW5kZXgiLCJBOjp0YXJnZXQiLCJBOjp0eXBlIiwi
-QVJFQTo6YWNjZXNza2V5IiwiQVJFQTo6YWx0IiwiQVJFQTo6Y29vcmRzIiwiQVJFQTo6bm9ocmVmIiwi
-QVJFQTo6c2hhcGUiLCJBUkVBOjp0YWJpbmRleCIsIkFSRUE6OnRhcmdldCIsIkFVRElPOjpjb250cm9s
-cyIsIkFVRElPOjpsb29wIiwiQVVESU86Om1lZGlhZ3JvdXAiLCJBVURJTzo6bXV0ZWQiLCJBVURJTzo6
-cHJlbG9hZCIsIkJETzo6ZGlyIiwiQk9EWTo6YWxpbmsiLCJCT0RZOjpiZ2NvbG9yIiwiQk9EWTo6bGlu
-ayIsIkJPRFk6OnRleHQiLCJCT0RZOjp2bGluayIsIkJSOjpjbGVhciIsIkJVVFRPTjo6YWNjZXNza2V5
-IiwiQlVUVE9OOjpkaXNhYmxlZCIsIkJVVFRPTjo6bmFtZSIsIkJVVFRPTjo6dGFiaW5kZXgiLCJCVVRU
-T046OnR5cGUiLCJCVVRUT046OnZhbHVlIiwiQ0FOVkFTOjpoZWlnaHQiLCJDQU5WQVM6OndpZHRoIiwi
-Q0FQVElPTjo6YWxpZ24iLCJDT0w6OmFsaWduIiwiQ09MOjpjaGFyIiwiQ09MOjpjaGFyb2ZmIiwiQ09M
-OjpzcGFuIiwiQ09MOjp2YWxpZ24iLCJDT0w6OndpZHRoIiwiQ09MR1JPVVA6OmFsaWduIiwiQ09MR1JP
-VVA6OmNoYXIiLCJDT0xHUk9VUDo6Y2hhcm9mZiIsIkNPTEdST1VQOjpzcGFuIiwiQ09MR1JPVVA6OnZh
-bGlnbiIsIkNPTEdST1VQOjp3aWR0aCIsIkNPTU1BTkQ6OmNoZWNrZWQiLCJDT01NQU5EOjpjb21tYW5k
-IiwiQ09NTUFORDo6ZGlzYWJsZWQiLCJDT01NQU5EOjpsYWJlbCIsIkNPTU1BTkQ6OnJhZGlvZ3JvdXAi
-LCJDT01NQU5EOjp0eXBlIiwiREFUQTo6dmFsdWUiLCJERUw6OmRhdGV0aW1lIiwiREVUQUlMUzo6b3Bl
-biIsIkRJUjo6Y29tcGFjdCIsIkRJVjo6YWxpZ24iLCJETDo6Y29tcGFjdCIsIkZJRUxEU0VUOjpkaXNh
-YmxlZCIsIkZPTlQ6OmNvbG9yIiwiRk9OVDo6ZmFjZSIsIkZPTlQ6OnNpemUiLCJGT1JNOjphY2NlcHQi
-LCJGT1JNOjphdXRvY29tcGxldGUiLCJGT1JNOjplbmN0eXBlIiwiRk9STTo6bWV0aG9kIiwiRk9STTo6
-bmFtZSIsIkZPUk06Om5vdmFsaWRhdGUiLCJGT1JNOjp0YXJnZXQiLCJGUkFNRTo6bmFtZSIsIkgxOjph
-bGlnbiIsIkgyOjphbGlnbiIsIkgzOjphbGlnbiIsIkg0OjphbGlnbiIsIkg1OjphbGlnbiIsIkg2Ojph
-bGlnbiIsIkhSOjphbGlnbiIsIkhSOjpub3NoYWRlIiwiSFI6OnNpemUiLCJIUjo6d2lkdGgiLCJIVE1M
-Ojp2ZXJzaW9uIiwiSUZSQU1FOjphbGlnbiIsIklGUkFNRTo6ZnJhbWVib3JkZXIiLCJJRlJBTUU6Omhl
-aWdodCIsIklGUkFNRTo6bWFyZ2luaGVpZ2h0IiwiSUZSQU1FOjptYXJnaW53aWR0aCIsIklGUkFNRTo6
-d2lkdGgiLCJJTUc6OmFsaWduIiwiSU1HOjphbHQiLCJJTUc6OmJvcmRlciIsIklNRzo6aGVpZ2h0Iiwi
-SU1HOjpoc3BhY2UiLCJJTUc6OmlzbWFwIiwiSU1HOjpuYW1lIiwiSU1HOjp1c2VtYXAiLCJJTUc6OnZz
-cGFjZSIsIklNRzo6d2lkdGgiLCJJTlBVVDo6YWNjZXB0IiwiSU5QVVQ6OmFjY2Vzc2tleSIsIklOUFVU
-OjphbGlnbiIsIklOUFVUOjphbHQiLCJJTlBVVDo6YXV0b2NvbXBsZXRlIiwiSU5QVVQ6OmF1dG9mb2N1
-cyIsIklOUFVUOjpjaGVja2VkIiwiSU5QVVQ6OmRpc2FibGVkIiwiSU5QVVQ6OmlucHV0bW9kZSIsIklO
-UFVUOjppc21hcCIsIklOUFVUOjpsaXN0IiwiSU5QVVQ6Om1heCIsIklOUFVUOjptYXhsZW5ndGgiLCJJ
-TlBVVDo6bWluIiwiSU5QVVQ6Om11bHRpcGxlIiwiSU5QVVQ6Om5hbWUiLCJJTlBVVDo6cGxhY2Vob2xk
-ZXIiLCJJTlBVVDo6cmVhZG9ubHkiLCJJTlBVVDo6cmVxdWlyZWQiLCJJTlBVVDo6c2l6ZSIsIklOUFVU
-OjpzdGVwIiwiSU5QVVQ6OnRhYmluZGV4IiwiSU5QVVQ6OnR5cGUiLCJJTlBVVDo6dXNlbWFwIiwiSU5Q
-VVQ6OnZhbHVlIiwiSU5TOjpkYXRldGltZSIsIktFWUdFTjo6ZGlzYWJsZWQiLCJLRVlHRU46OmtleXR5
-cGUiLCJLRVlHRU46Om5hbWUiLCJMQUJFTDo6YWNjZXNza2V5IiwiTEFCRUw6OmZvciIsIkxFR0VORDo6
-YWNjZXNza2V5IiwiTEVHRU5EOjphbGlnbiIsIkxJOjp0eXBlIiwiTEk6OnZhbHVlIiwiTElOSzo6c2l6
-ZXMiLCJNQVA6Om5hbWUiLCJNRU5VOjpjb21wYWN0IiwiTUVOVTo6bGFiZWwiLCJNRU5VOjp0eXBlIiwi
-TUVURVI6OmhpZ2giLCJNRVRFUjo6bG93IiwiTUVURVI6Om1heCIsIk1FVEVSOjptaW4iLCJNRVRFUjo6
-dmFsdWUiLCJPQkpFQ1Q6OnR5cGVtdXN0bWF0Y2giLCJPTDo6Y29tcGFjdCIsIk9MOjpyZXZlcnNlZCIs
-Ik9MOjpzdGFydCIsIk9MOjp0eXBlIiwiT1BUR1JPVVA6OmRpc2FibGVkIiwiT1BUR1JPVVA6OmxhYmVs
-IiwiT1BUSU9OOjpkaXNhYmxlZCIsIk9QVElPTjo6bGFiZWwiLCJPUFRJT046OnNlbGVjdGVkIiwiT1BU
-SU9OOjp2YWx1ZSIsIk9VVFBVVDo6Zm9yIiwiT1VUUFVUOjpuYW1lIiwiUDo6YWxpZ24iLCJQUkU6Ondp
-ZHRoIiwiUFJPR1JFU1M6Om1heCIsIlBST0dSRVNTOjptaW4iLCJQUk9HUkVTUzo6dmFsdWUiLCJTRUxF
-Q1Q6OmF1dG9jb21wbGV0ZSIsIlNFTEVDVDo6ZGlzYWJsZWQiLCJTRUxFQ1Q6Om11bHRpcGxlIiwiU0VM
-RUNUOjpuYW1lIiwiU0VMRUNUOjpyZXF1aXJlZCIsIlNFTEVDVDo6c2l6ZSIsIlNFTEVDVDo6dGFiaW5k
-ZXgiLCJTT1VSQ0U6OnR5cGUiLCJUQUJMRTo6YWxpZ24iLCJUQUJMRTo6Ymdjb2xvciIsIlRBQkxFOjpi
-b3JkZXIiLCJUQUJMRTo6Y2VsbHBhZGRpbmciLCJUQUJMRTo6Y2VsbHNwYWNpbmciLCJUQUJMRTo6ZnJh
-bWUiLCJUQUJMRTo6cnVsZXMiLCJUQUJMRTo6c3VtbWFyeSIsIlRBQkxFOjp3aWR0aCIsIlRCT0RZOjph
-bGlnbiIsIlRCT0RZOjpjaGFyIiwiVEJPRFk6OmNoYXJvZmYiLCJUQk9EWTo6dmFsaWduIiwiVEQ6OmFi
-YnIiLCJURDo6YWxpZ24iLCJURDo6YXhpcyIsIlREOjpiZ2NvbG9yIiwiVEQ6OmNoYXIiLCJURDo6Y2hh
-cm9mZiIsIlREOjpjb2xzcGFuIiwiVEQ6OmhlYWRlcnMiLCJURDo6aGVpZ2h0IiwiVEQ6Om5vd3JhcCIs
-IlREOjpyb3dzcGFuIiwiVEQ6OnNjb3BlIiwiVEQ6OnZhbGlnbiIsIlREOjp3aWR0aCIsIlRFWFRBUkVB
-OjphY2Nlc3NrZXkiLCJURVhUQVJFQTo6YXV0b2NvbXBsZXRlIiwiVEVYVEFSRUE6OmNvbHMiLCJURVhU
-QVJFQTo6ZGlzYWJsZWQiLCJURVhUQVJFQTo6aW5wdXRtb2RlIiwiVEVYVEFSRUE6Om5hbWUiLCJURVhU
-QVJFQTo6cGxhY2Vob2xkZXIiLCJURVhUQVJFQTo6cmVhZG9ubHkiLCJURVhUQVJFQTo6cmVxdWlyZWQi
-LCJURVhUQVJFQTo6cm93cyIsIlRFWFRBUkVBOjp0YWJpbmRleCIsIlRFWFRBUkVBOjp3cmFwIiwiVEZP
-T1Q6OmFsaWduIiwiVEZPT1Q6OmNoYXIiLCJURk9PVDo6Y2hhcm9mZiIsIlRGT09UOjp2YWxpZ24iLCJU
-SDo6YWJiciIsIlRIOjphbGlnbiIsIlRIOjpheGlzIiwiVEg6OmJnY29sb3IiLCJUSDo6Y2hhciIsIlRI
-OjpjaGFyb2ZmIiwiVEg6OmNvbHNwYW4iLCJUSDo6aGVhZGVycyIsIlRIOjpoZWlnaHQiLCJUSDo6bm93
-cmFwIiwiVEg6OnJvd3NwYW4iLCJUSDo6c2NvcGUiLCJUSDo6dmFsaWduIiwiVEg6OndpZHRoIiwiVEhF
-QUQ6OmFsaWduIiwiVEhFQUQ6OmNoYXIiLCJUSEVBRDo6Y2hhcm9mZiIsIlRIRUFEOjp2YWxpZ24iLCJU
-Ujo6YWxpZ24iLCJUUjo6Ymdjb2xvciIsIlRSOjpjaGFyIiwiVFI6OmNoYXJvZmYiLCJUUjo6dmFsaWdu
-IiwiVFJBQ0s6OmRlZmF1bHQiLCJUUkFDSzo6a2luZCIsIlRSQUNLOjpsYWJlbCIsIlRSQUNLOjpzcmNs
-YW5nIiwiVUw6OmNvbXBhY3QiLCJVTDo6dHlwZSIsIlZJREVPOjpjb250cm9scyIsIlZJREVPOjpoZWln
-aHQiLCJWSURFTzo6bG9vcCIsIlZJREVPOjptZWRpYWdyb3VwIiwiVklERU86Om11dGVkIiwiVklERU86
-OnByZWxvYWQiLCJWSURFTzo6d2lkdGgiXSksdS5zKQpDLlZDPUguVk0odChbMCwwLDY1NDkwLDQ1MDU1
-LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLm1LPUguVk0odChbMCwwLDI2NjI0LDEwMjMs
-NjU1MzQsMjA0Nyw2NTUzNCwyMDQ3XSksdS50KQpDLlNxPUguVk0odChbIkhFQUQiLCJBUkVBIiwiQkFT
-RSIsIkJBU0VGT05UIiwiQlIiLCJDT0wiLCJDT0xHUk9VUCIsIkVNQkVEIiwiRlJBTUUiLCJGUkFNRVNF
-VCIsIkhSIiwiSU1BR0UiLCJJTUciLCJJTlBVVCIsIklTSU5ERVgiLCJMSU5LIiwiTUVUQSIsIlBBUkFN
-IiwiU09VUkNFIiwiU1RZTEUiLCJUSVRMRSIsIldCUiJdKSx1LnMpCkMueEQ9SC5WTSh0KFtdKSx1LnUp
-CkMuZG49SC5WTSh0KFtdKSx1LnMpCkMuaFU9SC5WTSh0KFtdKSx1Lm0pCkMudG89SC5WTSh0KFswLDAs
-MzI3MjIsMTIyODcsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQpCkMuRjM9SC5WTSh0KFswLDAs
-MjQ1NzYsMTAyMyw2NTUzNCwzNDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5lYT1ILlZNKHQoWzAsMCwz
-Mjc1NCwxMTI2Myw2NTUzNCwzNDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5aSj1ILlZNKHQoWzAsMCwz
-MjcyMiwxMjI4Nyw2NTUzNSwzNDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5XZD1ILlZNKHQoWzAsMCw2
-NTQ5MCwxMjI4Nyw2NTUzNSwzNDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5ReD1ILlZNKHQoWyJiaW5k
-IiwiaWYiLCJyZWYiLCJyZXBlYXQiLCJzeW50YXgiXSksdS5zKQpDLkJJPUguVk0odChbIkE6OmhyZWYi
-LCJBUkVBOjpocmVmIiwiQkxPQ0tRVU9URTo6Y2l0ZSIsIkJPRFk6OmJhY2tncm91bmQiLCJDT01NQU5E
-OjppY29uIiwiREVMOjpjaXRlIiwiRk9STTo6YWN0aW9uIiwiSU1HOjpzcmMiLCJJTlBVVDo6c3JjIiwi
-SU5TOjpjaXRlIiwiUTo6Y2l0ZSIsIlZJREVPOjpwb3N0ZXIiXSksdS5zKQpDLkNNPW5ldyBILkxQKDAs
-e30sQy5kbixILk4wKCJMUDxxVSxxVT4iKSkKQy5pSD1ILlZNKHQoW10pLEguTjAoImpkPEdEPiIpKQpD
-LldPPW5ldyBILkxQKDAse30sQy5pSCxILk4wKCJMUDxHRCxAPiIpKQpDLlkyPW5ldyBMLk85KCJOYXZp
-Z2F0aW9uVHJlZU5vZGVUeXBlLmRpcmVjdG9yeSIpCkMucmY9bmV3IEwuTzkoIk5hdmlnYXRpb25UcmVl
-Tm9kZVR5cGUuZmlsZSIpCkMuVGU9bmV3IEgud3YoImNhbGwiKQpDLndRPW5ldyBQLkZ5KG51bGwsMil9
-KSgpOyhmdW5jdGlvbiBzdGF0aWNGaWVsZHMoKXskLnlqPTAKJC5tSj1udWxsCiQuUDQ9bnVsbAokLnk9
-bnVsbAokLnU9bnVsbAokLng3PW51bGwKJC5qPW51bGwKJC52PW51bGwKJC5LPW51bGwKJC5TNj1udWxs
-CiQuazg9bnVsbAokLm1nPW51bGwKJC5VRD0hMQokLlgzPUMuTlUKJC54Zz1bXQokLnhvPW51bGwKJC5C
-Tz1udWxsCiQubHQ9bnVsbAokLkVVPW51bGwKJC5vcj1QLkZsKHUuTix1LlopCiQuSTY9bnVsbAokLkZm
-PW51bGx9KSgpOyhmdW5jdGlvbiBsYXp5SW5pdGlhbGl6ZXJzKCl7dmFyIHQ9aHVua0hlbHBlcnMubGF6
-eQp0KCQsImZhIiwid1EiLGZ1bmN0aW9uKCl7cmV0dXJuIEguWWcoIl8kZGFydF9kYXJ0Q2xvc3VyZSIp
-fSkKdCgkLCJZMiIsIkEiLGZ1bmN0aW9uKCl7cmV0dXJuIEguWWcoIl8kZGFydF9qcyIpfSkKdCgkLCJV
-MiIsIlNuIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguUzcoewp0b1N0cmluZzpmdW5jdGlvbigpe3Jl
-dHVybiIkcmVjZWl2ZXIkIn19KSl9KQp0KCQsInhxIiwibHEiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00o
-SC5TNyh7JG1ldGhvZCQ6bnVsbCwKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4iJHJlY2VpdmVyJCJ9
-fSkpfSkKdCgkLCJSMSIsIk45IixmdW5jdGlvbigpe3JldHVybiBILmNNKEguUzcobnVsbCkpfSkKdCgk
-LCJmTiIsImlJIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dmFyICRhcmd1bWVudHNF
-eHByJD0nJGFyZ3VtZW50cyQnCnRyeXtudWxsLiRtZXRob2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2go
-cyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJxaSIsIlVOIixmdW5jdGlvbigpe3JldHVybiBI
-LmNNKEguUzcodm9pZCAwKSl9KQp0KCQsInJaIiwiWmgiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVu
-Y3Rpb24oKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5eyh2b2lkIDApLiRtZXRo
-b2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2gocyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJr
-cSIsInJOIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguTWoobnVsbCkpfSkKdCgkLCJ0dCIsImMzIixm
-dW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dHJ5e251bGwuJG1ldGhvZCR9Y2F0Y2gocyl7
-cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJkdCIsIkhLIixmdW5jdGlvbigpe3JldHVybiBILmNN
-KEguTWoodm9pZCAwKSl9KQp0KCQsIkE3IiwicjEiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rp
-b24oKXt0cnl7KHZvaWQgMCkuJG1ldGhvZCR9Y2F0Y2gocyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkK
-dCgkLCJXYyIsInV0IixmdW5jdGlvbigpe3JldHVybiBQLk9qKCl9KQp0KCQsImtoIiwidEwiLGZ1bmN0
-aW9uKCl7cmV0dXJuIFAuV0koKX0pCnQoJCwiYnQiLCJWNyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5EUShI
-LlhGKEguVk0oWy0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
-LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
-LC0xLC0yLC0yLC0yLC0yLC0yLDYyLC0yLDYyLC0yLDYzLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYw
-LDYxLC0yLC0yLC0yLC0xLC0yLC0yLC0yLDAsMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQs
-MTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsLTIsLTIsLTIsLTIsNjMsLTIsMjYsMjcsMjgs
-MjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMsNDQsNDUsNDYsNDcsNDgs
-NDksNTAsNTEsLTIsLTIsLTIsLTIsLTJdLHUudCkpKX0pCnQoJCwiTTUiLCJPeCIsZnVuY3Rpb24oKXty
-ZXR1cm4gdHlwZW9mIHByb2Nlc3MhPSJ1bmRlZmluZWQiJiZPYmplY3QucHJvdG90eXBlLnRvU3RyaW5n
-LmNhbGwocHJvY2Vzcyk9PSJbb2JqZWN0IHByb2Nlc3NdIiYmcHJvY2Vzcy5wbGF0Zm9ybT09IndpbjMy
-In0pCnQoJCwibWYiLCJ6NCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5udSgiXltcXC1cXC4wLTlBLVpfYS16
-fl0qJCIpfSkKdCgkLCJBdiIsInA2IixmdW5jdGlvbigpe3JldHVybiBuZXcgRXJyb3IoKS5zdGFjayE9
-dm9pZCAwfSkKdCgkLCJKRyIsInZaIixmdW5jdGlvbigpe3JldHVybiBQLktOKCl9KQp0KCQsIlNDIiwi
-QU4iLGZ1bmN0aW9uKCl7cmV0dXJuIFAudE0oWyJBIiwiQUJCUiIsIkFDUk9OWU0iLCJBRERSRVNTIiwi
-QVJFQSIsIkFSVElDTEUiLCJBU0lERSIsIkFVRElPIiwiQiIsIkJESSIsIkJETyIsIkJJRyIsIkJMT0NL
-UVVPVEUiLCJCUiIsIkJVVFRPTiIsIkNBTlZBUyIsIkNBUFRJT04iLCJDRU5URVIiLCJDSVRFIiwiQ09E
-RSIsIkNPTCIsIkNPTEdST1VQIiwiQ09NTUFORCIsIkRBVEEiLCJEQVRBTElTVCIsIkREIiwiREVMIiwi
-REVUQUlMUyIsIkRGTiIsIkRJUiIsIkRJViIsIkRMIiwiRFQiLCJFTSIsIkZJRUxEU0VUIiwiRklHQ0FQ
-VElPTiIsIkZJR1VSRSIsIkZPTlQiLCJGT09URVIiLCJGT1JNIiwiSDEiLCJIMiIsIkgzIiwiSDQiLCJI
-NSIsIkg2IiwiSEVBREVSIiwiSEdST1VQIiwiSFIiLCJJIiwiSUZSQU1FIiwiSU1HIiwiSU5QVVQiLCJJ
-TlMiLCJLQkQiLCJMQUJFTCIsIkxFR0VORCIsIkxJIiwiTUFQIiwiTUFSSyIsIk1FTlUiLCJNRVRFUiIs
-Ik5BViIsIk5PQlIiLCJPTCIsIk9QVEdST1VQIiwiT1BUSU9OIiwiT1VUUFVUIiwiUCIsIlBSRSIsIlBS
-T0dSRVNTIiwiUSIsIlMiLCJTQU1QIiwiU0VDVElPTiIsIlNFTEVDVCIsIlNNQUxMIiwiU09VUkNFIiwi
-U1BBTiIsIlNUUklLRSIsIlNUUk9ORyIsIlNVQiIsIlNVTU1BUlkiLCJTVVAiLCJUQUJMRSIsIlRCT0RZ
-IiwiVEQiLCJURVhUQVJFQSIsIlRGT09UIiwiVEgiLCJUSEVBRCIsIlRJTUUiLCJUUiIsIlRSQUNLIiwi
-VFQiLCJVIiwiVUwiLCJWQVIiLCJWSURFTyIsIldCUiJdLHUuTil9KQp0KCQsIlg0IiwiaEciLGZ1bmN0
-aW9uKCl7cmV0dXJuIFAubnUoIl5cXFMrJCIpfSkKdCgkLCJ3TyIsIm93IixmdW5jdGlvbigpe3JldHVy
-biB1LnYuYShQLk5EKHNlbGYpKX0pCnQoJCwia3QiLCJDciIsZnVuY3Rpb24oKXtyZXR1cm4gSC5ZZygi
-XyRkYXJ0X2RhcnRPYmplY3QiKX0pCnQoJCwiZksiLCJrSSIsZnVuY3Rpb24oKXtyZXR1cm4gZnVuY3Rp
-b24gRGFydE9iamVjdChhKXt0aGlzLm89YX19KQp0KCQsInF0IiwiekIiLGZ1bmN0aW9uKCl7cmV0dXJu
-IG5ldyBULm1RKCl9KQp0KCQsIk9sIiwiVUUiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuaEsoQy5vbC5nbVco
-Vy54MygpKS5ocmVmKS5naFkoKS5xKDAsImF1dGhUb2tlbiIpfSkKdCgkLCJoVCIsInlQIixmdW5jdGlv
-bigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiLmVkaXQtbGlzdCAucGFuZWwtY29udGVudCIp
-fSkKdCgkLCJXNiIsImhMIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiLmVk
-aXQtcGFuZWwgLnBhbmVsLWNvbnRlbnQiKX0pCnQoJCwiVFIiLCJEVyIsZnVuY3Rpb24oKXtyZXR1cm4g
-Vy5acigpLnF1ZXJ5U2VsZWN0b3IoImZvb3RlciIpfSkKdCgkLCJFWSIsImZpIixmdW5jdGlvbigpe3Jl
-dHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiaGVhZGVyIil9KQp0KCQsImF2IiwiRDkiLGZ1bmN0aW9u
-KCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIjdW5pdC1uYW1lIil9KQp0KCQsImZlIiwiS0ci
-LGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLlhBKCl9KQp0KCQsImVvIiwiblUiLGZ1bmN0aW9uKCl7cmV0
-dXJuIG5ldyBNLmxJKCQuSGsoKSl9KQp0KCQsInlyIiwiYkQiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBF
-Lk9GKFAubnUoIi8iKSxQLm51KCJbXi9dJCIpLFAubnUoIl4vIikpfSkKdCgkLCJNayIsIktrIixmdW5j
-dGlvbigpe3JldHVybiBuZXcgTC5JVihQLm51KCJbL1xcXFxdIiksUC5udSgiW14vXFxcXF0kIiksUC5u
-dSgiXihcXFxcXFxcXFteXFxcXF0rXFxcXFteXFxcXC9dK3xbYS16QS1aXTpbL1xcXFxdKSIpLFAubnUo
-Il5bL1xcXFxdKD8hWy9cXFxcXSkiKSl9KQp0KCQsImFrIiwiRWIiLGZ1bmN0aW9uKCl7cmV0dXJuIG5l
-dyBGLnJ1KFAubnUoIi8iKSxQLm51KCIoXlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8vfFteL10pJCIp
-LFAubnUoIlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8vW14vXSoiKSxQLm51KCJeLyIpKX0pCnQoJCwi
-bHMiLCJIayIsZnVuY3Rpb24oKXtyZXR1cm4gTy5SaCgpfSl9KSgpOyhmdW5jdGlvbiBuYXRpdmVTdXBw
-b3J0KCl7IWZ1bmN0aW9uKCl7dmFyIHQ9ZnVuY3Rpb24oYSl7dmFyIG49e30KblthXT0xCnJldHVybiBP
-YmplY3Qua2V5cyhodW5rSGVscGVycy5jb252ZXJ0VG9GYXN0T2JqZWN0KG4pKVswXX0Kdi5nZXRJc29s
-YXRlVGFnPWZ1bmN0aW9uKGEpe3JldHVybiB0KCJfX19kYXJ0XyIrYSt2Lmlzb2xhdGVUYWcpfQp2YXIg
-cz0iX19fZGFydF9pc29sYXRlX3RhZ3NfIgp2YXIgcj1PYmplY3Rbc118fChPYmplY3Rbc109T2JqZWN0
-LmNyZWF0ZShudWxsKSkKdmFyIHE9Il9aeFl4WCIKZm9yKHZhciBwPTA7O3ArKyl7dmFyIG89dChxKyJf
-IitwKyJfIikKaWYoIShvIGluIHIpKXtyW29dPTEKdi5pc29sYXRlVGFnPW8KYnJlYWt9fXYuZGlzcGF0
-Y2hQcm9wZXJ0eU5hbWU9di5nZXRJc29sYXRlVGFnKCJkaXNwYXRjaF9yZWNvcmQiKX0oKQpodW5rSGVs
-cGVycy5zZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFnKHtET01FcnJvcjpKLnZCLERPTUltcGxlbWVu
-dGF0aW9uOkoudkIsTWVkaWFFcnJvcjpKLnZCLE5hdmlnYXRvcjpKLnZCLE5hdmlnYXRvckNvbmN1cnJl
-bnRIYXJkd2FyZTpKLnZCLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOkoudkIsT3ZlcmNvbnN0cmFpbmVk
-RXJyb3I6Si52QixQb3NpdGlvbkVycm9yOkoudkIsUmFuZ2U6Si52QixTUUxFcnJvcjpKLnZCLERhdGFW
-aWV3OkgucEYsQXJyYXlCdWZmZXJWaWV3OkgucEYsRmxvYXQzMkFycmF5OkguRGcsRmxvYXQ2NEFycmF5
-OkguRGcsSW50MTZBcnJheTpILnhqLEludDMyQXJyYXk6SC5kRSxJbnQ4QXJyYXk6SC5aQSxVaW50MTZB
-cnJheTpILndmLFVpbnQzMkFycmF5OkguUHEsVWludDhDbGFtcGVkQXJyYXk6SC5lRSxDYW52YXNQaXhl
-bEFycmF5OkguZUUsVWludDhBcnJheTpILlY2LEhUTUxBdWRpb0VsZW1lbnQ6Vy5xRSxIVE1MQlJFbGVt
-ZW50OlcucUUsSFRNTEJ1dHRvbkVsZW1lbnQ6Vy5xRSxIVE1MQ2FudmFzRWxlbWVudDpXLnFFLEhUTUxD
-b250ZW50RWxlbWVudDpXLnFFLEhUTUxETGlzdEVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUVsZW1lbnQ6Vy5x
-RSxIVE1MRGF0YUxpc3RFbGVtZW50OlcucUUsSFRNTERldGFpbHNFbGVtZW50OlcucUUsSFRNTERpYWxv
-Z0VsZW1lbnQ6Vy5xRSxIVE1MRGl2RWxlbWVudDpXLnFFLEhUTUxFbWJlZEVsZW1lbnQ6Vy5xRSxIVE1M
-RmllbGRTZXRFbGVtZW50OlcucUUsSFRNTEhSRWxlbWVudDpXLnFFLEhUTUxIZWFkRWxlbWVudDpXLnFF
-LEhUTUxIZWFkaW5nRWxlbWVudDpXLnFFLEhUTUxIdG1sRWxlbWVudDpXLnFFLEhUTUxJRnJhbWVFbGVt
-ZW50OlcucUUsSFRNTEltYWdlRWxlbWVudDpXLnFFLEhUTUxJbnB1dEVsZW1lbnQ6Vy5xRSxIVE1MTElF
-bGVtZW50OlcucUUsSFRNTExhYmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50OlcucUUsSFRN
-TExpbmtFbGVtZW50OlcucUUsSFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50OlcucUUs
-SFRNTE1lbnVFbGVtZW50OlcucUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1ldGVyRWxlbWVudDpX
-LnFFLEhUTUxNb2RFbGVtZW50OlcucUUsSFRNTE9MaXN0RWxlbWVudDpXLnFFLEhUTUxPYmplY3RFbGVt
-ZW50OlcucUUsSFRNTE9wdEdyb3VwRWxlbWVudDpXLnFFLEhUTUxPcHRpb25FbGVtZW50OlcucUUsSFRN
-TE91dHB1dEVsZW1lbnQ6Vy5xRSxIVE1MUGFyYW1FbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50
-OlcucUUsSFRNTFByZUVsZW1lbnQ6Vy5xRSxIVE1MUHJvZ3Jlc3NFbGVtZW50OlcucUUsSFRNTFF1b3Rl
-RWxlbWVudDpXLnFFLEhUTUxTY3JpcHRFbGVtZW50OlcucUUsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5xRSxI
-VE1MU2xvdEVsZW1lbnQ6Vy5xRSxIVE1MU291cmNlRWxlbWVudDpXLnFFLEhUTUxTcGFuRWxlbWVudDpX
-LnFFLEhUTUxTdHlsZUVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDpXLnFFLEhUTUxU
-YWJsZUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxl
-SGVhZGVyQ2VsbEVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDb2xFbGVtZW50OlcucUUsSFRNTFRleHRBcmVh
-RWxlbWVudDpXLnFFLEhUTUxUaW1lRWxlbWVudDpXLnFFLEhUTUxUaXRsZUVsZW1lbnQ6Vy5xRSxIVE1M
-VHJhY2tFbGVtZW50OlcucUUsSFRNTFVMaXN0RWxlbWVudDpXLnFFLEhUTUxVbmtub3duRWxlbWVudDpX
-LnFFLEhUTUxWaWRlb0VsZW1lbnQ6Vy5xRSxIVE1MRGlyZWN0b3J5RWxlbWVudDpXLnFFLEhUTUxGb250
-RWxlbWVudDpXLnFFLEhUTUxGcmFtZUVsZW1lbnQ6Vy5xRSxIVE1MRnJhbWVTZXRFbGVtZW50OlcucUUs
-SFRNTE1hcnF1ZWVFbGVtZW50OlcucUUsSFRNTEVsZW1lbnQ6Vy5xRSxIVE1MQW5jaG9yRWxlbWVudDpX
-LkdoLEhUTUxBcmVhRWxlbWVudDpXLmZZLEhUTUxCYXNlRWxlbWVudDpXLm5CLEJsb2I6Vy5BeixIVE1M
-Qm9keUVsZW1lbnQ6Vy5RUCxDREFUQVNlY3Rpb246Vy5ueCxDaGFyYWN0ZXJEYXRhOlcubngsQ29tbWVu
-dDpXLm54LFByb2Nlc3NpbmdJbnN0cnVjdGlvbjpXLm54LFRleHQ6Vy5ueCxDU1NTdHlsZURlY2xhcmF0
-aW9uOlcub0osTVNTdHlsZUNTU1Byb3BlcnRpZXM6Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLFhNTERv
-Y3VtZW50OlcuUUYsRG9jdW1lbnQ6Vy5RRixET01FeGNlcHRpb246Vy5OaCxET01SZWN0UmVhZE9ubHk6
-Vy5JQixET01Ub2tlbkxpc3Q6Vy5uNyxFbGVtZW50OlcuY3YsQWJvcnRQYXltZW50RXZlbnQ6Vy5lYSxB
-bmltYXRpb25FdmVudDpXLmVhLEFuaW1hdGlvblBsYXliYWNrRXZlbnQ6Vy5lYSxBcHBsaWNhdGlvbkNh
-Y2hlRXJyb3JFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaENsaWNrRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5k
-RmV0Y2hFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaEZhaWxFdmVudDpXLmVhLEJhY2tncm91bmRGZXRj
-aGVkRXZlbnQ6Vy5lYSxCZWZvcmVJbnN0YWxsUHJvbXB0RXZlbnQ6Vy5lYSxCZWZvcmVVbmxvYWRFdmVu
-dDpXLmVhLEJsb2JFdmVudDpXLmVhLENhbk1ha2VQYXltZW50RXZlbnQ6Vy5lYSxDbGlwYm9hcmRFdmVu
-dDpXLmVhLENsb3NlRXZlbnQ6Vy5lYSxDdXN0b21FdmVudDpXLmVhLERldmljZU1vdGlvbkV2ZW50Olcu
-ZWEsRGV2aWNlT3JpZW50YXRpb25FdmVudDpXLmVhLEVycm9yRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlRXZl
-bnQ6Vy5lYSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OlcuZWEsRmV0Y2hFdmVudDpXLmVhLEZvbnRGYWNl
-U2V0TG9hZEV2ZW50OlcuZWEsRm9yZWlnbkZldGNoRXZlbnQ6Vy5lYSxHYW1lcGFkRXZlbnQ6Vy5lYSxI
-YXNoQ2hhbmdlRXZlbnQ6Vy5lYSxJbnN0YWxsRXZlbnQ6Vy5lYSxNZWRpYUVuY3J5cHRlZEV2ZW50Olcu
-ZWEsTWVkaWFLZXlNZXNzYWdlRXZlbnQ6Vy5lYSxNZWRpYVF1ZXJ5TGlzdEV2ZW50OlcuZWEsTWVkaWFT
-dHJlYW1FdmVudDpXLmVhLE1lZGlhU3RyZWFtVHJhY2tFdmVudDpXLmVhLE1lc3NhZ2VFdmVudDpXLmVh
-LE1JRElDb25uZWN0aW9uRXZlbnQ6Vy5lYSxNSURJTWVzc2FnZUV2ZW50OlcuZWEsTXV0YXRpb25FdmVu
-dDpXLmVhLE5vdGlmaWNhdGlvbkV2ZW50OlcuZWEsUGFnZVRyYW5zaXRpb25FdmVudDpXLmVhLFBheW1l
-bnRSZXF1ZXN0RXZlbnQ6Vy5lYSxQYXltZW50UmVxdWVzdFVwZGF0ZUV2ZW50OlcuZWEsUG9wU3RhdGVF
-dmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25BdmFpbGFibGVFdmVudDpXLmVhLFByZXNlbnRh
-dGlvbkNvbm5lY3Rpb25DbG9zZUV2ZW50OlcuZWEsUHJvbWlzZVJlamVjdGlvbkV2ZW50OlcuZWEsUHVz
-aEV2ZW50OlcuZWEsUlRDRGF0YUNoYW5uZWxFdmVudDpXLmVhLFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6
-Vy5lYSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OlcuZWEsUlRDVHJhY2tFdmVudDpXLmVhLFNlY3Vy
-aXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6Vy5lYSxTZW5zb3JFcnJvckV2ZW50OlcuZWEsU3BlZWNoUmVj
-b2duaXRpb25FcnJvcjpXLmVhLFNwZWVjaFJlY29nbml0aW9uRXZlbnQ6Vy5lYSxTcGVlY2hTeW50aGVz
-aXNFdmVudDpXLmVhLFN0b3JhZ2VFdmVudDpXLmVhLFN5bmNFdmVudDpXLmVhLFRyYWNrRXZlbnQ6Vy5l
-YSxUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxXZWJLaXRUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxWUkRldmljZUV2
-ZW50OlcuZWEsVlJEaXNwbGF5RXZlbnQ6Vy5lYSxWUlNlc3Npb25FdmVudDpXLmVhLE1vam9JbnRlcmZh
-Y2VSZXF1ZXN0RXZlbnQ6Vy5lYSxVU0JDb25uZWN0aW9uRXZlbnQ6Vy5lYSxJREJWZXJzaW9uQ2hhbmdl
-RXZlbnQ6Vy5lYSxBdWRpb1Byb2Nlc3NpbmdFdmVudDpXLmVhLE9mZmxpbmVBdWRpb0NvbXBsZXRpb25F
-dmVudDpXLmVhLFdlYkdMQ29udGV4dEV2ZW50OlcuZWEsRXZlbnQ6Vy5lYSxJbnB1dEV2ZW50OlcuZWEs
-RXZlbnRUYXJnZXQ6Vy5EMCxGaWxlOlcuVDUsSFRNTEZvcm1FbGVtZW50OlcuaDQsSGlzdG9yeTpXLmJy
-LEhUTUxEb2N1bWVudDpXLlZiLFhNTEh0dHBSZXF1ZXN0OlcuZkosWE1MSHR0cFJlcXVlc3RFdmVudFRh
-cmdldDpXLndhLEltYWdlRGF0YTpXLlNnLExvY2F0aW9uOlcudTgsTW91c2VFdmVudDpXLk9LLERyYWdF
-dmVudDpXLk9LLFBvaW50ZXJFdmVudDpXLk9LLFdoZWVsRXZlbnQ6Vy5PSyxEb2N1bWVudEZyYWdtZW50
-OlcudUgsU2hhZG93Um9vdDpXLnVILERvY3VtZW50VHlwZTpXLnVILE5vZGU6Vy51SCxOb2RlTGlzdDpX
-LkJILFJhZGlvTm9kZUxpc3Q6Vy5CSCxIVE1MUGFyYWdyYXBoRWxlbWVudDpXLlNOLFByb2dyZXNzRXZl
-bnQ6Vy5ldyxSZXNvdXJjZVByb2dyZXNzRXZlbnQ6Vy5ldyxIVE1MU2VsZWN0RWxlbWVudDpXLmxwLEhU
-TUxUYWJsZUVsZW1lbnQ6Vy5UYixIVE1MVGFibGVSb3dFbGVtZW50OlcuSXYsSFRNTFRhYmxlU2VjdGlv
-bkVsZW1lbnQ6Vy5CVCxIVE1MVGVtcGxhdGVFbGVtZW50OlcueVksQ29tcG9zaXRpb25FdmVudDpXLnc2
-LEZvY3VzRXZlbnQ6Vy53NixLZXlib2FyZEV2ZW50OlcudzYsVGV4dEV2ZW50OlcudzYsVG91Y2hFdmVu
-dDpXLnc2LFVJRXZlbnQ6Vy53NixXaW5kb3c6Vy5LNSxET01XaW5kb3c6Vy5LNSxEZWRpY2F0ZWRXb3Jr
-ZXJHbG9iYWxTY29wZTpXLkNtLFNlcnZpY2VXb3JrZXJHbG9iYWxTY29wZTpXLkNtLFNoYXJlZFdvcmtl
-ckdsb2JhbFNjb3BlOlcuQ20sV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxBdHRyOlcuQ1EsQ2xpZW50UmVj
-dDpXLnc0LERPTVJlY3Q6Vy53NCxOYW1lZE5vZGVNYXA6Vy5yaCxNb3pOYW1lZEF0dHJNYXA6Vy5yaCxJ
-REJLZXlSYW5nZTpQLmhGLFNWR1NjcmlwdEVsZW1lbnQ6UC5uZCxTVkdBRWxlbWVudDpQLmQ1LFNWR0Fu
-aW1hdGVFbGVtZW50OlAuZDUsU1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6UC5kNSxTVkdBbmltYXRlVHJh
-bnNmb3JtRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGlvbkVsZW1lbnQ6UC5kNSxTVkdDaXJjbGVFbGVtZW50
-OlAuZDUsU1ZHQ2xpcFBhdGhFbGVtZW50OlAuZDUsU1ZHRGVmc0VsZW1lbnQ6UC5kNSxTVkdEZXNjRWxl
-bWVudDpQLmQ1LFNWR0Rpc2NhcmRFbGVtZW50OlAuZDUsU1ZHRWxsaXBzZUVsZW1lbnQ6UC5kNSxTVkdG
-RUJsZW5kRWxlbWVudDpQLmQ1LFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OlAuZDUsU1ZHRkVDb21wb25l
-bnRUcmFuc2ZlckVsZW1lbnQ6UC5kNSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6UC5kNSxTVkdGRUNvbnZv
-bHZlTWF0cml4RWxlbWVudDpQLmQ1LFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxlbWVudDpQLmQ1LFNWR0ZF
-RGlzcGxhY2VtZW50TWFwRWxlbWVudDpQLmQ1LFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDpQLmQ1LFNW
-R0ZFRmxvb2RFbGVtZW50OlAuZDUsU1ZHRkVGdW5jQUVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNCRWxlbWVu
-dDpQLmQ1LFNWR0ZFRnVuY0dFbGVtZW50OlAuZDUsU1ZHRkVGdW5jUkVsZW1lbnQ6UC5kNSxTVkdGRUdh
-dXNzaWFuQmx1ckVsZW1lbnQ6UC5kNSxTVkdGRUltYWdlRWxlbWVudDpQLmQ1LFNWR0ZFTWVyZ2VFbGVt
-ZW50OlAuZDUsU1ZHRkVNZXJnZU5vZGVFbGVtZW50OlAuZDUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDpQ
-LmQ1LFNWR0ZFT2Zmc2V0RWxlbWVudDpQLmQ1LFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdG
-RVNwZWN1bGFyTGlnaHRpbmdFbGVtZW50OlAuZDUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OlAuZDUsU1ZH
-RkVUaWxlRWxlbWVudDpQLmQ1LFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6UC5kNSxTVkdGaWx0ZXJFbGVt
-ZW50OlAuZDUsU1ZHRm9yZWlnbk9iamVjdEVsZW1lbnQ6UC5kNSxTVkdHRWxlbWVudDpQLmQ1LFNWR0dl
-b21ldHJ5RWxlbWVudDpQLmQ1LFNWR0dyYXBoaWNzRWxlbWVudDpQLmQ1LFNWR0ltYWdlRWxlbWVudDpQ
-LmQ1LFNWR0xpbmVFbGVtZW50OlAuZDUsU1ZHTGluZWFyR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHTWFy
-a2VyRWxlbWVudDpQLmQ1LFNWR01hc2tFbGVtZW50OlAuZDUsU1ZHTWV0YWRhdGFFbGVtZW50OlAuZDUs
-U1ZHUGF0aEVsZW1lbnQ6UC5kNSxTVkdQYXR0ZXJuRWxlbWVudDpQLmQ1LFNWR1BvbHlnb25FbGVtZW50
-OlAuZDUsU1ZHUG9seWxpbmVFbGVtZW50OlAuZDUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OlAuZDUs
-U1ZHUmVjdEVsZW1lbnQ6UC5kNSxTVkdTZXRFbGVtZW50OlAuZDUsU1ZHU3RvcEVsZW1lbnQ6UC5kNSxT
-VkdTdHlsZUVsZW1lbnQ6UC5kNSxTVkdTVkdFbGVtZW50OlAuZDUsU1ZHU3dpdGNoRWxlbWVudDpQLmQ1
-LFNWR1N5bWJvbEVsZW1lbnQ6UC5kNSxTVkdUU3BhbkVsZW1lbnQ6UC5kNSxTVkdUZXh0Q29udGVudEVs
-ZW1lbnQ6UC5kNSxTVkdUZXh0RWxlbWVudDpQLmQ1LFNWR1RleHRQYXRoRWxlbWVudDpQLmQ1LFNWR1Rl
-eHRQb3NpdGlvbmluZ0VsZW1lbnQ6UC5kNSxTVkdUaXRsZUVsZW1lbnQ6UC5kNSxTVkdVc2VFbGVtZW50
-OlAuZDUsU1ZHVmlld0VsZW1lbnQ6UC5kNSxTVkdHcmFkaWVudEVsZW1lbnQ6UC5kNSxTVkdDb21wb25l
-bnRUcmFuc2ZlckZ1bmN0aW9uRWxlbWVudDpQLmQ1LFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6UC5kNSxT
-VkdNUGF0aEVsZW1lbnQ6UC5kNSxTVkdFbGVtZW50OlAuZDV9KQpodW5rSGVscGVycy5zZXRPclVwZGF0
-ZUxlYWZUYWdzKHtET01FcnJvcjp0cnVlLERPTUltcGxlbWVudGF0aW9uOnRydWUsTWVkaWFFcnJvcjp0
-cnVlLE5hdmlnYXRvcjp0cnVlLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTp0cnVlLE5hdmlnYXRv
-clVzZXJNZWRpYUVycm9yOnRydWUsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6dHJ1ZSxQb3NpdGlvbkVycm9y
-OnRydWUsUmFuZ2U6dHJ1ZSxTUUxFcnJvcjp0cnVlLERhdGFWaWV3OnRydWUsQXJyYXlCdWZmZXJWaWV3
-OmZhbHNlLEZsb2F0MzJBcnJheTp0cnVlLEZsb2F0NjRBcnJheTp0cnVlLEludDE2QXJyYXk6dHJ1ZSxJ
-bnQzMkFycmF5OnRydWUsSW50OEFycmF5OnRydWUsVWludDE2QXJyYXk6dHJ1ZSxVaW50MzJBcnJheTp0
-cnVlLFVpbnQ4Q2xhbXBlZEFycmF5OnRydWUsQ2FudmFzUGl4ZWxBcnJheTp0cnVlLFVpbnQ4QXJyYXk6
-ZmFsc2UsSFRNTEF1ZGlvRWxlbWVudDp0cnVlLEhUTUxCUkVsZW1lbnQ6dHJ1ZSxIVE1MQnV0dG9uRWxl
-bWVudDp0cnVlLEhUTUxDYW52YXNFbGVtZW50OnRydWUsSFRNTENvbnRlbnRFbGVtZW50OnRydWUsSFRN
-TERMaXN0RWxlbWVudDp0cnVlLEhUTUxEYXRhRWxlbWVudDp0cnVlLEhUTUxEYXRhTGlzdEVsZW1lbnQ6
-dHJ1ZSxIVE1MRGV0YWlsc0VsZW1lbnQ6dHJ1ZSxIVE1MRGlhbG9nRWxlbWVudDp0cnVlLEhUTUxEaXZF
-bGVtZW50OnRydWUsSFRNTEVtYmVkRWxlbWVudDp0cnVlLEhUTUxGaWVsZFNldEVsZW1lbnQ6dHJ1ZSxI
-VE1MSFJFbGVtZW50OnRydWUsSFRNTEhlYWRFbGVtZW50OnRydWUsSFRNTEhlYWRpbmdFbGVtZW50OnRy
-dWUsSFRNTEh0bWxFbGVtZW50OnRydWUsSFRNTElGcmFtZUVsZW1lbnQ6dHJ1ZSxIVE1MSW1hZ2VFbGVt
-ZW50OnRydWUsSFRNTElucHV0RWxlbWVudDp0cnVlLEhUTUxMSUVsZW1lbnQ6dHJ1ZSxIVE1MTGFiZWxF
-bGVtZW50OnRydWUsSFRNTExlZ2VuZEVsZW1lbnQ6dHJ1ZSxIVE1MTGlua0VsZW1lbnQ6dHJ1ZSxIVE1M
-TWFwRWxlbWVudDp0cnVlLEhUTUxNZWRpYUVsZW1lbnQ6dHJ1ZSxIVE1MTWVudUVsZW1lbnQ6dHJ1ZSxI
-VE1MTWV0YUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0ZXJFbGVtZW50OnRydWUsSFRNTE1vZEVsZW1lbnQ6dHJ1
-ZSxIVE1MT0xpc3RFbGVtZW50OnRydWUsSFRNTE9iamVjdEVsZW1lbnQ6dHJ1ZSxIVE1MT3B0R3JvdXBF
-bGVtZW50OnRydWUsSFRNTE9wdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MT3V0cHV0RWxlbWVudDp0cnVlLEhU
-TUxQYXJhbUVsZW1lbnQ6dHJ1ZSxIVE1MUGljdHVyZUVsZW1lbnQ6dHJ1ZSxIVE1MUHJlRWxlbWVudDp0
-cnVlLEhUTUxQcm9ncmVzc0VsZW1lbnQ6dHJ1ZSxIVE1MUXVvdGVFbGVtZW50OnRydWUsSFRNTFNjcmlw
-dEVsZW1lbnQ6dHJ1ZSxIVE1MU2hhZG93RWxlbWVudDp0cnVlLEhUTUxTbG90RWxlbWVudDp0cnVlLEhU
-TUxTb3VyY2VFbGVtZW50OnRydWUsSFRNTFNwYW5FbGVtZW50OnRydWUsSFRNTFN0eWxlRWxlbWVudDp0
-cnVlLEhUTUxUYWJsZUNhcHRpb25FbGVtZW50OnRydWUsSFRNTFRhYmxlQ2VsbEVsZW1lbnQ6dHJ1ZSxI
-VE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVIZWFkZXJDZWxsRWxlbWVudDp0cnVl
-LEhUTUxUYWJsZUNvbEVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFyZWFFbGVtZW50OnRydWUsSFRNTFRpbWVF
-bGVtZW50OnRydWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhUTUxUcmFja0VsZW1lbnQ6dHJ1ZSxIVE1M
-VUxpc3RFbGVtZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50OnRydWUsSFRNTFZpZGVvRWxlbWVudDp0
-cnVlLEhUTUxEaXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZvbnRFbGVtZW50OnRydWUsSFRNTEZyYW1l
-RWxlbWVudDp0cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1ZSxIVE1MTWFycXVlZUVsZW1lbnQ6dHJ1
-ZSxIVE1MRWxlbWVudDpmYWxzZSxIVE1MQW5jaG9yRWxlbWVudDp0cnVlLEhUTUxBcmVhRWxlbWVudDp0
-cnVlLEhUTUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2UsSFRNTEJvZHlFbGVtZW50OnRydWUsQ0RB
-VEFTZWN0aW9uOnRydWUsQ2hhcmFjdGVyRGF0YTp0cnVlLENvbW1lbnQ6dHJ1ZSxQcm9jZXNzaW5nSW5z
-dHJ1Y3Rpb246dHJ1ZSxUZXh0OnRydWUsQ1NTU3R5bGVEZWNsYXJhdGlvbjp0cnVlLE1TU3R5bGVDU1NQ
-cm9wZXJ0aWVzOnRydWUsQ1NTMlByb3BlcnRpZXM6dHJ1ZSxYTUxEb2N1bWVudDp0cnVlLERvY3VtZW50
-OmZhbHNlLERPTUV4Y2VwdGlvbjp0cnVlLERPTVJlY3RSZWFkT25seTpmYWxzZSxET01Ub2tlbkxpc3Q6
-dHJ1ZSxFbGVtZW50OmZhbHNlLEFib3J0UGF5bWVudEV2ZW50OnRydWUsQW5pbWF0aW9uRXZlbnQ6dHJ1
-ZSxBbmltYXRpb25QbGF5YmFja0V2ZW50OnRydWUsQXBwbGljYXRpb25DYWNoZUVycm9yRXZlbnQ6dHJ1
-ZSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRXZlbnQ6dHJ1ZSxC
-YWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hlZEV2ZW50OnRydWUsQmVm
-b3JlSW5zdGFsbFByb21wdEV2ZW50OnRydWUsQmVmb3JlVW5sb2FkRXZlbnQ6dHJ1ZSxCbG9iRXZlbnQ6
-dHJ1ZSxDYW5NYWtlUGF5bWVudEV2ZW50OnRydWUsQ2xpcGJvYXJkRXZlbnQ6dHJ1ZSxDbG9zZUV2ZW50
-OnRydWUsQ3VzdG9tRXZlbnQ6dHJ1ZSxEZXZpY2VNb3Rpb25FdmVudDp0cnVlLERldmljZU9yaWVudGF0
-aW9uRXZlbnQ6dHJ1ZSxFcnJvckV2ZW50OnRydWUsRXh0ZW5kYWJsZUV2ZW50OnRydWUsRXh0ZW5kYWJs
-ZU1lc3NhZ2VFdmVudDp0cnVlLEZldGNoRXZlbnQ6dHJ1ZSxGb250RmFjZVNldExvYWRFdmVudDp0cnVl
-LEZvcmVpZ25GZXRjaEV2ZW50OnRydWUsR2FtZXBhZEV2ZW50OnRydWUsSGFzaENoYW5nZUV2ZW50OnRy
-dWUsSW5zdGFsbEV2ZW50OnRydWUsTWVkaWFFbmNyeXB0ZWRFdmVudDp0cnVlLE1lZGlhS2V5TWVzc2Fn
-ZUV2ZW50OnRydWUsTWVkaWFRdWVyeUxpc3RFdmVudDp0cnVlLE1lZGlhU3RyZWFtRXZlbnQ6dHJ1ZSxN
-ZWRpYVN0cmVhbVRyYWNrRXZlbnQ6dHJ1ZSxNZXNzYWdlRXZlbnQ6dHJ1ZSxNSURJQ29ubmVjdGlvbkV2
-ZW50OnRydWUsTUlESU1lc3NhZ2VFdmVudDp0cnVlLE11dGF0aW9uRXZlbnQ6dHJ1ZSxOb3RpZmljYXRp
-b25FdmVudDp0cnVlLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVzdEV2ZW50OnRy
-dWUsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDp0cnVlLFBvcFN0YXRlRXZlbnQ6dHJ1ZSxQcmVzZW50
-YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9uQ2xv
-c2VFdmVudDp0cnVlLFByb21pc2VSZWplY3Rpb25FdmVudDp0cnVlLFB1c2hFdmVudDp0cnVlLFJUQ0Rh
-dGFDaGFubmVsRXZlbnQ6dHJ1ZSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OnRydWUsUlRDUGVlckNvbm5l
-Y3Rpb25JY2VFdmVudDp0cnVlLFJUQ1RyYWNrRXZlbnQ6dHJ1ZSxTZWN1cml0eVBvbGljeVZpb2xhdGlv
-bkV2ZW50OnRydWUsU2Vuc29yRXJyb3JFdmVudDp0cnVlLFNwZWVjaFJlY29nbml0aW9uRXJyb3I6dHJ1
-ZSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OnRydWUsU3BlZWNoU3ludGhlc2lzRXZlbnQ6dHJ1ZSxTdG9y
-YWdlRXZlbnQ6dHJ1ZSxTeW5jRXZlbnQ6dHJ1ZSxUcmFja0V2ZW50OnRydWUsVHJhbnNpdGlvbkV2ZW50
-OnRydWUsV2ViS2l0VHJhbnNpdGlvbkV2ZW50OnRydWUsVlJEZXZpY2VFdmVudDp0cnVlLFZSRGlzcGxh
-eUV2ZW50OnRydWUsVlJTZXNzaW9uRXZlbnQ6dHJ1ZSxNb2pvSW50ZXJmYWNlUmVxdWVzdEV2ZW50OnRy
-dWUsVVNCQ29ubmVjdGlvbkV2ZW50OnRydWUsSURCVmVyc2lvbkNoYW5nZUV2ZW50OnRydWUsQXVkaW9Q
-cm9jZXNzaW5nRXZlbnQ6dHJ1ZSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6dHJ1ZSxXZWJHTENv
-bnRleHRFdmVudDp0cnVlLEV2ZW50OmZhbHNlLElucHV0RXZlbnQ6ZmFsc2UsRXZlbnRUYXJnZXQ6ZmFs
-c2UsRmlsZTp0cnVlLEhUTUxGb3JtRWxlbWVudDp0cnVlLEhpc3Rvcnk6dHJ1ZSxIVE1MRG9jdW1lbnQ6
-dHJ1ZSxYTUxIdHRwUmVxdWVzdDp0cnVlLFhNTEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6ZmFsc2UsSW1h
-Z2VEYXRhOnRydWUsTG9jYXRpb246dHJ1ZSxNb3VzZUV2ZW50OnRydWUsRHJhZ0V2ZW50OnRydWUsUG9p
-bnRlckV2ZW50OnRydWUsV2hlZWxFdmVudDp0cnVlLERvY3VtZW50RnJhZ21lbnQ6dHJ1ZSxTaGFkb3dS
-b290OnRydWUsRG9jdW1lbnRUeXBlOnRydWUsTm9kZTpmYWxzZSxOb2RlTGlzdDp0cnVlLFJhZGlvTm9k
-ZUxpc3Q6dHJ1ZSxIVE1MUGFyYWdyYXBoRWxlbWVudDp0cnVlLFByb2dyZXNzRXZlbnQ6dHJ1ZSxSZXNv
-dXJjZVByb2dyZXNzRXZlbnQ6dHJ1ZSxIVE1MU2VsZWN0RWxlbWVudDp0cnVlLEhUTUxUYWJsZUVsZW1l
-bnQ6dHJ1ZSxIVE1MVGFibGVSb3dFbGVtZW50OnRydWUsSFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ6dHJ1
-ZSxIVE1MVGVtcGxhdGVFbGVtZW50OnRydWUsQ29tcG9zaXRpb25FdmVudDp0cnVlLEZvY3VzRXZlbnQ6
-dHJ1ZSxLZXlib2FyZEV2ZW50OnRydWUsVGV4dEV2ZW50OnRydWUsVG91Y2hFdmVudDp0cnVlLFVJRXZl
-bnQ6ZmFsc2UsV2luZG93OnRydWUsRE9NV2luZG93OnRydWUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2Nv
-cGU6dHJ1ZSxTZXJ2aWNlV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxTaGFyZWRXb3JrZXJHbG9iYWxTY29w
-ZTp0cnVlLFdvcmtlckdsb2JhbFNjb3BlOnRydWUsQXR0cjp0cnVlLENsaWVudFJlY3Q6dHJ1ZSxET01S
-ZWN0OnRydWUsTmFtZWROb2RlTWFwOnRydWUsTW96TmFtZWRBdHRyTWFwOnRydWUsSURCS2V5UmFuZ2U6
-dHJ1ZSxTVkdTY3JpcHRFbGVtZW50OnRydWUsU1ZHQUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlRWxlbWVu
-dDp0cnVlLFNWR0FuaW1hdGVNb3Rpb25FbGVtZW50OnRydWUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1l
-bnQ6dHJ1ZSxTVkdBbmltYXRpb25FbGVtZW50OnRydWUsU1ZHQ2lyY2xlRWxlbWVudDp0cnVlLFNWR0Ns
-aXBQYXRoRWxlbWVudDp0cnVlLFNWR0RlZnNFbGVtZW50OnRydWUsU1ZHRGVzY0VsZW1lbnQ6dHJ1ZSxT
-VkdEaXNjYXJkRWxlbWVudDp0cnVlLFNWR0VsbGlwc2VFbGVtZW50OnRydWUsU1ZHRkVCbGVuZEVsZW1l
-bnQ6dHJ1ZSxTVkdGRUNvbG9yTWF0cml4RWxlbWVudDp0cnVlLFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJF
-bGVtZW50OnRydWUsU1ZHRkVDb21wb3NpdGVFbGVtZW50OnRydWUsU1ZHRkVDb252b2x2ZU1hdHJpeEVs
-ZW1lbnQ6dHJ1ZSxTVkdGRURpZmZ1c2VMaWdodGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRURpc3BsYWNlbWVu
-dE1hcEVsZW1lbnQ6dHJ1ZSxTVkdGRURpc3RhbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRUZsb29kRWxl
-bWVudDp0cnVlLFNWR0ZFRnVuY0FFbGVtZW50OnRydWUsU1ZHRkVGdW5jQkVsZW1lbnQ6dHJ1ZSxTVkdG
-RUZ1bmNHRWxlbWVudDp0cnVlLFNWR0ZFRnVuY1JFbGVtZW50OnRydWUsU1ZHRkVHYXVzc2lhbkJsdXJF
-bGVtZW50OnRydWUsU1ZHRkVJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1lcmdlRWxlbWVudDp0cnVlLFNW
-R0ZFTWVyZ2VOb2RlRWxlbWVudDp0cnVlLFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6dHJ1ZSxTVkdGRU9m
-ZnNldEVsZW1lbnQ6dHJ1ZSxTVkdGRVBvaW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVTcGVjdWxhckxp
-Z2h0aW5nRWxlbWVudDp0cnVlLFNWR0ZFU3BvdExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFVGlsZUVsZW1l
-bnQ6dHJ1ZSxTVkdGRVR1cmJ1bGVuY2VFbGVtZW50OnRydWUsU1ZHRmlsdGVyRWxlbWVudDp0cnVlLFNW
-R0ZvcmVpZ25PYmplY3RFbGVtZW50OnRydWUsU1ZHR0VsZW1lbnQ6dHJ1ZSxTVkdHZW9tZXRyeUVsZW1l
-bnQ6dHJ1ZSxTVkdHcmFwaGljc0VsZW1lbnQ6dHJ1ZSxTVkdJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5l
-RWxlbWVudDp0cnVlLFNWR0xpbmVhckdyYWRpZW50RWxlbWVudDp0cnVlLFNWR01hcmtlckVsZW1lbnQ6
-dHJ1ZSxTVkdNYXNrRWxlbWVudDp0cnVlLFNWR01ldGFkYXRhRWxlbWVudDp0cnVlLFNWR1BhdGhFbGVt
-ZW50OnRydWUsU1ZHUGF0dGVybkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5Z29uRWxlbWVudDp0cnVlLFNWR1Bv
-bHlsaW5lRWxlbWVudDp0cnVlLFNWR1JhZGlhbEdyYWRpZW50RWxlbWVudDp0cnVlLFNWR1JlY3RFbGVt
-ZW50OnRydWUsU1ZHU2V0RWxlbWVudDp0cnVlLFNWR1N0b3BFbGVtZW50OnRydWUsU1ZHU3R5bGVFbGVt
-ZW50OnRydWUsU1ZHU1ZHRWxlbWVudDp0cnVlLFNWR1N3aXRjaEVsZW1lbnQ6dHJ1ZSxTVkdTeW1ib2xF
-bGVtZW50OnRydWUsU1ZHVFNwYW5FbGVtZW50OnRydWUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OnRydWUs
-U1ZHVGV4dEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UGF0aEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UG9zaXRpb25p
-bmdFbGVtZW50OnRydWUsU1ZHVGl0bGVFbGVtZW50OnRydWUsU1ZHVXNlRWxlbWVudDp0cnVlLFNWR1Zp
-ZXdFbGVtZW50OnRydWUsU1ZHR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHQ29tcG9uZW50VHJhbnNmZXJG
-dW5jdGlvbkVsZW1lbnQ6dHJ1ZSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OnRydWUsU1ZHTVBhdGhFbGVt
-ZW50OnRydWUsU1ZHRWxlbWVudDpmYWxzZX0pCkguYjAuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5
-QnVmZmVyVmlldyIKSC5SRy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlZQ
-LiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguRGcuJG5hdGl2ZVN1cGVyY2xh
-c3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5XQi4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZm
-ZXJWaWV3IgpILlpHLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguUGcuJG5h
-dGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyJ9KSgpCmNvbnZlcnRBbGxUb0Zhc3RPYmpl
-Y3QodykKY29udmVydFRvRmFzdE9iamVjdCgkKTsoZnVuY3Rpb24oYSl7aWYodHlwZW9mIGRvY3VtZW50
-PT09InVuZGVmaW5lZCIpe2EobnVsbCkKcmV0dXJufWlmKHR5cGVvZiBkb2N1bWVudC5jdXJyZW50U2Ny
-aXB0IT0ndW5kZWZpbmVkJyl7YShkb2N1bWVudC5jdXJyZW50U2NyaXB0KQpyZXR1cm59dmFyIHQ9ZG9j
-dW1lbnQuc2NyaXB0cwpmdW5jdGlvbiBvbkxvYWQoYil7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDsrK3Ip
-dFtyXS5yZW1vdmVFdmVudExpc3RlbmVyKCJsb2FkIixvbkxvYWQsZmFsc2UpCmEoYi50YXJnZXQpfWZv
-cih2YXIgcz0wO3M8dC5sZW5ndGg7KytzKXRbc10uYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsb25Mb2Fk
-LGZhbHNlKX0pKGZ1bmN0aW9uKGEpe3YuY3VycmVudFNjcmlwdD1hCmlmKHR5cGVvZiBkYXJ0TWFpblJ1
-bm5lcj09PSJmdW5jdGlvbiIpZGFydE1haW5SdW5uZXIoTC5JcSxbXSkKZWxzZSBMLklxKFtdKX0pfSko
-KQovLyMgc291cmNlTWFwcGluZ1VSTD1taWdyYXRpb24uanMubWFwCg==
+IiwKICAgICJHZW9HZW9sb2NhdGlvbiI6ICJHZW9sb2NhdGlvbiIsCiAgICAiTG9jYXRpb24iOiAiIUxv
+Y2F0aW9uIiwKICAgICJXb3JrZXJNZXNzYWdlRXZlbnQiOiAiTWVzc2FnZUV2ZW50IiwKICAgICJYTUxE
+b2N1bWVudCI6ICIhRG9jdW1lbnQifTsKICBmdW5jdGlvbiBnZXRUYWdGaXJlZm94KG8pIHsKICAgIHZh
+ciB0YWcgPSBnZXRUYWcobyk7CiAgICByZXR1cm4gcXVpY2tNYXBbdGFnXSB8fCB0YWc7CiAgfQogIGhv
+b2tzLmdldFRhZyA9IGdldFRhZ0ZpcmVmb3g7Cn0KQy5pNz1mdW5jdGlvbihob29rcykgewogIHZhciB1
+c2VyQWdlbnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJBZ2Vu
+dCA6ICIiOwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiVHJpZGVudC8iKSA9PSAtMSkgcmV0dXJuIGhv
+b2tzOwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJl
+Zm9yZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwK
+ICAgICJIVE1MRERFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJIVE1MRFRFbGVtZW50IjogIkhU
+TUxFbGVtZW50IiwKICAgICJIVE1MUGhyYXNlRWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiUG9z
+aXRpb24iOiAiR2VvcG9zaXRpb24iCiAgfTsKICBmdW5jdGlvbiBnZXRUYWdJRShvKSB7CiAgICB2YXIg
+dGFnID0gZ2V0VGFnKG8pOwogICAgdmFyIG5ld1RhZyA9IHF1aWNrTWFwW3RhZ107CiAgICBpZiAobmV3
+VGFnKSByZXR1cm4gbmV3VGFnOwogICAgaWYgKHRhZyA9PSAiT2JqZWN0IikgewogICAgICBpZiAod2lu
+ZG93LkRhdGFWaWV3ICYmIChvIGluc3RhbmNlb2Ygd2luZG93LkRhdGFWaWV3KSkgcmV0dXJuICJEYXRh
+VmlldyI7CiAgICB9CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdJ
+RSh0YWcpIHsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKGNvbnN0cnVj
+dG9yID09IG51bGwpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsK
+ICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnSUU7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0gcHJv
+dG90eXBlRm9yVGFnSUU7Cn0KQy5mUT1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0KCkMu
+Q3Q9bmV3IFAuYnkoKQpDLkVxPW5ldyBQLms1KCkKQy54TT1uZXcgUC51NSgpCkMuUWs9bmV3IFAuRTMo
+KQpDLk5VPW5ldyBQLkppKCkKQy5wZD1uZXcgUC5aZCgpCkMuQTM9bmV3IFAuTXgobnVsbCkKQy5HYj1I
+LlZNKHQoWzEyNywyMDQ3LDY1NTM1LDExMTQxMTFdKSx1LnQpCkMuYWs9SC5WTSh0KFswLDAsMzI3NzYs
+MzM3OTIsMSwxMDI0MCwwLDBdKSx1LnQpCkMuY209SC5WTSh0KFsiKjo6Y2xhc3MiLCIqOjpkaXIiLCIq
+OjpkcmFnZ2FibGUiLCIqOjpoaWRkZW4iLCIqOjppZCIsIio6OmluZXJ0IiwiKjo6aXRlbXByb3AiLCIq
+OjppdGVtcmVmIiwiKjo6aXRlbXNjb3BlIiwiKjo6bGFuZyIsIio6OnNwZWxsY2hlY2siLCIqOjp0aXRs
+ZSIsIio6OnRyYW5zbGF0ZSIsIkE6OmFjY2Vzc2tleSIsIkE6OmNvb3JkcyIsIkE6OmhyZWZsYW5nIiwi
+QTo6bmFtZSIsIkE6OnNoYXBlIiwiQTo6dGFiaW5kZXgiLCJBOjp0YXJnZXQiLCJBOjp0eXBlIiwiQVJF
+QTo6YWNjZXNza2V5IiwiQVJFQTo6YWx0IiwiQVJFQTo6Y29vcmRzIiwiQVJFQTo6bm9ocmVmIiwiQVJF
+QTo6c2hhcGUiLCJBUkVBOjp0YWJpbmRleCIsIkFSRUE6OnRhcmdldCIsIkFVRElPOjpjb250cm9scyIs
+IkFVRElPOjpsb29wIiwiQVVESU86Om1lZGlhZ3JvdXAiLCJBVURJTzo6bXV0ZWQiLCJBVURJTzo6cHJl
+bG9hZCIsIkJETzo6ZGlyIiwiQk9EWTo6YWxpbmsiLCJCT0RZOjpiZ2NvbG9yIiwiQk9EWTo6bGluayIs
+IkJPRFk6OnRleHQiLCJCT0RZOjp2bGluayIsIkJSOjpjbGVhciIsIkJVVFRPTjo6YWNjZXNza2V5Iiwi
+QlVUVE9OOjpkaXNhYmxlZCIsIkJVVFRPTjo6bmFtZSIsIkJVVFRPTjo6dGFiaW5kZXgiLCJCVVRUT046
+OnR5cGUiLCJCVVRUT046OnZhbHVlIiwiQ0FOVkFTOjpoZWlnaHQiLCJDQU5WQVM6OndpZHRoIiwiQ0FQ
+VElPTjo6YWxpZ24iLCJDT0w6OmFsaWduIiwiQ09MOjpjaGFyIiwiQ09MOjpjaGFyb2ZmIiwiQ09MOjpz
+cGFuIiwiQ09MOjp2YWxpZ24iLCJDT0w6OndpZHRoIiwiQ09MR1JPVVA6OmFsaWduIiwiQ09MR1JPVVA6
+OmNoYXIiLCJDT0xHUk9VUDo6Y2hhcm9mZiIsIkNPTEdST1VQOjpzcGFuIiwiQ09MR1JPVVA6OnZhbGln
+biIsIkNPTEdST1VQOjp3aWR0aCIsIkNPTU1BTkQ6OmNoZWNrZWQiLCJDT01NQU5EOjpjb21tYW5kIiwi
+Q09NTUFORDo6ZGlzYWJsZWQiLCJDT01NQU5EOjpsYWJlbCIsIkNPTU1BTkQ6OnJhZGlvZ3JvdXAiLCJD
+T01NQU5EOjp0eXBlIiwiREFUQTo6dmFsdWUiLCJERUw6OmRhdGV0aW1lIiwiREVUQUlMUzo6b3BlbiIs
+IkRJUjo6Y29tcGFjdCIsIkRJVjo6YWxpZ24iLCJETDo6Y29tcGFjdCIsIkZJRUxEU0VUOjpkaXNhYmxl
+ZCIsIkZPTlQ6OmNvbG9yIiwiRk9OVDo6ZmFjZSIsIkZPTlQ6OnNpemUiLCJGT1JNOjphY2NlcHQiLCJG
+T1JNOjphdXRvY29tcGxldGUiLCJGT1JNOjplbmN0eXBlIiwiRk9STTo6bWV0aG9kIiwiRk9STTo6bmFt
+ZSIsIkZPUk06Om5vdmFsaWRhdGUiLCJGT1JNOjp0YXJnZXQiLCJGUkFNRTo6bmFtZSIsIkgxOjphbGln
+biIsIkgyOjphbGlnbiIsIkgzOjphbGlnbiIsIkg0OjphbGlnbiIsIkg1OjphbGlnbiIsIkg2OjphbGln
+biIsIkhSOjphbGlnbiIsIkhSOjpub3NoYWRlIiwiSFI6OnNpemUiLCJIUjo6d2lkdGgiLCJIVE1MOjp2
+ZXJzaW9uIiwiSUZSQU1FOjphbGlnbiIsIklGUkFNRTo6ZnJhbWVib3JkZXIiLCJJRlJBTUU6OmhlaWdo
+dCIsIklGUkFNRTo6bWFyZ2luaGVpZ2h0IiwiSUZSQU1FOjptYXJnaW53aWR0aCIsIklGUkFNRTo6d2lk
+dGgiLCJJTUc6OmFsaWduIiwiSU1HOjphbHQiLCJJTUc6OmJvcmRlciIsIklNRzo6aGVpZ2h0IiwiSU1H
+Ojpoc3BhY2UiLCJJTUc6OmlzbWFwIiwiSU1HOjpuYW1lIiwiSU1HOjp1c2VtYXAiLCJJTUc6OnZzcGFj
+ZSIsIklNRzo6d2lkdGgiLCJJTlBVVDo6YWNjZXB0IiwiSU5QVVQ6OmFjY2Vzc2tleSIsIklOUFVUOjph
+bGlnbiIsIklOUFVUOjphbHQiLCJJTlBVVDo6YXV0b2NvbXBsZXRlIiwiSU5QVVQ6OmF1dG9mb2N1cyIs
+IklOUFVUOjpjaGVja2VkIiwiSU5QVVQ6OmRpc2FibGVkIiwiSU5QVVQ6OmlucHV0bW9kZSIsIklOUFVU
+Ojppc21hcCIsIklOUFVUOjpsaXN0IiwiSU5QVVQ6Om1heCIsIklOUFVUOjptYXhsZW5ndGgiLCJJTlBV
+VDo6bWluIiwiSU5QVVQ6Om11bHRpcGxlIiwiSU5QVVQ6Om5hbWUiLCJJTlBVVDo6cGxhY2Vob2xkZXIi
+LCJJTlBVVDo6cmVhZG9ubHkiLCJJTlBVVDo6cmVxdWlyZWQiLCJJTlBVVDo6c2l6ZSIsIklOUFVUOjpz
+dGVwIiwiSU5QVVQ6OnRhYmluZGV4IiwiSU5QVVQ6OnR5cGUiLCJJTlBVVDo6dXNlbWFwIiwiSU5QVVQ6
+OnZhbHVlIiwiSU5TOjpkYXRldGltZSIsIktFWUdFTjo6ZGlzYWJsZWQiLCJLRVlHRU46OmtleXR5cGUi
+LCJLRVlHRU46Om5hbWUiLCJMQUJFTDo6YWNjZXNza2V5IiwiTEFCRUw6OmZvciIsIkxFR0VORDo6YWNj
+ZXNza2V5IiwiTEVHRU5EOjphbGlnbiIsIkxJOjp0eXBlIiwiTEk6OnZhbHVlIiwiTElOSzo6c2l6ZXMi
+LCJNQVA6Om5hbWUiLCJNRU5VOjpjb21wYWN0IiwiTUVOVTo6bGFiZWwiLCJNRU5VOjp0eXBlIiwiTUVU
+RVI6OmhpZ2giLCJNRVRFUjo6bG93IiwiTUVURVI6Om1heCIsIk1FVEVSOjptaW4iLCJNRVRFUjo6dmFs
+dWUiLCJPQkpFQ1Q6OnR5cGVtdXN0bWF0Y2giLCJPTDo6Y29tcGFjdCIsIk9MOjpyZXZlcnNlZCIsIk9M
+OjpzdGFydCIsIk9MOjp0eXBlIiwiT1BUR1JPVVA6OmRpc2FibGVkIiwiT1BUR1JPVVA6OmxhYmVsIiwi
+T1BUSU9OOjpkaXNhYmxlZCIsIk9QVElPTjo6bGFiZWwiLCJPUFRJT046OnNlbGVjdGVkIiwiT1BUSU9O
+Ojp2YWx1ZSIsIk9VVFBVVDo6Zm9yIiwiT1VUUFVUOjpuYW1lIiwiUDo6YWxpZ24iLCJQUkU6OndpZHRo
+IiwiUFJPR1JFU1M6Om1heCIsIlBST0dSRVNTOjptaW4iLCJQUk9HUkVTUzo6dmFsdWUiLCJTRUxFQ1Q6
+OmF1dG9jb21wbGV0ZSIsIlNFTEVDVDo6ZGlzYWJsZWQiLCJTRUxFQ1Q6Om11bHRpcGxlIiwiU0VMRUNU
+OjpuYW1lIiwiU0VMRUNUOjpyZXF1aXJlZCIsIlNFTEVDVDo6c2l6ZSIsIlNFTEVDVDo6dGFiaW5kZXgi
+LCJTT1VSQ0U6OnR5cGUiLCJUQUJMRTo6YWxpZ24iLCJUQUJMRTo6Ymdjb2xvciIsIlRBQkxFOjpib3Jk
+ZXIiLCJUQUJMRTo6Y2VsbHBhZGRpbmciLCJUQUJMRTo6Y2VsbHNwYWNpbmciLCJUQUJMRTo6ZnJhbWUi
+LCJUQUJMRTo6cnVsZXMiLCJUQUJMRTo6c3VtbWFyeSIsIlRBQkxFOjp3aWR0aCIsIlRCT0RZOjphbGln
+biIsIlRCT0RZOjpjaGFyIiwiVEJPRFk6OmNoYXJvZmYiLCJUQk9EWTo6dmFsaWduIiwiVEQ6OmFiYnIi
+LCJURDo6YWxpZ24iLCJURDo6YXhpcyIsIlREOjpiZ2NvbG9yIiwiVEQ6OmNoYXIiLCJURDo6Y2hhcm9m
+ZiIsIlREOjpjb2xzcGFuIiwiVEQ6OmhlYWRlcnMiLCJURDo6aGVpZ2h0IiwiVEQ6Om5vd3JhcCIsIlRE
+Ojpyb3dzcGFuIiwiVEQ6OnNjb3BlIiwiVEQ6OnZhbGlnbiIsIlREOjp3aWR0aCIsIlRFWFRBUkVBOjph
+Y2Nlc3NrZXkiLCJURVhUQVJFQTo6YXV0b2NvbXBsZXRlIiwiVEVYVEFSRUE6OmNvbHMiLCJURVhUQVJF
+QTo6ZGlzYWJsZWQiLCJURVhUQVJFQTo6aW5wdXRtb2RlIiwiVEVYVEFSRUE6Om5hbWUiLCJURVhUQVJF
+QTo6cGxhY2Vob2xkZXIiLCJURVhUQVJFQTo6cmVhZG9ubHkiLCJURVhUQVJFQTo6cmVxdWlyZWQiLCJU
+RVhUQVJFQTo6cm93cyIsIlRFWFRBUkVBOjp0YWJpbmRleCIsIlRFWFRBUkVBOjp3cmFwIiwiVEZPT1Q6
+OmFsaWduIiwiVEZPT1Q6OmNoYXIiLCJURk9PVDo6Y2hhcm9mZiIsIlRGT09UOjp2YWxpZ24iLCJUSDo6
+YWJiciIsIlRIOjphbGlnbiIsIlRIOjpheGlzIiwiVEg6OmJnY29sb3IiLCJUSDo6Y2hhciIsIlRIOjpj
+aGFyb2ZmIiwiVEg6OmNvbHNwYW4iLCJUSDo6aGVhZGVycyIsIlRIOjpoZWlnaHQiLCJUSDo6bm93cmFw
+IiwiVEg6OnJvd3NwYW4iLCJUSDo6c2NvcGUiLCJUSDo6dmFsaWduIiwiVEg6OndpZHRoIiwiVEhFQUQ6
+OmFsaWduIiwiVEhFQUQ6OmNoYXIiLCJUSEVBRDo6Y2hhcm9mZiIsIlRIRUFEOjp2YWxpZ24iLCJUUjo6
+YWxpZ24iLCJUUjo6Ymdjb2xvciIsIlRSOjpjaGFyIiwiVFI6OmNoYXJvZmYiLCJUUjo6dmFsaWduIiwi
+VFJBQ0s6OmRlZmF1bHQiLCJUUkFDSzo6a2luZCIsIlRSQUNLOjpsYWJlbCIsIlRSQUNLOjpzcmNsYW5n
+IiwiVUw6OmNvbXBhY3QiLCJVTDo6dHlwZSIsIlZJREVPOjpjb250cm9scyIsIlZJREVPOjpoZWlnaHQi
+LCJWSURFTzo6bG9vcCIsIlZJREVPOjptZWRpYWdyb3VwIiwiVklERU86Om11dGVkIiwiVklERU86OnBy
+ZWxvYWQiLCJWSURFTzo6d2lkdGgiXSksdS5zKQpDLlZDPUguVk0odChbMCwwLDY1NDkwLDQ1MDU1LDY1
+NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLm1LPUguVk0odChbMCwwLDI2NjI0LDEwMjMsNjU1
+MzQsMjA0Nyw2NTUzNCwyMDQ3XSksdS50KQpDLlNxPUguVk0odChbIkhFQUQiLCJBUkVBIiwiQkFTRSIs
+IkJBU0VGT05UIiwiQlIiLCJDT0wiLCJDT0xHUk9VUCIsIkVNQkVEIiwiRlJBTUUiLCJGUkFNRVNFVCIs
+IkhSIiwiSU1BR0UiLCJJTUciLCJJTlBVVCIsIklTSU5ERVgiLCJMSU5LIiwiTUVUQSIsIlBBUkFNIiwi
+U09VUkNFIiwiU1RZTEUiLCJUSVRMRSIsIldCUiJdKSx1LnMpCkMueEQ9SC5WTSh0KFtdKSx1LnMpCkMu
+ZG49SC5WTSh0KFtdKSx1LnYpCkMudG89SC5WTSh0KFswLDAsMzI3MjIsMTIyODcsNjU1MzQsMzQ4MTUs
+NjU1MzQsMTg0MzFdKSx1LnQpCkMuRjM9SC5WTSh0KFswLDAsMjQ1NzYsMTAyMyw2NTUzNCwzNDgxNSw2
+NTUzNCwxODQzMV0pLHUudCkKQy5lYT1ILlZNKHQoWzAsMCwzMjc1NCwxMTI2Myw2NTUzNCwzNDgxNSw2
+NTUzNCwxODQzMV0pLHUudCkKQy5aSj1ILlZNKHQoWzAsMCwzMjcyMiwxMjI4Nyw2NTUzNSwzNDgxNSw2
+NTUzNCwxODQzMV0pLHUudCkKQy5XZD1ILlZNKHQoWzAsMCw2NTQ5MCwxMjI4Nyw2NTUzNSwzNDgxNSw2
+NTUzNCwxODQzMV0pLHUudCkKQy5ReD1ILlZNKHQoWyJiaW5kIiwiaWYiLCJyZWYiLCJyZXBlYXQiLCJz
+eW50YXgiXSksdS5zKQpDLkJJPUguVk0odChbIkE6OmhyZWYiLCJBUkVBOjpocmVmIiwiQkxPQ0tRVU9U
+RTo6Y2l0ZSIsIkJPRFk6OmJhY2tncm91bmQiLCJDT01NQU5EOjppY29uIiwiREVMOjpjaXRlIiwiRk9S
+TTo6YWN0aW9uIiwiSU1HOjpzcmMiLCJJTlBVVDo6c3JjIiwiSU5TOjpjaXRlIiwiUTo6Y2l0ZSIsIlZJ
+REVPOjpwb3N0ZXIiXSksdS5zKQpDLkNNPW5ldyBILkxQKDAse30sQy54RCxILkRQKCJMUDxxVSx6TTxq
+OD4+IikpCkMuV089bmV3IEguTFAoMCx7fSxDLnhELEguRFAoIkxQPHFVLHFVPiIpKQpDLmhVPUguVk0o
+dChbXSksSC5EUCgiamQ8R0Q+IikpCkMuRHg9bmV3IEguTFAoMCx7fSxDLmhVLEguRFAoIkxQPEdELEA+
+IikpCkMuWTI9bmV3IEwuV0EoIk5hdmlnYXRpb25UcmVlTm9kZVR5cGUuZGlyZWN0b3J5IikKQy5yZj1u
+ZXcgTC5XQSgiTmF2aWdhdGlvblRyZWVOb2RlVHlwZS5maWxlIikKQy5UZT1uZXcgSC53digiY2FsbCIp
+CkMud1E9bmV3IFAuRnkobnVsbCwyKX0pKCk7KGZ1bmN0aW9uIHN0YXRpY0ZpZWxkcygpeyQueWo9MAok
+Lm1KPW51bGwKJC5QND1udWxsCiQueT1udWxsCiQudT1udWxsCiQueDc9bnVsbAokLmo9bnVsbAokLnY9
+bnVsbAokLks9bnVsbAokLlM2PW51bGwKJC5rOD1udWxsCiQubWc9bnVsbAokLlVEPSExCiQuWDM9Qy5O
+VQokLnhnPVtdCiQueG89bnVsbAokLkJPPW51bGwKJC5sdD1udWxsCiQuRVU9bnVsbAokLm9yPVAuRmwo
+dS5OLHUuWikKJC5JNj1udWxsCiQuRmY9bnVsbH0pKCk7KGZ1bmN0aW9uIGxhenlJbml0aWFsaXplcnMo
+KXt2YXIgdD1odW5rSGVscGVycy5sYXp5CnQoJCwiZmEiLCJ3USIsZnVuY3Rpb24oKXtyZXR1cm4gSC5Z
+ZygiXyRkYXJ0X2RhcnRDbG9zdXJlIil9KQp0KCQsIlkyIiwiQSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5Z
+ZygiXyRkYXJ0X2pzIil9KQp0KCQsIlUyIiwiU24iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5TNyh7
+CnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnQoJCwieHEiLCJscSIs
+ZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHskbWV0aG9kJDpudWxsLAp0b1N0cmluZzpmdW5jdGlv
+bigpe3JldHVybiIkcmVjZWl2ZXIkIn19KSl9KQp0KCQsIlIxIiwiTjkiLGZ1bmN0aW9uKCl7cmV0dXJu
+IEguY00oSC5TNyhudWxsKSl9KQp0KCQsImZOIiwiaUkiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVu
+Y3Rpb24oKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5e251bGwuJG1ldGhvZCQo
+JGFyZ3VtZW50c0V4cHIkKX1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0oKSl9KQp0KCQsInFpIiwi
+VU4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5TNyh2b2lkIDApKX0pCnQoJCwicloiLCJaaCIsZnVu
+Y3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVu
+dHMkJwp0cnl7KHZvaWQgMCkuJG1ldGhvZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChzKXtyZXR1cm4g
+cy5tZXNzYWdlfX0oKSl9KQp0KCQsImtxIiwick4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5Naihu
+dWxsKSl9KQp0KCQsInR0IiwiYzMiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rpb24oKXt0cnl7
+bnVsbC4kbWV0aG9kJH1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0oKSl9KQp0KCQsImR0IiwiSEsi
+LGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5Naih2b2lkIDApKX0pCnQoJCwiQTciLCJyMSIsZnVuY3Rp
+b24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3RyeXsodm9pZCAwKS4kbWV0aG9kJH1jYXRjaChzKXty
+ZXR1cm4gcy5tZXNzYWdlfX0oKSl9KQp0KCQsIldjIiwidXQiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuT2oo
+KX0pCnQoJCwia2giLCJyZiIsZnVuY3Rpb24oKXtyZXR1cm4gUC5XSSgpfSkKdCgkLCJidCIsIlY3Iixm
+dW5jdGlvbigpe3JldHVybiBILkRRKEguWEYoSC5WTShbLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIs
+LTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIs
+LTIsLTIsLTIsLTIsLTIsLTIsLTIsLTIsLTEsLTIsLTIsLTIsLTIsLTIsNjIsLTIsNjIsLTIsNjMsNTIs
+NTMsNTQsNTUsNTYsNTcsNTgsNTksNjAsNjEsLTIsLTIsLTIsLTEsLTIsLTIsLTIsMCwxLDIsMyw0LDUs
+Niw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwxOSwyMCwyMSwyMiwyMywyNCwyNSwtMiwt
+MiwtMiwtMiw2MywtMiwyNiwyNywyOCwyOSwzMCwzMSwzMiwzMywzNCwzNSwzNiwzNywzOCwzOSw0MCw0
+MSw0Miw0Myw0NCw0NSw0Niw0Nyw0OCw0OSw1MCw1MSwtMiwtMiwtMiwtMiwtMl0sdS50KSkpfSkKdCgk
+LCJNNSIsIk94IixmdW5jdGlvbigpe3JldHVybiB0eXBlb2YgcHJvY2VzcyE9InVuZGVmaW5lZCImJk9i
+amVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChwcm9jZXNzKT09IltvYmplY3QgcHJvY2Vzc10iJiZw
+cm9jZXNzLnBsYXRmb3JtPT0id2luMzIifSkKdCgkLCJtZiIsIno0IixmdW5jdGlvbigpe3JldHVybiBQ
+Lm51KCJeW1xcLVxcLjAtOUEtWl9hLXp+XSokIil9KQp0KCQsIkF2IiwicDYiLGZ1bmN0aW9uKCl7cmV0
+dXJuIG5ldyBFcnJvcigpLnN0YWNrIT12b2lkIDB9KQp0KCQsIkpHIiwidloiLGZ1bmN0aW9uKCl7cmV0
+dXJuIFAuS04oKX0pCnQoJCwiU0MiLCJBTiIsZnVuY3Rpb24oKXtyZXR1cm4gUC50TShbIkEiLCJBQkJS
+IiwiQUNST05ZTSIsIkFERFJFU1MiLCJBUkVBIiwiQVJUSUNMRSIsIkFTSURFIiwiQVVESU8iLCJCIiwi
+QkRJIiwiQkRPIiwiQklHIiwiQkxPQ0tRVU9URSIsIkJSIiwiQlVUVE9OIiwiQ0FOVkFTIiwiQ0FQVElP
+TiIsIkNFTlRFUiIsIkNJVEUiLCJDT0RFIiwiQ09MIiwiQ09MR1JPVVAiLCJDT01NQU5EIiwiREFUQSIs
+IkRBVEFMSVNUIiwiREQiLCJERUwiLCJERVRBSUxTIiwiREZOIiwiRElSIiwiRElWIiwiREwiLCJEVCIs
+IkVNIiwiRklFTERTRVQiLCJGSUdDQVBUSU9OIiwiRklHVVJFIiwiRk9OVCIsIkZPT1RFUiIsIkZPUk0i
+LCJIMSIsIkgyIiwiSDMiLCJINCIsIkg1IiwiSDYiLCJIRUFERVIiLCJIR1JPVVAiLCJIUiIsIkkiLCJJ
+RlJBTUUiLCJJTUciLCJJTlBVVCIsIklOUyIsIktCRCIsIkxBQkVMIiwiTEVHRU5EIiwiTEkiLCJNQVAi
+LCJNQVJLIiwiTUVOVSIsIk1FVEVSIiwiTkFWIiwiTk9CUiIsIk9MIiwiT1BUR1JPVVAiLCJPUFRJT04i
+LCJPVVRQVVQiLCJQIiwiUFJFIiwiUFJPR1JFU1MiLCJRIiwiUyIsIlNBTVAiLCJTRUNUSU9OIiwiU0VM
+RUNUIiwiU01BTEwiLCJTT1VSQ0UiLCJTUEFOIiwiU1RSSUtFIiwiU1RST05HIiwiU1VCIiwiU1VNTUFS
+WSIsIlNVUCIsIlRBQkxFIiwiVEJPRFkiLCJURCIsIlRFWFRBUkVBIiwiVEZPT1QiLCJUSCIsIlRIRUFE
+IiwiVElNRSIsIlRSIiwiVFJBQ0siLCJUVCIsIlUiLCJVTCIsIlZBUiIsIlZJREVPIiwiV0JSIl0sdS5O
+KX0pCnQoJCwiVlEiLCJFZSIsZnVuY3Rpb24oKXtyZXR1cm4gUC5udSgiXlxcUyskIil9KQp0KCQsIndP
+Iiwib3ciLGZ1bmN0aW9uKCl7cmV0dXJuIHUudy5hKFAuTkQoc2VsZikpfSkKdCgkLCJrdCIsIkNyIixm
+dW5jdGlvbigpe3JldHVybiBILllnKCJfJGRhcnRfZGFydE9iamVjdCIpfSkKdCgkLCJMRiIsImtJIixm
+dW5jdGlvbigpe3JldHVybiBmdW5jdGlvbiBEYXJ0T2JqZWN0KGEpe3RoaXMubz1hfX0pCnQoJCwicXQi
+LCJ6QiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFQubVEoKX0pCnQoJCwiT2wiLCJVRSIsZnVuY3Rpb24o
+KXtyZXR1cm4gUC5oSyhDLm9sLmdtVyhXLngzKCkpLmhyZWYpLmdoWSgpLnEoMCwiYXV0aFRva2VuIil9
+KQp0KCQsImhUIiwieVAiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRp
+dC1saXN0IC5wYW5lbC1jb250ZW50Iil9KQp0KCQsIlc2IiwiaEwiLGZ1bmN0aW9uKCl7cmV0dXJuIFcu
+WnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIpfSkKdCgkLCJUUiIs
+IkRXIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiZm9vdGVyIil9KQp0KCQs
+IkVZIiwiZmkiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJoZWFkZXIiKX0p
+CnQoJCwiYWQiLCJEOSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiN1bml0
+LW5hbWUiKX0pCnQoJCwibXEiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnQoJCwi
+ZW8iLCJuVSIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IE0ubEkoJC5IaygpKX0pCnQoJCwiZTkiLCJiRCIs
+ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEUuT0YoUC5udSgiLyIpLFAubnUoIlteL10kIiksUC5udSgiXi8i
+KSl9KQp0KCQsIllLIiwiS2siLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLklWKFAubnUoIlsvXFxcXF0i
+KSxQLm51KCJbXi9cXFxcXSQiKSxQLm51KCJeKFxcXFxcXFxcW15cXFxcXStcXFxcW15cXFxcL10rfFth
+LXpBLVpdOlsvXFxcXF0pIiksUC5udSgiXlsvXFxcXF0oPyFbL1xcXFxdKSIpKX0pCnQoJCwiYUMiLCJF
+YiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEYucnUoUC5udSgiLyIpLFAubnUoIiheW2EtekEtWl1bLSsu
+YS16QS1aXFxkXSo6Ly98W14vXSkkIiksUC5udSgiW2EtekEtWl1bLSsuYS16QS1aXFxkXSo6Ly9bXi9d
+KiIpLFAubnUoIl4vIikpfSkKdCgkLCJscyIsIkhrIixmdW5jdGlvbigpe3JldHVybiBPLlJoKCl9KX0p
+KCk7KGZ1bmN0aW9uIG5hdGl2ZVN1cHBvcnQoKXshZnVuY3Rpb24oKXt2YXIgdD1mdW5jdGlvbihhKXt2
+YXIgbj17fQpuW2FdPTEKcmV0dXJuIE9iamVjdC5rZXlzKGh1bmtIZWxwZXJzLmNvbnZlcnRUb0Zhc3RP
+YmplY3QobikpWzBdfQp2LmdldElzb2xhdGVUYWc9ZnVuY3Rpb24oYSl7cmV0dXJuIHQoIl9fX2RhcnRf
+IithK3YuaXNvbGF0ZVRhZyl9CnZhciBzPSJfX19kYXJ0X2lzb2xhdGVfdGFnc18iCnZhciByPU9iamVj
+dFtzXXx8KE9iamVjdFtzXT1PYmplY3QuY3JlYXRlKG51bGwpKQp2YXIgcT0iX1p4WXhYIgpmb3IodmFy
+IHA9MDs7cCsrKXt2YXIgbz10KHErIl8iK3ArIl8iKQppZighKG8gaW4gcikpe3Jbb109MQp2Lmlzb2xh
+dGVUYWc9bwpicmVha319di5kaXNwYXRjaFByb3BlcnR5TmFtZT12LmdldElzb2xhdGVUYWcoImRpc3Bh
+dGNoX3JlY29yZCIpfSgpCmh1bmtIZWxwZXJzLnNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlUYWcoe0Fu
+aW1hdGlvbkVmZmVjdFJlYWRPbmx5OkoudkIsQW5pbWF0aW9uRWZmZWN0VGltaW5nOkoudkIsQW5pbWF0
+aW9uRWZmZWN0VGltaW5nUmVhZE9ubHk6Si52QixBbmltYXRpb25UaW1lbGluZTpKLnZCLEFuaW1hdGlv
+bldvcmtsZXRHbG9iYWxTY29wZTpKLnZCLEF1dGhlbnRpY2F0b3JBc3NlcnRpb25SZXNwb25zZTpKLnZC
+LEF1dGhlbnRpY2F0b3JBdHRlc3RhdGlvblJlc3BvbnNlOkoudkIsQXV0aGVudGljYXRvclJlc3BvbnNl
+OkoudkIsQmFja2dyb3VuZEZldGNoRmV0Y2g6Si52QixCYWNrZ3JvdW5kRmV0Y2hNYW5hZ2VyOkoudkIs
+QmFja2dyb3VuZEZldGNoU2V0dGxlZEZldGNoOkoudkIsQmFyUHJvcDpKLnZCLEJhcmNvZGVEZXRlY3Rv
+cjpKLnZCLEJvZHk6Si52QixCdWRnZXRTdGF0ZTpKLnZCLENhY2hlU3RvcmFnZTpKLnZCLENhbnZhc0dy
+YWRpZW50OkoudkIsQ2FudmFzUGF0dGVybjpKLnZCLENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDpKLnZC
+LENsaWVudDpKLnZCLENsaWVudHM6Si52QixDb29raWVTdG9yZTpKLnZCLENvb3JkaW5hdGVzOkoudkIs
+Q3JlZGVudGlhbDpKLnZCLENyZWRlbnRpYWxVc2VyRGF0YTpKLnZCLENyZWRlbnRpYWxzQ29udGFpbmVy
+OkoudkIsQ3J5cHRvOkoudkIsQ3J5cHRvS2V5OkoudkIsQ1NTOkoudkIsQ1NTVmFyaWFibGVSZWZlcmVu
+Y2VWYWx1ZTpKLnZCLEN1c3RvbUVsZW1lbnRSZWdpc3RyeTpKLnZCLERhdGFUcmFuc2ZlcjpKLnZCLERh
+dGFUcmFuc2Zlckl0ZW06Si52QixEZXByZWNhdGVkU3RvcmFnZUluZm86Si52QixEZXByZWNhdGVkU3Rv
+cmFnZVF1b3RhOkoudkIsRGVwcmVjYXRpb25SZXBvcnQ6Si52QixEZXRlY3RlZEJhcmNvZGU6Si52QixE
+ZXRlY3RlZEZhY2U6Si52QixEZXRlY3RlZFRleHQ6Si52QixEZXZpY2VBY2NlbGVyYXRpb246Si52QixE
+ZXZpY2VSb3RhdGlvblJhdGU6Si52QixEaXJlY3RvcnlFbnRyeTpKLnZCLERpcmVjdG9yeVJlYWRlcjpK
+LnZCLERvY3VtZW50T3JTaGFkb3dSb290OkoudkIsRG9jdW1lbnRUaW1lbGluZTpKLnZCLERPTUVycm9y
+OkoudkIsRE9NSW1wbGVtZW50YXRpb246Si52QixJdGVyYXRvcjpKLnZCLERPTU1hdHJpeDpKLnZCLERP
+TU1hdHJpeFJlYWRPbmx5OkoudkIsRE9NUGFyc2VyOkoudkIsRE9NUG9pbnQ6Si52QixET01Qb2ludFJl
+YWRPbmx5OkoudkIsRE9NUXVhZDpKLnZCLERPTVN0cmluZ01hcDpKLnZCLEVudHJ5OkoudkIsRXh0ZXJu
+YWw6Si52QixGYWNlRGV0ZWN0b3I6Si52QixGZWRlcmF0ZWRDcmVkZW50aWFsOkoudkIsRmlsZUVudHJ5
+OkoudkIsRE9NRmlsZVN5c3RlbTpKLnZCLEZvbnRGYWNlOkoudkIsRm9udEZhY2VTb3VyY2U6Si52QixG
+b3JtRGF0YTpKLnZCLEdhbWVwYWRQb3NlOkoudkIsR2VvbG9jYXRpb246Si52QixQb3NpdGlvbjpKLnZC
+LEhlYWRlcnM6Si52QixIVE1MSHlwZXJsaW5rRWxlbWVudFV0aWxzOkoudkIsSWRsZURlYWRsaW5lOkou
+dkIsSW1hZ2VCaXRtYXA6Si52QixJbWFnZUJpdG1hcFJlbmRlcmluZ0NvbnRleHQ6Si52QixJbWFnZUNh
+cHR1cmU6Si52QixJbnB1dERldmljZUNhcGFiaWxpdGllczpKLnZCLEludGVyc2VjdGlvbk9ic2VydmVy
+OkoudkIsSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeTpKLnZCLEludGVydmVudGlvblJlcG9ydDpKLnZC
+LEtleWZyYW1lRWZmZWN0OkoudkIsS2V5ZnJhbWVFZmZlY3RSZWFkT25seTpKLnZCLE1lZGlhQ2FwYWJp
+bGl0aWVzOkoudkIsTWVkaWFDYXBhYmlsaXRpZXNJbmZvOkoudkIsTWVkaWFEZXZpY2VJbmZvOkoudkIs
+TWVkaWFFcnJvcjpKLnZCLE1lZGlhS2V5U3RhdHVzTWFwOkoudkIsTWVkaWFLZXlTeXN0ZW1BY2Nlc3M6
+Si52QixNZWRpYUtleXM6Si52QixNZWRpYUtleXNQb2xpY3k6Si52QixNZWRpYU1ldGFkYXRhOkoudkIs
+TWVkaWFTZXNzaW9uOkoudkIsTWVkaWFTZXR0aW5nc1JhbmdlOkoudkIsTWVtb3J5SW5mbzpKLnZCLE1l
+c3NhZ2VDaGFubmVsOkoudkIsTWV0YWRhdGE6Si52QixNdXRhdGlvbk9ic2VydmVyOkoudkIsV2ViS2l0
+TXV0YXRpb25PYnNlcnZlcjpKLnZCLE11dGF0aW9uUmVjb3JkOkoudkIsTmF2aWdhdGlvblByZWxvYWRN
+YW5hZ2VyOkoudkIsTmF2aWdhdG9yOkoudkIsTmF2aWdhdG9yQXV0b21hdGlvbkluZm9ybWF0aW9uOkou
+dkIsTmF2aWdhdG9yQ29uY3VycmVudEhhcmR3YXJlOkoudkIsTmF2aWdhdG9yQ29va2llczpKLnZCLE5h
+dmlnYXRvclVzZXJNZWRpYUVycm9yOkoudkIsTm9kZUZpbHRlcjpKLnZCLE5vZGVJdGVyYXRvcjpKLnZC
+LE5vbkRvY3VtZW50VHlwZUNoaWxkTm9kZTpKLnZCLE5vbkVsZW1lbnRQYXJlbnROb2RlOkoudkIsTm9u
+Y2VkRWxlbWVudDpKLnZCLE9mZnNjcmVlbkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDpKLnZCLE92ZXJj
+b25zdHJhaW5lZEVycm9yOkoudkIsUGFpbnRSZW5kZXJpbmdDb250ZXh0MkQ6Si52QixQYWludFNpemU6
+Si52QixQYWludFdvcmtsZXRHbG9iYWxTY29wZTpKLnZCLFBhc3N3b3JkQ3JlZGVudGlhbDpKLnZCLFBh
+dGgyRDpKLnZCLFBheW1lbnRBZGRyZXNzOkoudkIsUGF5bWVudEluc3RydW1lbnRzOkoudkIsUGF5bWVu
+dE1hbmFnZXI6Si52QixQYXltZW50UmVzcG9uc2U6Si52QixQZXJmb3JtYW5jZUVudHJ5OkoudkIsUGVy
+Zm9ybWFuY2VMb25nVGFza1RpbWluZzpKLnZCLFBlcmZvcm1hbmNlTWFyazpKLnZCLFBlcmZvcm1hbmNl
+TWVhc3VyZTpKLnZCLFBlcmZvcm1hbmNlTmF2aWdhdGlvbjpKLnZCLFBlcmZvcm1hbmNlTmF2aWdhdGlv
+blRpbWluZzpKLnZCLFBlcmZvcm1hbmNlT2JzZXJ2ZXI6Si52QixQZXJmb3JtYW5jZU9ic2VydmVyRW50
+cnlMaXN0OkoudkIsUGVyZm9ybWFuY2VQYWludFRpbWluZzpKLnZCLFBlcmZvcm1hbmNlUmVzb3VyY2VU
+aW1pbmc6Si52QixQZXJmb3JtYW5jZVNlcnZlclRpbWluZzpKLnZCLFBlcmZvcm1hbmNlVGltaW5nOkou
+dkIsUGVybWlzc2lvbnM6Si52QixQaG90b0NhcGFiaWxpdGllczpKLnZCLFBvc2l0aW9uRXJyb3I6Si52
+QixQcmVzZW50YXRpb246Si52QixQcmVzZW50YXRpb25SZWNlaXZlcjpKLnZCLFB1YmxpY0tleUNyZWRl
+bnRpYWw6Si52QixQdXNoTWFuYWdlcjpKLnZCLFB1c2hNZXNzYWdlRGF0YTpKLnZCLFB1c2hTdWJzY3Jp
+cHRpb246Si52QixQdXNoU3Vic2NyaXB0aW9uT3B0aW9uczpKLnZCLFJhbmdlOkoudkIsUmVsYXRlZEFw
+cGxpY2F0aW9uOkoudkIsUmVwb3J0Qm9keTpKLnZCLFJlcG9ydGluZ09ic2VydmVyOkoudkIsUmVzaXpl
+T2JzZXJ2ZXI6Si52QixSZXNpemVPYnNlcnZlckVudHJ5OkoudkIsUlRDQ2VydGlmaWNhdGU6Si52QixS
+VENJY2VDYW5kaWRhdGU6Si52Qixtb3pSVENJY2VDYW5kaWRhdGU6Si52QixSVENMZWdhY3lTdGF0c1Jl
+cG9ydDpKLnZCLFJUQ1J0cENvbnRyaWJ1dGluZ1NvdXJjZTpKLnZCLFJUQ1J0cFJlY2VpdmVyOkoudkIs
+UlRDUnRwU2VuZGVyOkoudkIsUlRDU2Vzc2lvbkRlc2NyaXB0aW9uOkoudkIsbW96UlRDU2Vzc2lvbkRl
+c2NyaXB0aW9uOkoudkIsUlRDU3RhdHNSZXNwb25zZTpKLnZCLFNjcmVlbjpKLnZCLFNjcm9sbFN0YXRl
+OkoudkIsU2Nyb2xsVGltZWxpbmU6Si52QixTZWxlY3Rpb246Si52QixTaGFyZWRBcnJheUJ1ZmZlcjpK
+LnZCLFNwZWVjaFJlY29nbml0aW9uQWx0ZXJuYXRpdmU6Si52QixTcGVlY2hTeW50aGVzaXNWb2ljZTpK
+LnZCLFN0YXRpY1JhbmdlOkoudkIsU3RvcmFnZU1hbmFnZXI6Si52QixTdHlsZU1lZGlhOkoudkIsU3R5
+bGVQcm9wZXJ0eU1hcDpKLnZCLFN0eWxlUHJvcGVydHlNYXBSZWFkb25seTpKLnZCLFN5bmNNYW5hZ2Vy
+OkoudkIsVGFza0F0dHJpYnV0aW9uVGltaW5nOkoudkIsVGV4dERldGVjdG9yOkoudkIsVGV4dE1ldHJp
+Y3M6Si52QixUcmFja0RlZmF1bHQ6Si52QixUcmVlV2Fsa2VyOkoudkIsVHJ1c3RlZEhUTUw6Si52QixU
+cnVzdGVkU2NyaXB0VVJMOkoudkIsVHJ1c3RlZFVSTDpKLnZCLFVuZGVybHlpbmdTb3VyY2VCYXNlOkou
+dkIsVVJMU2VhcmNoUGFyYW1zOkoudkIsVlJDb29yZGluYXRlU3lzdGVtOkoudkIsVlJEaXNwbGF5Q2Fw
+YWJpbGl0aWVzOkoudkIsVlJFeWVQYXJhbWV0ZXJzOkoudkIsVlJGcmFtZURhdGE6Si52QixWUkZyYW1l
+T2ZSZWZlcmVuY2U6Si52QixWUlBvc2U6Si52QixWUlN0YWdlQm91bmRzOkoudkIsVlJTdGFnZUJvdW5k
+c1BvaW50OkoudkIsVlJTdGFnZVBhcmFtZXRlcnM6Si52QixWYWxpZGl0eVN0YXRlOkoudkIsVmlkZW9Q
+bGF5YmFja1F1YWxpdHk6Si52QixWaWRlb1RyYWNrOkoudkIsVlRUUmVnaW9uOkoudkIsV2luZG93Q2xp
+ZW50OkoudkIsV29ya2xldEFuaW1hdGlvbjpKLnZCLFdvcmtsZXRHbG9iYWxTY29wZTpKLnZCLFhQYXRo
+RXZhbHVhdG9yOkoudkIsWFBhdGhFeHByZXNzaW9uOkoudkIsWFBhdGhOU1Jlc29sdmVyOkoudkIsWFBh
+dGhSZXN1bHQ6Si52QixYTUxTZXJpYWxpemVyOkoudkIsWFNMVFByb2Nlc3NvcjpKLnZCLEJsdWV0b290
+aDpKLnZCLEJsdWV0b290aENoYXJhY3RlcmlzdGljUHJvcGVydGllczpKLnZCLEJsdWV0b290aFJlbW90
+ZUdBVFRTZXJ2ZXI6Si52QixCbHVldG9vdGhSZW1vdGVHQVRUU2VydmljZTpKLnZCLEJsdWV0b290aFVV
+SUQ6Si52QixCdWRnZXRTZXJ2aWNlOkoudkIsQ2FjaGU6Si52QixET01GaWxlU3lzdGVtU3luYzpKLnZC
+LERpcmVjdG9yeUVudHJ5U3luYzpKLnZCLERpcmVjdG9yeVJlYWRlclN5bmM6Si52QixFbnRyeVN5bmM6
+Si52QixGaWxlRW50cnlTeW5jOkoudkIsRmlsZVJlYWRlclN5bmM6Si52QixGaWxlV3JpdGVyU3luYzpK
+LnZCLEhUTUxBbGxDb2xsZWN0aW9uOkoudkIsTW9qbzpKLnZCLE1vam9IYW5kbGU6Si52QixNb2pvV2F0
+Y2hlcjpKLnZCLE5GQzpKLnZCLFBhZ2VQb3B1cENvbnRyb2xsZXI6Si52QixSZXBvcnQ6Si52QixSZXF1
+ZXN0OkoudkIsUmVzcG9uc2U6Si52QixTdWJ0bGVDcnlwdG86Si52QixVU0JBbHRlcm5hdGVJbnRlcmZh
+Y2U6Si52QixVU0JDb25maWd1cmF0aW9uOkoudkIsVVNCRGV2aWNlOkoudkIsVVNCRW5kcG9pbnQ6Si52
+QixVU0JJblRyYW5zZmVyUmVzdWx0OkoudkIsVVNCSW50ZXJmYWNlOkoudkIsVVNCSXNvY2hyb25vdXNJ
+blRyYW5zZmVyUGFja2V0OkoudkIsVVNCSXNvY2hyb25vdXNJblRyYW5zZmVyUmVzdWx0OkoudkIsVVNC
+SXNvY2hyb25vdXNPdXRUcmFuc2ZlclBhY2tldDpKLnZCLFVTQklzb2Nocm9ub3VzT3V0VHJhbnNmZXJS
+ZXN1bHQ6Si52QixVU0JPdXRUcmFuc2ZlclJlc3VsdDpKLnZCLFdvcmtlckxvY2F0aW9uOkoudkIsV29y
+a2VyTmF2aWdhdG9yOkoudkIsV29ya2xldDpKLnZCLElEQkZhY3Rvcnk6Si52QixJREJJbmRleDpKLnZC
+LElEQk9iamVjdFN0b3JlOkoudkIsSURCT2JzZXJ2ZXI6Si52QixJREJPYnNlcnZlckNoYW5nZXM6Si52
+QixTVkdBbmltYXRlZEFuZ2xlOkoudkIsU1ZHQW5pbWF0ZWRCb29sZWFuOkoudkIsU1ZHQW5pbWF0ZWRF
+bnVtZXJhdGlvbjpKLnZCLFNWR0FuaW1hdGVkSW50ZWdlcjpKLnZCLFNWR0FuaW1hdGVkTGVuZ3RoOkou
+dkIsU1ZHQW5pbWF0ZWRMZW5ndGhMaXN0OkoudkIsU1ZHQW5pbWF0ZWROdW1iZXI6Si52QixTVkdBbmlt
+YXRlZE51bWJlckxpc3Q6Si52QixTVkdBbmltYXRlZFByZXNlcnZlQXNwZWN0UmF0aW86Si52QixTVkdB
+bmltYXRlZFJlY3Q6Si52QixTVkdBbmltYXRlZFN0cmluZzpKLnZCLFNWR0FuaW1hdGVkVHJhbnNmb3Jt
+TGlzdDpKLnZCLFNWR01hdHJpeDpKLnZCLFNWR1BvaW50OkoudkIsU1ZHUHJlc2VydmVBc3BlY3RSYXRp
+bzpKLnZCLFNWR1JlY3Q6Si52QixTVkdVbml0VHlwZXM6Si52QixBdWRpb0xpc3RlbmVyOkoudkIsQXVk
+aW9UcmFjazpKLnZCLEF1ZGlvV29ya2xldEdsb2JhbFNjb3BlOkoudkIsQXVkaW9Xb3JrbGV0UHJvY2Vz
+c29yOkoudkIsUGVyaW9kaWNXYXZlOkoudkIsV2ViR0xBY3RpdmVJbmZvOkoudkIsQU5HTEVJbnN0YW5j
+ZWRBcnJheXM6Si52QixBTkdMRV9pbnN0YW5jZWRfYXJyYXlzOkoudkIsV2ViR0xCdWZmZXI6Si52QixX
+ZWJHTENhbnZhczpKLnZCLFdlYkdMQ29sb3JCdWZmZXJGbG9hdDpKLnZCLFdlYkdMQ29tcHJlc3NlZFRl
+eHR1cmVBU1RDOkoudkIsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUFUQzpKLnZCLFdFQkdMX2NvbXByZXNz
+ZWRfdGV4dHVyZV9hdGM6Si52QixXZWJHTENvbXByZXNzZWRUZXh0dXJlRVRDMTpKLnZCLFdFQkdMX2Nv
+bXByZXNzZWRfdGV4dHVyZV9ldGMxOkoudkIsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUVUQzpKLnZCLFdl
+YkdMQ29tcHJlc3NlZFRleHR1cmVQVlJUQzpKLnZCLFdFQkdMX2NvbXByZXNzZWRfdGV4dHVyZV9wdnJ0
+YzpKLnZCLFdlYkdMQ29tcHJlc3NlZFRleHR1cmVTM1RDOkoudkIsV0VCR0xfY29tcHJlc3NlZF90ZXh0
+dXJlX3MzdGM6Si52QixXZWJHTENvbXByZXNzZWRUZXh0dXJlUzNUQ3NSR0I6Si52QixXZWJHTERlYnVn
+UmVuZGVyZXJJbmZvOkoudkIsV0VCR0xfZGVidWdfcmVuZGVyZXJfaW5mbzpKLnZCLFdlYkdMRGVidWdT
+aGFkZXJzOkoudkIsV0VCR0xfZGVidWdfc2hhZGVyczpKLnZCLFdlYkdMRGVwdGhUZXh0dXJlOkoudkIs
+V0VCR0xfZGVwdGhfdGV4dHVyZTpKLnZCLFdlYkdMRHJhd0J1ZmZlcnM6Si52QixXRUJHTF9kcmF3X2J1
+ZmZlcnM6Si52QixFWFRzUkdCOkoudkIsRVhUX3NSR0I6Si52QixFWFRCbGVuZE1pbk1heDpKLnZCLEVY
+VF9ibGVuZF9taW5tYXg6Si52QixFWFRDb2xvckJ1ZmZlckZsb2F0OkoudkIsRVhUQ29sb3JCdWZmZXJI
+YWxmRmxvYXQ6Si52QixFWFREaXNqb2ludFRpbWVyUXVlcnk6Si52QixFWFREaXNqb2ludFRpbWVyUXVl
+cnlXZWJHTDI6Si52QixFWFRGcmFnRGVwdGg6Si52QixFWFRfZnJhZ19kZXB0aDpKLnZCLEVYVFNoYWRl
+clRleHR1cmVMT0Q6Si52QixFWFRfc2hhZGVyX3RleHR1cmVfbG9kOkoudkIsRVhUVGV4dHVyZUZpbHRl
+ckFuaXNvdHJvcGljOkoudkIsRVhUX3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljOkoudkIsV2ViR0xG
+cmFtZWJ1ZmZlcjpKLnZCLFdlYkdMR2V0QnVmZmVyU3ViRGF0YUFzeW5jOkoudkIsV2ViR0xMb3NlQ29u
+dGV4dDpKLnZCLFdlYkdMRXh0ZW5zaW9uTG9zZUNvbnRleHQ6Si52QixXRUJHTF9sb3NlX2NvbnRleHQ6
+Si52QixPRVNFbGVtZW50SW5kZXhVaW50OkoudkIsT0VTX2VsZW1lbnRfaW5kZXhfdWludDpKLnZCLE9F
+U1N0YW5kYXJkRGVyaXZhdGl2ZXM6Si52QixPRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXM6Si52QixPRVNU
+ZXh0dXJlRmxvYXQ6Si52QixPRVNfdGV4dHVyZV9mbG9hdDpKLnZCLE9FU1RleHR1cmVGbG9hdExpbmVh
+cjpKLnZCLE9FU190ZXh0dXJlX2Zsb2F0X2xpbmVhcjpKLnZCLE9FU1RleHR1cmVIYWxmRmxvYXQ6Si52
+QixPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0OkoudkIsT0VTVGV4dHVyZUhhbGZGbG9hdExpbmVhcjpKLnZC
+LE9FU190ZXh0dXJlX2hhbGZfZmxvYXRfbGluZWFyOkoudkIsT0VTVmVydGV4QXJyYXlPYmplY3Q6Si52
+QixPRVNfdmVydGV4X2FycmF5X29iamVjdDpKLnZCLFdlYkdMUHJvZ3JhbTpKLnZCLFdlYkdMUXVlcnk6
+Si52QixXZWJHTFJlbmRlcmJ1ZmZlcjpKLnZCLFdlYkdMUmVuZGVyaW5nQ29udGV4dDpKLnZCLFdlYkdM
+MlJlbmRlcmluZ0NvbnRleHQ6Si52QixXZWJHTFNhbXBsZXI6Si52QixXZWJHTFNoYWRlcjpKLnZCLFdl
+YkdMU2hhZGVyUHJlY2lzaW9uRm9ybWF0OkoudkIsV2ViR0xTeW5jOkoudkIsV2ViR0xUZXh0dXJlOkou
+dkIsV2ViR0xUaW1lclF1ZXJ5RVhUOkoudkIsV2ViR0xUcmFuc2Zvcm1GZWVkYmFjazpKLnZCLFdlYkdM
+VW5pZm9ybUxvY2F0aW9uOkoudkIsV2ViR0xWZXJ0ZXhBcnJheU9iamVjdDpKLnZCLFdlYkdMVmVydGV4
+QXJyYXlPYmplY3RPRVM6Si52QixXZWJHTDpKLnZCLFdlYkdMMlJlbmRlcmluZ0NvbnRleHRCYXNlOkou
+dkIsRGF0YWJhc2U6Si52QixTUUxFcnJvcjpKLnZCLFNRTFJlc3VsdFNldDpKLnZCLFNRTFRyYW5zYWN0
+aW9uOkoudkIsQXJyYXlCdWZmZXI6SC5XWixEYXRhVmlldzpILnBGLEFycmF5QnVmZmVyVmlldzpILnBG
+LEZsb2F0MzJBcnJheTpILkRnLEZsb2F0NjRBcnJheTpILkRnLEludDE2QXJyYXk6SC54aixJbnQzMkFy
+cmF5OkguZEUsSW50OEFycmF5OkguWkEsVWludDE2QXJyYXk6SC53ZixVaW50MzJBcnJheTpILlBxLFVp
+bnQ4Q2xhbXBlZEFycmF5OkguZUUsQ2FudmFzUGl4ZWxBcnJheTpILmVFLFVpbnQ4QXJyYXk6SC5WNixI
+VE1MQXVkaW9FbGVtZW50OlcucUUsSFRNTEJSRWxlbWVudDpXLnFFLEhUTUxDYW52YXNFbGVtZW50Olcu
+cUUsSFRNTENvbnRlbnRFbGVtZW50OlcucUUsSFRNTERMaXN0RWxlbWVudDpXLnFFLEhUTUxEYXRhTGlz
+dEVsZW1lbnQ6Vy5xRSxIVE1MRGV0YWlsc0VsZW1lbnQ6Vy5xRSxIVE1MRGlhbG9nRWxlbWVudDpXLnFF
+LEhUTUxEaXZFbGVtZW50OlcucUUsSFRNTEVtYmVkRWxlbWVudDpXLnFFLEhUTUxGaWVsZFNldEVsZW1l
+bnQ6Vy5xRSxIVE1MSFJFbGVtZW50OlcucUUsSFRNTEhlYWRFbGVtZW50OlcucUUsSFRNTEhlYWRpbmdF
+bGVtZW50OlcucUUsSFRNTEh0bWxFbGVtZW50OlcucUUsSFRNTElGcmFtZUVsZW1lbnQ6Vy5xRSxIVE1M
+SW1hZ2VFbGVtZW50OlcucUUsSFRNTExhYmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50Olcu
+cUUsSFRNTExpbmtFbGVtZW50OlcucUUsSFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50
+OlcucUUsSFRNTE1lbnVFbGVtZW50OlcucUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1vZEVsZW1l
+bnQ6Vy5xRSxIVE1MT0xpc3RFbGVtZW50OlcucUUsSFRNTE9iamVjdEVsZW1lbnQ6Vy5xRSxIVE1MT3B0
+R3JvdXBFbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50OlcucUUsSFRNTFByZUVsZW1lbnQ6Vy5x
+RSxIVE1MUXVvdGVFbGVtZW50OlcucUUsSFRNTFNjcmlwdEVsZW1lbnQ6Vy5xRSxIVE1MU2hhZG93RWxl
+bWVudDpXLnFFLEhUTUxTbG90RWxlbWVudDpXLnFFLEhUTUxTb3VyY2VFbGVtZW50OlcucUUsSFRNTFNw
+YW5FbGVtZW50OlcucUUsSFRNTFN0eWxlRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNhcHRpb25FbGVtZW50
+OlcucUUsSFRNTFRhYmxlQ2VsbEVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6Vy5x
+RSxIVE1MVGFibGVIZWFkZXJDZWxsRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNvbEVsZW1lbnQ6Vy5xRSxI
+VE1MVGltZUVsZW1lbnQ6Vy5xRSxIVE1MVGl0bGVFbGVtZW50OlcucUUsSFRNTFRyYWNrRWxlbWVudDpX
+LnFFLEhUTUxVTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MVW5rbm93bkVsZW1lbnQ6Vy5xRSxIVE1MVmlkZW9F
+bGVtZW50OlcucUUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6Vy5xRSxIVE1MRm9udEVsZW1lbnQ6Vy5xRSxI
+VE1MRnJhbWVFbGVtZW50OlcucUUsSFRNTEZyYW1lU2V0RWxlbWVudDpXLnFFLEhUTUxNYXJxdWVlRWxl
+bWVudDpXLnFFLEhUTUxFbGVtZW50OlcucUUsQWNjZXNzaWJsZU5vZGVMaXN0OlcuWWUsSFRNTEFuY2hv
+ckVsZW1lbnQ6Vy5HaCxIVE1MQXJlYUVsZW1lbnQ6Vy5mWSxIVE1MQmFzZUVsZW1lbnQ6Vy5uQixCbG9i
+OlcuQXosQmx1ZXRvb3RoUmVtb3RlR0FUVERlc2NyaXB0b3I6Vy5QVSxIVE1MQm9keUVsZW1lbnQ6Vy5R
+UCxIVE1MQnV0dG9uRWxlbWVudDpXLklGLENEQVRBU2VjdGlvbjpXLm54LENoYXJhY3RlckRhdGE6Vy5u
+eCxDb21tZW50OlcubngsUHJvY2Vzc2luZ0luc3RydWN0aW9uOlcubngsVGV4dDpXLm54LENTU0tleXdv
+cmRWYWx1ZTpXLlJkLENTU051bWVyaWNWYWx1ZTpXLmtSLENTU1BlcnNwZWN0aXZlOlcuVGYsQ1NTQ2hh
+cnNldFJ1bGU6Vy5sdyxDU1NDb25kaXRpb25SdWxlOlcubHcsQ1NTRm9udEZhY2VSdWxlOlcubHcsQ1NT
+R3JvdXBpbmdSdWxlOlcubHcsQ1NTSW1wb3J0UnVsZTpXLmx3LENTU0tleWZyYW1lUnVsZTpXLmx3LE1v
+ekNTU0tleWZyYW1lUnVsZTpXLmx3LFdlYktpdENTU0tleWZyYW1lUnVsZTpXLmx3LENTU0tleWZyYW1l
+c1J1bGU6Vy5sdyxNb3pDU1NLZXlmcmFtZXNSdWxlOlcubHcsV2ViS2l0Q1NTS2V5ZnJhbWVzUnVsZTpX
+Lmx3LENTU01lZGlhUnVsZTpXLmx3LENTU05hbWVzcGFjZVJ1bGU6Vy5sdyxDU1NQYWdlUnVsZTpXLmx3
+LENTU1J1bGU6Vy5sdyxDU1NTdHlsZVJ1bGU6Vy5sdyxDU1NTdXBwb3J0c1J1bGU6Vy5sdyxDU1NWaWV3
+cG9ydFJ1bGU6Vy5sdyxDU1NTdHlsZURlY2xhcmF0aW9uOlcub0osTVNTdHlsZUNTU1Byb3BlcnRpZXM6
+Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLENTU0ltYWdlVmFsdWU6Vy5CdyxDU1NQb3NpdGlvblZhbHVl
+OlcuQncsQ1NTUmVzb3VyY2VWYWx1ZTpXLkJ3LENTU1VSTEltYWdlVmFsdWU6Vy5CdyxDU1NTdHlsZVZh
+bHVlOlcuQncsQ1NTTWF0cml4Q29tcG9uZW50OlcubzQsQ1NTUm90YXRpb246Vy5vNCxDU1NTY2FsZTpX
+Lm80LENTU1NrZXc6Vy5vNCxDU1NUcmFuc2xhdGlvbjpXLm80LENTU1RyYW5zZm9ybUNvbXBvbmVudDpX
+Lm80LENTU1RyYW5zZm9ybVZhbHVlOlcuSFMsQ1NTVW5pdFZhbHVlOlcuVm8sQ1NTVW5wYXJzZWRWYWx1
+ZTpXLkZoLEhUTUxEYXRhRWxlbWVudDpXLmN4LERhdGFUcmFuc2Zlckl0ZW1MaXN0OlcuU2IsWE1MRG9j
+dW1lbnQ6Vy5RRixEb2N1bWVudDpXLlFGLERPTUV4Y2VwdGlvbjpXLk5oLENsaWVudFJlY3RMaXN0Olcu
+RnYsRE9NUmVjdExpc3Q6Vy5GdixET01SZWN0UmVhZE9ubHk6Vy5JQixET01TdHJpbmdMaXN0OlcuWWws
+RE9NVG9rZW5MaXN0OlcubjcsRWxlbWVudDpXLmN2LEFib3J0UGF5bWVudEV2ZW50OlcuZWEsQW5pbWF0
+aW9uRXZlbnQ6Vy5lYSxBbmltYXRpb25QbGF5YmFja0V2ZW50OlcuZWEsQXBwbGljYXRpb25DYWNoZUVy
+cm9yRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNo
+RXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hlZEV2
+ZW50OlcuZWEsQmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OlcuZWEsQmVmb3JlVW5sb2FkRXZlbnQ6Vy5l
+YSxCbG9iRXZlbnQ6Vy5lYSxDYW5NYWtlUGF5bWVudEV2ZW50OlcuZWEsQ2xpcGJvYXJkRXZlbnQ6Vy5l
+YSxDbG9zZUV2ZW50OlcuZWEsQ3VzdG9tRXZlbnQ6Vy5lYSxEZXZpY2VNb3Rpb25FdmVudDpXLmVhLERl
+dmljZU9yaWVudGF0aW9uRXZlbnQ6Vy5lYSxFcnJvckV2ZW50OlcuZWEsRXh0ZW5kYWJsZUV2ZW50Olcu
+ZWEsRXh0ZW5kYWJsZU1lc3NhZ2VFdmVudDpXLmVhLEZldGNoRXZlbnQ6Vy5lYSxGb250RmFjZVNldExv
+YWRFdmVudDpXLmVhLEZvcmVpZ25GZXRjaEV2ZW50OlcuZWEsR2FtZXBhZEV2ZW50OlcuZWEsSGFzaENo
+YW5nZUV2ZW50OlcuZWEsSW5zdGFsbEV2ZW50OlcuZWEsTWVkaWFFbmNyeXB0ZWRFdmVudDpXLmVhLE1l
+ZGlhS2V5TWVzc2FnZUV2ZW50OlcuZWEsTWVkaWFRdWVyeUxpc3RFdmVudDpXLmVhLE1lZGlhU3RyZWFt
+RXZlbnQ6Vy5lYSxNZWRpYVN0cmVhbVRyYWNrRXZlbnQ6Vy5lYSxNZXNzYWdlRXZlbnQ6Vy5lYSxNSURJ
+Q29ubmVjdGlvbkV2ZW50OlcuZWEsTUlESU1lc3NhZ2VFdmVudDpXLmVhLE11dGF0aW9uRXZlbnQ6Vy5l
+YSxOb3RpZmljYXRpb25FdmVudDpXLmVhLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxQYXltZW50UmVx
+dWVzdEV2ZW50OlcuZWEsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDpXLmVhLFBvcFN0YXRlRXZlbnQ6
+Vy5lYSxQcmVzZW50YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6Vy5lYSxQcmVzZW50YXRpb25D
+b25uZWN0aW9uQ2xvc2VFdmVudDpXLmVhLFByb21pc2VSZWplY3Rpb25FdmVudDpXLmVhLFB1c2hFdmVu
+dDpXLmVhLFJUQ0RhdGFDaGFubmVsRXZlbnQ6Vy5lYSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OlcuZWEs
+UlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudDpXLmVhLFJUQ1RyYWNrRXZlbnQ6Vy5lYSxTZWN1cml0eVBv
+bGljeVZpb2xhdGlvbkV2ZW50OlcuZWEsU2Vuc29yRXJyb3JFdmVudDpXLmVhLFNwZWVjaFJlY29nbml0
+aW9uRXJyb3I6Vy5lYSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OlcuZWEsU3BlZWNoU3ludGhlc2lzRXZl
+bnQ6Vy5lYSxTeW5jRXZlbnQ6Vy5lYSxUcmFja0V2ZW50OlcuZWEsVHJhbnNpdGlvbkV2ZW50OlcuZWEs
+V2ViS2l0VHJhbnNpdGlvbkV2ZW50OlcuZWEsVlJEZXZpY2VFdmVudDpXLmVhLFZSRGlzcGxheUV2ZW50
+OlcuZWEsVlJTZXNzaW9uRXZlbnQ6Vy5lYSxNb2pvSW50ZXJmYWNlUmVxdWVzdEV2ZW50OlcuZWEsVVNC
+Q29ubmVjdGlvbkV2ZW50OlcuZWEsSURCVmVyc2lvbkNoYW5nZUV2ZW50OlcuZWEsQXVkaW9Qcm9jZXNz
+aW5nRXZlbnQ6Vy5lYSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6Vy5lYSxXZWJHTENvbnRleHRF
+dmVudDpXLmVhLEV2ZW50OlcuZWEsSW5wdXRFdmVudDpXLmVhLEFic29sdXRlT3JpZW50YXRpb25TZW5z
+b3I6Vy5EMCxBY2NlbGVyb21ldGVyOlcuRDAsQWNjZXNzaWJsZU5vZGU6Vy5EMCxBbWJpZW50TGlnaHRT
+ZW5zb3I6Vy5EMCxBbmltYXRpb246Vy5EMCxBcHBsaWNhdGlvbkNhY2hlOlcuRDAsRE9NQXBwbGljYXRp
+b25DYWNoZTpXLkQwLE9mZmxpbmVSZXNvdXJjZUxpc3Q6Vy5EMCxCYWNrZ3JvdW5kRmV0Y2hSZWdpc3Ry
+YXRpb246Vy5EMCxCYXR0ZXJ5TWFuYWdlcjpXLkQwLEJyb2FkY2FzdENoYW5uZWw6Vy5EMCxDYW52YXND
+YXB0dXJlTWVkaWFTdHJlYW1UcmFjazpXLkQwLEV2ZW50U291cmNlOlcuRDAsRmlsZVJlYWRlcjpXLkQw
+LEZvbnRGYWNlU2V0OlcuRDAsR3lyb3Njb3BlOlcuRDAsTGluZWFyQWNjZWxlcmF0aW9uU2Vuc29yOlcu
+RDAsTWFnbmV0b21ldGVyOlcuRDAsTWVkaWFEZXZpY2VzOlcuRDAsTWVkaWFLZXlTZXNzaW9uOlcuRDAs
+TWVkaWFRdWVyeUxpc3Q6Vy5EMCxNZWRpYVJlY29yZGVyOlcuRDAsTWVkaWFTb3VyY2U6Vy5EMCxNZWRp
+YVN0cmVhbTpXLkQwLE1lZGlhU3RyZWFtVHJhY2s6Vy5EMCxNSURJQWNjZXNzOlcuRDAsTUlESUlucHV0
+OlcuRDAsTUlESU91dHB1dDpXLkQwLE1JRElQb3J0OlcuRDAsTmV0d29ya0luZm9ybWF0aW9uOlcuRDAs
+Tm90aWZpY2F0aW9uOlcuRDAsT2Zmc2NyZWVuQ2FudmFzOlcuRDAsT3JpZW50YXRpb25TZW5zb3I6Vy5E
+MCxQYXltZW50UmVxdWVzdDpXLkQwLFBlcmZvcm1hbmNlOlcuRDAsUGVybWlzc2lvblN0YXR1czpXLkQw
+LFByZXNlbnRhdGlvbkNvbm5lY3Rpb246Vy5EMCxQcmVzZW50YXRpb25Db25uZWN0aW9uTGlzdDpXLkQw
+LFByZXNlbnRhdGlvblJlcXVlc3Q6Vy5EMCxSZWxhdGl2ZU9yaWVudGF0aW9uU2Vuc29yOlcuRDAsUmVt
+b3RlUGxheWJhY2s6Vy5EMCxSVENEYXRhQ2hhbm5lbDpXLkQwLERhdGFDaGFubmVsOlcuRDAsUlRDRFRN
+RlNlbmRlcjpXLkQwLFJUQ1BlZXJDb25uZWN0aW9uOlcuRDAsd2Via2l0UlRDUGVlckNvbm5lY3Rpb246
+Vy5EMCxtb3pSVENQZWVyQ29ubmVjdGlvbjpXLkQwLFNjcmVlbk9yaWVudGF0aW9uOlcuRDAsU2Vuc29y
+OlcuRDAsU2VydmljZVdvcmtlcjpXLkQwLFNlcnZpY2VXb3JrZXJDb250YWluZXI6Vy5EMCxTZXJ2aWNl
+V29ya2VyUmVnaXN0cmF0aW9uOlcuRDAsU2hhcmVkV29ya2VyOlcuRDAsU3BlZWNoUmVjb2duaXRpb246
+Vy5EMCxTcGVlY2hTeW50aGVzaXM6Vy5EMCxTcGVlY2hTeW50aGVzaXNVdHRlcmFuY2U6Vy5EMCxWUjpX
+LkQwLFZSRGV2aWNlOlcuRDAsVlJEaXNwbGF5OlcuRDAsVlJTZXNzaW9uOlcuRDAsVmlzdWFsVmlld3Bv
+cnQ6Vy5EMCxXZWJTb2NrZXQ6Vy5EMCxXb3JrZXI6Vy5EMCxXb3JrZXJQZXJmb3JtYW5jZTpXLkQwLEJs
+dWV0b290aERldmljZTpXLkQwLEJsdWV0b290aFJlbW90ZUdBVFRDaGFyYWN0ZXJpc3RpYzpXLkQwLENs
+aXBib2FyZDpXLkQwLE1vam9JbnRlcmZhY2VJbnRlcmNlcHRvcjpXLkQwLFVTQjpXLkQwLElEQkRhdGFi
+YXNlOlcuRDAsSURCT3BlbkRCUmVxdWVzdDpXLkQwLElEQlZlcnNpb25DaGFuZ2VSZXF1ZXN0OlcuRDAs
+SURCUmVxdWVzdDpXLkQwLElEQlRyYW5zYWN0aW9uOlcuRDAsQW5hbHlzZXJOb2RlOlcuRDAsUmVhbHRp
+bWVBbmFseXNlck5vZGU6Vy5EMCxBdWRpb0J1ZmZlclNvdXJjZU5vZGU6Vy5EMCxBdWRpb0Rlc3RpbmF0
+aW9uTm9kZTpXLkQwLEF1ZGlvTm9kZTpXLkQwLEF1ZGlvU2NoZWR1bGVkU291cmNlTm9kZTpXLkQwLEF1
+ZGlvV29ya2xldE5vZGU6Vy5EMCxCaXF1YWRGaWx0ZXJOb2RlOlcuRDAsQ2hhbm5lbE1lcmdlck5vZGU6
+Vy5EMCxBdWRpb0NoYW5uZWxNZXJnZXI6Vy5EMCxDaGFubmVsU3BsaXR0ZXJOb2RlOlcuRDAsQXVkaW9D
+aGFubmVsU3BsaXR0ZXI6Vy5EMCxDb25zdGFudFNvdXJjZU5vZGU6Vy5EMCxDb252b2x2ZXJOb2RlOlcu
+RDAsRGVsYXlOb2RlOlcuRDAsRHluYW1pY3NDb21wcmVzc29yTm9kZTpXLkQwLEdhaW5Ob2RlOlcuRDAs
+QXVkaW9HYWluTm9kZTpXLkQwLElJUkZpbHRlck5vZGU6Vy5EMCxNZWRpYUVsZW1lbnRBdWRpb1NvdXJj
+ZU5vZGU6Vy5EMCxNZWRpYVN0cmVhbUF1ZGlvRGVzdGluYXRpb25Ob2RlOlcuRDAsTWVkaWFTdHJlYW1B
+dWRpb1NvdXJjZU5vZGU6Vy5EMCxPc2NpbGxhdG9yTm9kZTpXLkQwLE9zY2lsbGF0b3I6Vy5EMCxQYW5u
+ZXJOb2RlOlcuRDAsQXVkaW9QYW5uZXJOb2RlOlcuRDAsd2Via2l0QXVkaW9QYW5uZXJOb2RlOlcuRDAs
+U2NyaXB0UHJvY2Vzc29yTm9kZTpXLkQwLEphdmFTY3JpcHRBdWRpb05vZGU6Vy5EMCxTdGVyZW9QYW5u
+ZXJOb2RlOlcuRDAsV2F2ZVNoYXBlck5vZGU6Vy5EMCxFdmVudFRhcmdldDpXLkQwLEZpbGU6Vy5UNSxG
+aWxlTGlzdDpXLlhWLEZpbGVXcml0ZXI6Vy53SixIVE1MRm9ybUVsZW1lbnQ6Vy5oNCxHYW1lcGFkOlcu
+R08sR2FtZXBhZEJ1dHRvbjpXLkpDLEhpc3Rvcnk6Vy5icixIVE1MQ29sbGVjdGlvbjpXLnhuLEhUTUxG
+b3JtQ29udHJvbHNDb2xsZWN0aW9uOlcueG4sSFRNTE9wdGlvbnNDb2xsZWN0aW9uOlcueG4sSFRNTERv
+Y3VtZW50OlcuVmIsWE1MSHR0cFJlcXVlc3Q6Vy5mSixYTUxIdHRwUmVxdWVzdFVwbG9hZDpXLndhLFhN
+TEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6Vy53YSxJbWFnZURhdGE6Vy5TZyxIVE1MSW5wdXRFbGVtZW50
+OlcuSkssS2V5Ym9hcmRFdmVudDpXLkhMLEhUTUxMSUVsZW1lbnQ6Vy53UCxMb2NhdGlvbjpXLnU4LE1l
+ZGlhTGlzdDpXLno2LE1lc3NhZ2VQb3J0OlcuQ2YsSFRNTE1ldGVyRWxlbWVudDpXLlFiLE1JRElJbnB1
+dE1hcDpXLlMwLE1JRElPdXRwdXRNYXA6Vy56MixNaW1lVHlwZTpXLkFXLE1pbWVUeXBlQXJyYXk6Vy5E
+TSxNb3VzZUV2ZW50OlcuT0ssRHJhZ0V2ZW50OlcuT0ssUG9pbnRlckV2ZW50OlcuT0ssV2hlZWxFdmVu
+dDpXLk9LLERvY3VtZW50RnJhZ21lbnQ6Vy51SCxTaGFkb3dSb290OlcudUgsRG9jdW1lbnRUeXBlOlcu
+dUgsTm9kZTpXLnVILE5vZGVMaXN0OlcuQkgsUmFkaW9Ob2RlTGlzdDpXLkJILEhUTUxPcHRpb25FbGVt
+ZW50OlcuUWwsSFRNTE91dHB1dEVsZW1lbnQ6Vy5HWCxIVE1MUGFyYWdyYXBoRWxlbWVudDpXLlNOLEhU
+TUxQYXJhbUVsZW1lbnQ6Vy5IRCxQbHVnaW46Vy5jbCxQbHVnaW5BcnJheTpXLkV2LFByZXNlbnRhdGlv
+bkF2YWlsYWJpbGl0eTpXLkxyLEhUTUxQcm9ncmVzc0VsZW1lbnQ6Vy5LUixQcm9ncmVzc0V2ZW50Olcu
+ZXcsUmVzb3VyY2VQcm9ncmVzc0V2ZW50OlcuZXcsUlRDU3RhdHNSZXBvcnQ6Vy5wOCxIVE1MU2VsZWN0
+RWxlbWVudDpXLmxwLFNvdXJjZUJ1ZmZlcjpXLlNWLFNvdXJjZUJ1ZmZlckxpc3Q6Vy5NayxTcGVlY2hH
+cmFtbWFyOlcuWTQsU3BlZWNoR3JhbW1hckxpc3Q6Vy5ObixTcGVlY2hSZWNvZ25pdGlvblJlc3VsdDpX
+Lmw4LFN0b3JhZ2U6Vy5BcyxTdG9yYWdlRXZlbnQ6Vy5iayxDU1NTdHlsZVNoZWV0OlcuV1csU3R5bGVT
+aGVldDpXLldXLEhUTUxUYWJsZUVsZW1lbnQ6Vy5UYixIVE1MVGFibGVSb3dFbGVtZW50OlcuSXYsSFRN
+TFRhYmxlU2VjdGlvbkVsZW1lbnQ6Vy5CVCxIVE1MVGVtcGxhdGVFbGVtZW50OlcuZlgsSFRNTFRleHRB
+cmVhRWxlbWVudDpXLkZCLFRleHRUcmFjazpXLkExLFRleHRUcmFja0N1ZTpXLk1OLFZUVEN1ZTpXLk1O
+LFRleHRUcmFja0N1ZUxpc3Q6Vy5YMCxUZXh0VHJhY2tMaXN0OlcubkosVGltZVJhbmdlczpXLm16LFRv
+dWNoOlcuYTMsVG91Y2hMaXN0OlcuY2ksVHJhY2tEZWZhdWx0TGlzdDpXLmNuLENvbXBvc2l0aW9uRXZl
+bnQ6Vy53NixGb2N1c0V2ZW50OlcudzYsVGV4dEV2ZW50OlcudzYsVG91Y2hFdmVudDpXLnc2LFVJRXZl
+bnQ6Vy53NixVUkw6Vy5GaixWaWRlb1RyYWNrTGlzdDpXLnZGLFdpbmRvdzpXLk9pLERPTVdpbmRvdzpX
+Lk9pLERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOlcuQ20sU2VydmljZVdvcmtlckdsb2JhbFNjb3Bl
+OlcuQ20sU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxXb3JrZXJHbG9iYWxTY29wZTpXLkNtLEF0
+dHI6Vy5DUSxDU1NSdWxlTGlzdDpXLlBSLENsaWVudFJlY3Q6Vy53NCxET01SZWN0OlcudzQsR2FtZXBh
+ZExpc3Q6Vy5GMixOYW1lZE5vZGVNYXA6Vy5yaCxNb3pOYW1lZEF0dHJNYXA6Vy5yaCxTcGVlY2hSZWNv
+Z25pdGlvblJlc3VsdExpc3Q6Vy5MTyxTdHlsZVNoZWV0TGlzdDpXLmIxLElEQkN1cnNvcjpQLlcyLElE
+QkN1cnNvcldpdGhWYWx1ZTpQLmUzLElEQktleVJhbmdlOlAuaEYsSURCT2JzZXJ2YXRpb246UC5CVixT
+VkdBbmdsZTpQLnVqLFNWR0xlbmd0aDpQLngwLFNWR0xlbmd0aExpc3Q6UC5xNixTVkdOdW1iZXI6UC51
+UCxTVkdOdW1iZXJMaXN0OlAuTFosU1ZHUG9pbnRMaXN0OlAuRUQsU1ZHU2NyaXB0RWxlbWVudDpQLm5k
+LFNWR1N0cmluZ0xpc3Q6UC5LcSxTVkdBRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGVFbGVtZW50OlAuZDUs
+U1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6UC5kNSxTVkdBbmltYXRlVHJhbnNmb3JtRWxlbWVudDpQLmQ1
+LFNWR0FuaW1hdGlvbkVsZW1lbnQ6UC5kNSxTVkdDaXJjbGVFbGVtZW50OlAuZDUsU1ZHQ2xpcFBhdGhF
+bGVtZW50OlAuZDUsU1ZHRGVmc0VsZW1lbnQ6UC5kNSxTVkdEZXNjRWxlbWVudDpQLmQ1LFNWR0Rpc2Nh
+cmRFbGVtZW50OlAuZDUsU1ZHRWxsaXBzZUVsZW1lbnQ6UC5kNSxTVkdGRUJsZW5kRWxlbWVudDpQLmQ1
+LFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OlAuZDUsU1ZHRkVDb21wb25lbnRUcmFuc2ZlckVsZW1lbnQ6
+UC5kNSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6UC5kNSxTVkdGRUNvbnZvbHZlTWF0cml4RWxlbWVudDpQ
+LmQ1LFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxlbWVudDpQLmQ1LFNWR0ZFRGlzcGxhY2VtZW50TWFwRWxl
+bWVudDpQLmQ1LFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZFRmxvb2RFbGVtZW50OlAu
+ZDUsU1ZHRkVGdW5jQUVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNCRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY0dF
+bGVtZW50OlAuZDUsU1ZHRkVGdW5jUkVsZW1lbnQ6UC5kNSxTVkdGRUdhdXNzaWFuQmx1ckVsZW1lbnQ6
+UC5kNSxTVkdGRUltYWdlRWxlbWVudDpQLmQ1LFNWR0ZFTWVyZ2VFbGVtZW50OlAuZDUsU1ZHRkVNZXJn
+ZU5vZGVFbGVtZW50OlAuZDUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDpQLmQ1LFNWR0ZFT2Zmc2V0RWxl
+bWVudDpQLmQ1LFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdGRVNwZWN1bGFyTGlnaHRpbmdF
+bGVtZW50OlAuZDUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVUaWxlRWxlbWVudDpQLmQ1
+LFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6UC5kNSxTVkdGaWx0ZXJFbGVtZW50OlAuZDUsU1ZHRm9yZWln
+bk9iamVjdEVsZW1lbnQ6UC5kNSxTVkdHRWxlbWVudDpQLmQ1LFNWR0dlb21ldHJ5RWxlbWVudDpQLmQ1
+LFNWR0dyYXBoaWNzRWxlbWVudDpQLmQ1LFNWR0ltYWdlRWxlbWVudDpQLmQ1LFNWR0xpbmVFbGVtZW50
+OlAuZDUsU1ZHTGluZWFyR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHTWFya2VyRWxlbWVudDpQLmQ1LFNW
+R01hc2tFbGVtZW50OlAuZDUsU1ZHTWV0YWRhdGFFbGVtZW50OlAuZDUsU1ZHUGF0aEVsZW1lbnQ6UC5k
+NSxTVkdQYXR0ZXJuRWxlbWVudDpQLmQ1LFNWR1BvbHlnb25FbGVtZW50OlAuZDUsU1ZHUG9seWxpbmVF
+bGVtZW50OlAuZDUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHUmVjdEVsZW1lbnQ6UC5k
+NSxTVkdTZXRFbGVtZW50OlAuZDUsU1ZHU3RvcEVsZW1lbnQ6UC5kNSxTVkdTdHlsZUVsZW1lbnQ6UC5k
+NSxTVkdTVkdFbGVtZW50OlAuZDUsU1ZHU3dpdGNoRWxlbWVudDpQLmQ1LFNWR1N5bWJvbEVsZW1lbnQ6
+UC5kNSxTVkdUU3BhbkVsZW1lbnQ6UC5kNSxTVkdUZXh0Q29udGVudEVsZW1lbnQ6UC5kNSxTVkdUZXh0
+RWxlbWVudDpQLmQ1LFNWR1RleHRQYXRoRWxlbWVudDpQLmQ1LFNWR1RleHRQb3NpdGlvbmluZ0VsZW1l
+bnQ6UC5kNSxTVkdUaXRsZUVsZW1lbnQ6UC5kNSxTVkdVc2VFbGVtZW50OlAuZDUsU1ZHVmlld0VsZW1l
+bnQ6UC5kNSxTVkdHcmFkaWVudEVsZW1lbnQ6UC5kNSxTVkdDb21wb25lbnRUcmFuc2ZlckZ1bmN0aW9u
+RWxlbWVudDpQLmQ1LFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6UC5kNSxTVkdNUGF0aEVsZW1lbnQ6UC5k
+NSxTVkdFbGVtZW50OlAuZDUsU1ZHVHJhbnNmb3JtOlAuelksU1ZHVHJhbnNmb3JtTGlzdDpQLk5DLEF1
+ZGlvQnVmZmVyOlAucjIsQXVkaW9QYXJhbTpQLnJPLEF1ZGlvUGFyYW1NYXA6UC5EWCxBdWRpb1RyYWNr
+TGlzdDpQLmZvLEF1ZGlvQ29udGV4dDpQLlY4LHdlYmtpdEF1ZGlvQ29udGV4dDpQLlY4LEJhc2VBdWRp
+b0NvbnRleHQ6UC5WOCxPZmZsaW5lQXVkaW9Db250ZXh0OlAuR24sU1FMUmVzdWx0U2V0Um93TGlzdDpQ
+LkZufSkKaHVua0hlbHBlcnMuc2V0T3JVcGRhdGVMZWFmVGFncyh7QW5pbWF0aW9uRWZmZWN0UmVhZE9u
+bHk6dHJ1ZSxBbmltYXRpb25FZmZlY3RUaW1pbmc6dHJ1ZSxBbmltYXRpb25FZmZlY3RUaW1pbmdSZWFk
+T25seTp0cnVlLEFuaW1hdGlvblRpbWVsaW5lOnRydWUsQW5pbWF0aW9uV29ya2xldEdsb2JhbFNjb3Bl
+OnRydWUsQXV0aGVudGljYXRvckFzc2VydGlvblJlc3BvbnNlOnRydWUsQXV0aGVudGljYXRvckF0dGVz
+dGF0aW9uUmVzcG9uc2U6dHJ1ZSxBdXRoZW50aWNhdG9yUmVzcG9uc2U6dHJ1ZSxCYWNrZ3JvdW5kRmV0
+Y2hGZXRjaDp0cnVlLEJhY2tncm91bmRGZXRjaE1hbmFnZXI6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hTZXR0
+bGVkRmV0Y2g6dHJ1ZSxCYXJQcm9wOnRydWUsQmFyY29kZURldGVjdG9yOnRydWUsQm9keTp0cnVlLEJ1
+ZGdldFN0YXRlOnRydWUsQ2FjaGVTdG9yYWdlOnRydWUsQ2FudmFzR3JhZGllbnQ6dHJ1ZSxDYW52YXNQ
+YXR0ZXJuOnRydWUsQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEOnRydWUsQ2xpZW50OnRydWUsQ2xpZW50
+czp0cnVlLENvb2tpZVN0b3JlOnRydWUsQ29vcmRpbmF0ZXM6dHJ1ZSxDcmVkZW50aWFsOnRydWUsQ3Jl
+ZGVudGlhbFVzZXJEYXRhOnRydWUsQ3JlZGVudGlhbHNDb250YWluZXI6dHJ1ZSxDcnlwdG86dHJ1ZSxD
+cnlwdG9LZXk6dHJ1ZSxDU1M6dHJ1ZSxDU1NWYXJpYWJsZVJlZmVyZW5jZVZhbHVlOnRydWUsQ3VzdG9t
+RWxlbWVudFJlZ2lzdHJ5OnRydWUsRGF0YVRyYW5zZmVyOnRydWUsRGF0YVRyYW5zZmVySXRlbTp0cnVl
+LERlcHJlY2F0ZWRTdG9yYWdlSW5mbzp0cnVlLERlcHJlY2F0ZWRTdG9yYWdlUXVvdGE6dHJ1ZSxEZXBy
+ZWNhdGlvblJlcG9ydDp0cnVlLERldGVjdGVkQmFyY29kZTp0cnVlLERldGVjdGVkRmFjZTp0cnVlLERl
+dGVjdGVkVGV4dDp0cnVlLERldmljZUFjY2VsZXJhdGlvbjp0cnVlLERldmljZVJvdGF0aW9uUmF0ZTp0
+cnVlLERpcmVjdG9yeUVudHJ5OnRydWUsRGlyZWN0b3J5UmVhZGVyOnRydWUsRG9jdW1lbnRPclNoYWRv
+d1Jvb3Q6dHJ1ZSxEb2N1bWVudFRpbWVsaW5lOnRydWUsRE9NRXJyb3I6dHJ1ZSxET01JbXBsZW1lbnRh
+dGlvbjp0cnVlLEl0ZXJhdG9yOnRydWUsRE9NTWF0cml4OnRydWUsRE9NTWF0cml4UmVhZE9ubHk6dHJ1
+ZSxET01QYXJzZXI6dHJ1ZSxET01Qb2ludDp0cnVlLERPTVBvaW50UmVhZE9ubHk6dHJ1ZSxET01RdWFk
+OnRydWUsRE9NU3RyaW5nTWFwOnRydWUsRW50cnk6dHJ1ZSxFeHRlcm5hbDp0cnVlLEZhY2VEZXRlY3Rv
+cjp0cnVlLEZlZGVyYXRlZENyZWRlbnRpYWw6dHJ1ZSxGaWxlRW50cnk6dHJ1ZSxET01GaWxlU3lzdGVt
+OnRydWUsRm9udEZhY2U6dHJ1ZSxGb250RmFjZVNvdXJjZTp0cnVlLEZvcm1EYXRhOnRydWUsR2FtZXBh
+ZFBvc2U6dHJ1ZSxHZW9sb2NhdGlvbjp0cnVlLFBvc2l0aW9uOnRydWUsSGVhZGVyczp0cnVlLEhUTUxI
+eXBlcmxpbmtFbGVtZW50VXRpbHM6dHJ1ZSxJZGxlRGVhZGxpbmU6dHJ1ZSxJbWFnZUJpdG1hcDp0cnVl
+LEltYWdlQml0bWFwUmVuZGVyaW5nQ29udGV4dDp0cnVlLEltYWdlQ2FwdHVyZTp0cnVlLElucHV0RGV2
+aWNlQ2FwYWJpbGl0aWVzOnRydWUsSW50ZXJzZWN0aW9uT2JzZXJ2ZXI6dHJ1ZSxJbnRlcnNlY3Rpb25P
+YnNlcnZlckVudHJ5OnRydWUsSW50ZXJ2ZW50aW9uUmVwb3J0OnRydWUsS2V5ZnJhbWVFZmZlY3Q6dHJ1
+ZSxLZXlmcmFtZUVmZmVjdFJlYWRPbmx5OnRydWUsTWVkaWFDYXBhYmlsaXRpZXM6dHJ1ZSxNZWRpYUNh
+cGFiaWxpdGllc0luZm86dHJ1ZSxNZWRpYURldmljZUluZm86dHJ1ZSxNZWRpYUVycm9yOnRydWUsTWVk
+aWFLZXlTdGF0dXNNYXA6dHJ1ZSxNZWRpYUtleVN5c3RlbUFjY2Vzczp0cnVlLE1lZGlhS2V5czp0cnVl
+LE1lZGlhS2V5c1BvbGljeTp0cnVlLE1lZGlhTWV0YWRhdGE6dHJ1ZSxNZWRpYVNlc3Npb246dHJ1ZSxN
+ZWRpYVNldHRpbmdzUmFuZ2U6dHJ1ZSxNZW1vcnlJbmZvOnRydWUsTWVzc2FnZUNoYW5uZWw6dHJ1ZSxN
+ZXRhZGF0YTp0cnVlLE11dGF0aW9uT2JzZXJ2ZXI6dHJ1ZSxXZWJLaXRNdXRhdGlvbk9ic2VydmVyOnRy
+dWUsTXV0YXRpb25SZWNvcmQ6dHJ1ZSxOYXZpZ2F0aW9uUHJlbG9hZE1hbmFnZXI6dHJ1ZSxOYXZpZ2F0
+b3I6dHJ1ZSxOYXZpZ2F0b3JBdXRvbWF0aW9uSW5mb3JtYXRpb246dHJ1ZSxOYXZpZ2F0b3JDb25jdXJy
+ZW50SGFyZHdhcmU6dHJ1ZSxOYXZpZ2F0b3JDb29raWVzOnRydWUsTmF2aWdhdG9yVXNlck1lZGlhRXJy
+b3I6dHJ1ZSxOb2RlRmlsdGVyOnRydWUsTm9kZUl0ZXJhdG9yOnRydWUsTm9uRG9jdW1lbnRUeXBlQ2hp
+bGROb2RlOnRydWUsTm9uRWxlbWVudFBhcmVudE5vZGU6dHJ1ZSxOb25jZWRFbGVtZW50OnRydWUsT2Zm
+c2NyZWVuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEOnRydWUsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6dHJ1
+ZSxQYWludFJlbmRlcmluZ0NvbnRleHQyRDp0cnVlLFBhaW50U2l6ZTp0cnVlLFBhaW50V29ya2xldEds
+b2JhbFNjb3BlOnRydWUsUGFzc3dvcmRDcmVkZW50aWFsOnRydWUsUGF0aDJEOnRydWUsUGF5bWVudEFk
+ZHJlc3M6dHJ1ZSxQYXltZW50SW5zdHJ1bWVudHM6dHJ1ZSxQYXltZW50TWFuYWdlcjp0cnVlLFBheW1l
+bnRSZXNwb25zZTp0cnVlLFBlcmZvcm1hbmNlRW50cnk6dHJ1ZSxQZXJmb3JtYW5jZUxvbmdUYXNrVGlt
+aW5nOnRydWUsUGVyZm9ybWFuY2VNYXJrOnRydWUsUGVyZm9ybWFuY2VNZWFzdXJlOnRydWUsUGVyZm9y
+bWFuY2VOYXZpZ2F0aW9uOnRydWUsUGVyZm9ybWFuY2VOYXZpZ2F0aW9uVGltaW5nOnRydWUsUGVyZm9y
+bWFuY2VPYnNlcnZlcjp0cnVlLFBlcmZvcm1hbmNlT2JzZXJ2ZXJFbnRyeUxpc3Q6dHJ1ZSxQZXJmb3Jt
+YW5jZVBhaW50VGltaW5nOnRydWUsUGVyZm9ybWFuY2VSZXNvdXJjZVRpbWluZzp0cnVlLFBlcmZvcm1h
+bmNlU2VydmVyVGltaW5nOnRydWUsUGVyZm9ybWFuY2VUaW1pbmc6dHJ1ZSxQZXJtaXNzaW9uczp0cnVl
+LFBob3RvQ2FwYWJpbGl0aWVzOnRydWUsUG9zaXRpb25FcnJvcjp0cnVlLFByZXNlbnRhdGlvbjp0cnVl
+LFByZXNlbnRhdGlvblJlY2VpdmVyOnRydWUsUHVibGljS2V5Q3JlZGVudGlhbDp0cnVlLFB1c2hNYW5h
+Z2VyOnRydWUsUHVzaE1lc3NhZ2VEYXRhOnRydWUsUHVzaFN1YnNjcmlwdGlvbjp0cnVlLFB1c2hTdWJz
+Y3JpcHRpb25PcHRpb25zOnRydWUsUmFuZ2U6dHJ1ZSxSZWxhdGVkQXBwbGljYXRpb246dHJ1ZSxSZXBv
+cnRCb2R5OnRydWUsUmVwb3J0aW5nT2JzZXJ2ZXI6dHJ1ZSxSZXNpemVPYnNlcnZlcjp0cnVlLFJlc2l6
+ZU9ic2VydmVyRW50cnk6dHJ1ZSxSVENDZXJ0aWZpY2F0ZTp0cnVlLFJUQ0ljZUNhbmRpZGF0ZTp0cnVl
+LG1velJUQ0ljZUNhbmRpZGF0ZTp0cnVlLFJUQ0xlZ2FjeVN0YXRzUmVwb3J0OnRydWUsUlRDUnRwQ29u
+dHJpYnV0aW5nU291cmNlOnRydWUsUlRDUnRwUmVjZWl2ZXI6dHJ1ZSxSVENSdHBTZW5kZXI6dHJ1ZSxS
+VENTZXNzaW9uRGVzY3JpcHRpb246dHJ1ZSxtb3pSVENTZXNzaW9uRGVzY3JpcHRpb246dHJ1ZSxSVENT
+dGF0c1Jlc3BvbnNlOnRydWUsU2NyZWVuOnRydWUsU2Nyb2xsU3RhdGU6dHJ1ZSxTY3JvbGxUaW1lbGlu
+ZTp0cnVlLFNlbGVjdGlvbjp0cnVlLFNoYXJlZEFycmF5QnVmZmVyOnRydWUsU3BlZWNoUmVjb2duaXRp
+b25BbHRlcm5hdGl2ZTp0cnVlLFNwZWVjaFN5bnRoZXNpc1ZvaWNlOnRydWUsU3RhdGljUmFuZ2U6dHJ1
+ZSxTdG9yYWdlTWFuYWdlcjp0cnVlLFN0eWxlTWVkaWE6dHJ1ZSxTdHlsZVByb3BlcnR5TWFwOnRydWUs
+U3R5bGVQcm9wZXJ0eU1hcFJlYWRvbmx5OnRydWUsU3luY01hbmFnZXI6dHJ1ZSxUYXNrQXR0cmlidXRp
+b25UaW1pbmc6dHJ1ZSxUZXh0RGV0ZWN0b3I6dHJ1ZSxUZXh0TWV0cmljczp0cnVlLFRyYWNrRGVmYXVs
+dDp0cnVlLFRyZWVXYWxrZXI6dHJ1ZSxUcnVzdGVkSFRNTDp0cnVlLFRydXN0ZWRTY3JpcHRVUkw6dHJ1
+ZSxUcnVzdGVkVVJMOnRydWUsVW5kZXJseWluZ1NvdXJjZUJhc2U6dHJ1ZSxVUkxTZWFyY2hQYXJhbXM6
+dHJ1ZSxWUkNvb3JkaW5hdGVTeXN0ZW06dHJ1ZSxWUkRpc3BsYXlDYXBhYmlsaXRpZXM6dHJ1ZSxWUkV5
+ZVBhcmFtZXRlcnM6dHJ1ZSxWUkZyYW1lRGF0YTp0cnVlLFZSRnJhbWVPZlJlZmVyZW5jZTp0cnVlLFZS
+UG9zZTp0cnVlLFZSU3RhZ2VCb3VuZHM6dHJ1ZSxWUlN0YWdlQm91bmRzUG9pbnQ6dHJ1ZSxWUlN0YWdl
+UGFyYW1ldGVyczp0cnVlLFZhbGlkaXR5U3RhdGU6dHJ1ZSxWaWRlb1BsYXliYWNrUXVhbGl0eTp0cnVl
+LFZpZGVvVHJhY2s6dHJ1ZSxWVFRSZWdpb246dHJ1ZSxXaW5kb3dDbGllbnQ6dHJ1ZSxXb3JrbGV0QW5p
+bWF0aW9uOnRydWUsV29ya2xldEdsb2JhbFNjb3BlOnRydWUsWFBhdGhFdmFsdWF0b3I6dHJ1ZSxYUGF0
+aEV4cHJlc3Npb246dHJ1ZSxYUGF0aE5TUmVzb2x2ZXI6dHJ1ZSxYUGF0aFJlc3VsdDp0cnVlLFhNTFNl
+cmlhbGl6ZXI6dHJ1ZSxYU0xUUHJvY2Vzc29yOnRydWUsQmx1ZXRvb3RoOnRydWUsQmx1ZXRvb3RoQ2hh
+cmFjdGVyaXN0aWNQcm9wZXJ0aWVzOnRydWUsQmx1ZXRvb3RoUmVtb3RlR0FUVFNlcnZlcjp0cnVlLEJs
+dWV0b290aFJlbW90ZUdBVFRTZXJ2aWNlOnRydWUsQmx1ZXRvb3RoVVVJRDp0cnVlLEJ1ZGdldFNlcnZp
+Y2U6dHJ1ZSxDYWNoZTp0cnVlLERPTUZpbGVTeXN0ZW1TeW5jOnRydWUsRGlyZWN0b3J5RW50cnlTeW5j
+OnRydWUsRGlyZWN0b3J5UmVhZGVyU3luYzp0cnVlLEVudHJ5U3luYzp0cnVlLEZpbGVFbnRyeVN5bmM6
+dHJ1ZSxGaWxlUmVhZGVyU3luYzp0cnVlLEZpbGVXcml0ZXJTeW5jOnRydWUsSFRNTEFsbENvbGxlY3Rp
+b246dHJ1ZSxNb2pvOnRydWUsTW9qb0hhbmRsZTp0cnVlLE1vam9XYXRjaGVyOnRydWUsTkZDOnRydWUs
+UGFnZVBvcHVwQ29udHJvbGxlcjp0cnVlLFJlcG9ydDp0cnVlLFJlcXVlc3Q6dHJ1ZSxSZXNwb25zZTp0
+cnVlLFN1YnRsZUNyeXB0bzp0cnVlLFVTQkFsdGVybmF0ZUludGVyZmFjZTp0cnVlLFVTQkNvbmZpZ3Vy
+YXRpb246dHJ1ZSxVU0JEZXZpY2U6dHJ1ZSxVU0JFbmRwb2ludDp0cnVlLFVTQkluVHJhbnNmZXJSZXN1
+bHQ6dHJ1ZSxVU0JJbnRlcmZhY2U6dHJ1ZSxVU0JJc29jaHJvbm91c0luVHJhbnNmZXJQYWNrZXQ6dHJ1
+ZSxVU0JJc29jaHJvbm91c0luVHJhbnNmZXJSZXN1bHQ6dHJ1ZSxVU0JJc29jaHJvbm91c091dFRyYW5z
+ZmVyUGFja2V0OnRydWUsVVNCSXNvY2hyb25vdXNPdXRUcmFuc2ZlclJlc3VsdDp0cnVlLFVTQk91dFRy
+YW5zZmVyUmVzdWx0OnRydWUsV29ya2VyTG9jYXRpb246dHJ1ZSxXb3JrZXJOYXZpZ2F0b3I6dHJ1ZSxX
+b3JrbGV0OnRydWUsSURCRmFjdG9yeTp0cnVlLElEQkluZGV4OnRydWUsSURCT2JqZWN0U3RvcmU6dHJ1
+ZSxJREJPYnNlcnZlcjp0cnVlLElEQk9ic2VydmVyQ2hhbmdlczp0cnVlLFNWR0FuaW1hdGVkQW5nbGU6
+dHJ1ZSxTVkdBbmltYXRlZEJvb2xlYW46dHJ1ZSxTVkdBbmltYXRlZEVudW1lcmF0aW9uOnRydWUsU1ZH
+QW5pbWF0ZWRJbnRlZ2VyOnRydWUsU1ZHQW5pbWF0ZWRMZW5ndGg6dHJ1ZSxTVkdBbmltYXRlZExlbmd0
+aExpc3Q6dHJ1ZSxTVkdBbmltYXRlZE51bWJlcjp0cnVlLFNWR0FuaW1hdGVkTnVtYmVyTGlzdDp0cnVl
+LFNWR0FuaW1hdGVkUHJlc2VydmVBc3BlY3RSYXRpbzp0cnVlLFNWR0FuaW1hdGVkUmVjdDp0cnVlLFNW
+R0FuaW1hdGVkU3RyaW5nOnRydWUsU1ZHQW5pbWF0ZWRUcmFuc2Zvcm1MaXN0OnRydWUsU1ZHTWF0cml4
+OnRydWUsU1ZHUG9pbnQ6dHJ1ZSxTVkdQcmVzZXJ2ZUFzcGVjdFJhdGlvOnRydWUsU1ZHUmVjdDp0cnVl
+LFNWR1VuaXRUeXBlczp0cnVlLEF1ZGlvTGlzdGVuZXI6dHJ1ZSxBdWRpb1RyYWNrOnRydWUsQXVkaW9X
+b3JrbGV0R2xvYmFsU2NvcGU6dHJ1ZSxBdWRpb1dvcmtsZXRQcm9jZXNzb3I6dHJ1ZSxQZXJpb2RpY1dh
+dmU6dHJ1ZSxXZWJHTEFjdGl2ZUluZm86dHJ1ZSxBTkdMRUluc3RhbmNlZEFycmF5czp0cnVlLEFOR0xF
+X2luc3RhbmNlZF9hcnJheXM6dHJ1ZSxXZWJHTEJ1ZmZlcjp0cnVlLFdlYkdMQ2FudmFzOnRydWUsV2Vi
+R0xDb2xvckJ1ZmZlckZsb2F0OnRydWUsV2ViR0xDb21wcmVzc2VkVGV4dHVyZUFTVEM6dHJ1ZSxXZWJH
+TENvbXByZXNzZWRUZXh0dXJlQVRDOnRydWUsV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX2F0Yzp0cnVl
+LFdlYkdMQ29tcHJlc3NlZFRleHR1cmVFVEMxOnRydWUsV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX2V0
+YzE6dHJ1ZSxXZWJHTENvbXByZXNzZWRUZXh0dXJlRVRDOnRydWUsV2ViR0xDb21wcmVzc2VkVGV4dHVy
+ZVBWUlRDOnRydWUsV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX3B2cnRjOnRydWUsV2ViR0xDb21wcmVz
+c2VkVGV4dHVyZVMzVEM6dHJ1ZSxXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfczN0Yzp0cnVlLFdlYkdM
+Q29tcHJlc3NlZFRleHR1cmVTM1RDc1JHQjp0cnVlLFdlYkdMRGVidWdSZW5kZXJlckluZm86dHJ1ZSxX
+RUJHTF9kZWJ1Z19yZW5kZXJlcl9pbmZvOnRydWUsV2ViR0xEZWJ1Z1NoYWRlcnM6dHJ1ZSxXRUJHTF9k
+ZWJ1Z19zaGFkZXJzOnRydWUsV2ViR0xEZXB0aFRleHR1cmU6dHJ1ZSxXRUJHTF9kZXB0aF90ZXh0dXJl
+OnRydWUsV2ViR0xEcmF3QnVmZmVyczp0cnVlLFdFQkdMX2RyYXdfYnVmZmVyczp0cnVlLEVYVHNSR0I6
+dHJ1ZSxFWFRfc1JHQjp0cnVlLEVYVEJsZW5kTWluTWF4OnRydWUsRVhUX2JsZW5kX21pbm1heDp0cnVl
+LEVYVENvbG9yQnVmZmVyRmxvYXQ6dHJ1ZSxFWFRDb2xvckJ1ZmZlckhhbGZGbG9hdDp0cnVlLEVYVERp
+c2pvaW50VGltZXJRdWVyeTp0cnVlLEVYVERpc2pvaW50VGltZXJRdWVyeVdlYkdMMjp0cnVlLEVYVEZy
+YWdEZXB0aDp0cnVlLEVYVF9mcmFnX2RlcHRoOnRydWUsRVhUU2hhZGVyVGV4dHVyZUxPRDp0cnVlLEVY
+VF9zaGFkZXJfdGV4dHVyZV9sb2Q6dHJ1ZSxFWFRUZXh0dXJlRmlsdGVyQW5pc290cm9waWM6dHJ1ZSxF
+WFRfdGV4dHVyZV9maWx0ZXJfYW5pc290cm9waWM6dHJ1ZSxXZWJHTEZyYW1lYnVmZmVyOnRydWUsV2Vi
+R0xHZXRCdWZmZXJTdWJEYXRhQXN5bmM6dHJ1ZSxXZWJHTExvc2VDb250ZXh0OnRydWUsV2ViR0xFeHRl
+bnNpb25Mb3NlQ29udGV4dDp0cnVlLFdFQkdMX2xvc2VfY29udGV4dDp0cnVlLE9FU0VsZW1lbnRJbmRl
+eFVpbnQ6dHJ1ZSxPRVNfZWxlbWVudF9pbmRleF91aW50OnRydWUsT0VTU3RhbmRhcmREZXJpdmF0aXZl
+czp0cnVlLE9FU19zdGFuZGFyZF9kZXJpdmF0aXZlczp0cnVlLE9FU1RleHR1cmVGbG9hdDp0cnVlLE9F
+U190ZXh0dXJlX2Zsb2F0OnRydWUsT0VTVGV4dHVyZUZsb2F0TGluZWFyOnRydWUsT0VTX3RleHR1cmVf
+ZmxvYXRfbGluZWFyOnRydWUsT0VTVGV4dHVyZUhhbGZGbG9hdDp0cnVlLE9FU190ZXh0dXJlX2hhbGZf
+ZmxvYXQ6dHJ1ZSxPRVNUZXh0dXJlSGFsZkZsb2F0TGluZWFyOnRydWUsT0VTX3RleHR1cmVfaGFsZl9m
+bG9hdF9saW5lYXI6dHJ1ZSxPRVNWZXJ0ZXhBcnJheU9iamVjdDp0cnVlLE9FU192ZXJ0ZXhfYXJyYXlf
+b2JqZWN0OnRydWUsV2ViR0xQcm9ncmFtOnRydWUsV2ViR0xRdWVyeTp0cnVlLFdlYkdMUmVuZGVyYnVm
+ZmVyOnRydWUsV2ViR0xSZW5kZXJpbmdDb250ZXh0OnRydWUsV2ViR0wyUmVuZGVyaW5nQ29udGV4dDp0
+cnVlLFdlYkdMU2FtcGxlcjp0cnVlLFdlYkdMU2hhZGVyOnRydWUsV2ViR0xTaGFkZXJQcmVjaXNpb25G
+b3JtYXQ6dHJ1ZSxXZWJHTFN5bmM6dHJ1ZSxXZWJHTFRleHR1cmU6dHJ1ZSxXZWJHTFRpbWVyUXVlcnlF
+WFQ6dHJ1ZSxXZWJHTFRyYW5zZm9ybUZlZWRiYWNrOnRydWUsV2ViR0xVbmlmb3JtTG9jYXRpb246dHJ1
+ZSxXZWJHTFZlcnRleEFycmF5T2JqZWN0OnRydWUsV2ViR0xWZXJ0ZXhBcnJheU9iamVjdE9FUzp0cnVl
+LFdlYkdMOnRydWUsV2ViR0wyUmVuZGVyaW5nQ29udGV4dEJhc2U6dHJ1ZSxEYXRhYmFzZTp0cnVlLFNR
+TEVycm9yOnRydWUsU1FMUmVzdWx0U2V0OnRydWUsU1FMVHJhbnNhY3Rpb246dHJ1ZSxBcnJheUJ1ZmZl
+cjp0cnVlLERhdGFWaWV3OnRydWUsQXJyYXlCdWZmZXJWaWV3OmZhbHNlLEZsb2F0MzJBcnJheTp0cnVl
+LEZsb2F0NjRBcnJheTp0cnVlLEludDE2QXJyYXk6dHJ1ZSxJbnQzMkFycmF5OnRydWUsSW50OEFycmF5
+OnRydWUsVWludDE2QXJyYXk6dHJ1ZSxVaW50MzJBcnJheTp0cnVlLFVpbnQ4Q2xhbXBlZEFycmF5OnRy
+dWUsQ2FudmFzUGl4ZWxBcnJheTp0cnVlLFVpbnQ4QXJyYXk6ZmFsc2UsSFRNTEF1ZGlvRWxlbWVudDp0
+cnVlLEhUTUxCUkVsZW1lbnQ6dHJ1ZSxIVE1MQ2FudmFzRWxlbWVudDp0cnVlLEhUTUxDb250ZW50RWxl
+bWVudDp0cnVlLEhUTUxETGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MRGF0YUxpc3RFbGVtZW50OnRydWUsSFRN
+TERldGFpbHNFbGVtZW50OnRydWUsSFRNTERpYWxvZ0VsZW1lbnQ6dHJ1ZSxIVE1MRGl2RWxlbWVudDp0
+cnVlLEhUTUxFbWJlZEVsZW1lbnQ6dHJ1ZSxIVE1MRmllbGRTZXRFbGVtZW50OnRydWUsSFRNTEhSRWxl
+bWVudDp0cnVlLEhUTUxIZWFkRWxlbWVudDp0cnVlLEhUTUxIZWFkaW5nRWxlbWVudDp0cnVlLEhUTUxI
+dG1sRWxlbWVudDp0cnVlLEhUTUxJRnJhbWVFbGVtZW50OnRydWUsSFRNTEltYWdlRWxlbWVudDp0cnVl
+LEhUTUxMYWJlbEVsZW1lbnQ6dHJ1ZSxIVE1MTGVnZW5kRWxlbWVudDp0cnVlLEhUTUxMaW5rRWxlbWVu
+dDp0cnVlLEhUTUxNYXBFbGVtZW50OnRydWUsSFRNTE1lZGlhRWxlbWVudDp0cnVlLEhUTUxNZW51RWxl
+bWVudDp0cnVlLEhUTUxNZXRhRWxlbWVudDp0cnVlLEhUTUxNb2RFbGVtZW50OnRydWUsSFRNTE9MaXN0
+RWxlbWVudDp0cnVlLEhUTUxPYmplY3RFbGVtZW50OnRydWUsSFRNTE9wdEdyb3VwRWxlbWVudDp0cnVl
+LEhUTUxQaWN0dXJlRWxlbWVudDp0cnVlLEhUTUxQcmVFbGVtZW50OnRydWUsSFRNTFF1b3RlRWxlbWVu
+dDp0cnVlLEhUTUxTY3JpcHRFbGVtZW50OnRydWUsSFRNTFNoYWRvd0VsZW1lbnQ6dHJ1ZSxIVE1MU2xv
+dEVsZW1lbnQ6dHJ1ZSxIVE1MU291cmNlRWxlbWVudDp0cnVlLEhUTUxTcGFuRWxlbWVudDp0cnVlLEhU
+TUxTdHlsZUVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNl
+bGxFbGVtZW50OnRydWUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OnRydWUsSFRNTFRhYmxlSGVhZGVy
+Q2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVDb2xFbGVtZW50OnRydWUsSFRNTFRpbWVFbGVtZW50OnRy
+dWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhUTUxUcmFja0VsZW1lbnQ6dHJ1ZSxIVE1MVUxpc3RFbGVt
+ZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50OnRydWUsSFRNTFZpZGVvRWxlbWVudDp0cnVlLEhUTUxE
+aXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZvbnRFbGVtZW50OnRydWUsSFRNTEZyYW1lRWxlbWVudDp0
+cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1ZSxIVE1MTWFycXVlZUVsZW1lbnQ6dHJ1ZSxIVE1MRWxl
+bWVudDpmYWxzZSxBY2Nlc3NpYmxlTm9kZUxpc3Q6dHJ1ZSxIVE1MQW5jaG9yRWxlbWVudDp0cnVlLEhU
+TUxBcmVhRWxlbWVudDp0cnVlLEhUTUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2UsQmx1ZXRvb3Ro
+UmVtb3RlR0FUVERlc2NyaXB0b3I6dHJ1ZSxIVE1MQm9keUVsZW1lbnQ6dHJ1ZSxIVE1MQnV0dG9uRWxl
+bWVudDp0cnVlLENEQVRBU2VjdGlvbjp0cnVlLENoYXJhY3RlckRhdGE6dHJ1ZSxDb21tZW50OnRydWUs
+UHJvY2Vzc2luZ0luc3RydWN0aW9uOnRydWUsVGV4dDp0cnVlLENTU0tleXdvcmRWYWx1ZTp0cnVlLENT
+U051bWVyaWNWYWx1ZTpmYWxzZSxDU1NQZXJzcGVjdGl2ZTp0cnVlLENTU0NoYXJzZXRSdWxlOnRydWUs
+Q1NTQ29uZGl0aW9uUnVsZTp0cnVlLENTU0ZvbnRGYWNlUnVsZTp0cnVlLENTU0dyb3VwaW5nUnVsZTp0
+cnVlLENTU0ltcG9ydFJ1bGU6dHJ1ZSxDU1NLZXlmcmFtZVJ1bGU6dHJ1ZSxNb3pDU1NLZXlmcmFtZVJ1
+bGU6dHJ1ZSxXZWJLaXRDU1NLZXlmcmFtZVJ1bGU6dHJ1ZSxDU1NLZXlmcmFtZXNSdWxlOnRydWUsTW96
+Q1NTS2V5ZnJhbWVzUnVsZTp0cnVlLFdlYktpdENTU0tleWZyYW1lc1J1bGU6dHJ1ZSxDU1NNZWRpYVJ1
+bGU6dHJ1ZSxDU1NOYW1lc3BhY2VSdWxlOnRydWUsQ1NTUGFnZVJ1bGU6dHJ1ZSxDU1NSdWxlOnRydWUs
+Q1NTU3R5bGVSdWxlOnRydWUsQ1NTU3VwcG9ydHNSdWxlOnRydWUsQ1NTVmlld3BvcnRSdWxlOnRydWUs
+Q1NTU3R5bGVEZWNsYXJhdGlvbjp0cnVlLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOnRydWUsQ1NTMlByb3Bl
+cnRpZXM6dHJ1ZSxDU1NJbWFnZVZhbHVlOnRydWUsQ1NTUG9zaXRpb25WYWx1ZTp0cnVlLENTU1Jlc291
+cmNlVmFsdWU6dHJ1ZSxDU1NVUkxJbWFnZVZhbHVlOnRydWUsQ1NTU3R5bGVWYWx1ZTpmYWxzZSxDU1NN
+YXRyaXhDb21wb25lbnQ6dHJ1ZSxDU1NSb3RhdGlvbjp0cnVlLENTU1NjYWxlOnRydWUsQ1NTU2tldzp0
+cnVlLENTU1RyYW5zbGF0aW9uOnRydWUsQ1NTVHJhbnNmb3JtQ29tcG9uZW50OmZhbHNlLENTU1RyYW5z
+Zm9ybVZhbHVlOnRydWUsQ1NTVW5pdFZhbHVlOnRydWUsQ1NTVW5wYXJzZWRWYWx1ZTp0cnVlLEhUTUxE
+YXRhRWxlbWVudDp0cnVlLERhdGFUcmFuc2Zlckl0ZW1MaXN0OnRydWUsWE1MRG9jdW1lbnQ6dHJ1ZSxE
+b2N1bWVudDpmYWxzZSxET01FeGNlcHRpb246dHJ1ZSxDbGllbnRSZWN0TGlzdDp0cnVlLERPTVJlY3RM
+aXN0OnRydWUsRE9NUmVjdFJlYWRPbmx5OmZhbHNlLERPTVN0cmluZ0xpc3Q6dHJ1ZSxET01Ub2tlbkxp
+c3Q6dHJ1ZSxFbGVtZW50OmZhbHNlLEFib3J0UGF5bWVudEV2ZW50OnRydWUsQW5pbWF0aW9uRXZlbnQ6
+dHJ1ZSxBbmltYXRpb25QbGF5YmFja0V2ZW50OnRydWUsQXBwbGljYXRpb25DYWNoZUVycm9yRXZlbnQ6
+dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRXZlbnQ6dHJ1
+ZSxCYWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hlZEV2ZW50OnRydWUs
+QmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OnRydWUsQmVmb3JlVW5sb2FkRXZlbnQ6dHJ1ZSxCbG9iRXZl
+bnQ6dHJ1ZSxDYW5NYWtlUGF5bWVudEV2ZW50OnRydWUsQ2xpcGJvYXJkRXZlbnQ6dHJ1ZSxDbG9zZUV2
+ZW50OnRydWUsQ3VzdG9tRXZlbnQ6dHJ1ZSxEZXZpY2VNb3Rpb25FdmVudDp0cnVlLERldmljZU9yaWVu
+dGF0aW9uRXZlbnQ6dHJ1ZSxFcnJvckV2ZW50OnRydWUsRXh0ZW5kYWJsZUV2ZW50OnRydWUsRXh0ZW5k
+YWJsZU1lc3NhZ2VFdmVudDp0cnVlLEZldGNoRXZlbnQ6dHJ1ZSxGb250RmFjZVNldExvYWRFdmVudDp0
+cnVlLEZvcmVpZ25GZXRjaEV2ZW50OnRydWUsR2FtZXBhZEV2ZW50OnRydWUsSGFzaENoYW5nZUV2ZW50
+OnRydWUsSW5zdGFsbEV2ZW50OnRydWUsTWVkaWFFbmNyeXB0ZWRFdmVudDp0cnVlLE1lZGlhS2V5TWVz
+c2FnZUV2ZW50OnRydWUsTWVkaWFRdWVyeUxpc3RFdmVudDp0cnVlLE1lZGlhU3RyZWFtRXZlbnQ6dHJ1
+ZSxNZWRpYVN0cmVhbVRyYWNrRXZlbnQ6dHJ1ZSxNZXNzYWdlRXZlbnQ6dHJ1ZSxNSURJQ29ubmVjdGlv
+bkV2ZW50OnRydWUsTUlESU1lc3NhZ2VFdmVudDp0cnVlLE11dGF0aW9uRXZlbnQ6dHJ1ZSxOb3RpZmlj
+YXRpb25FdmVudDp0cnVlLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVzdEV2ZW50
+OnRydWUsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDp0cnVlLFBvcFN0YXRlRXZlbnQ6dHJ1ZSxQcmVz
+ZW50YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9u
+Q2xvc2VFdmVudDp0cnVlLFByb21pc2VSZWplY3Rpb25FdmVudDp0cnVlLFB1c2hFdmVudDp0cnVlLFJU
+Q0RhdGFDaGFubmVsRXZlbnQ6dHJ1ZSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OnRydWUsUlRDUGVlckNv
+bm5lY3Rpb25JY2VFdmVudDp0cnVlLFJUQ1RyYWNrRXZlbnQ6dHJ1ZSxTZWN1cml0eVBvbGljeVZpb2xh
+dGlvbkV2ZW50OnRydWUsU2Vuc29yRXJyb3JFdmVudDp0cnVlLFNwZWVjaFJlY29nbml0aW9uRXJyb3I6
+dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OnRydWUsU3BlZWNoU3ludGhlc2lzRXZlbnQ6dHJ1ZSxT
+eW5jRXZlbnQ6dHJ1ZSxUcmFja0V2ZW50OnRydWUsVHJhbnNpdGlvbkV2ZW50OnRydWUsV2ViS2l0VHJh
+bnNpdGlvbkV2ZW50OnRydWUsVlJEZXZpY2VFdmVudDp0cnVlLFZSRGlzcGxheUV2ZW50OnRydWUsVlJT
+ZXNzaW9uRXZlbnQ6dHJ1ZSxNb2pvSW50ZXJmYWNlUmVxdWVzdEV2ZW50OnRydWUsVVNCQ29ubmVjdGlv
+bkV2ZW50OnRydWUsSURCVmVyc2lvbkNoYW5nZUV2ZW50OnRydWUsQXVkaW9Qcm9jZXNzaW5nRXZlbnQ6
+dHJ1ZSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6dHJ1ZSxXZWJHTENvbnRleHRFdmVudDp0cnVl
+LEV2ZW50OmZhbHNlLElucHV0RXZlbnQ6ZmFsc2UsQWJzb2x1dGVPcmllbnRhdGlvblNlbnNvcjp0cnVl
+LEFjY2VsZXJvbWV0ZXI6dHJ1ZSxBY2Nlc3NpYmxlTm9kZTp0cnVlLEFtYmllbnRMaWdodFNlbnNvcjp0
+cnVlLEFuaW1hdGlvbjp0cnVlLEFwcGxpY2F0aW9uQ2FjaGU6dHJ1ZSxET01BcHBsaWNhdGlvbkNhY2hl
+OnRydWUsT2ZmbGluZVJlc291cmNlTGlzdDp0cnVlLEJhY2tncm91bmRGZXRjaFJlZ2lzdHJhdGlvbjp0
+cnVlLEJhdHRlcnlNYW5hZ2VyOnRydWUsQnJvYWRjYXN0Q2hhbm5lbDp0cnVlLENhbnZhc0NhcHR1cmVN
+ZWRpYVN0cmVhbVRyYWNrOnRydWUsRXZlbnRTb3VyY2U6dHJ1ZSxGaWxlUmVhZGVyOnRydWUsRm9udEZh
+Y2VTZXQ6dHJ1ZSxHeXJvc2NvcGU6dHJ1ZSxMaW5lYXJBY2NlbGVyYXRpb25TZW5zb3I6dHJ1ZSxNYWdu
+ZXRvbWV0ZXI6dHJ1ZSxNZWRpYURldmljZXM6dHJ1ZSxNZWRpYUtleVNlc3Npb246dHJ1ZSxNZWRpYVF1
+ZXJ5TGlzdDp0cnVlLE1lZGlhUmVjb3JkZXI6dHJ1ZSxNZWRpYVNvdXJjZTp0cnVlLE1lZGlhU3RyZWFt
+OnRydWUsTWVkaWFTdHJlYW1UcmFjazp0cnVlLE1JRElBY2Nlc3M6dHJ1ZSxNSURJSW5wdXQ6dHJ1ZSxN
+SURJT3V0cHV0OnRydWUsTUlESVBvcnQ6dHJ1ZSxOZXR3b3JrSW5mb3JtYXRpb246dHJ1ZSxOb3RpZmlj
+YXRpb246dHJ1ZSxPZmZzY3JlZW5DYW52YXM6dHJ1ZSxPcmllbnRhdGlvblNlbnNvcjp0cnVlLFBheW1l
+bnRSZXF1ZXN0OnRydWUsUGVyZm9ybWFuY2U6dHJ1ZSxQZXJtaXNzaW9uU3RhdHVzOnRydWUsUHJlc2Vu
+dGF0aW9uQ29ubmVjdGlvbjp0cnVlLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25MaXN0OnRydWUsUHJlc2Vu
+dGF0aW9uUmVxdWVzdDp0cnVlLFJlbGF0aXZlT3JpZW50YXRpb25TZW5zb3I6dHJ1ZSxSZW1vdGVQbGF5
+YmFjazp0cnVlLFJUQ0RhdGFDaGFubmVsOnRydWUsRGF0YUNoYW5uZWw6dHJ1ZSxSVENEVE1GU2VuZGVy
+OnRydWUsUlRDUGVlckNvbm5lY3Rpb246dHJ1ZSx3ZWJraXRSVENQZWVyQ29ubmVjdGlvbjp0cnVlLG1v
+elJUQ1BlZXJDb25uZWN0aW9uOnRydWUsU2NyZWVuT3JpZW50YXRpb246dHJ1ZSxTZW5zb3I6dHJ1ZSxT
+ZXJ2aWNlV29ya2VyOnRydWUsU2VydmljZVdvcmtlckNvbnRhaW5lcjp0cnVlLFNlcnZpY2VXb3JrZXJS
+ZWdpc3RyYXRpb246dHJ1ZSxTaGFyZWRXb3JrZXI6dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbjp0cnVlLFNw
+ZWVjaFN5bnRoZXNpczp0cnVlLFNwZWVjaFN5bnRoZXNpc1V0dGVyYW5jZTp0cnVlLFZSOnRydWUsVlJE
+ZXZpY2U6dHJ1ZSxWUkRpc3BsYXk6dHJ1ZSxWUlNlc3Npb246dHJ1ZSxWaXN1YWxWaWV3cG9ydDp0cnVl
+LFdlYlNvY2tldDp0cnVlLFdvcmtlcjp0cnVlLFdvcmtlclBlcmZvcm1hbmNlOnRydWUsQmx1ZXRvb3Ro
+RGV2aWNlOnRydWUsQmx1ZXRvb3RoUmVtb3RlR0FUVENoYXJhY3RlcmlzdGljOnRydWUsQ2xpcGJvYXJk
+OnRydWUsTW9qb0ludGVyZmFjZUludGVyY2VwdG9yOnRydWUsVVNCOnRydWUsSURCRGF0YWJhc2U6dHJ1
+ZSxJREJPcGVuREJSZXF1ZXN0OnRydWUsSURCVmVyc2lvbkNoYW5nZVJlcXVlc3Q6dHJ1ZSxJREJSZXF1
+ZXN0OnRydWUsSURCVHJhbnNhY3Rpb246dHJ1ZSxBbmFseXNlck5vZGU6dHJ1ZSxSZWFsdGltZUFuYWx5
+c2VyTm9kZTp0cnVlLEF1ZGlvQnVmZmVyU291cmNlTm9kZTp0cnVlLEF1ZGlvRGVzdGluYXRpb25Ob2Rl
+OnRydWUsQXVkaW9Ob2RlOnRydWUsQXVkaW9TY2hlZHVsZWRTb3VyY2VOb2RlOnRydWUsQXVkaW9Xb3Jr
+bGV0Tm9kZTp0cnVlLEJpcXVhZEZpbHRlck5vZGU6dHJ1ZSxDaGFubmVsTWVyZ2VyTm9kZTp0cnVlLEF1
+ZGlvQ2hhbm5lbE1lcmdlcjp0cnVlLENoYW5uZWxTcGxpdHRlck5vZGU6dHJ1ZSxBdWRpb0NoYW5uZWxT
+cGxpdHRlcjp0cnVlLENvbnN0YW50U291cmNlTm9kZTp0cnVlLENvbnZvbHZlck5vZGU6dHJ1ZSxEZWxh
+eU5vZGU6dHJ1ZSxEeW5hbWljc0NvbXByZXNzb3JOb2RlOnRydWUsR2Fpbk5vZGU6dHJ1ZSxBdWRpb0dh
+aW5Ob2RlOnRydWUsSUlSRmlsdGVyTm9kZTp0cnVlLE1lZGlhRWxlbWVudEF1ZGlvU291cmNlTm9kZTp0
+cnVlLE1lZGlhU3RyZWFtQXVkaW9EZXN0aW5hdGlvbk5vZGU6dHJ1ZSxNZWRpYVN0cmVhbUF1ZGlvU291
+cmNlTm9kZTp0cnVlLE9zY2lsbGF0b3JOb2RlOnRydWUsT3NjaWxsYXRvcjp0cnVlLFBhbm5lck5vZGU6
+dHJ1ZSxBdWRpb1Bhbm5lck5vZGU6dHJ1ZSx3ZWJraXRBdWRpb1Bhbm5lck5vZGU6dHJ1ZSxTY3JpcHRQ
+cm9jZXNzb3JOb2RlOnRydWUsSmF2YVNjcmlwdEF1ZGlvTm9kZTp0cnVlLFN0ZXJlb1Bhbm5lck5vZGU6
+dHJ1ZSxXYXZlU2hhcGVyTm9kZTp0cnVlLEV2ZW50VGFyZ2V0OmZhbHNlLEZpbGU6dHJ1ZSxGaWxlTGlz
+dDp0cnVlLEZpbGVXcml0ZXI6dHJ1ZSxIVE1MRm9ybUVsZW1lbnQ6dHJ1ZSxHYW1lcGFkOnRydWUsR2Ft
+ZXBhZEJ1dHRvbjp0cnVlLEhpc3Rvcnk6dHJ1ZSxIVE1MQ29sbGVjdGlvbjp0cnVlLEhUTUxGb3JtQ29u
+dHJvbHNDb2xsZWN0aW9uOnRydWUsSFRNTE9wdGlvbnNDb2xsZWN0aW9uOnRydWUsSFRNTERvY3VtZW50
+OnRydWUsWE1MSHR0cFJlcXVlc3Q6dHJ1ZSxYTUxIdHRwUmVxdWVzdFVwbG9hZDp0cnVlLFhNTEh0dHBS
+ZXF1ZXN0RXZlbnRUYXJnZXQ6ZmFsc2UsSW1hZ2VEYXRhOnRydWUsSFRNTElucHV0RWxlbWVudDp0cnVl
+LEtleWJvYXJkRXZlbnQ6dHJ1ZSxIVE1MTElFbGVtZW50OnRydWUsTG9jYXRpb246dHJ1ZSxNZWRpYUxp
+c3Q6dHJ1ZSxNZXNzYWdlUG9ydDp0cnVlLEhUTUxNZXRlckVsZW1lbnQ6dHJ1ZSxNSURJSW5wdXRNYXA6
+dHJ1ZSxNSURJT3V0cHV0TWFwOnRydWUsTWltZVR5cGU6dHJ1ZSxNaW1lVHlwZUFycmF5OnRydWUsTW91
+c2VFdmVudDp0cnVlLERyYWdFdmVudDp0cnVlLFBvaW50ZXJFdmVudDp0cnVlLFdoZWVsRXZlbnQ6dHJ1
+ZSxEb2N1bWVudEZyYWdtZW50OnRydWUsU2hhZG93Um9vdDp0cnVlLERvY3VtZW50VHlwZTp0cnVlLE5v
+ZGU6ZmFsc2UsTm9kZUxpc3Q6dHJ1ZSxSYWRpb05vZGVMaXN0OnRydWUsSFRNTE9wdGlvbkVsZW1lbnQ6
+dHJ1ZSxIVE1MT3V0cHV0RWxlbWVudDp0cnVlLEhUTUxQYXJhZ3JhcGhFbGVtZW50OnRydWUsSFRNTFBh
+cmFtRWxlbWVudDp0cnVlLFBsdWdpbjp0cnVlLFBsdWdpbkFycmF5OnRydWUsUHJlc2VudGF0aW9uQXZh
+aWxhYmlsaXR5OnRydWUsSFRNTFByb2dyZXNzRWxlbWVudDp0cnVlLFByb2dyZXNzRXZlbnQ6dHJ1ZSxS
+ZXNvdXJjZVByb2dyZXNzRXZlbnQ6dHJ1ZSxSVENTdGF0c1JlcG9ydDp0cnVlLEhUTUxTZWxlY3RFbGVt
+ZW50OnRydWUsU291cmNlQnVmZmVyOnRydWUsU291cmNlQnVmZmVyTGlzdDp0cnVlLFNwZWVjaEdyYW1t
+YXI6dHJ1ZSxTcGVlY2hHcmFtbWFyTGlzdDp0cnVlLFNwZWVjaFJlY29nbml0aW9uUmVzdWx0OnRydWUs
+U3RvcmFnZTp0cnVlLFN0b3JhZ2VFdmVudDp0cnVlLENTU1N0eWxlU2hlZXQ6dHJ1ZSxTdHlsZVNoZWV0
+OnRydWUsSFRNTFRhYmxlRWxlbWVudDp0cnVlLEhUTUxUYWJsZVJvd0VsZW1lbnQ6dHJ1ZSxIVE1MVGFi
+bGVTZWN0aW9uRWxlbWVudDp0cnVlLEhUTUxUZW1wbGF0ZUVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFyZWFF
+bGVtZW50OnRydWUsVGV4dFRyYWNrOnRydWUsVGV4dFRyYWNrQ3VlOnRydWUsVlRUQ3VlOnRydWUsVGV4
+dFRyYWNrQ3VlTGlzdDp0cnVlLFRleHRUcmFja0xpc3Q6dHJ1ZSxUaW1lUmFuZ2VzOnRydWUsVG91Y2g6
+dHJ1ZSxUb3VjaExpc3Q6dHJ1ZSxUcmFja0RlZmF1bHRMaXN0OnRydWUsQ29tcG9zaXRpb25FdmVudDp0
+cnVlLEZvY3VzRXZlbnQ6dHJ1ZSxUZXh0RXZlbnQ6dHJ1ZSxUb3VjaEV2ZW50OnRydWUsVUlFdmVudDpm
+YWxzZSxVUkw6dHJ1ZSxWaWRlb1RyYWNrTGlzdDp0cnVlLFdpbmRvdzp0cnVlLERPTVdpbmRvdzp0cnVl
+LERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2VydmljZVdvcmtlckdsb2JhbFNjb3BlOnRy
+dWUsU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxXb3JrZXJHbG9iYWxTY29wZTp0cnVlLEF0dHI6
+dHJ1ZSxDU1NSdWxlTGlzdDp0cnVlLENsaWVudFJlY3Q6dHJ1ZSxET01SZWN0OnRydWUsR2FtZXBhZExp
+c3Q6dHJ1ZSxOYW1lZE5vZGVNYXA6dHJ1ZSxNb3pOYW1lZEF0dHJNYXA6dHJ1ZSxTcGVlY2hSZWNvZ25p
+dGlvblJlc3VsdExpc3Q6dHJ1ZSxTdHlsZVNoZWV0TGlzdDp0cnVlLElEQkN1cnNvcjpmYWxzZSxJREJD
+dXJzb3JXaXRoVmFsdWU6dHJ1ZSxJREJLZXlSYW5nZTp0cnVlLElEQk9ic2VydmF0aW9uOnRydWUsU1ZH
+QW5nbGU6dHJ1ZSxTVkdMZW5ndGg6dHJ1ZSxTVkdMZW5ndGhMaXN0OnRydWUsU1ZHTnVtYmVyOnRydWUs
+U1ZHTnVtYmVyTGlzdDp0cnVlLFNWR1BvaW50TGlzdDp0cnVlLFNWR1NjcmlwdEVsZW1lbnQ6dHJ1ZSxT
+VkdTdHJpbmdMaXN0OnRydWUsU1ZHQUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlRWxlbWVudDp0cnVlLFNW
+R0FuaW1hdGVNb3Rpb25FbGVtZW50OnRydWUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6dHJ1ZSxT
+VkdBbmltYXRpb25FbGVtZW50OnRydWUsU1ZHQ2lyY2xlRWxlbWVudDp0cnVlLFNWR0NsaXBQYXRoRWxl
+bWVudDp0cnVlLFNWR0RlZnNFbGVtZW50OnRydWUsU1ZHRGVzY0VsZW1lbnQ6dHJ1ZSxTVkdEaXNjYXJk
+RWxlbWVudDp0cnVlLFNWR0VsbGlwc2VFbGVtZW50OnRydWUsU1ZHRkVCbGVuZEVsZW1lbnQ6dHJ1ZSxT
+VkdGRUNvbG9yTWF0cml4RWxlbWVudDp0cnVlLFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50OnRy
+dWUsU1ZHRkVDb21wb3NpdGVFbGVtZW50OnRydWUsU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6dHJ1
+ZSxTVkdGRURpZmZ1c2VMaWdodGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRURpc3BsYWNlbWVudE1hcEVsZW1l
+bnQ6dHJ1ZSxTVkdGRURpc3RhbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRUZsb29kRWxlbWVudDp0cnVl
+LFNWR0ZFRnVuY0FFbGVtZW50OnRydWUsU1ZHRkVGdW5jQkVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNHRWxl
+bWVudDp0cnVlLFNWR0ZFRnVuY1JFbGVtZW50OnRydWUsU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50OnRy
+dWUsU1ZHRkVJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1lcmdlRWxlbWVudDp0cnVlLFNWR0ZFTWVyZ2VO
+b2RlRWxlbWVudDp0cnVlLFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6dHJ1ZSxTVkdGRU9mZnNldEVsZW1l
+bnQ6dHJ1ZSxTVkdGRVBvaW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVTcGVjdWxhckxpZ2h0aW5nRWxl
+bWVudDp0cnVlLFNWR0ZFU3BvdExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFVGlsZUVsZW1lbnQ6dHJ1ZSxT
+VkdGRVR1cmJ1bGVuY2VFbGVtZW50OnRydWUsU1ZHRmlsdGVyRWxlbWVudDp0cnVlLFNWR0ZvcmVpZ25P
+YmplY3RFbGVtZW50OnRydWUsU1ZHR0VsZW1lbnQ6dHJ1ZSxTVkdHZW9tZXRyeUVsZW1lbnQ6dHJ1ZSxT
+VkdHcmFwaGljc0VsZW1lbnQ6dHJ1ZSxTVkdJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5lRWxlbWVudDp0
+cnVlLFNWR0xpbmVhckdyYWRpZW50RWxlbWVudDp0cnVlLFNWR01hcmtlckVsZW1lbnQ6dHJ1ZSxTVkdN
+YXNrRWxlbWVudDp0cnVlLFNWR01ldGFkYXRhRWxlbWVudDp0cnVlLFNWR1BhdGhFbGVtZW50OnRydWUs
+U1ZHUGF0dGVybkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5Z29uRWxlbWVudDp0cnVlLFNWR1BvbHlsaW5lRWxl
+bWVudDp0cnVlLFNWR1JhZGlhbEdyYWRpZW50RWxlbWVudDp0cnVlLFNWR1JlY3RFbGVtZW50OnRydWUs
+U1ZHU2V0RWxlbWVudDp0cnVlLFNWR1N0b3BFbGVtZW50OnRydWUsU1ZHU3R5bGVFbGVtZW50OnRydWUs
+U1ZHU1ZHRWxlbWVudDp0cnVlLFNWR1N3aXRjaEVsZW1lbnQ6dHJ1ZSxTVkdTeW1ib2xFbGVtZW50OnRy
+dWUsU1ZHVFNwYW5FbGVtZW50OnRydWUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OnRydWUsU1ZHVGV4dEVs
+ZW1lbnQ6dHJ1ZSxTVkdUZXh0UGF0aEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UG9zaXRpb25pbmdFbGVtZW50
+OnRydWUsU1ZHVGl0bGVFbGVtZW50OnRydWUsU1ZHVXNlRWxlbWVudDp0cnVlLFNWR1ZpZXdFbGVtZW50
+OnRydWUsU1ZHR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlvbkVs
+ZW1lbnQ6dHJ1ZSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OnRydWUsU1ZHTVBhdGhFbGVtZW50OnRydWUs
+U1ZHRWxlbWVudDpmYWxzZSxTVkdUcmFuc2Zvcm06dHJ1ZSxTVkdUcmFuc2Zvcm1MaXN0OnRydWUsQXVk
+aW9CdWZmZXI6dHJ1ZSxBdWRpb1BhcmFtOnRydWUsQXVkaW9QYXJhbU1hcDp0cnVlLEF1ZGlvVHJhY2tM
+aXN0OnRydWUsQXVkaW9Db250ZXh0OnRydWUsd2Via2l0QXVkaW9Db250ZXh0OnRydWUsQmFzZUF1ZGlv
+Q29udGV4dDpmYWxzZSxPZmZsaW5lQXVkaW9Db250ZXh0OnRydWUsU1FMUmVzdWx0U2V0Um93TGlzdDp0
+cnVlfSkKSC5iMC4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlJHLiRuYXRp
+dmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguVlAuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9
+IkFycmF5QnVmZmVyVmlldyIKSC5EZy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3
+IgpILldCLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguWkcuJG5hdGl2ZVN1
+cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5QZy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJy
+YXlCdWZmZXJWaWV3IgpXLm9ILiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJFdmVudFRhcmdldCIKVy5DRS4k
+bmF0aXZlU3VwZXJjbGFzc1RhZz0iRXZlbnRUYXJnZXQiClcuUVYuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9
+IkV2ZW50VGFyZ2V0IgpXLkF3LiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJFdmVudFRhcmdldCJ9KSgpCmNv
+bnZlcnRBbGxUb0Zhc3RPYmplY3QodykKY29udmVydFRvRmFzdE9iamVjdCgkKTsoZnVuY3Rpb24oYSl7
+aWYodHlwZW9mIGRvY3VtZW50PT09InVuZGVmaW5lZCIpe2EobnVsbCkKcmV0dXJufWlmKHR5cGVvZiBk
+b2N1bWVudC5jdXJyZW50U2NyaXB0IT0ndW5kZWZpbmVkJyl7YShkb2N1bWVudC5jdXJyZW50U2NyaXB0
+KQpyZXR1cm59dmFyIHQ9ZG9jdW1lbnQuc2NyaXB0cwpmdW5jdGlvbiBvbkxvYWQoYil7Zm9yKHZhciBy
+PTA7cjx0Lmxlbmd0aDsrK3IpdFtyXS5yZW1vdmVFdmVudExpc3RlbmVyKCJsb2FkIixvbkxvYWQsZmFs
+c2UpCmEoYi50YXJnZXQpfWZvcih2YXIgcz0wO3M8dC5sZW5ndGg7KytzKXRbc10uYWRkRXZlbnRMaXN0
+ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKX0pKGZ1bmN0aW9uKGEpe3YuY3VycmVudFNjcmlwdD1hCmlm
+KHR5cGVvZiBkYXJ0TWFpblJ1bm5lcj09PSJmdW5jdGlvbiIpZGFydE1haW5SdW5uZXIoTC5EZSxbXSkK
+ZWxzZSBMLkRlKFtdKX0pfSkoKQovLyMgc291cmNlTWFwcGluZ1VSTD1taWdyYXRpb24uanMubWFwCg==
 ''';
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart
index b85ff1d..aabfdd8 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart
@@ -7,6 +7,8 @@
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/web/file_details.dart';
+import 'package:meta/meta.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:path/path.dart' as path;
 
 /// Instrumentation display output for a library that was migrated to use
@@ -17,6 +19,24 @@
   static const HtmlEscape _htmlEscape =
       HtmlEscape(HtmlEscapeMode(escapeLtGt: true));
 
+  /// List of kinds of nullability fixes that should be displayed in the
+  /// "proposed edits" area, in the order in which they should be displayed.
+  @visibleForTesting
+  static const List<NullabilityFixKind> kindPriorityOrder = [
+    NullabilityFixKind.removeDeadCode,
+    NullabilityFixKind.otherCastExpression,
+    NullabilityFixKind.checkExpression,
+    NullabilityFixKind.addRequired,
+    NullabilityFixKind.makeTypeNullable,
+    NullabilityFixKind.downcastExpression,
+    NullabilityFixKind.addType,
+    NullabilityFixKind.replaceVar,
+    NullabilityFixKind.removeAs,
+    NullabilityFixKind.checkExpressionDueToHint,
+    NullabilityFixKind.makeTypeNullableDueToHint,
+    NullabilityFixKind.removeLanguageVersionComment
+  ];
+
   /// Displays information for a compilation unit.
   final UnitInfo unitInfo;
 
@@ -44,13 +64,26 @@
   }
 
   /// Returns the list of edits, as JSON.
-  List<EditListItem> _computeEditList() {
-    return unitInfo.fixRegions.map((RegionInfo region) {
-      return EditListItem(
-          line: region.lineNumber,
-          explanation: region.explanation,
-          offset: region.offset);
-    }).toList();
+  Map<String, List<EditListItem>> _computeEditList() {
+    var editListsByKind = <NullabilityFixKind, List<EditListItem>>{};
+    for (var region in unitInfo.fixRegions) {
+      var kind = region.kind;
+      if (kind != null) {
+        (editListsByKind[kind] ??= []).add(EditListItem(
+            line: region.lineNumber,
+            explanation: region.explanation,
+            offset: region.offset));
+      }
+    }
+    // Order the lists and filter out empty categories.
+    var result = <String, List<EditListItem>>{};
+    for (var kind in kindPriorityOrder) {
+      var edits = editListsByKind[kind];
+      if (edits != null) {
+        result[_headerForKind(kind, edits.length)] = edits;
+      }
+    }
+    return result;
   }
 
   /// Returns the content of the file with navigation links and anchors added.
@@ -188,8 +221,8 @@
       if (offset > previousOffset) {
         // Display a region of unmodified content.
         writeSplitLines(content.substring(previousOffset, offset));
-        previousOffset = offset + length;
       }
+      previousOffset = offset + length;
       var regionClass = classForRegion(region.regionType);
       var regionSpanTag = '<span class="region $regionClass" '
           'data-offset="$offset" data-line="$lineNumber">';
@@ -204,6 +237,43 @@
     return regions.toString();
   }
 
+  String _headerForKind(NullabilityFixKind kind, int count) {
+    var s = count == 1 ? '' : 's';
+    switch (kind) {
+      case NullabilityFixKind.addRequired:
+        return '$count required keyword$s added';
+      case NullabilityFixKind.downcastExpression:
+        return '$count downcast$s added';
+      case NullabilityFixKind.otherCastExpression:
+        return '$count cast$s (non-downcast) added';
+      case NullabilityFixKind.checkExpression:
+        return '$count null check$s added';
+      case NullabilityFixKind.checkExpressionDueToHint:
+        return '$count null check hint$s converted to null check$s';
+      case NullabilityFixKind.addType:
+        return '$count type$s added';
+      case NullabilityFixKind.makeTypeNullable:
+        return '$count type$s made nullable';
+      case NullabilityFixKind.makeTypeNullableDueToHint:
+        return '$count nullability hint$s converted to ?$s';
+      case NullabilityFixKind.removeAs:
+        return '$count cast$s now unnecessary';
+      case NullabilityFixKind.removeDeadCode:
+        // TODO(paulberry): when we change to not removing dead code, change
+        // this description string.
+        return '$count dead code removal$s';
+      case NullabilityFixKind.removeLanguageVersionComment:
+        return '$count language version comment$s removed';
+      case NullabilityFixKind.replaceVar:
+        return "$count 'var' declaration$s replaced";
+      case NullabilityFixKind.typeNotMadeNullable:
+        return '$count type$s not made nullable';
+      case NullabilityFixKind.typeNotMadeNullableDueToHint:
+        return '$count type$s not made nullable due to hint$s';
+    }
+    throw StateError('Null kind');
+  }
+
   /// Returns the URL that will navigate to the given [target] in the file at
   /// the given [relativePath].
   String _uriForRelativePath(String relativePath, NavigationTarget target) {
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/edit_details.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/edit_details.dart
index 6c7afbd..f74657f 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/edit_details.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/edit_details.dart
@@ -7,10 +7,6 @@
 /// Information about what should be populated into the "Edit Details" view of
 /// the migration preview tool.
 class EditDetails {
-  /// A list of the bulleted items that should be displayed as rationale for the
-  /// edit.
-  final List<EditRationale> details;
-
   /// A list of edits that can be offered to the user related to this source
   /// location (e.g. adding/removing hints).  `null` if this feature is
   /// disabled.
@@ -30,25 +26,20 @@
   final List<Trace> traces;
 
   EditDetails(
-      {@required this.details,
-      this.edits,
+      {this.edits,
       @required this.explanation,
       @required this.line,
       @required this.path,
       this.traces = const []});
 
   EditDetails.fromJson(dynamic json)
-      : details = [
-          for (var detail in json['details']) EditRationale.fromJson(detail)
-        ],
-        edits = _decodeEdits(json['edits']),
+      : edits = _decodeEdits(json['edits']),
         explanation = json['explanation'],
         line = json['line'],
         path = json['path'],
         traces = _decodeTraces(json['traces']);
 
   Map<String, Object> toJson() => {
-        'details': [for (var detail in details) detail.toJson()],
         if (edits != null) 'edits': [for (var edit in edits) edit.toJson()],
         'explanation': explanation,
         'line': line,
@@ -87,30 +78,6 @@
       };
 }
 
-/// Information about what should be populated into a single "rational" bullet
-/// item in the "Edit Details" view of the migration preview tool.
-class EditRationale {
-  /// Description of the rationale.
-  final String description;
-
-  /// Link the user may click to see the source code in question.  May be null.
-  final TargetLink link;
-
-  EditRationale({@required this.description, this.link});
-
-  EditRationale.fromJson(dynamic json)
-      : description = json['description'],
-        link = _decodeLink(json['link']);
-
-  Map<String, Object> toJson() => {
-        'description': description,
-        if (link != null) 'link': link.toJson(),
-      };
-
-  static TargetLink _decodeLink(dynamic json) =>
-      json == null ? null : TargetLink.fromJson(json);
-}
-
 /// Information about a single link that should be included in the
 /// "Edit Details" view of the migration preview tool, where the purpose of the
 /// link is to allow the user to navigate to a source file containing
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/file_details.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/file_details.dart
index 7d0276f..cee2167 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/file_details.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/file_details.dart
@@ -46,7 +46,11 @@
   final String sourceCode;
 
   /// Items that should show up in the "proposed edits" panel for the file.
-  final List<EditListItem> edits;
+  ///
+  /// Map keys are headers, and values are the list of edits under each header.
+  /// Map order is important--entries appearing earlier in the map are
+  /// considered more likely to be of interest to the user.
+  final Map<String, List<EditListItem>> edits;
 
   FileDetails(
       {@required this.regions,
@@ -58,18 +62,26 @@
       : regions = '',
         navigationContent = '',
         sourceCode = '',
-        edits = const [];
+        edits = const {};
 
   FileDetails.fromJson(dynamic json)
       : regions = json['regions'],
         navigationContent = json['navigationContent'],
         sourceCode = json['sourceCode'],
-        edits = [for (var edit in json['edits']) EditListItem.fromJson(edit)];
+        edits = {
+          for (var entry in json['edits'].entries)
+            entry.key: [
+              for (var edit in entry.value) EditListItem.fromJson(edit)
+            ]
+        };
 
   Map<String, Object> toJson() => {
         'regions': regions,
         'navigationContent': navigationContent,
         'sourceCode': sourceCode,
-        'edits': [for (var edit in edits) edit.toJson()]
+        'edits': {
+          for (var entry in edits.entries)
+            entry.key: [for (var edit in entry.value) edit.toJson()]
+        }
       };
 }
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart
index 4dc2537..4423317 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart
@@ -217,19 +217,16 @@
   // Don't navigate on link click.
   event.preventDefault();
 
-  document.body.classes.add('rerunning');
-
   try {
     // Directing the server to produce an edit; request it, then do work with the
     // response.
     await doPost(path);
+    // TODO(mfairhurst): Only refresh the regions/dart code, not the window.
     (document.window.location as Location).reload();
   } catch (e, st) {
     logError('handlePostLinkClick: $e', st);
 
     window.alert('Could not load $path ($e).');
-  } finally {
-    document.body.classes.remove('rerunning');
   }
 }
 
@@ -446,40 +443,42 @@
   explanation.scrollIntoView();
   _populateEditTraces(response, editPanel, parentDirectory);
   _populateEditLinks(response, editPanel);
-  _populateEditRationale(response, editPanel, parentDirectory);
 }
 
 /// Write the contents of the Edit List, from JSON data [editListData].
 void populateProposedEdits(
-    String path, List<EditListItem> edits, bool clearEditDetails) {
+    String path, Map<String, List<EditListItem>> edits, bool clearEditDetails) {
   editListElement.innerHtml = '';
 
-  Element p = editListElement.append(document.createElement('p'));
   var editCount = edits.length;
   if (editCount == 0) {
+    Element p = editListElement.append(document.createElement('p'));
     p.append(Text('No proposed edits'));
   } else {
-    p.append(Text('$editCount proposed ${pluralize(editCount, 'edit')}:'));
-  }
+    for (var entry in edits.entries) {
+      Element p = editListElement.append(document.createElement('p'));
+      p.append(Text('${entry.key}:'));
 
-  Element list = editListElement.append(document.createElement('ul'));
-  for (var edit in edits) {
-    Element item = list.append(document.createElement('li'));
-    item.classes.add('edit');
-    AnchorElement anchor = item.append(document.createElement('a'));
-    anchor.classes.add('edit-link');
-    var offset = edit.offset;
-    anchor.dataset['offset'] = '$offset';
-    var line = edit.line;
-    anchor.dataset['line'] = '$line';
-    anchor.append(Text('line $line'));
-    anchor.onClick.listen((MouseEvent event) {
-      navigate(window.location.pathname, offset, line, true, callback: () {
-        pushState(window.location.pathname, offset, line);
-      });
-      loadAndPopulateEditDetails(path, offset, line);
-    });
-    item.append(Text(': ${edit.explanation}'));
+      Element list = editListElement.append(document.createElement('ul'));
+      for (var edit in entry.value) {
+        Element item = list.append(document.createElement('li'));
+        item.classes.add('edit');
+        AnchorElement anchor = item.append(document.createElement('a'));
+        anchor.classes.add('edit-link');
+        var offset = edit.offset;
+        anchor.dataset['offset'] = '$offset';
+        var line = edit.line;
+        anchor.dataset['line'] = '$line';
+        anchor.append(Text('line $line'));
+        anchor.onClick.listen((MouseEvent event) {
+          navigate(window.location.pathname, offset, line, true, callback: () {
+            pushState(window.location.pathname, offset, line);
+          });
+          loadAndPopulateEditDetails(path, offset, line);
+        });
+        item.append(Text(': ${edit.explanation}'));
+      }
+    }
   }
 
   if (clearEditDetails) {
@@ -609,8 +608,8 @@
 
 void _populateEditLinks(EditDetails response, Element editPanel) {
   if (response.edits != null) {
+    Element editParagraph = editPanel.append(document.createElement('p'));
     for (var edit in response.edits) {
-      Element editParagraph = editPanel.append(document.createElement('p'));
       Element a = editParagraph.append(document.createElement('a'));
       a.append(Text(edit.description));
       a.setAttribute('href', edit.href);
@@ -619,30 +618,6 @@
   }
 }
 
-void _populateEditRationale(
-    EditDetails response, Element editPanel, String parentDirectory) {
-  var detailCount = response.details.length;
-  if (detailCount == 0) {
-    // Having 0 details is not necessarily an expected possibility, but handling
-    // the possibility prevents awkward text, "for 0 reasons:".
-  } else {
-    editPanel
-        .append(ParagraphElement()..text = 'Edit rationale (experimental):');
-
-    Element detailList = editPanel.append(document.createElement('ul'));
-    for (var detail in response.details) {
-      var detailItem = detailList.append(document.createElement('li'));
-      detailItem.append(Text(detail.description));
-      var link = detail.link;
-      if (link != null) {
-        detailItem.append(Text(' ('));
-        detailItem.append(_aElementForLink(link, parentDirectory));
-        detailItem.append(Text(')'));
-      }
-    }
-  }
-}
-
 void _populateEditTraces(
     EditDetails response, Element editPanel, String parentDirectory) {
   for (var trace in response.traces) {
@@ -655,10 +630,11 @@
     var ul = traceParagraph
         .append(document.createElement('ul')..classes = ['trace']);
     for (var entry in trace.entries) {
-      var li = ul.append(document.createElement('li')..innerHtml = '&#x274F; ');
+      Element li =
+          ul.append(document.createElement('li')..innerHtml = '&#x274F; ');
       li.append(document.createElement('span')
         ..classes = ['function']
-        ..append(Text(entry.function ?? 'unknown')));
+        ..appendTextWithBreaks(entry.function ?? 'unknown'));
       var link = entry.link;
       if (link != null) {
         li.append(Text(' ('));
@@ -666,7 +642,7 @@
         li.append(Text(')'));
       }
       li.append(Text(': '));
-      li.append(Text(entry.description));
+      li.appendTextWithBreaks(entry.description ?? 'unknown');
     }
   }
 }
@@ -688,3 +664,17 @@
     element.setInnerHtml(html, validator: instance);
   }
 }
+
+/// An extension on Element that fits into cascades.
+extension on Element {
+  /// Append [text] to this, inserting a word break before each '.' character.
+  void appendTextWithBreaks(String text) {
+    var textParts = text.split('.');
+    append(Text(textParts.first));
+    for (var substring in textParts.skip(1)) {
+      // Replace the '.' with a zero-width space and a '.'.
+      appendHtml('&#8203;.');
+      append(Text(substring));
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart b/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart
index caf4d48..ccdcde1 100644
--- a/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart
@@ -35,8 +35,13 @@
   // A function which allows the migration to be rerun, taking changed paths.
   final Future<MigrationState> Function([List<String>]) rerunFunction;
 
+  /// Integer for a port to run the preview server on.  If null or zero, allow
+  /// [HttpServer.bind] to pick one.
+  final int preferredPort;
+
   /// Initialize a newly created HTTP server.
-  HttpPreviewServer(this.migrationState, this.rerunFunction);
+  HttpPreviewServer(
+      this.migrationState, this.rerunFunction, this.preferredPort);
 
   Future<String> get authToken async {
     await _serverFuture;
@@ -56,14 +61,14 @@
   }
 
   /// Begin serving HTTP requests over the given port.
-  Future<int> serveHttp([int initialPort]) async {
+  Future<int> serveHttp() async {
     if (_serverFuture != null) {
       return boundPort;
     }
 
     try {
       _serverFuture =
-          HttpServer.bind(InternetAddress.loopbackIPv4, initialPort ?? 0);
+          HttpServer.bind(InternetAddress.loopbackIPv4, preferredPort ?? 0);
 
       var server = await _serverFuture;
       _handleServer(server);
@@ -72,8 +77,8 @@
       // If we can't bind to the specified port, don't remember the broken
       // server.
       _serverFuture = null;
-
-      return null;
+      // TODO(jcollins-g): Display a better error message?
+      rethrow;
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/edit/preview/index_file_page.dart b/pkg/analysis_server/lib/src/edit/preview/index_file_page.dart
index d3e5fa5..7931445 100644
--- a/pkg/analysis_server/lib/src/edit/preview/index_file_page.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/index_file_page.dart
@@ -23,7 +23,7 @@
   @override
   Future<void> generatePage(Map<String, String> params) async {
     var renderer = InstrumentationRenderer(site.migrationInfo, site.pathMapper,
-        site.migrationState.hasBeenApplied);
+        site.migrationState.hasBeenApplied, site.migrationState.needsRerun);
     buf.write(renderer.render());
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/preview/preview_site.dart b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
index cdbb8fb..3cebbbf 100644
--- a/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
@@ -197,6 +197,15 @@
 
     final edits = migrationState.listener.sourceChange.edits;
 
+    // Perform a full check that no files have changed before touching the disk.
+    for (final fileEdit in edits) {
+      final file = pathMapper.provider.getFile(fileEdit.file);
+      var code = file.exists ? file.readAsStringSync() : '';
+      if (!unitInfoMap[file.path].hadDiskContent(code)) {
+        throw StateError('${file.path} has changed, rerun migration to apply.');
+      }
+    }
+
     // Eagerly mark the migration applied. If this throws, we cannot go back.
     migrationState.markApplied();
     for (final fileEdit in edits) {
@@ -213,15 +222,30 @@
     // Update the code on disk.
     //
     var params = uri.queryParameters;
-    var path = uri.path;
+    var path = Uri.parse(uri.path).toFilePath();
     var offset = int.parse(params['offset']);
     var end = int.parse(params['end']);
     var replacement = params['replacement'];
     var file = pathMapper.provider.getFile(path);
-    var oldContent = file.readAsStringSync();
-    var newContent = oldContent.replaceRange(offset, end, replacement);
+    var diskContent = file.readAsStringSync();
+    if (!unitInfoMap[path].hadDiskContent(diskContent)) {
+      throw StateError(
+          'Cannot add hint, $path has changed. Rerun migration and try again.');
+    }
+    final unitInfo = unitInfoMap[path];
+    final diskMapper = unitInfo.diskChangesOffsetMapper;
+    final insertionOnly = offset == end;
+    if (insertionOnly) {
+      unitInfo.handleInsertion(offset, replacement);
+      migrationState.needsRerun = true;
+    }
+    var newContent = diskContent.replaceRange(
+        diskMapper.map(offset), diskMapper.map(end), replacement);
     file.writeAsStringSync(newContent);
-    await rerunMigration([path]);
+    unitInfo.diskContent = newContent;
+    if (!insertionOnly) {
+      await rerunMigration([path]);
+    }
   }
 
   Future<void> rerunMigration([List<String> changedPaths]) async {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
index dfa4dba..0997d44 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -6,11 +6,16 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart'
+    hide AnalysisGetNavigationParams;
 import 'package:analysis_server/src/domains/analysis/navigation_dart.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/plugin/result_merger.dart';
 import 'package:analysis_server/src/protocol_server.dart' show NavigationTarget;
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
 
 class DefinitionHandler
@@ -23,30 +28,77 @@
   LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
       TextDocumentPositionParams.jsonHandler;
 
+  Future<List<AnalysisNavigationParams>> getPluginResults(
+    String path,
+    int offset,
+  ) async {
+    // LSP requests must be converted to DAS-protocol requests for compatibility
+    // with plugins.
+    final requestParams = plugin.AnalysisGetNavigationParams(path, offset, 0);
+
+    final driver = server.getAnalysisDriver(path);
+    final pluginFutures = server.pluginManager
+        .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
+
+    final responses =
+        await waitForResponses(pluginFutures, requestParameters: requestParams);
+
+    return responses
+        .map((response) =>
+            plugin.AnalysisGetNavigationResult.fromResponse(response))
+        .map((result) => AnalysisNavigationParams(
+            path, result.regions, result.targets, result.files))
+        .toList();
+  }
+
+  Future<AnalysisNavigationParams> getServerResult(
+      String path, int offset) async {
+    final collector = NavigationCollectorImpl();
+
+    final result = await server.getResolvedUnit(path);
+    if (result?.state == ResultState.VALID) {
+      computeDartNavigation(
+          server.resourceProvider, collector, result.unit, offset, 0);
+    }
+
+    return AnalysisNavigationParams(
+        path, collector.regions, collector.targets, collector.files);
+  }
+
   @override
   Future<ErrorOr<List<Location>>> handle(
       TextDocumentPositionParams params, CancellationToken token) async {
-    if (!isDartDocument(params.textDocument)) {
-      return success(const []);
-    }
-
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
-    final unit = await path.mapResult(requireResolvedUnit);
-    final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
 
-    return offset.mapResult((offset) {
-      var collector = NavigationCollectorImpl();
-      computeDartNavigation(
-          server.resourceProvider, collector, unit.result.unit, offset, 0);
-
-      Location toLocation(NavigationTarget target) {
-        final targetFilePath = collector.files[target.fileIndex];
-        final lineInfo = server.getLineInfo(targetFilePath);
-        return navigationTargetToLocation(targetFilePath, target, lineInfo);
+    return path.mapResult((path) async {
+      final lineInfo = server.getLineInfo(path);
+      // If there is no lineInfo, the request canot be translated from LSP line/col
+      // to server offset/length.
+      if (lineInfo == null) {
+        return success(const []);
       }
 
-      return success(convert(collector.targets, toLocation).toList());
+      final offset = toOffset(lineInfo, pos);
+
+      return offset.mapResult((offset) async {
+        final allResults = [
+          await getServerResult(path, offset),
+          ...await getPluginResults(path, offset),
+        ];
+
+        final merger = ResultMerger();
+        final mergedResults = merger.mergeNavigation(allResults);
+        final mergedTargets = mergedResults?.targets ?? [];
+
+        Location toLocation(NavigationTarget target) {
+          final targetFilePath = mergedResults.files[target.fileIndex];
+          final lineInfo = server.getLineInfo(targetFilePath);
+          return navigationTargetToLocation(targetFilePath, target, lineInfo);
+        }
+
+        return success(convert(mergedTargets, toLocation).toList());
+      });
     });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
index b25a5d8..4d36a7e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -6,6 +6,7 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/domain_abstract.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_cancel_request.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_reject.dart';
@@ -68,7 +69,8 @@
 /// An object that can handle messages and produce responses for requests.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class MessageHandler<P, R> with Handler<P, R> {
+abstract class MessageHandler<P, R>
+    with Handler<P, R>, RequestHandlerMixin<LspAnalysisServer> {
   MessageHandler(LspAnalysisServer server) {
     this.server = server;
   }
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 0145248..c91a44c 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 import 'dart:collection';
-import 'dart:io' as io;
 
 import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -18,7 +17,6 @@
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domain_completion.dart'
     show CompletionDomainHandler;
-import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
 import 'package:analysis_server/src/flutter/flutter_outline_computer.dart';
 import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
@@ -32,9 +30,6 @@
 import 'package:analysis_server/src/services/completion/completion_performance.dart'
     show CompletionPerformance;
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analysis_server/src/services/search/search_engine_internal.dart';
-import 'package:analysis_server/src/utilities/null_string_sink.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -44,11 +39,9 @@
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/status.dart' as nd;
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:watcher/watcher.dart';
 
 /// Instances of the class [LspAnalysisServer] implement an LSP-based server
@@ -66,21 +59,6 @@
   /// be sent.
   final LspServerCommunicationChannel channel;
 
-  /// The [SearchEngine] for this server, may be `null` if indexing is disabled.
-  SearchEngine searchEngine;
-
-  final NotificationManager notificationManager = NullNotificationManager();
-
-  /// The object used to manage the SDK's known to this server.
-  final DartSdkManager sdkManager;
-
-  /// The instrumentation service that is to be used by this analysis server.
-  final InstrumentationService instrumentationService;
-
-  /// The default options used to create new analysis contexts. This object is
-  /// also referenced by the ContextManager.
-  final AnalysisOptionsImpl defaultContextOptions = AnalysisOptionsImpl();
-
   /// The workspace for rename refactorings. Should be accessed through the
   /// refactoringWorkspace getter to be automatically created (lazily).
   RefactoringWorkspace _refactoringWorkspace;
@@ -94,8 +72,6 @@
   /// not known.
   final Map<String, VersionedTextDocumentIdentifier> documentVersions = {};
 
-  PerformanceLog _analysisPerformanceLogger;
-
   ServerStateMessageHandler messageHandler;
 
   int nextRequestId = 1;
@@ -118,50 +94,26 @@
     this.channel,
     ResourceProvider baseResourceProvider,
     AnalysisServerOptions options,
-    this.sdkManager,
+    DartSdkManager sdkManager,
     CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
-    this.instrumentationService, {
+    InstrumentationService instrumentationService, {
     DiagnosticServer diagnosticServer,
-  }) : super(options, diagnosticServer, crashReportingAttachmentsBuilder,
-            baseResourceProvider) {
+  }) : super(
+            options,
+            sdkManager,
+            diagnosticServer,
+            crashReportingAttachmentsBuilder,
+            baseResourceProvider,
+            instrumentationService,
+            NullNotificationManager()) {
     messageHandler = UninitializedStateMessageHandler(this);
-    // TODO(dantup): This code is almost identical to AnalysisServer, consider
-    // moving it the base class that already holds many of these fields.
-    defaultContextOptions.generateImplicitErrors = false;
-    defaultContextOptions.useFastaParser = options.useFastaParser;
 
-    {
-      var name = options.newAnalysisDriverLog;
-      StringSink sink = NullStringSink();
-      if (name != null) {
-        if (name == 'stdout') {
-          sink = io.stdout;
-        } else if (name.startsWith('file:')) {
-          var path = name.substring('file:'.length);
-          sink = io.File(path).openWrite(mode: io.FileMode.append);
-        }
-      }
-      _analysisPerformanceLogger = PerformanceLog(sink);
-    }
-    byteStore = createByteStore(resourceProvider);
-    analysisDriverScheduler =
-        nd.AnalysisDriverScheduler(_analysisPerformanceLogger);
-    analysisDriverScheduler.status.listen(sendStatusNotification);
-    analysisDriverScheduler.start();
-
-    if (options.featureSet.completion) {
-      declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
-      declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
-      analysisDriverScheduler.outOfBandWorker =
-          CompletionLibrariesWorker(declarationsTracker);
-    }
-
-    contextManager = ContextManagerImpl(resourceProvider, sdkManager,
-        analyzedFilesGlobs, instrumentationService, defaultContextOptions);
     final contextManagerCallbacks =
         LspServerContextManagerCallbacks(this, resourceProvider);
     contextManager.callbacks = contextManagerCallbacks;
-    searchEngine = SearchEngineImpl(driverMap.values);
+
+    analysisDriverScheduler.status.listen(sendStatusNotification);
+    analysisDriverScheduler.start();
 
     channel.listen(handleMessage, onDone: done, onError: socketError);
   }
@@ -193,10 +145,6 @@
   /// analyzed in one of the analysis drivers to which the file was added,
   /// otherwise in the first driver, otherwise `null` is returned.
   LineInfo getLineInfo(String path) {
-    if (!AnalysisEngine.isDartFileName(path)) {
-      return null;
-    }
-
     return getAnalysisDriver(path)?.getFileSync(path)?.lineInfo;
   }
 
@@ -673,7 +621,7 @@
   void broadcastWatchEvent(WatchEvent event) {
     analysisServer.notifyDeclarationsTracker(event.path);
     analysisServer.notifyFlutterWidgetDescriptions(event.path);
-    // TODO: implement plugin broadcastWatchEvent
+    analysisServer.pluginManager.broadcastWatchEvent(event);
   }
 
   @override
@@ -701,7 +649,7 @@
         resourceProvider, analysisServer.sdkManager, null,
         options: builderOptions);
     builder.analysisDriverScheduler = analysisServer.analysisDriverScheduler;
-    builder.performanceLog = analysisServer._analysisPerformanceLogger;
+    builder.performanceLog = analysisServer.analysisPerformanceLogger;
     builder.byteStore = analysisServer.byteStore;
     builder.enableIndex = true;
     return builder;
diff --git a/pkg/analysis_server/lib/src/plugin/notification_manager.dart b/pkg/analysis_server/lib/src/plugin/notification_manager.dart
index b1a4b44..c7987a2 100644
--- a/pkg/analysis_server/lib/src/plugin/notification_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/notification_manager.dart
@@ -9,11 +9,11 @@
 import 'package:analysis_server/src/plugin/result_collector.dart';
 import 'package:analysis_server/src/plugin/result_converter.dart';
 import 'package:analysis_server/src/plugin/result_merger.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
+import 'package:path/path.dart';
 
 /// The object used to coordinate the results of notifications from the analysis
 /// server and multiple plugins.
@@ -24,8 +24,8 @@
   /// The channel used to send notifications to the client.
   final ServerCommunicationChannel channel;
 
-  /// The resource provider used to get the path context.
-  final ResourceProvider provider;
+  /// The path context.
+  final Context pathContext;
 
   /// A list of the paths of files and directories that are included for
   /// analysis.
@@ -66,7 +66,7 @@
   final ResultMerger merger = ResultMerger();
 
   /// Initialize a newly created notification manager.
-  NotificationManager(this.channel, this.provider) {
+  NotificationManager(this.channel, this.pathContext) {
     errors =
         ResultCollector<List<AnalysisError>>(serverId, predicate: _isIncluded);
     folding = ResultCollector<List<FoldingRegion>>(serverId);
@@ -277,8 +277,8 @@
   bool _isIncluded(String path) {
     bool isIncluded() {
       for (var includedPath in includedPaths) {
-        if (provider.pathContext.isWithin(includedPath, path) ||
-            provider.pathContext.equals(includedPath, path)) {
+        if (pathContext.isWithin(includedPath, path) ||
+            pathContext.equals(includedPath, path)) {
           return true;
         }
       }
@@ -287,7 +287,7 @@
 
     bool isExcluded() {
       for (var excludedPath in excludedPaths) {
-        if (provider.pathContext.isWithin(excludedPath, path)) {
+        if (pathContext.isWithin(excludedPath, path)) {
           return true;
         }
       }
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index 5e20c2b..ebb6ea1 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -10,6 +10,7 @@
 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/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
@@ -34,6 +35,9 @@
   /// context, or `null` if the context does not impose any type.
   DartType get contextType;
 
+  /// Return the object used to resolve macros in Dartdoc comments.
+  DartdocDirectiveInfo get dartdocDirectiveInfo;
+
   /// Return the expression to the right of the "dot" or "dot dot",
   /// or `null` if this is not a "dot" completion (e.g. `foo.b`).
   Expression get dotTarget;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 23e8240..ca9e826 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analysis_server/src/computer/computer_hover.dart';
 import 'package:analysis_server/src/protocol_server.dart'
     hide Element, ElementKind;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
@@ -72,6 +73,7 @@
       var selectionOffset = completion.length;
 
       // Optionally add Flutter child widget details.
+      // todo (pq): revisit this special casing; likely it can be generalized away
       var element = parameter.enclosingElement;
       if (element is ConstructorElement) {
         var flutter = Flutter.of(request.result);
@@ -79,7 +81,7 @@
           var defaultValue = getDefaultStringParameterValue(parameter);
           // TODO(devoncarew): Should we remove the check here? We would then
           // suggest values for param types like closures.
-          if (defaultValue != null && defaultValue.text == '<Widget>[]') {
+          if (defaultValue != null && defaultValue.text == '[]') {
             var completionLength = completion.length;
             completion += defaultValue.text;
             if (defaultValue.cursorPosition != null) {
@@ -115,7 +117,7 @@
           parameterName: name,
           parameterType: type);
       if (parameter is FieldFormalParameterElement) {
-        _setDocumentation(suggestion, parameter.field?.documentationComment);
+        _setDocumentation(suggestion, parameter);
         suggestion.element = convertElement(parameter);
       }
 
@@ -333,10 +335,10 @@
 
   /// If the given [comment] is not `null`, fill the [suggestion] documentation
   /// fields.
-  static void _setDocumentation(
-      CompletionSuggestion suggestion, String comment) {
-    if (comment != null) {
-      var doc = getDartDocPlainText(comment);
+  void _setDocumentation(CompletionSuggestion suggestion, Element element) {
+    var doc = DartUnitHoverComputer.computeDocumentation(
+        request.dartdocDirectiveInfo, element);
+    if (doc != null) {
       suggestion.docComplete = doc;
       suggestion.docSummary = getDartDocSummary(doc);
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index e2544fe..c70981b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -43,6 +43,7 @@
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
+import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -57,6 +58,9 @@
   /// to maintain state between calls to [DartContributionSorter#sort(...)].
   static DartContributionSorter contributionSorter = CommonUsageSorter();
 
+  /// The object used to resolve macros in Dartdoc comments.
+  final DartdocDirectiveInfo dartdocDirectiveInfo;
+
   /// If not `null`, then instead of using [ImportedReferenceContributor],
   /// fill this set with kinds of elements that are applicable at the
   /// completion location, so should be suggested from available suggestion
@@ -78,6 +82,7 @@
   /// [includedSuggestionRelevanceTags] must either all be `null` or must all be
   /// non-`null`.
   DartCompletionManager({
+    this.dartdocDirectiveInfo,
     this.includedElementKinds,
     this.includedElementNames,
     this.includedSuggestionRelevanceTags,
@@ -98,7 +103,7 @@
 
     var performance = (request as CompletionRequestImpl).performance;
     DartCompletionRequestImpl dartRequest =
-        await DartCompletionRequestImpl.from(request);
+        await DartCompletionRequestImpl.from(request, dartdocDirectiveInfo);
 
     // Don't suggest in comments.
     if (dartRequest.target.isCommentText) {
@@ -372,6 +377,9 @@
   @override
   final FeatureComputer featureComputer;
 
+  @override
+  final DartdocDirectiveInfo dartdocDirectiveInfo;
+
   /// A flag indicating whether the [_contextType] has been computed.
   bool _hasComputedContextType = false;
 
@@ -390,6 +398,7 @@
       this.source,
       this.offset,
       CompilationUnit unit,
+      this.dartdocDirectiveInfo,
       this._originalRequest,
       this.performance)
       : featureComputer =
@@ -482,7 +491,8 @@
   /// Return a [Future] that completes with a newly created completion request
   /// based on the given [request]. This method will throw [AbortCompletion]
   /// if the completion request has been aborted.
-  static Future<DartCompletionRequest> from(CompletionRequest request) async {
+  static Future<DartCompletionRequest> from(CompletionRequest request,
+      DartdocDirectiveInfo dartdocDirectiveInfo) async {
     request.checkAborted();
     var performance = (request as CompletionRequestImpl).performance;
     const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
@@ -500,6 +510,7 @@
         request.source,
         request.offset,
         unit,
+        dartdocDirectiveInfo,
         request,
         performance);
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index 524ebf7..8a4ead8 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -12,11 +12,10 @@
 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/generic_inferrer.dart'
+    show GenericInferrer;
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/generated/resolver.dart'
-    show GenericInferrer, LibraryScope;
-import 'package:analyzer/src/generated/type_system.dart' show GenericInferrer;
 
 /// A contributor that produces suggestions based on the members of an
 /// extension.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
index 6b47032..aa8c9a4 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
@@ -64,7 +64,8 @@
             var fieldName = fieldId.name;
             if (fieldName != null && fieldName.isNotEmpty) {
               if (!referencedFields.contains(fieldName)) {
-                var suggestion = createSuggestion(fieldId.staticElement,
+                var suggestion = createSuggestion(
+                    request, fieldId.staticElement,
                     relevance: relevance);
                 if (suggestion != null) {
                   suggestions.add(suggestion);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
index 248b44f..28242f3 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
@@ -121,6 +121,8 @@
         if (!node.isStatic) {
           return node;
         }
+      } else if (node is ConstructorDeclaration) {
+        return node;
       }
       node = node.parent;
     }
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 3e25727..886dffa 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
@@ -360,11 +360,12 @@
     var constructorDeclaration =
         node.thisOrAncestorOfType<ConstructorDeclaration>();
     if (constructorDeclaration != null) {
-      _addSuggestions([Keyword.THIS]);
+      _addSuggestion(Keyword.THIS);
     }
     if (entity is Token && (entity as Token).type == TokenType.CLOSE_PAREN) {
       _addSuggestion(Keyword.COVARIANT);
       _addSuggestion(Keyword.DYNAMIC);
+      _addSuggestion(Keyword.VOID);
       if (request.featureSet.isEnabled(Feature.non_nullable)) {
         _addSuggestion(Keyword.REQUIRED);
       }
@@ -373,6 +374,14 @@
       if (beginToken != null && request.target.offset == beginToken.end) {
         _addSuggestion(Keyword.COVARIANT);
         _addSuggestion(Keyword.DYNAMIC);
+        _addSuggestion(Keyword.VOID);
+        if (request.featureSet.isEnabled(Feature.non_nullable)) {
+          _addSuggestion(Keyword.REQUIRED);
+        }
+      } else if (entity is FunctionTypedFormalParameter) {
+        _addSuggestion(Keyword.COVARIANT);
+        _addSuggestion(Keyword.DYNAMIC);
+        _addSuggestion(Keyword.VOID);
         if (request.featureSet.isEnabled(Feature.non_nullable)) {
           _addSuggestion(Keyword.REQUIRED);
         }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index 181c43c..8735a3b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -62,7 +62,7 @@
             var relevance = useNewRelevance
                 ? Relevance.loadLibrary
                 : DART_RELEVANCE_DEFAULT;
-            builder.suggestions.add(createSuggestion(function,
+            builder.suggestions.add(createSuggestion(request, function,
                 relevance: relevance, useNewRelevance: useNewRelevance));
           }
         }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
index 3ed0ef1..e41db25 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
@@ -38,7 +38,7 @@
         if (libraryElement != null) {
           var relevance =
               useNewRelevance ? Relevance.prefix : DART_RELEVANCE_DEFAULT;
-          var suggestion = createSuggestion(libraryElement,
+          var suggestion = createSuggestion(request, libraryElement,
               completion: completion,
               kind: CompletionSuggestionKind.IDENTIFIER,
               relevance: relevance,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
index db6852f..76944901 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -137,7 +137,7 @@
         completion = '$completion.$name';
       }
 
-      var suggestion = createSuggestion(element,
+      var suggestion = createSuggestion(request, element,
           completion: completion,
           relevance: relevance,
           useNewRelevance: useNewRelevance);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index 8ed08d6..d463c27 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -251,7 +251,7 @@
         continue;
       }
 
-      var suggestion = createSuggestion(constructor,
+      var suggestion = createSuggestion(request, constructor,
           relevance: relevance, useNewRelevance: useNewRelevance);
       if (suggestion != null) {
         var name = suggestion.completion;
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 2c27a26..1dc2aee 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
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analysis_server/src/computer/computer_hover.dart';
 import 'package:analysis_server/src/protocol_server.dart'
     show CompletionSuggestion, CompletionSuggestionKind, Location;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
@@ -12,7 +13,6 @@
 import 'package:analysis_server/src/utilities/strings.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/dart/element/type.dart';
@@ -142,7 +142,7 @@
   void declaredClass(ClassDeclaration declaration) {
     if (opType.includeTypeNameSuggestions) {
       _addLocalSuggestion_includeTypeNameSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         NO_RETURN_TYPE,
         protocol.ElementKind.CLASS,
@@ -157,7 +157,7 @@
   void declaredClassTypeAlias(ClassTypeAlias declaration) {
     if (opType.includeTypeNameSuggestions) {
       _addLocalSuggestion_includeTypeNameSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         NO_RETURN_TYPE,
         protocol.ElementKind.CLASS_TYPE_ALIAS,
@@ -172,7 +172,7 @@
   void declaredEnum(EnumDeclaration declaration) {
     if (opType.includeTypeNameSuggestions) {
       _addLocalSuggestion_includeTypeNameSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         NO_RETURN_TYPE,
         protocol.ElementKind.ENUM,
@@ -195,7 +195,7 @@
   void declaredExtension(ExtensionDeclaration declaration) {
     if (opType.includeReturnValueSuggestions && declaration.name != null) {
       _addLocalSuggestion_includeReturnValueSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         NO_RETURN_TYPE,
         protocol.ElementKind.EXTENSION,
@@ -211,7 +211,8 @@
             (!opType.inStaticMethodBody || fieldDecl.isStatic)) ||
         suggestLocalFields) {
       var deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
-      var fieldType = varDecl.declaredElement.type;
+      var fieldElement = varDecl.declaredElement;
+      var fieldType = fieldElement.type;
       var typeName = fieldDecl.fields.type;
       int relevance;
       if (useNewRelevance) {
@@ -220,7 +221,7 @@
         relevance = DART_RELEVANCE_LOCAL_FIELD;
       }
       _addLocalSuggestion_includeReturnValueSuggestions(
-        fieldDecl.documentationComment,
+        fieldElement,
         varDecl.name,
         typeName,
         protocol.ElementKind.FIELD,
@@ -260,7 +261,7 @@
         relevance = _relevanceForType(declaration.declaredElement.returnType);
       }
       _addLocalSuggestion_includeReturnValueSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         typeName,
         elemKind,
@@ -277,7 +278,7 @@
     if (opType.includeTypeNameSuggestions) {
       // TODO (danrubel) determine parameters and return type
       _addLocalSuggestion_includeTypeNameSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         declaration.returnType,
         protocol.ElementKind.FUNCTION_TYPE_ALIAS,
@@ -293,7 +294,7 @@
     if (opType.includeTypeNameSuggestions) {
       // TODO (danrubel) determine parameters and return type
       _addLocalSuggestion_includeTypeNameSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         declaration.functionType?.returnType,
         protocol.ElementKind.FUNCTION_TYPE_ALIAS,
@@ -364,7 +365,7 @@
         relevance = _relevanceForType(declaration.declaredElement.returnType);
       }
       _addLocalSuggestion_includeReturnValueSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         typeName,
         elemKind,
@@ -382,7 +383,7 @@
   void declaredMixin(MixinDeclaration declaration) {
     if (opType.includeTypeNameSuggestions) {
       _addLocalSuggestion_includeTypeNameSuggestions(
-        declaration.documentationComment,
+        declaration.declaredElement,
         declaration.name,
         NO_RETURN_TYPE,
         protocol.ElementKind.MIXIN,
@@ -418,7 +419,8 @@
   void declaredTopLevelVar(
       VariableDeclarationList varList, VariableDeclaration varDecl) {
     if (opType.includeReturnValueSuggestions) {
-      var variableType = varDecl.declaredElement.type;
+      var variableElement = varDecl.declaredElement;
+      var variableType = variableElement.type;
       int relevance;
       if (useNewRelevance) {
         relevance = _relevanceForType(variableType);
@@ -426,7 +428,7 @@
         relevance = DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE;
       }
       _addLocalSuggestion_includeReturnValueSuggestions(
-        varDecl.documentationComment,
+        variableElement,
         varDecl.name,
         varList.type,
         protocol.ElementKind.TOP_LEVEL_VARIABLE,
@@ -458,7 +460,7 @@
     }
   }
 
-  void _addLocalSuggestion(Comment documentationComment, SimpleIdentifier id,
+  void _addLocalSuggestion(Element element, SimpleIdentifier id,
       TypeAnnotation typeName, protocol.ElementKind elemKind,
       {bool isAbstract = false,
       bool isDeprecated = false,
@@ -476,7 +478,7 @@
         id, isDeprecated, relevance, typeName,
         classDecl: classDecl, kind: kind);
     if (suggestion != null) {
-      _setDocumentation(suggestion, documentationComment);
+      _setDocumentation(suggestion, element);
       if (!useNewRelevance &&
           privateMemberRelevance != null &&
           suggestion.completion.startsWith('_')) {
@@ -523,7 +525,7 @@
   }
 
   void _addLocalSuggestion_includeReturnValueSuggestions(
-      Comment documentationComment,
+      Element element,
       SimpleIdentifier id,
       TypeAnnotation typeName,
       protocol.ElementKind elemKind,
@@ -537,7 +539,7 @@
       relevance = opType.returnValueSuggestionsFilter(type, relevance);
     }
     if (relevance != null) {
-      _addLocalSuggestion(documentationComment, id, typeName, elemKind,
+      _addLocalSuggestion(element, id, typeName, elemKind,
           isAbstract: isAbstract,
           isDeprecated: isDeprecated,
           classDecl: classDecl,
@@ -565,7 +567,7 @@
   }
 
   void _addLocalSuggestion_includeTypeNameSuggestions(
-      Comment documentationComment,
+      Element element,
       SimpleIdentifier id,
       TypeAnnotation typeName,
       protocol.ElementKind elemKind,
@@ -580,7 +582,7 @@
           opType.typeNameSuggestionsFilter(type, DART_RELEVANCE_DEFAULT);
     }
     if (relevance != null) {
-      _addLocalSuggestion(documentationComment, id, typeName, elemKind,
+      _addLocalSuggestion(element, id, typeName, elemKind,
           isAbstract: isAbstract,
           isDeprecated: isDeprecated,
           relevance: relevance);
@@ -718,14 +720,10 @@
 
   /// If the given [documentationComment] is not `null`, fill the [suggestion]
   /// documentation fields.
-  static void _setDocumentation(
-      CompletionSuggestion suggestion, Comment documentationComment) {
-    if (documentationComment != null) {
-      var text = documentationComment.tokens
-          .map((Token t) => t.toString())
-          .join('\n')
-          .replaceAll('\r\n', '\n');
-      var doc = getDartDocPlainText(text);
+  void _setDocumentation(CompletionSuggestion suggestion, Element element) {
+    var doc = DartUnitHoverComputer.computeDocumentation(
+        request.dartdocDirectiveInfo, element);
+    if (doc != null) {
       suggestion.docComplete = doc;
       suggestion.docSummary = getDartDocSummary(doc);
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
index 5a0c30d..56cb00e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
@@ -33,7 +33,7 @@
           var element = type.element;
           if (element is ClassElement) {
             return _buildSuggestions(
-                libraryElement, element, request.useNewRelevance);
+                request, libraryElement, element, request.useNewRelevance);
           }
         }
       }
@@ -41,7 +41,7 @@
     return const <CompletionSuggestion>[];
   }
 
-  List<CompletionSuggestion> _buildSuggestions(
+  List<CompletionSuggestion> _buildSuggestions(DartCompletionRequest request,
       LibraryElement libElem, ClassElement classElem, bool useNewRelevance) {
     var isLocalClassDecl = classElem.library == libElem;
     var suggestions = <CompletionSuggestion>[];
@@ -52,7 +52,7 @@
           var relevance = useNewRelevance
               ? Relevance.namedConstructor
               : DART_RELEVANCE_DEFAULT;
-          var suggestion = createSuggestion(constructor,
+          var suggestion = createSuggestion(request, constructor,
               completion: name,
               relevance: relevance,
               useNewRelevance: useNewRelevance);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/probability_range.dart b/pkg/analysis_server/lib/src/services/completion/dart/probability_range.dart
new file mode 100644
index 0000000..0eefaa1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/probability_range.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.
+
+/// A range of probabilities that a given event has occurred.
+class ProbabilityRange {
+  /// The lower bound of the range.
+  final double lower;
+
+  /// The upper bound of the range.
+  final double upper;
+
+  /// Initialize a newly created probability range to have the given [lower] and
+  /// [upper] bounds.
+  const ProbabilityRange({this.lower, this.upper});
+
+  /// Given the [probability] of an occurrence of an event that is conditional
+  /// on the event represented by this range, return the probability of the
+  /// event independent of the event based on this range.
+  double conditionalProbability(double probability) {
+    return lower + (upper - lower) * probability;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/relevance_tables.g.dart b/pkg/analysis_server/lib/src/services/completion/dart/relevance_tables.g.dart
new file mode 100644
index 0000000..ab6d997
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/relevance_tables.g.dart
@@ -0,0 +1,873 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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 has been automatically generated. Please do not edit it manually.
+// To regenerate the file, use the script
+// "pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart",
+// passing it the location of a corpus of code that is large enough for the
+// computed values to be statistically meaningful.
+
+import 'package:analysis_server/src/services/completion/dart/probability_range.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+
+/// A table keyed by completion location and element kind whose values are the
+/// ranges of the relevance of those element kinds in those locations.
+const elementKindRelevance = {
+  'Annotation_name': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.029),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.029, upper: 1.000),
+  },
+  'ArgumentList_annotation_named': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.979),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.979, upper: 0.984),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.984, upper: 1.000),
+  },
+  'ArgumentList_annotation_unnamed': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ArgumentList_constructorRedirect_named': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.027),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.027, upper: 0.029),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.029, upper: 0.031),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.031, upper: 0.034),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.034, upper: 0.044),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.044, upper: 1.000),
+  },
+  'ArgumentList_constructorRedirect_unnamed': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.199),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.199, upper: 0.201),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.201, upper: 0.206),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.206, upper: 0.212),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.212, upper: 0.230),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.230, upper: 0.279),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.279, upper: 1.000),
+  },
+  'ArgumentList_constructor_named': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.485),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.485, upper: 0.487),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.487, upper: 0.489),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.489, upper: 0.501),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.501, upper: 0.539),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.539, upper: 0.579),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.579, upper: 0.646),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.646, upper: 0.735),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.735, upper: 1.000),
+  },
+  'ArgumentList_constructor_unnamed': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.617),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.617, upper: 0.621),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.621, upper: 0.629),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.629, upper: 0.645),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.645, upper: 0.683),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.683, upper: 0.733),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.733, upper: 0.811),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.811, upper: 0.905),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.905, upper: 1.000),
+  },
+  'ArgumentList_function_named': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.616),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.616, upper: 0.648),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.648, upper: 0.792),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.792, upper: 1.000),
+  },
+  'ArgumentList_function_unnamed': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.220),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.220, upper: 0.227),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.227, upper: 0.237),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.237, upper: 0.255),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.255, upper: 0.280),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.280, upper: 0.347),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.347, upper: 0.583),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.583, upper: 1.000),
+  },
+  'ArgumentList_method_named': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.548),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.548, upper: 0.551),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.551, upper: 0.555),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.555, upper: 0.568),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.568, upper: 0.626),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.626, upper: 0.686),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.686, upper: 0.764),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.764, upper: 0.854),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.854, upper: 1.000),
+  },
+  'ArgumentList_method_unnamed': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.387),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.387, upper: 0.387),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.387, upper: 0.387),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.387, upper: 0.388),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.388, upper: 0.394),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.394, upper: 0.402),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.402, upper: 0.425),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.425, upper: 0.452),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.452, upper: 0.510),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.510, upper: 0.624),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.624, upper: 0.746),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.746, upper: 1.000),
+  },
+  'ArgumentList_widgetConstructor_named': {
+    ElementKind.SETTER: ProbabilityRange(lower: 0.000, upper: 0.351),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.351, upper: 0.352),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.352, upper: 0.355),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.355, upper: 0.368),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.368, upper: 0.387),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.387, upper: 0.422),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.422, upper: 0.482),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.482, upper: 0.552),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.552, upper: 0.636),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.636, upper: 1.000),
+  },
+  'ArgumentList_widgetConstructor_unnamed': {
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.461),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.461, upper: 0.463),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.463, upper: 0.469),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.469, upper: 0.475),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.475, upper: 0.491),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.491, upper: 0.541),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.541, upper: 0.612),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.612, upper: 0.757),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.757, upper: 1.000),
+  },
+  'AsExpression_type': {
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.002, upper: 0.012),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.012, upper: 1.000),
+  },
+  'AssertInitializer_condition': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'AssertInitializer_message': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'AssertStatement_condition': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.142),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.142, upper: 0.176),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.176, upper: 0.226),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.226, upper: 0.332),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.332, upper: 0.662),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.662, upper: 1.000),
+  },
+  'AssertStatement_message': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'AssignmentExpression_rightHandSide': {
+    ElementKind.SETTER: ProbabilityRange(lower: 0.000, upper: 0.305),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.305, upper: 0.306),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.306, upper: 0.318),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.318, upper: 0.329),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.329, upper: 0.350),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.350, upper: 0.395),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.395, upper: 0.490),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.490, upper: 0.601),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.601, upper: 0.740),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.740, upper: 1.000),
+  },
+  'AwaitExpression_expression': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.022),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.022, upper: 0.049),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.049, upper: 0.144),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.144, upper: 0.291),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.291, upper: 0.448),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.448, upper: 0.606),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.606, upper: 0.773),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.773, upper: 1.000),
+  },
+  'BinaryExpression_!=_rightOperand': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.874),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.874, upper: 0.874),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.874, upper: 0.875),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.875, upper: 0.886),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.886, upper: 0.903),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.903, upper: 0.921),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.921, upper: 0.958),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.958, upper: 1.000),
+  },
+  'BinaryExpression_%_rightOperand': {
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.719),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.719, upper: 0.725),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.725, upper: 0.752),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.752, upper: 0.784),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.784, upper: 0.853),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.853, upper: 1.000),
+  },
+  'BinaryExpression_&&_rightOperand': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.108),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.108, upper: 0.113),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.113, upper: 0.123),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.123, upper: 0.138),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.138, upper: 0.260),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.260, upper: 0.442),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.442, upper: 1.000),
+  },
+  'BinaryExpression_&_rightOperand': {
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.266),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.266, upper: 0.364),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.364, upper: 0.462),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.462, upper: 0.723),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.723, upper: 1.000),
+  },
+  'BinaryExpression_*_rightOperand': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.611),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.611, upper: 0.613),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.613, upper: 0.616),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.616, upper: 0.625),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.625, upper: 0.640),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.640, upper: 0.663),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.663, upper: 0.714),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.714, upper: 0.850),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.850, upper: 1.000),
+  },
+  'BinaryExpression_+_rightOperand': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.500),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.500, upper: 0.505),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.505, upper: 0.511),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.511, upper: 0.526),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.526, upper: 0.549),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.549, upper: 0.668),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.668, upper: 0.825),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.825, upper: 1.000),
+  },
+  'BinaryExpression_-_rightOperand': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.473),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.473, upper: 0.477),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.477, upper: 0.483),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.483, upper: 0.491),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.491, upper: 0.506),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.506, upper: 0.597),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.597, upper: 0.793),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.793, upper: 1.000),
+  },
+  'BinaryExpression_/_rightOperand': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.762),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.762, upper: 0.763),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.763, upper: 0.765),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.765, upper: 0.771),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.771, upper: 0.779),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.779, upper: 0.818),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.818, upper: 0.907),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.907, upper: 1.000),
+  },
+  'BinaryExpression_<<_rightOperand': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.756),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.756, upper: 0.854),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.854, upper: 1.000),
+  },
+  'BinaryExpression_<=_rightOperand': {
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.607),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.607, upper: 0.717),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.717, upper: 0.848),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.848, upper: 1.000),
+  },
+  'BinaryExpression_<_rightOperand': {
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.424),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.424, upper: 0.425),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.425, upper: 0.426),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.426, upper: 0.438),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.438, upper: 0.557),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.557, upper: 0.773),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.773, upper: 1.000),
+  },
+  'BinaryExpression_==_rightOperand': {
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.567),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.567, upper: 0.567),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.567, upper: 0.567),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.567, upper: 0.567),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.567, upper: 0.568),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.568, upper: 0.591),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.591, upper: 0.629),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.629, upper: 0.679),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.679, upper: 0.807),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.807, upper: 1.000),
+  },
+  'BinaryExpression_>=_rightOperand': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.714),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.714, upper: 0.731),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.731, upper: 0.791),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.791, upper: 0.854),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.854, upper: 1.000),
+  },
+  'BinaryExpression_>>_rightOperand': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'BinaryExpression_>_rightOperand': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.813),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.813, upper: 0.814),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.814, upper: 0.815),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.815, upper: 0.818),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.818, upper: 0.826),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.826, upper: 0.867),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.867, upper: 0.928),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.928, upper: 1.000),
+  },
+  'BinaryExpression_??_rightOperand': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.665),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.665, upper: 0.668),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.668, upper: 0.673),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.673, upper: 0.684),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.684, upper: 0.726),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.726, upper: 0.768),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.768, upper: 0.816),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.816, upper: 0.871),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.871, upper: 1.000),
+  },
+  'BinaryExpression_^_rightOperand': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.118),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.118, upper: 1.000),
+  },
+  'BinaryExpression_|_rightOperand': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.143),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.143, upper: 0.429),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.429, upper: 1.000),
+  },
+  'BinaryExpression_||_rightOperand': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.144),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.144, upper: 0.148),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.148, upper: 0.168),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.168, upper: 0.378),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.378, upper: 0.663),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.663, upper: 1.000),
+  },
+  'BinaryExpression_~/_rightOperand': {
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.627),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.627, upper: 0.640),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.640, upper: 0.677),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.677, upper: 0.795),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.795, upper: 1.000),
+  },
+  'Block_statement': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.537),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.537, upper: 0.537),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.537, upper: 0.538),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.538, upper: 0.538),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.538, upper: 0.539),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.539, upper: 0.540),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.540, upper: 0.563),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.563, upper: 0.614),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.614, upper: 0.674),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.674, upper: 0.743),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.743, upper: 0.825),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.825, upper: 0.911),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.911, upper: 1.000),
+  },
+  'CatchClause_exceptionType': {
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ClassDeclaration_member': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.390),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.390, upper: 0.390),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.390, upper: 0.391),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.391, upper: 0.392),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.392, upper: 0.393),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.393, upper: 0.399),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.399, upper: 1.000),
+  },
+  'ClassTypeAlias_superclass': {
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'CommentReference_identifier': {
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.001, upper: 0.001),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.004, upper: 0.008),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.008, upper: 0.021),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.021, upper: 0.054),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.054, upper: 0.106),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.106, upper: 0.167),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.167, upper: 0.425),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.425, upper: 1.000),
+  },
+  'CompilationUnit_declaration': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.820),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.820, upper: 0.820),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.820, upper: 0.821),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.821, upper: 0.823),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.823, upper: 0.837),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.837, upper: 1.000),
+  },
+  'ConditionalExpression_elseExpression': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.370),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.370, upper: 0.375),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.375, upper: 0.383),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.383, upper: 0.403),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.403, upper: 0.427),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.427, upper: 0.482),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.482, upper: 0.549),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.549, upper: 0.655),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.655, upper: 0.790),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.790, upper: 1.000),
+  },
+  'ConditionalExpression_thenExpression': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.390),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.390, upper: 0.395),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.395, upper: 0.402),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.402, upper: 0.424),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.424, upper: 0.450),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.450, upper: 0.500),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.500, upper: 0.556),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.556, upper: 0.634),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.634, upper: 0.777),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.777, upper: 1.000),
+  },
+  'ConstructorDeclaration_initializer': {
+    ElementKind.FIELD: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ConstructorDeclaration_returnType': {
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ConstructorFieldInitializer_expression': {
+    ElementKind.GETTER: ProbabilityRange(lower: 0.000, upper: 0.183),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.183, upper: 0.187),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.187, upper: 0.195),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.195, upper: 0.220),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.220, upper: 0.272),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.272, upper: 0.396),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.396, upper: 1.000),
+  },
+  'DefaultFormalParameter_defaultValue': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.716),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.716, upper: 0.716),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.716, upper: 0.717),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.717, upper: 0.733),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.733, upper: 0.776),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.776, upper: 0.838),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.838, upper: 1.000),
+  },
+  'DoStatement_condition': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.333),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.333, upper: 1.000),
+  },
+  'Expression': {
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.386),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.386, upper: 0.386),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.386, upper: 0.386),
+    ElementKind.TOP_LEVEL_VARIABLE:
+        ProbabilityRange(lower: 0.386, upper: 0.386),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.386, upper: 0.386),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.386, upper: 0.388),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.388, upper: 0.402),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.402, upper: 0.418),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.418, upper: 0.434),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.434, upper: 0.450),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.450, upper: 0.522),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.522, upper: 0.607),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.607, upper: 0.701),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.701, upper: 0.839),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.839, upper: 1.000),
+  },
+  'ExpressionFunctionBody_expression': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.352),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.352, upper: 0.352),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.352, upper: 0.358),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.358, upper: 0.363),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.363, upper: 0.373),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.373, upper: 0.394),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.394, upper: 0.419),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.419, upper: 0.452),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.452, upper: 0.487),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.487, upper: 0.613),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.613, upper: 0.794),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.794, upper: 1.000),
+  },
+  'ExpressionStatement_expression': {
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.132),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.132, upper: 0.134),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.134, upper: 0.136),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.136, upper: 0.139),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.139, upper: 0.190),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.190, upper: 0.255),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.255, upper: 0.361),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.361, upper: 0.482),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.482, upper: 0.625),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.625, upper: 0.801),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.801, upper: 1.000),
+  },
+  'ExtendsClause_superclass': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ExtensionDeclaration_extendedType': {
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.053),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.053, upper: 0.105),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.105, upper: 1.000),
+  },
+  'ExtensionDeclaration_member': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.120),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.120, upper: 1.000),
+  },
+  'ForEachPartsWithDeclaration_iterable': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.016),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.016, upper: 0.018),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.018, upper: 0.022),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.022, upper: 0.029),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.029, upper: 0.036),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.036, upper: 0.288),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.288, upper: 0.607),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.607, upper: 1.000),
+  },
+  'ForEachPartsWithDeclaration_loopVariable': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.703),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.703, upper: 0.704),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.704, upper: 0.706),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.706, upper: 0.708),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.708, upper: 0.712),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.712, upper: 1.000),
+  },
+  'ForElement_body': {
+    ElementKind.GETTER: ProbabilityRange(lower: 0.000, upper: 0.900),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.900, upper: 0.904),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.904, upper: 0.908),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.908, upper: 0.918),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.918, upper: 0.937),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.937, upper: 1.000),
+  },
+  'ForParts_condition': {
+    ElementKind.GETTER: ProbabilityRange(lower: 0.000, upper: 0.023),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.023, upper: 1.000),
+  },
+  'ForParts_updater': {
+    ElementKind.SETTER: ProbabilityRange(lower: 0.000, upper: 0.067),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.067, upper: 1.000),
+  },
+  'FormalParameterList_parameter': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.245),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.245, upper: 0.247),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.247, upper: 0.255),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.255, upper: 0.267),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.267, upper: 0.284),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.284, upper: 0.311),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.311, upper: 1.000),
+  },
+  'GenericTypeAlias_functionType': {
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.000, upper: 0.590),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.590, upper: 0.610),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.610, upper: 0.660),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.660, upper: 1.000),
+  },
+  'HideCombinator_hiddenName': {
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.059),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.059, upper: 1.000),
+  },
+  'IfElement_condition': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.157),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.157, upper: 0.172),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.172, upper: 0.338),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.338, upper: 0.633),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.633, upper: 1.000),
+  },
+  'IfElement_elseElement': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.333),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.333, upper: 1.000),
+  },
+  'IfElement_thenElement': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.212),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.212, upper: 0.219),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.219, upper: 0.228),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.228, upper: 0.239),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.239, upper: 0.254),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.254, upper: 0.281),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.281, upper: 1.000),
+  },
+  'IfStatement_condition': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.117),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.117, upper: 0.118),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.118, upper: 0.118),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.118, upper: 0.118),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.118, upper: 0.119),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.119, upper: 0.129),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.129, upper: 0.145),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.145, upper: 0.167),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.167, upper: 0.388),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.388, upper: 0.688),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.688, upper: 1.000),
+  },
+  'IfStatement_else': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.968),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.968, upper: 0.969),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.969, upper: 0.972),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.972, upper: 0.976),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.976, upper: 0.981),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.981, upper: 0.990),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.990, upper: 1.000),
+  },
+  'IfStatement_then': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.934),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.934, upper: 0.935),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.935, upper: 0.937),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.937, upper: 0.942),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.942, upper: 0.952),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.952, upper: 0.964),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.964, upper: 0.981),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.981, upper: 1.000),
+  },
+  'ImplementsClause_interface': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.003),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.003, upper: 1.000),
+  },
+  'IndexExpression_index': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.655),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.655, upper: 0.655),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.655, upper: 0.656),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.656, upper: 0.656),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.656, upper: 0.657),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.657, upper: 0.659),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.659, upper: 0.664),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.664, upper: 0.760),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.760, upper: 0.863),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.863, upper: 1.000),
+  },
+  'InterpolationExpression_expression': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.035),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.035, upper: 0.035),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.035, upper: 0.036),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.036, upper: 0.036),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.036, upper: 0.044),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.044, upper: 0.074),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.074, upper: 0.198),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.198, upper: 0.388),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.388, upper: 0.633),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.633, upper: 1.000),
+  },
+  'IsExpression_type': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.002, upper: 0.005),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.005, upper: 0.008),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.008, upper: 0.013),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.013, upper: 1.000),
+  },
+  'ListLiteral_element': {
+    ElementKind.SETTER: ProbabilityRange(lower: 0.000, upper: 0.324),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.324, upper: 0.325),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.325, upper: 0.327),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.327, upper: 0.331),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.331, upper: 0.338),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.338, upper: 0.349),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.349, upper: 0.362),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.362, upper: 0.379),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.379, upper: 0.407),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.407, upper: 1.000),
+  },
+  'MapLiteralEntry_value': {
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.814),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.814, upper: 0.814),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.814, upper: 0.816),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.816, upper: 0.818),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.818, upper: 0.823),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.823, upper: 0.829),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.829, upper: 0.849),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.849, upper: 0.884),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.884, upper: 1.000),
+  },
+  'MixinDeclaration_member': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.116),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.116, upper: 0.121),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.121, upper: 0.128),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.128, upper: 1.000),
+  },
+  'OnClause_superclassConstraint': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.392),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.392, upper: 1.000),
+  },
+  'ParenthesizedExpression_expression': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.217),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.217, upper: 0.218),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.218, upper: 0.220),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.220, upper: 0.223),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.223, upper: 0.225),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.225, upper: 0.230),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.230, upper: 0.276),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.276, upper: 0.333),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.333, upper: 0.516),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.516, upper: 0.730),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.730, upper: 1.000),
+  },
+  'PrefixExpression_!_operand': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.063),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.063, upper: 0.094),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.094, upper: 0.142),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.142, upper: 0.330),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.330, upper: 0.584),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.584, upper: 1.000),
+  },
+  'PrefixExpression_++_operand': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.035),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.035, upper: 0.123),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.123, upper: 0.351),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.351, upper: 1.000),
+  },
+  'PrefixExpression_--_operand': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.063),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.063, upper: 0.313),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.313, upper: 0.625),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.625, upper: 1.000),
+  },
+  'PrefixExpression_-_operand': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.810),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.810, upper: 0.813),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.813, upper: 0.820),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.820, upper: 0.841),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.841, upper: 0.866),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.866, upper: 0.925),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.925, upper: 1.000),
+  },
+  'PrefixExpression_~_operand': {
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'PropertyAccess_propertyName': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.002, upper: 0.104),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.104, upper: 1.000),
+  },
+  'ReturnStatement_expression': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.242),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.242, upper: 0.242),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.242, upper: 0.245),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.245, upper: 0.252),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.252, upper: 0.269),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.269, upper: 0.294),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.294, upper: 0.346),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.346, upper: 0.403),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.403, upper: 0.464),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.464, upper: 0.561),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.561, upper: 1.000),
+  },
+  'SetOrMapLiteral_element': {
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.974),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.974, upper: 0.974),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.974, upper: 0.974),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.974, upper: 0.974),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.974, upper: 0.974),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.974, upper: 0.978),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.978, upper: 0.983),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.983, upper: 0.991),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.991, upper: 1.000),
+  },
+  'ShowCombinator_shownName': {
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.000, upper: 0.005),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.005, upper: 0.032),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.032, upper: 0.212),
+    ElementKind.TOP_LEVEL_VARIABLE:
+        ProbabilityRange(lower: 0.212, upper: 0.561),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.561, upper: 1.000),
+  },
+  'SpreadElement_expression': {
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.332),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.332, upper: 0.347),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.347, upper: 0.376),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.376, upper: 0.443),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.443, upper: 0.531),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.531, upper: 0.631),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.631, upper: 0.734),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.734, upper: 1.000),
+  },
+  'Statement': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.600),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.600, upper: 0.600),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.600, upper: 0.600),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.600, upper: 0.601),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.601, upper: 0.601),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.601, upper: 0.603),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.603, upper: 0.623),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.623, upper: 0.666),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.666, upper: 0.716),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.716, upper: 0.774),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.774, upper: 0.846),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.846, upper: 0.919),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.919, upper: 1.000),
+  },
+  'SwitchCase_expression': {
+    ElementKind.GETTER: ProbabilityRange(lower: 0.000, upper: 0.541),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.541, upper: 0.677),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.677, upper: 1.000),
+  },
+  'SwitchMember_statement': {
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.691),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.691, upper: 0.691),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.691, upper: 0.697),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.697, upper: 0.708),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.708, upper: 0.719),
+    ElementKind.SETTER: ProbabilityRange(lower: 0.719, upper: 0.733),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.733, upper: 0.748),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.748, upper: 0.765),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.765, upper: 1.000),
+  },
+  'SwitchStatement_expression': {
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.009),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.009, upper: 0.011),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.011, upper: 0.015),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.015, upper: 0.030),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.030, upper: 0.211),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.211, upper: 0.504),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.504, upper: 1.000),
+  },
+  'ThrowExpression_expression': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.833),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.833, upper: 0.834),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.834, upper: 0.836),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.836, upper: 1.000),
+  },
+  'TypeArgumentList_argument': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.021),
+    ElementKind.FUNCTION_TYPE_ALIAS:
+        ProbabilityRange(lower: 0.021, upper: 0.024),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.024, upper: 0.031),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.031, upper: 0.039),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.039, upper: 0.053),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.053, upper: 0.163),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.163, upper: 1.000),
+  },
+  'TypeParameter_bound': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.016),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.016, upper: 0.039),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.039, upper: 1.000),
+  },
+  'VariableDeclaration_initializer': {
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.452),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.452, upper: 0.452),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.452, upper: 0.456),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.456, upper: 0.460),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.460, upper: 0.472),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.472, upper: 0.497),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.497, upper: 0.561),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.561, upper: 0.630),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.630, upper: 0.712),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.712, upper: 0.794),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.794, upper: 1.000),
+  },
+  'WhileStatement_body': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.985),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.985, upper: 1.000),
+  },
+  'WhileStatement_condition': {
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.083),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.083, upper: 0.109),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.109, upper: 1.000),
+  },
+  'WithClause_mixinType': {
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.280),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.280, upper: 1.000),
+  },
+  'YieldStatement_expression': {
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.065),
+    ElementKind.GETTER: ProbabilityRange(lower: 0.065, upper: 0.086),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.086, upper: 0.122),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.122, upper: 0.161),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.161, upper: 0.309),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.309, upper: 1.000),
+  },
+};
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index 2ef8b70..9b0d656 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -116,7 +116,7 @@
       relevance = _computeRelevance(
           contextType: contextType, hasDeprecated: hasDeprecated);
     }
-    var suggestion = createSuggestion(element,
+    var suggestion = createSuggestion(request, element,
         completion: completion,
         relevance: relevance,
         useNewRelevance: useNewRelevance);
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 0831608..9d05145 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
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analysis_server/src/computer/computer_hover.dart';
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/protocol_server.dart'
     hide Element, ElementKind;
@@ -19,7 +20,8 @@
 
 /// Return a suggestion based upon the given element or `null` if a suggestion
 /// is not appropriate for the given element.
-CompletionSuggestion createSuggestion(Element element,
+CompletionSuggestion createSuggestion(
+    DartCompletionRequest request, Element element,
     {String completion,
     CompletionSuggestionKind kind,
     int relevance = DART_RELEVANCE_DEFAULT,
@@ -41,9 +43,12 @@
       kind, relevance, completion, completion.length, 0, isDeprecated, false);
 
   // Attach docs.
-  var doc = getDartDocPlainText(element.documentationComment);
-  suggestion.docComplete = doc;
-  suggestion.docSummary = getDartDocSummary(doc);
+  var doc = DartUnitHoverComputer.computeDocumentation(
+      request.dartdocDirectiveInfo, element);
+  if (doc != null) {
+    suggestion.docComplete = doc;
+    suggestion.docSummary = getDartDocSummary(doc);
+  }
 
   suggestion.element = protocol.convertElement(element);
   var enclosingElement = element.enclosingElement;
@@ -96,6 +101,9 @@
   /// Return the kind of suggestions that should be built.
   CompletionSuggestionKind get kind;
 
+  /// Return the completion request for which suggestions are being built.
+  DartCompletionRequest get request;
+
   /// Add a suggestion based upon the given element.
   CompletionSuggestion addSuggestion(Element element,
       {String prefix,
@@ -118,7 +126,7 @@
     if (completion == null || completion.isEmpty) {
       return null;
     }
-    var suggestion = createSuggestion(element,
+    var suggestion = createSuggestion(request, element,
         completion: completion,
         kind: kind,
         relevance: relevance,
@@ -168,7 +176,7 @@
 /// This class creates suggestions based on top-level elements.
 class LibraryElementSuggestionBuilder extends SimpleElementVisitor<void>
     with ElementSuggestionBuilder {
-  /// The completion request for which suggestions are being built.
+  @override
   final DartCompletionRequest request;
 
   @override
@@ -495,7 +503,7 @@
       assert(false);
       return null;
     }
-    var suggestion = createSuggestion(element,
+    var suggestion = createSuggestion(request, element,
         kind: kind, relevance: relevance, useNewRelevance: useNewRelevance);
     if (suggestion != null) {
       addCompletionSuggestion(suggestion);
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 d6da442..deea96b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -172,21 +172,7 @@
   if (param != null) {
     var type = param.type;
     if (type is InterfaceType && type.isDartCoreList) {
-      String getTypeArgumentsStr() {
-        var elementType = type.typeArguments.single;
-        if (elementType.isDynamic) {
-          return '';
-        } else {
-          var typeArgStr = elementType.getDisplayString(
-            withNullability: false,
-          );
-          return '<$typeArgStr>';
-        }
-      }
-
-      var typeArgumentStr = getTypeArgumentsStr();
-      var text = '$typeArgumentStr[]';
-      return DefaultArgument(text, cursorPosition: text.length - 1);
+      return DefaultArgument('[]', cursorPosition: 1);
     } else if (type is FunctionType) {
       var params = type.parameters
           .map((p) => '${getTypeString(p.type)}${p.name}')
diff --git a/pkg/analysis_server/lib/src/services/completion/filtering/fuzzy_matcher.dart b/pkg/analysis_server/lib/src/services/completion/filtering/fuzzy_matcher.dart
new file mode 100644
index 0000000..7868f80
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/filtering/fuzzy_matcher.dart
@@ -0,0 +1,507 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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' as math;
+
+/// Character role in a candidate string.
+enum CharRole {
+  NONE,
+  SEPARATOR,
+  TAIL,
+  UC_TAIL,
+  HEAD,
+}
+
+/// A fuzzy matcher that takes a pattern at construction time, and then can
+/// evaluate how well various strings match this pattern. Together with a score,
+/// it computes a corresponding mapping of pattern characters on the candidate
+/// string, which can be retrieved later by calling `getMatchedRanges`.
+///
+/// A string matches the pattern if every character of the pattern occurs in
+/// the string in the same order as in the pattern, and first letters of
+/// separate words in pattern are aligned with words in the string. Characters
+/// matching the beginning of a word, case-sensitive and just longer matches get
+/// higher scores.
+///
+/// The algorithm takes inspiration from Sublime, VS Code, and IntelliJ and is
+/// tuned to produce visually good results for code completion, navigation, and
+/// all other kinds of element filtering in the UI.
+///
+/// Note: if constructed in filename or symbol matching mode, the matcher
+/// requires that there is at least some match in the last segment of the path
+/// or in the symbol name. In this case, we also prefer reporting sub-matches in
+/// the last segment.
+///
+/// Similar implementations (for reference):
+/// - github.com/Microsoft/vscode/blob/master/src/vs/base/common/filters.ts#L439
+///
+/// Typical usage:
+/// ```dart
+/// var topN = TopN(100);
+/// var matcher = FuzzyMatcher(pattern, FuzzyInput.SYMBOL);
+/// for (var item of completionItems) {
+///   var score = matcher.score(item.title);
+///   if (score > -1) {
+///     var matchRanges = matcher.getMatchedRanges();
+///     topN.push({item, matchRanges}, score);
+///   }
+/// }
+/// // ... use topN.getTopElements();
+/// ```
+class FuzzyMatcher {
+  /// The maximum size of the input scored against the fuzzy matcher. Longer
+  /// inputs will be truncated to this size.
+  static const int maxInputSize = 127;
+
+  /// The maximum size of the pattern used to construct the fuzzy matcher.
+  /// Longer patterns are truncated to this size.
+  static const int maxPatternSize = 63;
+
+  /// The minimum integer score (before normalization).
+  static const int minScore = -10000;
+
+  /// Character types for the first 127 ASCII symbols encoded as a string.
+  ///
+  /// This is:
+  ///   [a-z0-9]  LOWER
+  ///   [A-Z]     UPPER
+  ///   [:./ ]    PUNCT
+  ///   otherwise NONE
+  static const String TYPES =
+      '0000000000000000000000000000000010000000000000112222222222100000'
+      '0333333333333333333333333330000002222222222222222222222222200000';
+
+  /// TODO(brianwilkerson) Use package:charcode.
+  static final int $a = 'a'.codeUnitAt(0);
+  static final int $z = 'z'.codeUnitAt(0);
+
+  /// The (potentially truncated) pattern to be matched.
+  String pattern;
+
+  /// The style of match to be performed.
+  MatchStyle matchStyle;
+
+  /// The lowercase version of the pattern.
+  String patternLower;
+
+  /// The first three characters of the lowercase version of the pattern.
+  String patternShort;
+
+  /// The length of the last matched candidate.
+  int lastCandidateLen = 0;
+
+  /// A flag indicating whether the last matched candidate matched the pattern.
+  bool lastCandidateMatched = false;
+
+  /// MatchStyle.FILENAME only: For the last matched candidate, the length of
+  /// text that was trimmed from the start of the string.
+  int lastCandidatePrefixTrimmedLen = 0;
+
+  /// Dynamic programming table.
+  ///
+  /// We use a 3-dimensional dynamic programming table, with the 3-rd dimension
+  /// telling us whether the last character matched (true or false). The table
+  /// for matched characters is stored adjacent to the table for unmatched
+  /// characters to avoid too nested arrays.
+  ///
+  /// The zero bit of the score value keeps track of where we came from (1 if
+  /// the previous character matched, and 0 otherwise).
+  List<List<int>> table;
+
+  /// The offset of the "previous symbol matched" table on the pattern axis.
+  int matchesLayerOffset;
+
+  /// Pre-allocated memory for storing the role of each character in the
+  /// candidate string.
+  List<CharRole> candidateRoles = List.filled(maxInputSize, CharRole.NONE);
+
+  /// The role of each character in the pattern.
+  List<CharRole> patternRoles;
+
+  /// A flag indicating whether scoring should be case-sensitive. Mix-case
+  /// patterns turn on case-sensitive scoring.
+  bool caseSensitive;
+
+  /// Normalizes scores for the pattern length.
+  double scoreScale;
+
+  /// Initialize a newly created matcher to match the [pattern] using the given
+  /// [matchStyle].
+  FuzzyMatcher(this.pattern, {this.matchStyle = MatchStyle.TEXT}) {
+    if (pattern.length > maxPatternSize) {
+      pattern = pattern.substring(0, maxPatternSize);
+    }
+    patternLower = pattern.toLowerCase();
+    caseSensitive = pattern != patternLower;
+    if (patternLower.length > 3) {
+      patternShort = patternLower.substring(0, 3);
+    } else {
+      patternShort = patternLower;
+    }
+    matchesLayerOffset = pattern.length + 1;
+
+    table = [];
+    for (var i = 0; i <= maxInputSize; i++) {
+      table.add(List.filled(2 * matchesLayerOffset, 0));
+    }
+
+    patternRoles = List.filled(pattern.length, CharRole.NONE);
+    fuzzyMap(pattern, patternRoles);
+    var maxCharScore = matchStyle == MatchStyle.TEXT ? 6 : 4;
+    scoreScale =
+        pattern.isNotEmpty ? 1.0 / (maxCharScore * pattern.length) : 0.0;
+  }
+
+  /// This function picks the matches layer with the best score.
+  int bestLayerIndexAt(int i, int j) {
+    return scoreAt(i, j, 0) < scoreAt(i, j, 1) ? 1 : 0;
+  }
+
+  /// Scores the candidate string.
+  ///
+  /// Return a non-negative value in case of success, or a negative value if the
+  /// candidate does not match or matches poorly.
+  int computeScore(String candidate, String candidateLower) {
+    for (var j = 0; j <= pattern.length; j++) {
+      var mj = matchesLayerOffset + j;
+      // We start with zero but only in the layer where the previous character
+      // didn't match.
+      table[0][j] = j == 0 ? 0 : minScore << 1;
+      table[0][mj] = minScore << 1;
+    }
+
+    var segmentsLeft = 1;
+    var lastSegmentStart = 0;
+    for (var i = 0; i < candidate.length; i++) {
+      if (candidateRoles[i] == CharRole.SEPARATOR) {
+        segmentsLeft++;
+        lastSegmentStart = i + 1;
+      }
+    }
+
+    for (var i = 1; i <= candidate.length; i++) {
+      var isHead = candidateRoles[i - 1] == CharRole.HEAD;
+      if (candidateRoles[i - 1] == CharRole.SEPARATOR && segmentsLeft > 1) {
+        segmentsLeft--;
+      }
+
+      // Boost the very last segment.
+      var segmentScore = segmentsLeft > 1 ? 0 : 1;
+
+      var skipPenalty = 0;
+      // Penalize missing words.
+      if (segmentsLeft == 1 && isHead && matchStyle != MatchStyle.TEXT) {
+        skipPenalty += 1;
+      }
+      // Penalize skipping the first letter of a last segment.
+      if (i - 1 == lastSegmentStart) {
+        skipPenalty += 3;
+      }
+
+      for (var j = 0; j <= pattern.length; j++) {
+        var mj = matchesLayerOffset + j;
+
+        // By default, we don't have a match. Fill in the skip data.
+        table[i][mj] = minScore << 1;
+        if (segmentsLeft > 1 && j == pattern.length) {
+          // The very last pattern character can only be matched in the last
+          // segment.
+          table[i][j] = minScore << 1;
+          continue;
+        }
+
+        // Keep track where we came from.
+        var k = bestLayerIndexAt(i - 1, j);
+        var skipScore = scoreAt(i - 1, j, k);
+        // Do not penalize missing characters after the last matched segment.
+        if (j != pattern.length) {
+          skipScore -= skipPenalty;
+        }
+
+        table[i][j] = (skipScore << 1) + k;
+
+        if (j == 0 ||
+            !(candidateLower.codeUnitAt(i - 1) ==
+                patternLower.codeUnitAt(j - 1))) {
+          // Not a match.
+          continue;
+        }
+
+        // Score the match.
+        var charScore = segmentScore;
+        if (candidateRoles[i - 1] == CharRole.TAIL &&
+            patternRoles[j - 1] == CharRole.HEAD) {
+          if (j > 1) {
+            // Not a match: a Head in the pattern matches some tail character.
+            continue;
+          }
+          // Special treatment for the first character of the pattern. We allow
+          // matches in the middle of a word if they are long enough, at least
+          // min(3, pattern.length) characters.
+          if (patternShort !=
+              candidateLower.substring(
+                  i - 1,
+                  math.min(
+                      candidateLower.length, i - 1 + patternShort.length))) {
+            continue;
+          }
+          charScore -= 4;
+        }
+
+        if ((candidate.codeUnitAt(i - 1) == pattern.codeUnitAt(j - 1)) ||
+            (isHead &&
+                (!caseSensitive || patternRoles[j - 1] == CharRole.HEAD))) {
+          // Case match, or a Head in the pattern aligns with one in the word.
+          // Single-case patterns lack segmentation signals and we assume any
+          // character can be a head of a segment.
+          charScore++;
+        }
+
+        // The third dimension tells us if there is a gap between the previous
+        // match and the current one.
+        for (var k = 0; k < 2; k++) {
+          var score = scoreAt(i - 1, j - 1, k) + charScore;
+          var prevMatches = k == 1;
+
+          var isConsecutive =
+              prevMatches || i - 1 == 0 || i - 1 == lastSegmentStart;
+          if (isConsecutive || (matchStyle == MatchStyle.TEXT && j - 1 == 0)) {
+            // Bonus for a consecutive match. First character match also gets a
+            // bonus to ensure prefix final match score normalizes to 1.0.
+            // Logically, this is a part of charScore, but we have to compute it
+            // here because it only applies for consecutive matches (k == 1).
+            score += matchStyle == MatchStyle.TEXT ? 4 : 2;
+          }
+
+          if (!prevMatches &&
+              (candidateRoles[i - 1] == CharRole.TAIL ||
+                  candidateRoles[i - 1] == CharRole.UC_TAIL)) {
+            // Match starts in the middle of a word. Penalize for the lack of
+            // alignment.
+            score -= 3;
+          }
+          if (score > (table[i][mj] >> 1)) {
+            table[i][mj] = (score << 1) + k;
+          }
+        }
+      }
+    }
+
+    return scoreAt(candidate.length, pattern.length,
+        bestLayerIndexAt(candidate.length, pattern.length));
+  }
+
+  /// Identify the role of each character in the given [string] for fuzzy
+  /// matching. The roles are stored in the list of [roles].
+  void fuzzyMap(String string, List<CharRole> roles) {
+    assert(roles.length >= string.length);
+    var prev = _CharType.NONE;
+    for (var i = 0; i < string.length; i++) {
+      var ch = string.codeUnitAt(i);
+      var type = ch < 128
+          ? _CharType.values[TYPES.codeUnitAt(ch) - 48]
+          : _CharType.LOWER;
+      var role = CharRole.NONE;
+      if (type == _CharType.LOWER) {
+        role = (prev.index <= _CharType.PUNCT.index)
+            ? CharRole.HEAD
+            : CharRole.TAIL;
+      } else if (type == _CharType.UPPER) {
+        role = CharRole.HEAD;
+        // Note: this treats RPCTest as two words.
+        if (prev == _CharType.UPPER &&
+            !(i + 1 < string.length &&
+                string.codeUnitAt(i + 1) >= $a &&
+                string.codeUnitAt(i + 1) <= $z)) {
+          role = CharRole.UC_TAIL;
+        }
+      } else if (type == _CharType.PUNCT) {
+        if (matchStyle == MatchStyle.FILENAME && string[i] == '/' ||
+            matchStyle == MatchStyle.SYMBOL &&
+                (string[i] == '.' || string[i] == ':' || string[i] == ' ')) {
+          role = CharRole.SEPARATOR;
+        }
+      }
+      roles[i] = role;
+      prev = type;
+    }
+    for (var i = string.length - 1;
+        i >= 0 && roles[i] == CharRole.SEPARATOR;
+        i--) {
+      roles[i] = CharRole.NONE;
+    }
+  }
+
+  /// Returns matched ranges for the last scored string as a flattened array of
+  /// [begin, end) pairs, where the start and end of each range aer consecutive
+  /// elements in the list.
+  List<int> getMatchedRanges() {
+    if (pattern.isEmpty || !lastCandidateMatched) {
+      return [];
+    }
+    var i = lastCandidateLen;
+    var j = pattern.length;
+    if (scoreAt(i, j, 0) < minScore / 2 && scoreAt(i, j, 1) < minScore / 2) {
+      return [];
+    }
+
+    var result = <int>[];
+    var k = bestLayerIndexAt(i, j); // bestK in go
+    while (i > 0) {
+      var take = k == 1;
+      k = prevK(i, j, k);
+      if (take) {
+        if (result.isEmpty || result[result.length - 1] != i) {
+          result.add(lastCandidatePrefixTrimmedLen + i);
+          result.add(lastCandidatePrefixTrimmedLen + i - 1);
+        } else {
+          result[result.length - 1] = lastCandidatePrefixTrimmedLen + i - 1;
+        }
+        j--;
+      }
+      i--;
+    }
+    return result.reversed.toList();
+  }
+
+  /// A match is poor if it has more than one short sub-match that is not
+  /// aligned at a word boundary.
+  bool isPoorMatch() {
+    if (pattern.length < 2) {
+      return false;
+    }
+    var i = lastCandidateLen;
+    var j = pattern.length;
+    var k = bestLayerIndexAt(i, j);
+    var counter = 0;
+    var len = 0;
+    while (i > 0) {
+      var take = k == 1;
+      k = prevK(i, j, k);
+      if (take) {
+        len++;
+        if (k == 0 && len < 3 && candidateRoles[i - 1] == CharRole.TAIL) {
+          // Short match in the middle of a word.
+          counter++;
+          if (counter > 1) {
+            return true;
+          }
+        }
+        j--;
+      } else {
+        len = 0;
+      }
+      i--;
+    }
+    return false;
+  }
+
+  /// Return `true` if the [candidate] matches the pattern at all.
+  bool match(String candidate, String candidateLower) {
+    var i = 0;
+    var j = 0;
+    for (; i < candidateLower.length && j < patternLower.length; i++) {
+      if (candidateLower.codeUnitAt(i) == patternLower.codeUnitAt(j)) {
+        j++;
+      }
+    }
+    if (j != patternLower.length) {
+      return false;
+    }
+
+    // The input passes the simple test against pattern, so it is time to
+    // classify its characters. Character roles are used below to find the last
+    // segment.
+    fuzzyMap(candidate, candidateRoles);
+    if (matchStyle != MatchStyle.TEXT) {
+      var sep = candidateLower.length - 1;
+      while (sep >= i && candidateRoles[sep] != CharRole.SEPARATOR) {
+        sep--;
+      }
+      if (sep >= i) {
+        // We are not in the last segment, check that we have at least one
+        // character match in the last segment of the candidate.
+        return candidateLower.contains(
+            patternLower.substring(patternLower.length - 1), sep);
+      }
+    }
+    return true;
+  }
+
+  /// Returns the previous value for the third dimension.
+  int prevK(int i, int j, int k) {
+    return table[i][j + k * matchesLayerOffset] & 1;
+  }
+
+  /// Computes the fuzzy score of how well the [candidate] matches the pattern,
+  /// and returns a value in the range of [0, 1] for matching strings, and -1
+  /// for non-matching ones.
+  double score(String candidate) {
+    lastCandidatePrefixTrimmedLen = 0;
+    if (candidate.length > maxInputSize) {
+      if (matchStyle == MatchStyle.FILENAME) {
+        lastCandidatePrefixTrimmedLen = candidate.length - maxInputSize;
+        candidate = candidate.substring(lastCandidatePrefixTrimmedLen);
+      } else {
+        candidate = candidate.substring(0, maxInputSize);
+      }
+    }
+    if (pattern.isEmpty) {
+      // Empty patterns perfectly match candidates.
+      return 1.0;
+    }
+    lastCandidateLen = candidate.length;
+    var candidateLower = candidate.toLowerCase();
+    if (match(candidate, candidateLower)) {
+      var score = computeScore(candidate, candidateLower);
+      if (score > minScore / 2 && !isPoorMatch()) {
+        lastCandidateMatched = true;
+        if (pattern.length == candidate.length) {
+          // Exact matches are always perfect.
+          return 1.0;
+        }
+        if (score < 0) {
+          score = 0;
+        }
+        var normalizedScore = score * scoreScale;
+        if (normalizedScore > 1) {
+          return 1.0;
+        }
+        return normalizedScore;
+      }
+    }
+
+    // Make sure subsequent calls to getMatchedRanges() return an empty list.
+    lastCandidateMatched = false;
+    return -1.0;
+  }
+
+  /// Returns the pre-computed score for a given cell.
+  int scoreAt(int i, int j, int k) {
+    return table[i][j + k * matchesLayerOffset] >> 1;
+  }
+
+  void setInput(MatchStyle style) {
+    if (matchStyle == style) {
+      return;
+    }
+    matchStyle = style;
+    fuzzyMap(pattern, patternRoles);
+  }
+}
+
+/// The type of strings to match against. For files and symbols, FuzzyMatcher
+/// ensures that the match touches the last segment of the candidate string.
+enum MatchStyle {
+  /// An arbitrary string such as a menu title.
+  TEXT,
+
+  /// A path that uses forward slashes for segment separation.
+  FILENAME,
+
+  /// A qualified symbol name.
+  SYMBOL,
+}
+
+enum _CharType { NONE, PUNCT, LOWER, UPPER }
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 56190d1..8478e7d 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -1922,9 +1922,7 @@
 
           builder.write(eol);
           builder.write(indentNew1);
-          builder.write('children: <');
-          builder.writeReference(widgetClassElement);
-          builder.write('>[');
+          builder.write('children: [');
           builder.write(eol);
 
           var newSrc = _replaceSourceIndent(src, indentOld, indentNew2);
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 35e0a65..8a8e8ec 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -395,6 +395,8 @@
       FixKind('REPLACE_WITH_VAR', 50, "Replace type annotation with 'var'");
   static const SORT_CHILD_PROPERTY_LAST = FixKind('SORT_CHILD_PROPERTY_LAST',
       50, 'Move child property to end of arguments');
+  static const SORT_DIRECTIVES =
+      FixKind('SORT_DIRECTIVES', 50, 'Sort directives');
   static const UPDATE_SDK_CONSTRAINTS =
       FixKind('UPDATE_SDK_CONSTRAINTS', 50, 'Update the SDK constraints');
   static const USE_CONST = FixKind('USE_CONST', 50, 'Change to constant');
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 11f111b..98df9e6 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -33,6 +33,7 @@
 import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/levenshtein.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
+import 'package:analysis_server/src/services/correction/organize_directives.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
@@ -633,6 +634,9 @@
       if (name == LintNames.diagnostic_describe_all_properties) {
         await _addFix_addDiagnosticPropertyReference();
       }
+      if (name == LintNames.directives_ordering) {
+        await _addFix_sortDirectives();
+      }
       if (name == LintNames.empty_catches) {
         await _addFix_removeEmptyCatch();
       }
@@ -4120,6 +4124,21 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.SORT_CHILD_PROPERTY_LAST);
   }
 
+  Future<void> _addFix_sortDirectives() async {
+    var organizer =
+        DirectiveOrganizer(resolvedResult.content, unit, resolvedResult.errors);
+
+    var changeBuilder = _newDartChangeBuilder();
+    // todo (pq): consider restructuring organizer to allow a passed-in change builder
+    for (var edit in organizer.organize()) {
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addSimpleReplacement(
+            SourceRange(edit.offset, edit.length), edit.replacement);
+      });
+    }
+    _addFixFromBuilder(changeBuilder, DartFixKind.SORT_DIRECTIVES);
+  }
+
   Future<void> _addFix_undefinedClass_useSimilar() async {
     var node = this.node;
     // Prepare the optional import prefix name.
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 6a91795..345d7d7 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -30,6 +30,7 @@
       'curly_braces_in_flow_control_structures';
   static const String diagnostic_describe_all_properties =
       'diagnostic_describe_all_properties';
+  static const String directives_ordering = 'directives_ordering';
   static const String empty_catches = 'empty_catches';
   static const String empty_constructor_bodies = 'empty_constructor_bodies';
   static const String empty_statements = 'empty_statements';
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 3814029..c633e59 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -447,15 +447,8 @@
     b.write(writeOption('Feature set', options.contextFeatures.toString()));
     b.write('<br>');
 
-    b.write(
-        writeOption('Analyze function bodies', options.analyzeFunctionBodies));
     b.write(writeOption('Generate dart2js hints', options.dart2jsHint));
-    b.write(writeOption(
-        'Generate errors in implicit files', options.generateImplicitErrors));
-    b.write(
-        writeOption('Generate errors in SDK files', options.generateSdkErrors));
     b.write(writeOption('Generate hints', options.hint));
-    b.write(writeOption('Preserve comments', options.preserveComments));
 
     return b.toString();
   }
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index a7c48cf..72c03d1 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -103,8 +103,15 @@
 class F {var x = !1false;}''', <String>['1+true']);
 
     buildTests('testCommentSnippets018', '''
-class Map{}class Arrays{}class C{ m(!1){} n(!2 x, q)''',
-        <String>['1+Map', '1-void', '1-null', '2+Arrays', '2-void', '2-null']);
+class Map{}class Arrays{}class C{ m(!1){} n(!2 x, q)''', <String>[
+      '1+Map',
+      '1+dynamic',
+      '1+void',
+      '1-null',
+      '2+Arrays',
+      '2-void',
+      '2-null'
+    ]);
 
     buildTests('testCommentSnippets019', '''
 class A{m(){Object x;x.!1/**/clear()''', <String>['1+toString']);
diff --git a/pkg/analysis_server/test/lsp/definition_test.dart b/pkg/analysis_server/test/lsp/definition_test.dart
index 2d5c444..5c5fd36 100644
--- a/pkg/analysis_server/test/lsp/definition_test.dart
+++ b/pkg/analysis_server/test/lsp/definition_test.dart
@@ -2,6 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -52,6 +55,29 @@
     expect(loc.uri, equals(referencedFileUri.toString()));
   }
 
+  Future<void> test_fromPlugins() async {
+    final pluginAnalyzedFilePath = join(projectFolderPath, 'lib', 'foo.foo');
+    final pluginAnalyzedFileUri = Uri.file(pluginAnalyzedFilePath);
+    final pluginResult = plugin.AnalysisGetNavigationResult(
+      [pluginAnalyzedFilePath],
+      [NavigationTarget(ElementKind.CLASS, 0, 0, 5, 0, 0)],
+      [
+        NavigationRegion(0, 5, [0])
+      ],
+    );
+    configureTestPlugin(respondWith: pluginResult);
+
+    newFile(pluginAnalyzedFilePath);
+    await initialize();
+    final res = await getDefinition(pluginAnalyzedFileUri, lsp.Position(0, 0));
+
+    expect(res, hasLength(1));
+    var loc = res.single;
+    expect(
+        loc.range, equals(lsp.Range(lsp.Position(0, 0), lsp.Position(0, 5))));
+    expect(loc.uri, equals(pluginAnalyzedFileUri.toString()));
+  }
+
   Future<void> test_nonDartFile() async {
     newFile(pubspecFilePath, content: simplePubspecContent);
     await initialize();
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index d393fb4..ebd7388 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -12,12 +12,17 @@
 import 'package:analysis_server/src/lsp/constants.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';
 import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer_plugin/protocol/protocol.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:meta/meta.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
@@ -38,11 +43,19 @@
         ClientCapabilitiesHelperMixin,
         LspAnalysisServerTestMixin {
   MockLspServerChannel channel;
+  TestPluginManager pluginManager;
   LspAnalysisServer server;
 
   @override
   Stream<Message> get serverToClient => channel.serverToClient;
 
+  void configureTestPlugin({plugin.ResponseResult respondWith}) {
+    PluginInfo info = DiscoveredPluginInfo('a', 'b', 'c', null, null);
+    pluginManager.broadcastResults = <PluginInfo, Future<plugin.Response>>{
+      info: Future.value(respondWith.toResponse('-', 1))
+    };
+  }
+
   /// Sends a request to the server and unwraps the result. Throws if the
   /// response was not successful or returned an error.
   @override
@@ -75,6 +88,7 @@
     channel = MockLspServerChannel(debugPrintCommunication);
     // Create an SDK in the mock file system.
     MockSdk(resourceProvider: resourceProvider);
+    pluginManager = TestPluginManager();
     server = LspAnalysisServer(
         channel,
         resourceProvider,
@@ -82,6 +96,7 @@
         DartSdkManager(convertPath('/sdk'), false),
         CrashReportingAttachmentsBuilder.empty,
         InstrumentationService.NULL_SERVICE);
+    server.pluginManager = pluginManager;
 
     projectFolderPath = convertPath('/home/test');
     projectFolderUri = Uri.file(projectFolderPath);
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 5267658..0ce5609 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -360,6 +360,9 @@
   bool get hasPublishedDocs => false;
 
   @override
+  bool get isIgnorable => true;
+
+  @override
   bool get isUnresolvedIdentifier => false;
 
   @override
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 33834f2..203a14c 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
@@ -400,11 +400,11 @@
 
     await computeSuggestions();
 
-    assertSuggest('children: <Widget>[],',
+    assertSuggest('children: [],',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
         defaultArgListString: null,
-        selectionOffset: 19,
+        selectionOffset: 11,
         defaultArgumentListTextRanges: null);
   }
 
@@ -444,11 +444,11 @@
 
     await computeSuggestions();
 
-    assertSuggest('children: <Widget>[],',
+    assertSuggest('children: [],',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
         defaultArgListString: null,
-        selectionOffset: 19,
+        selectionOffset: 11,
         defaultArgumentListTextRanges: null);
   }
 
@@ -466,11 +466,11 @@
 
     await computeSuggestions();
 
-    assertSuggest('children: <Widget>[],',
+    assertSuggest('children: [],',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
         defaultArgListString: null,
-        selectionOffset: 19,
+        selectionOffset: 11,
         defaultArgumentListTextRanges: null);
   }
 
@@ -494,11 +494,11 @@
 
     await computeSuggestions();
 
-    assertSuggest('children: ,',
+    assertSuggest('children: [],',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
         defaultArgListString: null,
-        selectionOffset: 10,
+        selectionOffset: 11,
         defaultArgumentListTextRanges: null);
   }
 
@@ -546,11 +546,11 @@
 
     await computeSuggestions();
 
-    assertSuggest('slivers: <Widget>[],',
+    assertSuggest('slivers: [],',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
         defaultArgListString: null,
-        selectionOffset: 18,
+        selectionOffset: 10,
         defaultArgumentListTextRanges: null);
   }
 
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index c4521dc..82556d2 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'
     show DartCompletionManager, DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
+import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
@@ -100,6 +101,9 @@
   int replacementOffset;
   int replacementLength;
 
+  /// The Dartdoc information passed to requests.
+  final DartdocDirectiveInfo dartdocInfo = DartdocDirectiveInfo();
+
   DartCompletionRequest request;
 
   List<CompletionSuggestion> suggestions;
@@ -132,6 +136,33 @@
     addSource(testFile, content);
   }
 
+  void assertCoreTypeSuggestions() {
+    assertSuggest('Comparable');
+    assertSuggest('Comparator');
+    assertSuggest('DateTime');
+    assertSuggest('Deprecated');
+    assertSuggest('Duration');
+    assertSuggest('Error');
+    assertSuggest('Exception');
+    assertSuggest('FormatException');
+    assertSuggest('Function');
+    assertSuggest('Future');
+    assertSuggest('Invocation');
+    assertSuggest('Iterable');
+    assertSuggest('Iterator');
+    assertSuggest('List');
+    assertSuggest('Map');
+    assertSuggest('MapEntry');
+    assertSuggest('Null');
+    assertSuggest('Object');
+    assertSuggest('Pattern');
+    assertSuggest('RegExp');
+    assertSuggest('Set');
+    assertSuggest('StackTrace');
+    assertSuggest('Stream');
+    assertSuggest('String');
+  }
+
   void assertHasNoParameterInfo(CompletionSuggestion suggestion) {
     expect(suggestion.parameterNames, isNull);
     expect(suggestion.parameterTypes, isNull);
@@ -544,7 +575,8 @@
         useNewRelevance, CompletionPerformance());
 
     // Build the request
-    var request = await DartCompletionRequestImpl.from(baseRequest);
+    var request =
+        await DartCompletionRequestImpl.from(baseRequest, dartdocInfo);
 
     var range = request.target.computeReplacementRange(request.offset);
     replacementOffset = range.offset;
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 86d3b20..ed776f5 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -51,7 +52,7 @@
         false,
         CompletionPerformance());
     var requestCompleter = Completer<DartCompletionRequest>();
-    DartCompletionRequestImpl.from(baseRequest)
+    DartCompletionRequestImpl.from(baseRequest, DartdocDirectiveInfo())
         .then((DartCompletionRequest request) {
       requestCompleter.complete(request);
     });
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 70752af..799104d 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
@@ -1959,6 +1959,80 @@
     assertNoSuggestions();
   }
 
+  Future<void> test_FieldDeclaration_type() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        class C {^ foo;) ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_FieldDeclaration_type_after_comment1() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        class C {
+          // comment
+          ^ foo;
+        } ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_FieldDeclaration_type_after_comment2() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        class C {
+          /* comment */
+          ^ foo;
+        } ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_FieldDeclaration_type_after_comment3() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        class C {
+          /// some dartdoc
+          ^ foo;
+        } ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_FieldDeclaration_type_without_semicolon() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        class C {^ foo} ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
   Future<void> test_FieldFormalParameter_in_non_constructor() async {
     // SimpleIdentifier  FieldFormalParameter  FormalParameterList
     addTestSource('class A {B(this.^foo) {}}');
@@ -4330,6 +4404,74 @@
     assertNotSuggested('==');
   }
 
+  Future<void> test_TopLevelVariableDeclaration_type() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        ^ foo; ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_TopLevelVariableDeclaration_type_after_comment1() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        // comment
+        ^ foo; ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_TopLevelVariableDeclaration_type_after_comment2() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        /* comment */
+        ^ foo; ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_TopLevelVariableDeclaration_type_after_comment3() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        /// some dartdoc
+        ^ foo; ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
+  Future<void> test_TopLevelVariableDeclaration_type_without_semicolon() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    addSource('/home/test/lib/a.dart', 'class A { }');
+    addTestSource('''
+        import 'a.dart';
+        ^ foo ''');
+
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertCoreTypeSuggestions();
+  }
+
   Future<void> test_TopLevelVariableDeclaration_typed_name() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // TopLevelVariableDeclaration
diff --git a/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart
index 8f3172c..420da3c 100644
--- a/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/inherited_reference_contributor_test.dart
@@ -75,7 +75,34 @@
     assertSuggestMethod('y', 'A', 'Future<dynamic>');
   }
 
-  Future<void> test_Block_inherited_imported() async {
+  Future<void> test_Block_inherited_imported_from_constructor() async {
+    // Block  BlockFunctionBody  ConstructorDeclaration  ClassDeclaration
+    resolveSource('/home/test/lib/b.dart', '''
+      lib B;
+      class F { var f1; f2() { } get f3 => 0; set f4(fx) { } var _pf; }
+      class E extends F { var e1; e2() { } }
+      class I { int i1; i2() { } }
+      class M { var m1; int m2() { } }''');
+    addTestSource('''
+      import "b.dart";
+      class A extends E implements I with M {const A() {^}}''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestField('e1', null);
+    assertSuggestField('f1', null);
+    assertSuggestField('i1', 'int');
+    assertSuggestField('m1', null);
+    assertSuggestGetter('f3', null);
+    assertSuggestSetter('f4');
+    assertSuggestMethod('e2', 'E', null);
+    assertSuggestMethod('f2', 'F', null);
+    assertSuggestMethod('i2', 'I', null);
+    assertSuggestMethod('m2', 'M', 'int');
+    assertNotSuggested('==');
+  }
+
+  Future<void> test_Block_inherited_imported_from_method() async {
     // Block  BlockFunctionBody  MethodDeclaration  ClassDeclaration
     resolveSource('/home/test/lib/b.dart', '''
       lib B;
@@ -102,7 +129,31 @@
     assertNotSuggested('==');
   }
 
-  Future<void> test_Block_inherited_local() async {
+  Future<void> test_Block_inherited_local_from_constructor() async {
+    // Block  BlockFunctionBody  ConstructorDeclaration  ClassDeclaration
+    addTestSource('''
+class F { var f1; f2() { } get f3 => 0; set f4(fx) { } }
+class E extends F { var e1; e2() { } }
+class I { int i1; i2() { } }
+class M { var m1; int m2() { } }
+class A extends E implements I with M {const A() {^}}''');
+    await computeSuggestions();
+
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestField('e1', null);
+    assertSuggestField('f1', null);
+    assertSuggestField('i1', 'int');
+    assertSuggestField('m1', null);
+    assertSuggestGetter('f3', null);
+    assertSuggestSetter('f4');
+    assertSuggestMethod('e2', 'E', null);
+    assertSuggestMethod('f2', 'F', null);
+    assertSuggestMethod('i2', 'I', null);
+    assertSuggestMethod('m2', 'M', 'int');
+  }
+
+  Future<void> test_Block_inherited_local_from_method() async {
     // Block  BlockFunctionBody  MethodDeclaration  ClassDeclaration
     addTestSource('''
 class F { var f1; f2() { } get f3 => 0; set f4(fx) { } }
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 4272bdc..0df9309 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -71,7 +71,13 @@
   }
 
   List<Keyword> get constructorParameter {
-    var keywords = <Keyword>[Keyword.COVARIANT, Keyword.DYNAMIC, Keyword.THIS];
+    var keywords = <Keyword>[
+      Keyword.COVARIANT,
+      Keyword.DYNAMIC,
+      Keyword.THIS,
+      Keyword.DYNAMIC,
+      Keyword.VOID
+    ];
     if (isEnabled(ExperimentalFeatures.non_nullable)) {
       keywords.add(Keyword.REQUIRED);
     }
@@ -156,7 +162,7 @@
   }
 
   List<Keyword> get methodParameter {
-    var keywords = <Keyword>[Keyword.COVARIANT, Keyword.DYNAMIC];
+    var keywords = <Keyword>[Keyword.COVARIANT, Keyword.DYNAMIC, Keyword.VOID];
     if (isEnabled(ExperimentalFeatures.non_nullable)) {
       keywords.add(Keyword.REQUIRED);
     }
@@ -1028,12 +1034,26 @@
     assertSuggestKeywords(constructorParameter);
   }
 
+  Future<void> test_constructor_param_noPrefix_func_parameter() async {
+    addTestSource('class A { A(^ Function(){}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(constructorParameter);
+  }
+
   Future<void> test_constructor_param_prefix() async {
     addTestSource('class A { A(t^) {}}');
     await computeSuggestions();
     assertSuggestKeywords(constructorParameter);
   }
 
+  Future<void> test_constructor_param_prefix_func_parameter() async {
+    addTestSource('class A { A(v^ Function(){}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(constructorParameter);
+  }
+
   Future<void> test_do_break_continue_insideClass() async {
     addTestSource('class A {foo() {do {^} while (true);}}');
     await computeSuggestions();
@@ -1971,6 +1991,13 @@
     assertSuggestKeywords(methodParameter);
   }
 
+  Future<void> test_method_param_noPrefix_func_parameter() async {
+    addTestSource('class A { foo(^ Function(){}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
   Future<void> test_method_param_positional_init() async {
     addTestSource('class A { foo([bool bar = ^]) {}}');
     await computeSuggestions();
@@ -1992,6 +2019,13 @@
     assertSuggestKeywords(methodParameter);
   }
 
+  Future<void> test_method_param_prefix_func_parameter() async {
+    addTestSource('class A { foo(v^ Function(){}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
   Future<void> test_mixin() async {
     addTestSource('mixin M o^ { }');
     await computeSuggestions();
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index 8bf8c19..4ddc388 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -2150,6 +2150,30 @@
     }
   }
 
+  Future<void> test_doc_macro() async {
+    dartdocInfo.addTemplateNamesAndValues([
+      'template_name'
+    ], [
+      '''
+Macro contents on
+multiple lines.
+'''
+    ]);
+    addTestSource('''
+/// {@macro template_name}
+///
+/// With an additional line.
+int x = 0;
+
+void main() {^}
+''');
+    await computeSuggestions();
+    var suggestion = assertSuggestTopLevelVar('x', 'int');
+    expect(suggestion.docSummary, 'Macro contents on\nmultiple lines.');
+    expect(suggestion.docComplete,
+        'Macro contents on\nmultiple lines.\n\n\nWith an additional line.');
+  }
+
   Future<void> test_doc_topLevel() async {
     var docLines = r'''
 /// My documentation.
diff --git a/pkg/analysis_server/test/src/edit/fix/dartfix_listener_test.dart b/pkg/analysis_server/test/src/edit/fix/dartfix_listener_test.dart
new file mode 100644
index 0000000..09382eb
--- /dev/null
+++ b/pkg/analysis_server/test/src/edit/fix/dartfix_listener_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 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DartFixListenerTest);
+  });
+}
+
+@reflectiveTest
+class DartFixListenerTest {
+  DartFixListener listener;
+
+  void setUp() {
+    listener = DartFixListener(null);
+  }
+
+  void test_clear_clears_edits() {
+    listener.addSourceChange(
+        "Example",
+        null,
+        SourceChange("foo")
+          ..edits = [
+            SourceFileEdit("foo", 2, edits: [SourceEdit(0, 0, "foo")])
+          ]);
+    expect(listener.sourceChange.edits, hasLength(1));
+    listener.reset();
+    expect(listener.sourceChange.edits, isEmpty);
+  }
+}
diff --git a/pkg/analysis_server/test/src/edit/fix/test_all.dart b/pkg/analysis_server/test/src/edit/fix/test_all.dart
index 3d33c83..d503cd9 100644
--- a/pkg/analysis_server/test/src/edit/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/edit/fix/test_all.dart
@@ -4,10 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'dartfix_listener_test.dart' as dartfix_listener;
 import 'non_nullable_fix_test.dart' as non_nullable_fix;
 
 void main() {
   defineReflectiveSuite(() {
+    dartfix_listener.main();
     non_nullable_fix.main();
   }, name: 'fix');
 }
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
index 59e080b..9d4a299 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -234,16 +235,6 @@
 
 @reflectiveTest
 class InfoBuilderTest extends NnbdMigrationTestBase {
-  /// Assert various properties of the given [detail].
-  void assertDetail({@required RegionDetail detail, int offset, int length}) {
-    if (offset != null) {
-      expect(detail.target.offset, offset);
-    }
-    if (length != null) {
-      expect(detail.target.length, length);
-    }
-  }
-
   /// Assert various properties of the given [edit].
   void assertEdit(
       {@required EditDetail edit, int offset, int length, String replacement}) {
@@ -259,37 +250,6 @@
     }
   }
 
-  /// Assert that some target in [targets] has various properties.
-  void assertInTargets(
-      {@required Iterable<NavigationTarget> targets, int offset, int length}) {
-    var failureReasons = [
-      if (offset != null) 'offset: $offset',
-      if (length != null) 'length: $length',
-    ].join(' and ');
-    expect(targets.any((t) {
-      return (offset == null || offset == t.offset) &&
-          (length == null || length == t.length);
-    }), isTrue, reason: 'Expected one of $targets to contain $failureReasons');
-  }
-
-  /// Assert various properties of the given [region]. If an [offset] is
-  /// provided but no [length] is provided, a default length of `1` will be
-  /// used.
-  void assertRegion(
-      {@required RegionInfo region,
-      int offset,
-      int length,
-      List<String> details}) {
-    if (offset != null) {
-      expect(region.offset, offset);
-      expect(region.length, length ?? 1);
-    }
-    if (details != null) {
-      expect(region.details.map((detail) => detail.description),
-          unorderedEquals(details));
-    }
-  }
-
   void assertTraceEntry(UnitInfo unit, TraceEntryInfo entryInfo,
       String function, int offset, Object descriptionMatcher) {
     assert(offset >= 0);
@@ -302,159 +262,12 @@
     expect(entryInfo.description, descriptionMatcher);
   }
 
-  Future<void> test_asExpression() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f([num a]) {
-  int b = a as int;
-}
-''', migratedContent: '''
-void f([num? a]) {
-  int? b = a as int?;
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(3));
-    // regions[0] is `num? a`.
-    assertRegion(
-        region: regions[1],
-        offset: 24,
-        details: ['This variable is initialized to a nullable value']);
-    assertRegion(
-        region: regions[2],
-        offset: 38,
-        details: ['The value of the expression is nullable']);
-  }
-
-  Future<void> test_asExpression_insideReturn() async {
-    var unit = await buildInfoForSingleTestFile('''
-int f([num a]) {
-  return a as int;
-}
-''', migratedContent: '''
-int? f([num? a]) {
-  return a as int?;
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(3));
-    // regions[0] is `inf? f`.
-    // regions[1] is `num? a`.
-    assertRegion(
-        region: regions[2],
-        offset: 36,
-        details: ['The value of the expression is nullable']);
-  }
-
-  Future<void> test_bound() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C<T extends Object> {}
-
-void f() {
-  C<int/*?*/> c = null;
-}
-''', migratedContent: '''
-class C<T extends Object?> {}
-
-void f() {
-  C<int?/*?*/>? c = null;
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(3));
-    assertRegion(
-        region: regions[0],
-        offset: 24,
-        details: ['This type parameter is instantiated with a nullable type']);
-  }
-
-  Future<void> test_bound_instantiation_explicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C<T extends Object> {}
-
-void main() {
-  C<int/*?*/>();
-}
-''', migratedContent: '''
-class C<T extends Object?> {}
-
-void main() {
-  C<int?/*?*/>();
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 24,
-        details: ['This type parameter is instantiated with a nullable type']);
-  }
-
-  Future<void> test_bound_instantiation_implicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C<T extends Object> {
-  C(T/*!*/ t);
-}
-
-void main() {
-  C(null);
-}
-''', migratedContent: '''
-class C<T extends Object?> {
-  C(T /*!*/ t);
-}
-
-void main() {
-  C(null);
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    assertRegion(region: regions[0], offset: 24, details: [
-      'This type parameter is instantiated with an inferred nullable type'
-    ]);
-  }
-
-  Future<void> test_bound_method_explicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-f<T extends Object> {}
-
-void main() {
-  f<int/*?*/>();
-}
-''', migratedContent: '''
-f<T extends Object?> {}
-
-void main() {
-  f<int?/*?*/>();
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 18,
-        details: ['This type parameter is instantiated with a nullable type']);
-  }
-
-  Future<void> test_bound_method_implicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-f<T extends Object>(T/*!*/ t) {}
-
-void main() {
-  f(null);
-}
-''', migratedContent: '''
-f<T extends Object?>(T /*!*/ t) {}
-
-void main() {
-  f(null);
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    assertRegion(region: regions[0], offset: 18, details: [
-      'This type parameter is instantiated with an inferred nullable type'
-    ]);
+  List<RegionInfo> getNonInformativeRegions(List<RegionInfo> regions) {
+    return regions
+        .where((region) =>
+            region.kind != NullabilityFixKind.typeNotMadeNullable &&
+            region.kind != NullabilityFixKind.typeNotMadeNullableDueToHint)
+        .toList();
   }
 
   Future<void> test_discardCondition() async {
@@ -471,30 +284,125 @@
 ''');
     var regions = unit.fixRegions;
     expect(regions, hasLength(2));
-    assertRegion(region: regions[0], offset: 38, length: 3);
-    assertRegion(region: regions[1], offset: 56, length: 3);
+    assertRegion(
+        region: regions[0],
+        offset: 38,
+        length: 3,
+        kind: NullabilityFixKind.removeDeadCode);
+    assertRegion(
+        region: regions[1],
+        offset: 56,
+        length: 3,
+        kind: NullabilityFixKind.removeDeadCode);
   }
 
-  Future<void> test_discardElse() async {
-    var unit = await buildInfoForSingleTestFile('''
-void g(int i) {
-  print(i.isEven);
-  if (i != null) print('NULL');
-  else print('NOT NULL');
-}
-''', migratedContent: '''
-void g(int  i) {
-  print(i.isEven);
-  /* if (i != null) */ print('NULL'); /*
-  else print('NOT NULL'); */
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(4));
-    assertRegion(region: regions[0], offset: 38, length: 3);
-    assertRegion(region: regions[1], offset: 56, length: 3);
-    assertRegion(region: regions[2], offset: 73, length: 3);
-    assertRegion(region: regions[3], offset: 102, length: 3);
+  Future<void> test_downcast_nonNullable() async {
+    var content = 'int/*!*/ f(num/*!*/ n) => n;';
+    var migratedContent = 'int /*!*/ f(num /*!*/ n) => n as int;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var regions = getNonInformativeRegions(unit.regions);
+    expect(regions, hasLength(1));
+    var region = regions.single;
+    var regionTarget = ' as int';
+    assertRegion(
+        region: region,
+        offset: migratedContent.indexOf(regionTarget),
+        length: regionTarget.length,
+        kind: NullabilityFixKind.downcastExpression,
+        edits: isEmpty,
+        traces: isEmpty);
+  }
+
+  Future<void> test_downcast_nonNullable_to_nullable() async {
+    var content = 'int/*?*/ f(num/*!*/ n) => n;';
+    // TODO(paulberry): we should actually cast to `int`, not `int?`, because we
+    // know `n` is non-nullable.
+    var migratedContent = 'int?/*?*/ f(num /*!*/ n) => n as int?;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var regions = getNonInformativeRegions(unit.regions);
+    var regionTarget = ' as int?';
+    var offset = migratedContent.indexOf(regionTarget);
+    var region = regions.where((region) => region.offset == offset).single;
+    // TODO(paulberry): once we are correctly casting to `int`, not `int?`, this
+    // should be classified as a downcast.  Currently it's classified as a side
+    // cast.
+    assertRegion(
+        region: region,
+        offset: offset,
+        length: regionTarget.length,
+        kind: NullabilityFixKind.otherCastExpression,
+        edits: isEmpty,
+        traces: isEmpty);
+  }
+
+  Future<void> test_downcast_nullable() async {
+    var content = 'int/*?*/ f(num/*?*/ n) => n;';
+    var migratedContent = 'int?/*?*/ f(num?/*?*/ n) => n as int?;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var regions = getNonInformativeRegions(unit.regions);
+    var regionTarget = ' as int?';
+    var offset = migratedContent.indexOf(regionTarget);
+    var region = regions.where((region) => region.offset == offset).single;
+    assertRegion(
+        region: region,
+        offset: offset,
+        length: regionTarget.length,
+        kind: NullabilityFixKind.downcastExpression,
+        edits: isEmpty,
+        traces: isEmpty);
+  }
+
+  Future<void> test_downcast_nullable_to_nonNullable() async {
+    var content = 'int/*!*/ f(num/*?*/ n) => n;';
+    var migratedContent = 'int /*!*/ f(num?/*?*/ n) => n as int;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var regions = getNonInformativeRegions(unit.regions);
+    var regionTarget = ' as int';
+    var offset = migratedContent.indexOf(regionTarget);
+    var region = regions.where((region) => region.offset == offset).single;
+    assertRegion(
+        region: region,
+        offset: offset,
+        length: regionTarget.length,
+        kind: NullabilityFixKind.downcastExpression,
+        edits: isEmpty,
+        traces: isNotEmpty);
+  }
+
+  Future<void> test_downcast_with_traces() async {
+    var content = 'List<int/*!*/>/*!*/ f(List<int/*?*/>/*?*/ x) => x;';
+    var migratedContent =
+        'List<int /*!*/> /*!*/ f(List<int?/*?*/>?/*?*/ x) => x as List<int>;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var regions = unit.regions.where(
+        (region) => region.kind == NullabilityFixKind.downcastExpression);
+    expect(regions, hasLength(1));
+    var region = regions.single;
+    var regionTarget = ' as List<int>';
+    assertRegion(
+        region: region,
+        offset: migratedContent.indexOf(regionTarget),
+        length: regionTarget.length,
+        kind: NullabilityFixKind.downcastExpression,
+        edits: isEmpty,
+        traces: isNotEmpty);
+    var traceDescriptionToOffset = {
+      for (var trace in region.traces)
+        trace.description: trace.entries[0].target.offset
+    };
+    // Note: +1's below are because trace offsets are actually column numbers.
+    expect(traceDescriptionToOffset, {
+      'Nullability reason': content.indexOf('List<int/*?*/>/*?*/') + 1,
+      'Non-nullability reason': content.indexOf('List<int/*!*/>/*!*/') + 1,
+      'Nullability reason for type argument 0': content.indexOf('int/*?*/') + 1,
+      'Non-nullability reason for type argument 0':
+          content.indexOf('int/*!*/') + 1
+    });
   }
 
   Future<void> test_dynamicValueIsUsed() async {
@@ -521,70 +429,14 @@
     expect(regions, hasLength(1));
     var region = regions[0];
     var edits = region.edits;
-    assertRegion(region: region, offset: 11, details: [
-      'A dynamic value, which is nullable is passed as an argument'
-    ]);
-    assertDetail(detail: region.details[0], offset: 104, length: 1);
+    assertRegion(
+        region: region,
+        offset: 11,
+        explanation: "Changed type 'int' to be nullable");
     assertEdit(edit: edits[0], offset: 10, replacement: '/*!*/');
     assertEdit(edit: edits[1], offset: 10, replacement: '/*?*/');
   }
 
-  Future<void> test_exactNullable() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f(List<int> list) {
-  list[0] = null;
-}
-
-void g() {
-  f(<int>[]);
-}
-''', migratedContent: '''
-void f(List<int?>  list) {
-  list[0] = null;
-}
-
-void g() {
-  f(<int?>[]);
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(3));
-    assertRegion(region: regions[0], offset: 15, details: [
-      "An explicit 'null' is assigned in the function 'f'",
-    ]);
-    // regions[1] is the hard edge that f's parameter is non-nullable.
-    assertRegion(
-        region: regions[2],
-        offset: 67,
-        details: ['This is later required to accept null.']);
-  }
-
-  @FailingTest(issue: 'https://dartbug.com/40587')
-  Future<void> test_exactNullable_exactNullable() async {
-    var unit = await buildInfoForSingleTestFile('''
-void g(List<int> list1, List<int> list2) {
-  list1[0] = null;
-  list2[0] = list1[0];
-}
-''', migratedContent: '''
-void g(List<int?> list1, List<int?> list2) {
-  list1[0] = null;
-  list2[0] = list1[0];
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(4));
-    // regions[0] is the hard edge that list1 is unconditionally indexed
-    assertRegion(region: regions[1], offset: 15, details: [
-      "An explicit 'null' is assigned in the function 'g'",
-    ]);
-    // regions[2] is the hard edge that list2 is unconditionally indexed
-    assertRegion(
-        region: regions[3],
-        offset: 33,
-        details: ["A nullable value is assigned in the function 'g'"]);
-  }
-
   Future<void> test_expressionFunctionReturnTarget() async {
     var unit = await buildInfoForSingleTestFile('''
 String g() => 1 == 2 ? "Hello" : null;
@@ -592,304 +444,12 @@
 String? g() => 1 == 2 ? "Hello" : null;
 ''');
     assertInTargets(targets: unit.targets, offset: 7, length: 1); // "g"
-    assertInTargets(targets: unit.targets, offset: 11, length: 2); // "=>"
     var regions = unit.regions;
     expect(regions, hasLength(1));
     assertRegion(
         region: regions[0],
         offset: 6,
-        details: ['This function returns a nullable value on line 1']);
-    assertDetail(detail: regions[0].details[0], offset: 11, length: 2);
-  }
-
-  Future<void> test_field_fieldFormalInitializer_optional() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  int _f;
-  A([this._f]);
-}
-''', migratedContent: '''
-class A {
-  int? _f;
-  A([this._f]);
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 15, details: [
-      'This field is initialized by an optional field formal parameter that '
-          "has an implicit default value of 'null'"
-    ]);
-  }
-
-  Future<void> test_field_fieldFormalInitializer_optional_defaultNull() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  int _f;
-  A([this._f = null]);
-}
-''', migratedContent: '''
-class A {
-  int? _f;
-  A([this._f = null]);
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 15, details: [
-      'This field is initialized by an optional field formal parameter that '
-          "has an explicit default value of 'null'"
-    ]);
-  }
-
-  Future<void> test_field_fieldFormalInitializer_required() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  int _f;
-  A(this._f);
-}
-void g() {
-  A(null);
-}
-''', migratedContent: '''
-class A {
-  int? _f;
-  A(this._f);
-}
-void g() {
-  A(null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    // TODO(brianwilkerson) It would be nice if the target for the region could
-    //  be the argument rather than the field formal parameter.
-    assertRegion(region: regions[0], offset: 15, details: [
-      'This field is initialized by a field formal parameter and a nullable '
-          'value is passed as an argument'
-    ]);
-  }
-
-  Future<void> test_field_initializer() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  int _f = null;
-  int _f2 = _f;
-}
-''', migratedContent: '''
-class A {
-  int? _f = null;
-  int? _f2 = _f;
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 15,
-        details: ["This field is initialized to an explicit 'null'"]);
-    assertRegion(
-        region: regions[1],
-        offset: 33,
-        details: ['This field is initialized to a nullable value']);
-  }
-
-  Future<void> test_fieldLaterAssignedNullable() async {
-    var unit = await buildInfoForSingleTestFile('''
-class Foo {
-  int value = 7;
-  void bar() {
-    value = null;
-  }
-}
-''', migratedContent: '''
-class Foo {
-  int? value = 7;
-  void bar() {
-    value = null;
-  }
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(1));
-    var region = regions.single;
-    assertRegion(region: region, offset: 17, details: [
-      "An explicit 'null' is assigned in the method 'Foo.bar'",
-    ]);
-
-    assertDetail(detail: region.details[0], offset: 56, length: 4);
-  }
-
-  Future<void> test_functionType_nullable_asArgument() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  f(void Function(int) cb1) {}
-  g(void Function(int) cb2) {
-    f(cb2);
-  }
-  h() => f(null);
-}
-''', migratedContent: '''
-class C {
-  f(void Function(int )? cb1) {}
-  g(void Function(int )  cb2) {
-    f(cb2);
-  }
-  h() => f(null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    assertRegion(
-        region: regions[0],
-        offset: 33,
-        details: ["An explicit 'null' is passed as an argument"]);
-    assertDetail(detail: regions[0].details[0], offset: 98, length: 4);
-  }
-
-  Future<void> test_functionType_nullableParameter_asArgument() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  f(void Function(int) cb1) {
-    cb1(null);
-  }
-  g(void Function(int) cb2) {
-    f(cb2);
-  }
-}
-''', migratedContent: '''
-class C {
-  f(void Function(int?)  cb1) {
-    cb1(null);
-  }
-  g(void Function(int?)  cb2) {
-    f(cb2);
-  }
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 31,
-        details: ["An explicit 'null' is passed as an argument"]);
-    assertRegion(region: regions[1], offset: 82, details: [
-      'The function-typed element in which this parameter is declared is '
-          'assigned to a function whose matching parameter is nullable'
-    ]);
-    assertDetail(detail: regions[1].details[0], offset: 95, length: 3);
-  }
-
-  Future<void> test_functionType_nullableParameter_assignment() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  void Function(int) _cb = (x) {};
-  f(void Function(int) cb) {
-    _cb = cb;
-  }
-  g() => _cb(null);
-}
-''', migratedContent: '''
-class C {
-  void Function(int?)  _cb = (x) {};
-  f(void Function(int?)  cb) {
-    _cb = cb;
-  }
-  g() => _cb(null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    // regions[0] is `void Function(int?) _cb`.
-    assertRegion(region: regions[1], offset: 68, details: [
-      'The function-typed element in which this parameter is declared is '
-          'assigned to a function whose matching parameter is nullable'
-    ]);
-    assertDetail(detail: regions[1].details[0], offset: 84, length: 2);
-  }
-
-  Future<void> test_functionType_nullableParameter_fieldInitializer() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  void Function(int) _cb;
-  C(void Function(int) cb): _cb = cb;
-  f() => _cb(null);
-}
-''', migratedContent: '''
-class C {
-  void Function(int?)  _cb;
-  C(void Function(int?)  cb): _cb = cb;
-  f() => _cb(null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 29,
-        details: ["An explicit 'null' is passed as an argument"]);
-    assertRegion(region: regions[1], offset: 59, details: [
-      'The function-typed element in which this parameter is declared is '
-          'assigned to a function whose matching parameter is nullable'
-    ]);
-    assertDetail(detail: regions[1].details[0], offset: 70, length: 2);
-  }
-
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40034')
-  Future<void> test_functionType_nullableParameter_typedef() async {
-    var unit = await buildInfoForSingleTestFile('''
-typedef Cb = void Function(int);
-class C {
-  Cb _cb;
-  C(void Function(int) cb): _cb = cb;
-  f() => _cb(null);
-}
-''', migratedContent: '''
-typedef Cb = void Function(int?);
-class C {
-  Cb _cb;
-  C(void Function(int?) cb): _cb = cb;
-  f() => _cb(null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    // regions[0] is `typedef Cb = void Function(int?);`.
-    assertRegion(region: regions[1], offset: 75, details: [
-      'The function-typed element in which this parameter is declared is '
-          'assigned to a function whose matching parameter is nullable'
-    ]);
-    assertDetail(detail: regions[1].details[0], offset: 70, length: 2);
-  }
-
-  Future<void> test_functionType_nullableReturn() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  int Function() _cb = () => 7;
-  f(int Function() cb) {
-    _cb = cb;
-  }
-  g() {
-    f(() => null);
-  }
-}
-''', migratedContent: '''
-class C {
-  int? Function()  _cb = () => 7;
-  f(int? Function()  cb) {
-    _cb = cb;
-  }
-  g() {
-    f(() => null);
-  }
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(region: regions[0], offset: 15, details: [
-      'A function-typed value with a nullable return type is assigned'
-    ]);
-    assertDetail(detail: regions[0].details[0], offset: 77, length: 2);
+        explanation: "Changed type 'String' to be nullable");
   }
 
   Future<void> test_insertedRequired_fieldFormal() async {
@@ -910,10 +470,12 @@
     expect(regions, hasLength(1));
     var region = regions[0];
     var edits = region.edits;
-    assertRegion(region: region, offset: 44, length: 9, details: [
-      'This parameter is non-nullable, so cannot have an implicit default '
-          "value of 'null'"
-    ]);
+    assertRegion(
+        region: region,
+        offset: 44,
+        length: 9,
+        explanation: "Add 'required' keyword to parameter 'level' in 'C.'",
+        kind: NullabilityFixKind.addRequired);
     assertEdit(
         edit: edits[0], offset: 42, length: 0, replacement: '@required ');
   }
@@ -934,10 +496,12 @@
     expect(regions, hasLength(1));
     var region = regions[0];
     var edits = region.edits;
-    assertRegion(region: region, offset: 39, length: 9, details: [
-      'This parameter is non-nullable, so cannot have an implicit default '
-          "value of 'null'"
-    ]);
+    assertRegion(
+        region: region,
+        offset: 39,
+        length: 9,
+        explanation: "Add 'required' keyword to parameter 'lvl' in 'C.f'",
+        kind: NullabilityFixKind.addRequired);
     assertEdit(
         edit: edits[0], offset: 37, length: 0, replacement: '@required ');
   }
@@ -963,233 +527,37 @@
         region: regions[0],
         offset: migratedContent.indexOf('? operator'),
         length: 1,
-        details: ["This method returns an explicit 'null' on line 2"]);
+        explanation: "Changed type 'C' to be nullable");
     assertRegion(
         region: regions[1],
         offset: migratedContent.indexOf('!;'),
         length: 1,
-        details: ['This value must be null-checked before use here.']);
+        explanation: 'Added a non-null assertion to nullable expression',
+        kind: NullabilityFixKind.checkExpression);
   }
 
-  Future<void> test_listAndSetLiteralTypeArgument() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  String s = null;
-  var x = <String>["hello", s];
-  var y = <String>{"hello", s};
-}
-''', migratedContent: '''
-void f() {
-  String? s = null;
-  var x = <String?>["hello", s];
-  var y = <String?>{"hello", s};
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(3));
-    // regions[0] is the `String? s` fix.
-    assertRegion(
-        region: regions[1],
-        offset: 48,
-        details: ['This list is initialized with a nullable value on line 3']);
-    assertDetail(detail: regions[1].details[0], offset: 58, length: 1);
-    assertRegion(
-        region: regions[2],
-        offset: 81,
-        details: ['This set is initialized with a nullable value on line 4']);
-    assertDetail(detail: regions[2].details[0], offset: 90, length: 1);
-  }
-
-  Future<void> test_listConstructor_length() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  List<int> list = List<int>(10);
-}
-''', migratedContent: '''
-void f() {
-  List<int?>  list = List<int?>(10);
-}
-''');
+  Future<void> test_nullCheck_dueToHint() async {
+    var content = 'int f(int/*?*/ x) => x/*!*/;';
+    var migratedContent = 'int  f(int?/*?*/ x) => x!/*!*/;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
     var regions = unit.fixRegions;
     expect(regions, hasLength(2));
-    // regions[0] is `num? a`.
-    assertRegion(region: regions[1], offset: 40, details: [
-      'A length is specified in the "List()" constructor and the list items '
-          'are initialized to null'
-    ]);
-  }
-
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40064')
-  Future<void> test_listConstructor_length_implicitType() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  List<int> list = List(10);
-}
-''', migratedContent: '''
-void f() {
-  List<int?> list = List(10);
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    // regions[0] is `num? a`.
-    assertRegion(region: regions[1], offset: 40, details: [
-      'List value type must be nullable because a length is specified,'
-          ' and the list items are initialized as null.'
-    ]);
-  }
-
-  Future<void> test_listLiteralTypeArgument_collectionIf() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  String s = null;
-  var x = <String>[
-    "hello",
-    if (1 == 2) s
-  ];
-}
-''', migratedContent: '''
-void f() {
-  String? s = null;
-  var x = <String?>[
-    "hello",
-    if (1 == 2) s
-  ];
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    // regions[0] is the `String? s` fix.
+    // regions[0] is `int?`.
+    var region = regions[1];
     assertRegion(
-        region: regions[1],
-        offset: 48,
-        details: ['This list is initialized with a nullable value on line 5']);
-    assertDetail(detail: regions[1].details[0], offset: 79, length: 1);
-  }
-
-  Future<void> test_localVariable() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  int v1 = null;
-  int v2 = v1;
-}
-''', migratedContent: '''
-void f() {
-  int? v1 = null;
-  int? v2 = v1;
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 16,
-        details: ["This variable is initialized to an explicit 'null'"]);
-    assertRegion(
-        region: regions[1],
-        offset: 34,
-        details: ['This variable is initialized to a nullable value']);
-  }
-
-  Future<void> test_mapLiteralTypeArgument() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  String s = null;
-  var x = <String, bool>{"hello": false, s: true};
-  var y = <bool, String>{false: "hello", true: s};
-}
-''', migratedContent: '''
-void f() {
-  String? s = null;
-  var x = <String?, bool >{"hello": false, s: true};
-  var y = <bool , String?>{false: "hello", true: s};
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(3));
-    // regions[0] is the `String? s` fix.
-    assertRegion(
-        region: regions[1],
-        offset: 48,
-        details: ['This map is initialized with a nullable value on line 3']);
-    assertDetail(detail: regions[1].details[0], offset: 71, length: 1);
-    assertRegion(
-        region: regions[2],
-        offset: 108,
-        details: ['This map is initialized with a nullable value on line 4']);
-    assertDetail(detail: regions[2].details[0], offset: 128, length: 1);
-  }
-
-  Future<void> test_namedParameterWithDefault_fromOverridden_explicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  void m({int p = 0}) {}
-}
-class B extends A {
-  void m({num p = 0}) {}
-}
-void f(A a) {
-  a.m(p: null);
-}
-''', migratedContent: '''
-class A {
-  void m({int? p = 0}) {}
-}
-class B extends A {
-  void m({num? p = 0}) {}
-}
-void f(A  a) {
-  a.m(p: null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    // regions[0] is "an explicit null is passed..."
-    assertRegion(region: regions[1], offset: 71, details: [
-      'The corresponding parameter in the overridden method, A.m, is nullable'
-    ]);
-    assertDetail(detail: regions[1].details[0], offset: 20, length: 3);
-  }
-
-  Future<void> test_nonNullableType_assert() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f(String s) {
-  assert(s != null);
-}
-''', migratedContent: '''
-void f(String  s) {
-  assert(s != null);
-}
-''');
-    var regions = unit.informativeRegions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 13, length: 1, details: []);
-  }
-
-  Future<void> test_nonNullableType_exclamationComment() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f(String /*!*/ s) {}
-''', migratedContent: '''
-void f(String  /*!*/ s) {}
-''');
-    var regions = unit.informativeRegions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 13, length: 1, details: []);
-  }
-
-  Future<void> test_nonNullableType_unconditionalFieldAccess() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f(String s) {
-  print(s.length);
-}
-''', migratedContent: '''
-void f(String  s) {
-  print(s.length);
-}
-''');
-    var regions = unit.informativeRegions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 13, length: 1, details: []);
+        region: region,
+        offset: migratedContent.indexOf('!/*!*/'),
+        explanation: 'Accepted a null check hint',
+        kind: NullabilityFixKind.checkExpressionDueToHint);
+    // Note that traces are still included.
+    expect(region.traces, isNotEmpty);
+    var textToRemove = '/*!*/';
+    assertEdit(
+        edit: region.edits.single,
+        offset: content.indexOf(textToRemove),
+        length: textToRemove.length,
+        replacement: '');
   }
 
   Future<void> test_nullCheck_onMemberAccess() async {
@@ -1215,175 +583,12 @@
     // regions[0] is `int?`.
     var region = regions[1];
     var edits = region.edits;
-    assertRegion(region: regions[1], offset: 65, details: [
-      'This value must be null-checked before accessing its properties.'
-    ]);
-    assertEdit(edit: edits[0], offset: 64, length: 0, replacement: '/*!*/');
-  }
-
-  Future<void> test_nullCheck_onMethodCall() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  int value;
-  C([this.value]);
-  void f() {
-    value.abs();
-  }
-}
-''', migratedContent: '''
-class C {
-  int? value;
-  C([this.value]);
-  void f() {
-    value!.abs();
-  }
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    // regions[0] is `int?`.
-    assertRegion(region: regions[1], offset: 65, details: [
-      'This value must be null-checked before calling its methods.'
-    ]);
-  }
-
-  Future<void> test_parameter_fromInvocation_explicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f(String s) {}
-void g() {
-  f(null);
-}
-''', migratedContent: '''
-void f(String? s) {}
-void g() {
-  f(null);
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(1));
     assertRegion(
-        region: regions[0],
-        offset: 13,
-        details: ["An explicit 'null' is passed as an argument"]);
-  }
-
-  Future<void> test_parameter_fromInvocation_implicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f(String s) {}
-void g(p) {
-  f(p);
-}
-void h() => g(null);
-''', migratedContent: '''
-void f(String? s) {}
-void g(p) {
-  f(p);
-}
-void h() => g(null);
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 13, details: [
-      'A dynamic value, which is nullable is passed as an argument'
-    ]);
-  }
-
-  Future<void> test_parameter_fromMultipleOverridden_explicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  void m(int p) {}
-}
-class B extends A {
-  void m(num p) {}
-}
-class C extends B {
-  void m(Object p) {}
-}
-void f(A a) {
-  a.m(null);
-}
-''', migratedContent: '''
-class A {
-  void m(int? p) {}
-}
-class B extends A {
-  void m(num? p) {}
-}
-class C extends B {
-  void m(Object? p) {}
-}
-void f(A  a) {
-  a.m(null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(3));
-    // regions[0] is "an explicit null is passed..."
-    assertRegion(region: regions[1], offset: 64, details: [
-      'The corresponding parameter in the overridden method, A.m, is nullable'
-    ]);
-    assertRegion(region: regions[2], offset: 109, details: [
-      'The corresponding parameter in the overridden method, B.m, is nullable'
-    ]);
-    assertDetail(detail: regions[1].details[0], offset: 19, length: 3);
-    assertDetail(detail: regions[2].details[0], offset: 60, length: 3);
-  }
-
-  Future<void> test_parameter_fromMultipleOverridden_implicit() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  void m(int p) {}
-}
-class B extends A {
-  void m(p) {}
-}
-class C extends B {
-  void m(Object p) {}
-}
-void f(A a) {
-  a.m(null);
-}
-''', migratedContent: '''
-class A {
-  void m(int? p) {}
-}
-class B extends A {
-  void m(p) {}
-}
-class C extends B {
-  void m(Object? p) {}
-}
-void f(A  a) {
-  a.m(null);
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    // regions[0] is "an explicit null is passed..."
-    assertRegion(region: regions[1], offset: 104, details: [
-      'The corresponding parameter in the overridden method is nullable'
-    ]);
-  }
-
-  Future<void> test_parameter_fromOverridden_implicitDynamic() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  void m(p) {}
-}
-class B extends A {
-  void m(Object p) {}
-}
-''', migratedContent: '''
-class A {
-  void m(p) {}
-}
-class B extends A {
-  void m(Object  p) {}
-}
-''');
-    var regions = unit.informativeRegions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 62, details: []);
+        region: regions[1],
+        offset: 65,
+        explanation: 'Added a non-null assertion to nullable expression',
+        kind: NullabilityFixKind.checkExpression);
+    assertEdit(edit: edits[0], offset: 64, length: 0, replacement: '/*!*/');
   }
 
   Future<void> test_parameter_fromOverriddenField_explicit() async {
@@ -1406,16 +611,14 @@
 ''');
     var regions = unit.fixRegions;
     expect(regions, hasLength(2));
-    assertRegion(region: regions[0], offset: 15, details: [
-      'This field is not initialized',
-      "An explicit 'null' is assigned in the function 'f'",
-    ]);
-    assertRegion(region: regions[1], offset: 61, details: [
-      // TODO(srawlins): Improve this message to include "B.m".
-      'The corresponding parameter in the overridden method is nullable'
-    ]);
-    assertDetail(detail: regions[0].details[1], offset: 90, length: 4);
-    assertDetail(detail: regions[1].details[0], offset: 12, length: 3);
+    assertRegion(
+        region: regions[0],
+        offset: 15,
+        explanation: "Changed type 'int' to be nullable");
+    assertRegion(
+        region: regions[1],
+        offset: 61,
+        explanation: "Changed type 'Object' to be nullable");
 
     expect(regions[0].traces, hasLength(1));
     var trace = regions[0].traces.first;
@@ -1428,105 +631,6 @@
         contains('explicit type'));
   }
 
-  Future<void> test_parameter_named_omittedInCall() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() { g(); }
-
-void g({int i}) {}
-''', migratedContent: '''
-void f() { g(); }
-
-void g({int? i}) {}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 30, details: [
-      'This named parameter is omitted in a call to this function',
-      "This parameter has an implicit default value of 'null'",
-    ]);
-    assertDetail(detail: regions[0].details[0], offset: 11, length: 3);
-  }
-
-  Future<void> test_parameter_named_omittedInCall_inArgumentList() async {
-    var unit = await buildInfoForSingleTestFile('''
-int f({int compare}) => 7
-void g() {
-  h(f());
-}
-void h(int x) {}
-''', migratedContent: '''
-int  f({int? compare}) => 7
-void g() {
-  h(f());
-}
-void h(int  x) {}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 11, details: [
-      "This parameter has an implicit default value of 'null'",
-      'This named parameter is omitted in a call to this function'
-    ]);
-  }
-
-  Future<void> test_parameter_optional_explicitDefault_null() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f({String s = null}) {}
-''', migratedContent: '''
-void f({String? s = null}) {}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    assertRegion(
-        region: regions[0],
-        offset: 14,
-        details: ["This parameter has an explicit default value of 'null'"]);
-  }
-
-  Future<void> test_parameter_optional_explicitDefault_nullable() async {
-    var unit = await buildInfoForSingleTestFile('''
-String sd = null;
-void f({String s = sd}) {}
-''', migratedContent: '''
-String? sd = null;
-void f({String? s = sd}) {}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[1],
-        offset: 33,
-        details: ['This parameter has a nullable default value']);
-  }
-
-  Future<void> test_parameter_optional_implicitDefault_named() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f({String s}) {}
-''', migratedContent: '''
-void f({String? s}) {}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    assertRegion(
-        region: regions[0],
-        offset: 14,
-        details: ["This parameter has an implicit default value of 'null'"]);
-  }
-
-  Future<void> test_parameter_optional_implicitDefault_positional() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f([String s]) {}
-''', migratedContent: '''
-void f([String? s]) {}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    assertRegion(
-        region: regions[0],
-        offset: 14,
-        details: ["This parameter has an implicit default value of 'null'"]);
-  }
-
   Future<void> test_removal_handles_offsets_correctly() async {
     var originalContent = '''
 void f(num n, int/*?*/ i) {
@@ -1553,59 +657,13 @@
         region: regions[1],
         offset: migratedContent.indexOf(' as int'),
         length: ' as int'.length,
-        details: []);
+        explanation: 'Discarded a downcast that is now unnecessary',
+        kind: NullabilityFixKind.removeAs);
     assertRegion(
         region: regions[2],
         offset: migratedContent.indexOf('! + 1'),
-        details: ['This value must be null-checked before use here.']);
-  }
-
-  Future<void> test_return_fromOverriden() async {
-    var unit = await buildInfoForSingleTestFile('''
-abstract class A {
-  String m();
-}
-class B implements A {
-  String m() => 1 == 2 ? "Hello" : null;
-}
-''', migratedContent: '''
-abstract class A {
-  String? m();
-}
-class B implements A {
-  String? m() => 1 == 2 ? "Hello" : null;
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 27,
-        details: ['An overridding method has a nullable return value']);
-    assertDetail(detail: regions[0].details[0], offset: 60, length: 6);
-  }
-
-  Future<void> test_return_multipleReturns() async {
-    var unit = await buildInfoForSingleTestFile('''
-String g() {
-  int x = 1;
-  if (x == 2) return x == 3 ? "Hello" : null;
-  return "Hello";
-}
-''', migratedContent: '''
-String? g() {
-  int  x = 1;
-  if (x == 2) return x == 3 ? "Hello" : null;
-  return "Hello";
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    assertRegion(
-        region: regions[0],
-        offset: 6,
-        details: ['This function returns a nullable value on line 3']);
-    assertInTargets(targets: unit.targets, offset: 40, length: 6); // "return"
+        explanation: 'Added a non-null assertion to nullable expression',
+        kind: NullabilityFixKind.checkExpression);
   }
 
   Future<void> test_returnDetailTarget() async {
@@ -1619,154 +677,39 @@
 }
 ''');
     assertInTargets(targets: unit.targets, offset: 7, length: 1); // "g"
-    assertInTargets(targets: unit.targets, offset: 15, length: 6); // "return"
     var regions = unit.regions;
     expect(regions, hasLength(1));
     assertRegion(
         region: regions[0],
         offset: 6,
-        details: ['This function returns a nullable value on line 2']);
-    assertDetail(detail: regions[0].details[0], offset: 15, length: 6);
+        explanation: "Changed type 'String' to be nullable");
   }
 
-  Future<void> test_returnNoValue() async {
-    var unit = await buildInfoForSingleTestFile('''
-int f() {
-  return;
+  Future<void> test_suspicious_cast() async {
+    var content = '''
+int f(Object o) {
+  if (o is! String) return 0;
+  return o;
 }
-''', migratedContent: '''
-int? f() {
-  return;
+''';
+    var migratedContent = '''
+int  f(Object  o) {
+  if (o is! String ) return 0;
+  return o as int;
 }
-''');
-    var regions = unit.fixRegions;
+''';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var regions = getNonInformativeRegions(unit.regions);
     expect(regions, hasLength(1));
-    assertRegion(region: regions[0], offset: 3, details: [
-      'This function contains a return statement with no value on line 2,'
-          ' which implicitly returns null.'
-    ]);
-  }
-
-  Future<void> test_returnType_function_expression() async {
-    var unit = await buildInfoForSingleTestFile('''
-int _f = null;
-int f() => _f;
-''', migratedContent: '''
-int? _f = null;
-int? f() => _f;
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
+    var region = regions.single;
+    var regionTarget = ' as int';
     assertRegion(
-        region: regions[0],
-        offset: 3,
-        details: ["This variable is initialized to an explicit 'null'"]);
-    assertRegion(
-        region: regions[1],
-        offset: 19,
-        details: ['This function returns a nullable value on line 2']);
-  }
-
-  Future<void> test_returnType_getter_block() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  int _f = null;
-  int get f {
-    return _f;
-  }
-}
-''', migratedContent: '''
-class A {
-  int? _f = null;
-  int? get f {
-    return _f;
-  }
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 15,
-        details: ["This field is initialized to an explicit 'null'"]);
-    assertRegion(
-        region: regions[1],
-        offset: 33,
-        details: ['This getter returns a nullable value on line 4']);
-  }
-
-  Future<void> test_returnType_getter_expression() async {
-    var unit = await buildInfoForSingleTestFile('''
-class A {
-  int _f = null;
-  int get f => _f;
-}
-''', migratedContent: '''
-class A {
-  int? _f = null;
-  int? get f => _f;
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 15,
-        details: ["This field is initialized to an explicit 'null'"]);
-    assertRegion(
-        region: regions[1],
-        offset: 33,
-        details: ['This getter returns a nullable value on line 3']);
-  }
-
-  Future<void> test_setLiteralTypeArgument_nestedList() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  String s = null;
-  var x = <List<String>>{
-    ["hello"],
-    if (1 == 2) [s]
-  };
-}
-''', migratedContent: '''
-void f() {
-  String? s = null;
-  var x = <List<String?> >{
-    ["hello"],
-    if (1 == 2) [s]
-  };
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    // regions[0] is the `String? s` fix.
-    assertRegion(
-        region: regions[1],
-        offset: 53,
-        details: ['This set is initialized with a nullable value on line 5']);
-    // TODO(srawlins): Actually, this is marking the `[s]`, but I think only
-    //  `s` should be marked. Minor bug for now.
-    assertDetail(detail: regions[1].details[0], offset: 87, length: 3);
-  }
-
-  Future<void> test_topLevelVariable() async {
-    var unit = await buildInfoForSingleTestFile('''
-int _f = null;
-int _f2 = _f;
-''', migratedContent: '''
-int? _f = null;
-int? _f2 = _f;
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 3,
-        details: ["This variable is initialized to an explicit 'null'"]);
-    assertRegion(
-        region: regions[1],
-        offset: 19,
-        details: ['This variable is initialized to a nullable value']);
+        region: region,
+        offset: migratedContent.indexOf(regionTarget),
+        length: regionTarget.length,
+        kind: NullabilityFixKind.otherCastExpression,
+        edits: isEmpty);
   }
 
   Future<void> test_trace_deadCode() async {
@@ -1928,8 +871,7 @@
   }
 
   Future<void> test_trace_nullCheckHint() async {
-    UnitInfo unit = await buildInfoForSingleTestFile(
-        'int f(int/*?*/ i) => i/*!*/;',
+    var unit = await buildInfoForSingleTestFile('int f(int/*?*/ i) => i/*!*/;',
         migratedContent: 'int  f(int?/*?*/ i) => i!/*!*/;');
     var region = unit.regions
         .where(
@@ -1971,6 +913,51 @@
     expect(region.traces[0].description, 'Non-nullability reason');
   }
 
+  Future<void> test_type_made_nullable() async {
+    var unit = await buildInfoForSingleTestFile('''
+String g() => 1 == 2 ? "Hello" : null;
+''', migratedContent: '''
+String? g() => 1 == 2 ? "Hello" : null;
+''');
+    assertInTargets(targets: unit.targets, offset: 7, length: 1); // "g"
+    var regions = unit.regions;
+    expect(regions, hasLength(1));
+    assertRegion(
+        region: regions[0],
+        offset: 6,
+        explanation: "Changed type 'String' to be nullable");
+  }
+
+  Future<void> test_type_made_nullable_due_to_hint() async {
+    var content = 'int/*?*/ x = 0;';
+    var migratedContent = 'int?/*?*/ x = 0;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var region = unit.fixRegions.single;
+    assertRegion(
+        region: region,
+        offset: migratedContent.indexOf('?/*?*/'),
+        explanation:
+            "Changed type 'int' to be nullable, due to a nullability hint",
+        kind: NullabilityFixKind.makeTypeNullableDueToHint);
+    // Note that traces are still included.
+    expect(region.traces, isNotNull);
+    var textToRemove = '/*?*/';
+    var edits = region.edits;
+    expect(edits, hasLength(2));
+    var editsByDescription = {for (var edit in edits) edit.description: edit};
+    assertEdit(
+        edit: editsByDescription['Add /*!*/ hint'],
+        offset: content.indexOf(textToRemove),
+        length: textToRemove.length,
+        replacement: '/*!*/');
+    assertEdit(
+        edit: editsByDescription['Remove /*?*/ hint'],
+        offset: content.indexOf(textToRemove),
+        length: textToRemove.length,
+        replacement: '');
+  }
+
   Future<void> test_type_not_made_nullable() async {
     var unit = await buildInfoForSingleTestFile('int i = 0;',
         migratedContent: 'int  i = 0;');
@@ -1980,91 +967,41 @@
     expect(region.length, 1);
     expect(region.lineNumber, 1);
     expect(region.explanation, "Type 'int' was not made nullable");
-    expect(region.details, isEmpty);
     expect(region.edits.map((edit) => edit.description).toSet(),
-        {'Force type to be non-nullable.', 'Force type to be nullable.'});
+        {'Add /*?*/ hint', 'Add /*!*/ hint'});
     expect(region.traces, isEmpty);
+    expect(region.kind, NullabilityFixKind.typeNotMadeNullable);
   }
 
-  Future<void> test_uninitializedField() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  int value;
-  C();
-  C.one() {
-    this.value = 7;
-  }
-  C.two() {}
-}
-''', migratedContent: '''
-class C {
-  int? value;
-  C();
-  C.one() {
-    this.value = 7;
-  }
-  C.two() {}
-}
-''');
-    var regions = unit.regions;
-    expect(regions, hasLength(1));
-    var region = regions.single;
-    assertRegion(region: region, offset: 15, details: [
-      "The constructor 'C' does not initialize this field in its initializer "
-          'list',
-      "The constructor 'C.one' does not initialize this field in its "
-          'initializer list',
-      "The constructor 'C.two' does not initialize this field in its "
-          'initializer list',
-    ]);
-
-    assertDetail(detail: region.details[0], offset: 25, length: 1);
-    assertDetail(detail: region.details[1], offset: 34, length: 3);
-    assertDetail(detail: region.details[2], offset: 70, length: 3);
-  }
-
-  Future<void> test_uninitializedMember() async {
-    var unit = await buildInfoForSingleTestFile('''
-class C {
-  int level;
-}
-''', migratedContent: '''
-class C {
-  int? level;
-}
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(1));
-    expect(regions[0].details, isNotEmpty);
+  Future<void> test_type_not_made_nullable_due_to_hint() async {
+    var content = 'int/*!*/ i = 0;';
+    var migratedContent = 'int /*!*/ i = 0;';
+    var unit = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    var region = unit.regions
+        .where((regionInfo) =>
+            regionInfo.offset == migratedContent.indexOf(' /*!*/ i'))
+        .single;
     assertRegion(
-        region: regions[0],
-        offset: 15,
-        length: 1,
-        details: ['This field is not initialized']);
-  }
-
-  Future<void> test_uninitializedVariable_notLate_uninitializedUse() async {
-    var unit = await buildInfoForSingleTestFile('''
-void f() {
-  int v1;
-  if (1 == 2) v1 = 7;
-  g(v1);
-}
-void g(int i) => print(i.isEven);
-''', migratedContent: '''
-void f() {
-  int? v1;
-  if (1 == 2) v1 = 7;
-  g(v1!);
-}
-void g(int  i) => print(i.isEven);
-''');
-    var regions = unit.fixRegions;
-    expect(regions, hasLength(2));
-    assertRegion(
-        region: regions[0],
-        offset: 16,
-        details: ['Used on line 4, when it is possibly uninitialized']);
-    // regions[1] is the `v1!` fix.
+        region: region,
+        offset: migratedContent.indexOf(' /*!*/ i'),
+        explanation: "Type 'int' was not made nullable due to a hint",
+        kind: NullabilityFixKind.typeNotMadeNullableDueToHint);
+    // Note that traces are still included.
+    expect(region.traces, isNotNull);
+    var textToRemove = '/*!*/';
+    var edits = region.edits;
+    expect(edits, hasLength(2));
+    var editsByDescription = {for (var edit in edits) edit.description: edit};
+    assertEdit(
+        edit: editsByDescription['Add /*?*/ hint'],
+        offset: content.indexOf(textToRemove),
+        length: textToRemove.length,
+        replacement: '/*?*/');
+    assertEdit(
+        edit: editsByDescription['Remove /*!*/ hint'],
+        offset: content.indexOf(textToRemove),
+        length: textToRemove.length,
+        replacement: '');
   }
 }
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart
index a680df94..12190ab 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart
@@ -20,13 +20,13 @@
 class InstrumentationRendererTest extends NnbdMigrationTestBase {
   /// Render the instrumentation view for [files].
   Future<String> renderViewForTestFiles(Map<String, String> files,
-      {bool applied = false}) async {
+      {bool applied = false, bool needsRerun = false}) async {
     var packageRoot = convertPath('/project');
     await buildInfoForTestFiles(files, includedRoot: packageRoot);
     var migrationInfo =
         MigrationInfo(infos, {}, resourceProvider.pathContext, packageRoot);
     var instrumentationRenderer = InstrumentationRenderer(
-        migrationInfo, PathMapper(resourceProvider), applied);
+        migrationInfo, PathMapper(resourceProvider), applied, needsRerun);
     return instrumentationRenderer.render();
   }
 
@@ -34,20 +34,30 @@
     var renderedView = await renderViewForTestFiles(
         {convertPath('/project/lib/a.dart'): 'int a = null;'},
         applied: true);
-    expect(renderedView, contains('<body class="applied">'));
+    // harmless space in class list due to other potential classes here.
+    expect(renderedView, contains('<body class="applied ">'));
   }
 
   Future<void> test_navigation_containsRoot() async {
     var renderedView = await renderViewForTestFiles(
         {convertPath('/project/lib/a.dart'): 'int a = null;'});
     var expectedPath = convertPath('/project');
+    // harmless space in class list due to other potential classes here.
     expect(renderedView, contains('<p class="root">$expectedPath</p>'));
   }
 
+  Future<void> test_needsRerunStyle() async {
+    var renderedView = await renderViewForTestFiles(
+        {convertPath('/project/lib/a.dart'): 'int a = null;'},
+        needsRerun: true);
+    expect(renderedView, contains('<body class="proposed needs-rerun">'));
+  }
+
   Future<void> test_notAppliedStyle() async {
     var renderedView = await renderViewForTestFiles(
         {convertPath('/project/lib/a.dart'): 'int a = null;'},
         applied: false);
-    expect(renderedView, contains('<body class="proposed">'));
+    // harmless space in class list due to other potential classes here.
+    expect(renderedView, contains('<body class="proposed ">'));
   }
 }
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/migration_info_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/migration_info_test.dart
new file mode 100644
index 0000000..1e17f2d
--- /dev/null
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/migration_info_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:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnitInfoTest);
+  });
+}
+
+@reflectiveTest
+class UnitInfoTest {
+  static bool get _areAssertsEnabled {
+    try {
+      assert(false);
+      return false;
+    } on AssertionError {
+      return true;
+    }
+  }
+
+  void test_hadDiskContent_different() {
+    final unitInfo = UnitInfo('/foo.dart');
+    unitInfo.diskContent = 'abcd';
+    expect(unitInfo.hadDiskContent('dcba'), false);
+  }
+
+  void test_hadDiskContent_nullContentMatchesEmptyString() {
+    final unitInfo = UnitInfo('/foo.dart');
+    unitInfo.diskContent = '';
+    expect(unitInfo.hadDiskContent(null), true);
+    expect(unitInfo.hadDiskContent(''), true);
+  }
+
+  void test_hadDiskContent_nullMatchesEmptyStringContent() {
+    final unitInfo = UnitInfo('/foo.dart');
+    unitInfo.diskContent = null;
+    expect(unitInfo.hadDiskContent(null), true);
+    expect(unitInfo.hadDiskContent(''), true);
+  }
+
+  void test_hadDiskContent_theSame() {
+    final unitInfo = UnitInfo('/foo.dart');
+    unitInfo.diskContent = 'abcd';
+    expect(unitInfo.hadDiskContent('abcd'), true);
+  }
+
+  void test_hadDiskContent_usedBeforeSet_assertsDisabled() {
+    if (_areAssertsEnabled) return;
+
+    final unitInfo = UnitInfo('/foo.dart');
+    expect(unitInfo.hadDiskContent(''), false);
+  }
+
+  void test_hadDiskContent_usedBeforeSet_assertsEnabled() {
+    if (!_areAssertsEnabled) return;
+
+    final unitInfo = UnitInfo('/foo.dart');
+    expect(() => unitInfo.hadDiskContent(''), throwsA(isA<AssertionError>()));
+  }
+}
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/nnbd_migration_test_base.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/nnbd_migration_test_base.dart
index e5bd693..b3e1c6b 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/nnbd_migration_test_base.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/nnbd_migration_test_base.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/edit/nnbd_migration/info_builder.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_listener.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:meta/meta.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
@@ -21,6 +22,45 @@
   /// not yet completed.
   Set<UnitInfo> infos;
 
+  /// Assert that some target in [targets] has various properties.
+  void assertInTargets(
+      {@required Iterable<NavigationTarget> targets,
+      int offset,
+      int length,
+      OffsetMapper offsetMapper}) {
+    var failureReasons = [
+      if (offset != null) 'offset: $offset',
+      if (length != null) 'length: $length',
+      if (offsetMapper != null) 'match a custom offset mapper',
+    ].join(' and ');
+    offsetMapper ??= OffsetMapper.identity;
+    expect(targets.any((t) {
+      return (offset == null || offset == offsetMapper.map(t.offset)) &&
+          (length == null || length == t.length);
+    }), isTrue, reason: 'Expected one of $targets to contain $failureReasons');
+  }
+
+  /// Assert various properties of the given [region]. If an [offset] is
+  /// provided but no [length] is provided, a default length of `1` will be
+  /// used.
+  void assertRegion(
+      {@required RegionInfo region,
+      int offset,
+      int length,
+      Object explanation = anything,
+      Object edits = anything,
+      Object traces = anything,
+      NullabilityFixKind kind = NullabilityFixKind.makeTypeNullable}) {
+    if (offset != null) {
+      expect(region.offset, offset);
+      expect(region.length, length ?? 1);
+    }
+    expect(region.kind, kind);
+    expect(region.edits, edits);
+    expect(region.explanation, explanation);
+    expect(region.traces, traces);
+  }
+
   /// Uses the InfoBuilder to build information for [testFile].
   ///
   /// The information is stored in [infos].
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/offset_mapper_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/offset_mapper_test.dart
index 87597b3..b873c31 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/offset_mapper_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/offset_mapper_test.dart
@@ -24,6 +24,15 @@
     expect(mapper.map(0xFFFFFF), 0xFFFFFF);
   }
 
+  void test_insertMapper() {
+    var mapper = OffsetMapper.forInsertion(10, 5);
+    expect(mapper.map(0), 0);
+    expect(mapper.map(9), 9);
+    expect(mapper.map(10), 15);
+    expect(mapper.map(11), 16);
+    expect(mapper.map(20), 25);
+  }
+
   void test_multipleEdits() {
     var mapper = OffsetMapper.forEdits([
       SourceEdit(13, 0, '?'),
@@ -40,6 +49,55 @@
     expect(mapper.map(55), 58);
   }
 
+  void test_rebase_insertMapper() {
+    var mapper = OffsetMapper.rebase(
+        OffsetMapper.forInsertion(5, 5), OffsetMapper.forInsertion(10, 5));
+    expect(mapper.map(0), 0);
+    expect(mapper.map(4), 4);
+    expect(mapper.map(5), 10);
+    expect(mapper.map(6), 11);
+    expect(mapper.map(9), 14);
+    expect(mapper.map(10), 20);
+    expect(mapper.map(11), 21);
+    expect(mapper.map(12), 22);
+  }
+
+  void test_sequence_insertMappers() {
+    var mapper = OffsetMapper.sequence(
+        OffsetMapper.forInsertion(30, 10), OffsetMapper.forInsertion(10, 10));
+    expect(mapper.map(0), 0);
+    expect(mapper.map(9), 9);
+    expect(mapper.map(10), 20);
+    expect(mapper.map(11), 21);
+    expect(mapper.map(29), 39);
+    expect(mapper.map(30), 50);
+    expect(mapper.map(31), 51);
+  }
+
+  void test_sequence_insertMappers_firstBeforeSecond() {
+    var mapper = OffsetMapper.sequence(
+        OffsetMapper.forInsertion(10, 10), OffsetMapper.forInsertion(30, 10));
+    expect(mapper.map(0), 0);
+    expect(mapper.map(9), 9);
+    expect(mapper.map(10), 20);
+    expect(mapper.map(11), 21);
+    expect(mapper.map(19), 29);
+    expect(mapper.map(20), 40);
+    expect(mapper.map(21), 41);
+  }
+
+  void test_sequence_insertMappers_overlapping() {
+    // by inserting into the middle of a previous insertion, we just effectively
+    // make the first insertion longer.
+    var mapper = OffsetMapper.sequence(
+        OffsetMapper.forInsertion(10, 10), OffsetMapper.forInsertion(15, 5));
+    expect(mapper.map(0), 0);
+    expect(mapper.map(9), 9);
+    expect(mapper.map(10), 25);
+    expect(mapper.map(11), 26);
+    expect(mapper.map(20), 35);
+  }
+
   void test_singleEdit() {
     var mapper = OffsetMapper.forEdits([
       SourceEdit(13, 0, '?'),
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/region_renderer_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/region_renderer_test.dart
index e6380b1..7f88d2b 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/region_renderer_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/region_renderer_test.dart
@@ -32,18 +32,6 @@
         .render();
   }
 
-  Future<void> test_modifiedOutput_containsDetail() async {
-    await buildInfoForSingleTestFile('int a = null;',
-        migratedContent: 'int? a = null;');
-    var response = renderRegion(3);
-    expect(response.details, hasLength(1));
-    var detail = response.details.single;
-    expect(detail.description,
-        equals("This variable is initialized to an explicit 'null'"));
-    expect(detail.link.path, equals('test.dart'));
-    expect(detail.link.href, equals('test.dart?offset=8&line=1'));
-  }
-
   Future<void> test_modifiedOutput_containsExplanation() async {
     await buildInfoForSingleTestFile('int a = null;',
         migratedContent: 'int? a = null;');
@@ -59,23 +47,6 @@
     expect(response.line, equals(1));
   }
 
-  @FailingTest(reason: "Unmodified output reason doesn't contain detail")
-  Future<void> test_unmodifiedOutput_containsDetail() async {
-    await buildInfoForSingleTestFile('f(int a) => a.isEven;',
-        migratedContent: 'f(int  a) => a.isEven;');
-    var response = renderRegion(5);
-    expect(response.details, isNotEmpty);
-    // TODO(paulberry): fix and re-enable.
-//    expect(response.details, hasLength(1));
-//    var detail = response.details.single;
-//    expect(
-//        detail.description,
-//        equals('This value is unconditionally used in a '
-//            'non-nullable context'));
-//    expect(detail.link.path, equals('test.dart'));
-//    expect(detail.link.href, equals('test.dart?offset=12&line=1'));
-  }
-
   Future<void> test_unmodifiedOutput_containsExplanation() async {
     await buildInfoForSingleTestFile('f(int a) => a.isEven;',
         migratedContent: 'f(int  a) => a.isEven;');
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart
index f2277ef..6ac9f59 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart
@@ -6,6 +6,7 @@
 
 import 'info_builder_test.dart' as info_builder;
 import 'instrumentation_renderer_test.dart' as instrumentation_renderer;
+import 'migration_info_test.dart' as migration_info;
 import 'navigation_tree_renderer_test.dart' as navigation_tree_renderer;
 import 'offset_mapper_test.dart' as offset_mapper;
 import 'region_renderer_test.dart' as region_renderer;
@@ -15,6 +16,7 @@
   defineReflectiveSuite(() {
     info_builder.main();
     instrumentation_renderer.main();
+    migration_info.main();
     navigation_tree_renderer.main();
     offset_mapper.main();
     region_renderer.main();
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart
index 5c26be5..a861fd6 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart
@@ -6,6 +6,7 @@
 import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/unit_renderer.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/web/file_details.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -57,17 +58,37 @@
 bool  b = a!.isEven;
 ''');
     var output = renderUnits()[0];
-    expect(output.edits, hasLength(2));
-    expect(output.edits[0].line, equals(1));
-    expect(output.edits[0].offset, equals(3));
-    expect(output.edits[0].explanation,
+    // The null checks are higher priority than the assertions.
+    expect(output.edits.keys,
+        orderedEquals(['1 null check added', '1 type made nullable']));
+    var typesMadeNullable = output.edits['1 type made nullable'];
+    expect(typesMadeNullable, hasLength(1));
+    var typeMadeNullable = typesMadeNullable.single;
+    expect(typeMadeNullable.line, equals(1));
+    expect(typeMadeNullable.offset, equals(3));
+    expect(typeMadeNullable.explanation,
         equals("Changed type 'int' to be nullable"));
-    expect(output.edits[1].line, equals(2));
-    expect(output.edits[1].offset, equals(26));
-    expect(output.edits[1].explanation,
+    var nullChecks = output.edits['1 null check added'];
+    expect(nullChecks, hasLength(1));
+    var nullCheck = nullChecks.single;
+    expect(nullCheck.line, equals(2));
+    expect(nullCheck.offset, equals(26));
+    expect(nullCheck.explanation,
         equals('Added a non-null assertion to nullable expression'));
   }
 
+  Future<void> test_editList_pluralHeader() async {
+    await buildInfoForSingleTestFile('''
+int a = null;
+int b = null;
+''', migratedContent: '''
+int? a = null;
+int? b = null;
+''');
+    var output = renderUnits()[0];
+    expect(output.edits.keys.toList(), ['2 types made nullable']);
+  }
+
   Future<void> test_handle_large_deleted_region_near_top_of_file() async {
     await buildInfoForSingleTestFile('''
 class C {
@@ -135,10 +156,23 @@
   }
 }
 
-<a href="..." class="nav-link">List</a>&lt;<a href="..." class="nav-link">int</a>?&gt;  <span id="...">x</span> = <span id="...">[null]</span>;
+<a href="..." class="nav-link">List</a>&lt;<a href="..." class="nav-link">int</a>?&gt;  <span id="...">x</span> = [null];
 ''');
   }
 
+  void test_kindPriorityOrder() {
+    var nonDisplayedKinds = NullabilityFixKind.values.toSet();
+    for (var kind in UnitRenderer.kindPriorityOrder) {
+      expect(nonDisplayedKinds.remove(kind), isTrue);
+    }
+    // The only kinds that should not be displayed are those associated with a
+    // place where nothing interesting occurred.
+    expect(nonDisplayedKinds, {
+      NullabilityFixKind.typeNotMadeNullable,
+      NullabilityFixKind.typeNotMadeNullableDueToHint
+    });
+  }
+
   Future<void> test_navContentContainsEscapedHtml() async {
     await buildInfoForSingleTestFile('List<String> a = null;',
         migratedContent: 'List<String >? a = null;');
@@ -150,7 +184,57 @@
         navContent,
         contains(r'<a href="..." class="nav-link">List</a>'
             r'&lt;<a href="..." class="nav-link">String</a> &gt;? '
-            r'<span id="o13">a</span> = <span id="o17">null</span>;'));
+            r'<span id="o13">a</span> = null;'));
+  }
+
+  Future<void> test_outputContains_addedType() async {
+    await buildInfoForSingleTestFile('''
+void f() {
+  final a = <List<int>>[];
+  a.add([null]);
+}
+''', migratedContent: '''
+void f() {
+  final List<List<int?>> a = <List<int > >[];
+  a.add([null]);
+}
+''');
+    var output = renderUnits()[0];
+    var regions = _stripDataAttributes(output.regions);
+    expect(
+        regions,
+        contains('final '
+            '<span class="region added-region">List&lt;List&lt;int?&gt;&gt;</span>'
+            ' a = &lt;List&lt;int'
+            '<span class="region informative-region"> </span>'
+            '&gt;'
+            '<span class="region informative-region"> </span>'
+            '&gt;[];'));
+  }
+
+  Future<void> test_outputContains_replacedVar() async {
+    await buildInfoForSingleTestFile('''
+void f() {
+  var a = <List<int>>[];
+  a.add([null]);
+}
+''', migratedContent: '''
+void f() {
+  varList<List<int?>> a = <List<int > >[];
+  a.add([null]);
+}
+''');
+    var output = renderUnits()[0];
+    var regions = _stripDataAttributes(output.regions);
+    expect(
+        regions,
+        contains('<span class="region removed-region">var</span>'
+            '<span class="region added-region">List&lt;List&lt;int?&gt;&gt;</span>'
+            ' a = &lt;List&lt;int'
+            '<span class="region informative-region"> </span>'
+            '&gt;'
+            '<span class="region informative-region"> </span>'
+            '&gt;[];'));
   }
 
   Future<void> test_outputContainsModifiedAndUnmodifiedRegions() async {
diff --git a/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart b/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart
index 52b74d1..bc66122 100644
--- a/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart
+++ b/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart
@@ -5,34 +5,46 @@
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/migration_state.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
 import 'package:analysis_server/src/edit/preview/preview_site.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart'
+    hide NavigationTarget;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../nnbd_migration/nnbd_migration_test_base.dart';
+
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PreviewSiteTest);
+    defineReflectiveTests(PreviewSiteWithEngineTest);
   });
 }
 
 @reflectiveTest
-class PreviewSiteTest with ResourceProviderMixin {
-  PreviewSite site;
-  DartFixListener dartfixListener;
-  MigrationState state;
+class PreviewSiteTest with ResourceProviderMixin, PreviewSiteTestMixin {
+  Future<void> performEdit(String path, int offset, String replacement) {
+    final pathUri = Uri.file(path).path;
+    return site
+        .performEdit(Uri.parse('localhost://$pathUri?offset=$offset&end=$offset'
+            '&replacement=${Uri.encodeComponent(replacement)}'));
+  }
 
   void setUp() {
+    reranPaths = null;
     dartfixListener = DartFixListener(null);
     resourceProvider = MemoryResourceProvider();
     final migrationInfo = MigrationInfo({}, {}, null, null);
     state = MigrationState(null, null, dartfixListener, null, null);
     state.pathMapper = PathMapper(resourceProvider);
     state.migrationInfo = migrationInfo;
-    site = PreviewSite(state, ([_]) => null);
+    site = PreviewSite(state, ([paths]) async {
+      reranPaths = paths;
+      return state;
+    });
   }
 
   void test_applyChangesEmpty() {
@@ -48,10 +60,30 @@
     expect(site.performApply, throwsA(isA<StateError>()));
   }
 
+  void test_applyMigration_sanityCheck_dontApply() async {
+    final path = convertPath('/test.dart');
+    final file = getFile(path);
+    site.unitInfoMap[path] = UnitInfo(path)
+      ..diskContent = '// different content';
+    final currentContent = 'void main() {}';
+    file.writeAsStringSync(currentContent);
+    dartfixListener.addSourceChange(
+        'test change',
+        Location(path, 10, 0, 1, 10),
+        SourceChange('test change', edits: [
+          SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')])
+        ]));
+    expect(() => site.performApply(), throwsA(isA<StateError>()));
+    expect(file.readAsStringSync(), currentContent);
+    expect(state.hasBeenApplied, false);
+  }
+
   void test_applyMultipleChanges() {
     final path = convertPath('/test.dart');
     final file = getFile(path);
-    file.writeAsStringSync('void main() {}');
+    final content = 'void main() {}';
+    file.writeAsStringSync(content);
+    site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
     dartfixListener.addSourceChange(
         'test change',
         Location(path, 10, 0, 1, 10),
@@ -72,7 +104,9 @@
   void test_applySingleChange() {
     final path = convertPath('/test.dart');
     final file = getFile(path);
-    file.writeAsStringSync('void main() {}');
+    final content = 'void main() {}';
+    file.writeAsStringSync(content);
+    site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
     dartfixListener.addSourceChange(
         'test change',
         Location(path, 10, 0, 1, 10),
@@ -83,4 +117,112 @@
     expect(file.readAsStringSync(), 'void main(List args) {}');
     expect(state.hasBeenApplied, true);
   }
+
+  void test_performEdit() {
+    final path = convertPath('/test.dart');
+    final file = getFile(path);
+    final content = 'int foo() {}';
+    final unitInfo = UnitInfo(path)
+      ..diskContent = content
+      ..content = content
+      ..diskChangesOffsetMapper = OffsetMapper.identity;
+    site.unitInfoMap[path] = unitInfo;
+    file.writeAsStringSync(content);
+    performEdit(path, 3, '/*?*/');
+    expect(file.readAsStringSync(), 'int/*?*/ foo() {}');
+    expect(state.hasBeenApplied, false);
+    expect(state.needsRerun, true);
+    expect(reranPaths, null);
+    expect(unitInfo.content, 'int/*?*/ foo() {}');
+  }
+
+  void test_performEdit_sanityCheck_dontApply() {
+    final path = convertPath('/test.dart');
+    final file = getFile(path);
+    site.unitInfoMap[path] = UnitInfo(path)
+      ..diskContent = '// different content';
+    final currentContent = 'void main() {}';
+    file.writeAsStringSync(currentContent);
+    expect(() => performEdit(path, 0, 'foo'), throwsA(isA<StateError>()));
+    expect(file.readAsStringSync(), currentContent);
+    expect(state.hasBeenApplied, false);
+  }
+}
+
+mixin PreviewSiteTestMixin {
+  PreviewSite site;
+  DartFixListener dartfixListener;
+  MigrationState state;
+  List<String> reranPaths;
+
+  Future<void> performEdit(String path, int offset, String replacement) {
+    final pathUri = Uri.file(path).path;
+    return site
+        .performEdit(Uri.parse('localhost://$pathUri?offset=$offset&end=$offset'
+            '&replacement=${Uri.encodeComponent(replacement)}'));
+  }
+}
+
+@reflectiveTest
+class PreviewSiteWithEngineTest extends NnbdMigrationTestBase
+    with ResourceProviderMixin, PreviewSiteTestMixin {
+  @override
+  void setUp() {
+    super.setUp();
+    reranPaths = null;
+    dartfixListener = DartFixListener(null);
+    final migrationInfo = MigrationInfo({}, {}, null, null);
+    state = MigrationState(null, null, dartfixListener, null, null);
+    state.pathMapper = PathMapper(resourceProvider);
+    state.migrationInfo = migrationInfo;
+    site = PreviewSite(state, ([paths]) async {
+      reranPaths = paths;
+      return state;
+    });
+  }
+
+  void test_performEdit_multiple() async {
+    final path = convertPath('/test.dart');
+    final file = getFile(path);
+    final content = r'''
+int x;
+int y = x;
+''';
+    file.writeAsStringSync(content);
+    final migratedContent = '''
+int? x;
+int? y = x;
+''';
+    final unitInfo = await buildInfoForSingleTestFile(content,
+        migratedContent: migratedContent);
+    site.unitInfoMap[path] = unitInfo;
+    final firstEditOffset = unitInfo.regions[0].edits[0].offset;
+    performEdit(path, firstEditOffset, '/*?*/');
+    final secondEditOffset = unitInfo.regions[1].edits[0].offset;
+    performEdit(path, secondEditOffset, '/*?*/');
+    expect(file.readAsStringSync(), '''
+int/*?*/ x;
+int/*?*/ y = x;
+''');
+    expect(unitInfo.content, '''
+int/*?*/? x;
+int/*?*/? y = x;
+''');
+    assertRegion(
+        region: unitInfo.regions[0], offset: unitInfo.content.indexOf('? x'));
+    assertRegion(
+        region: unitInfo.regions[1], offset: unitInfo.content.indexOf('? y'));
+    final targets = List<NavigationTarget>.from(unitInfo.targets);
+    assertInTargets(
+        targets: targets,
+        offset: unitInfo.content.indexOf('x'),
+        offsetMapper: unitInfo.offsetMapper);
+    assertInTargets(
+        targets: targets,
+        offset: unitInfo.content.indexOf('y'),
+        offsetMapper: unitInfo.offsetMapper);
+    expect(state.hasBeenApplied, false);
+    expect(state.needsRerun, true);
+    expect(reranPaths, null);
+  }
 }
diff --git a/pkg/analysis_server/test/src/plugin/notification_manager_test.dart b/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
index 891e189..88fd799 100644
--- a/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
@@ -47,7 +47,7 @@
     fileA = provider.convertPath('/test/a.dart');
     fileB = provider.convertPath('/test/b.dart');
     channel = TestChannel();
-    manager = NotificationManager(channel, provider);
+    manager = NotificationManager(channel, provider.pathContext);
   }
 
   void test_handlePluginNotification_errors() {
diff --git a/pkg/analysis_server/test/src/services/completion/filtering/fuzzy_matcher_test.dart b/pkg/analysis_server/test/src/services/completion/filtering/fuzzy_matcher_test.dart
new file mode 100644
index 0000000..3bc5d7a
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/completion/filtering/fuzzy_matcher_test.dart
@@ -0,0 +1,345 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/completion/filtering/fuzzy_matcher.dart';
+import 'package:meta/meta.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FuzzyMapTest);
+    defineReflectiveTests(FuzzyMatcherTest);
+    defineReflectiveTests(FuzzyScorerTest);
+    defineReflectiveTests(ScoringFunctionTest);
+  });
+}
+
+/// Surrounds all matching ranges with brackets.
+String highlightMatches(String str, FuzzyMatcher matcher) {
+  var matches = matcher.getMatchedRanges();
+  expect(matches.length % 2, 0);
+  for (var i = 1; i < matches.length; i++) {
+    expect(matches[i], isNot(lessThan(matches[i - 1])));
+  }
+
+  var index = 0;
+  var result = '';
+  for (var i = 0; i < matches.length - 1; i += 2) {
+    result += str.substring(index, matches[i]) +
+        '[' +
+        str.substring(matches[i], matches[i + 1]) +
+        ']';
+    index = matches[i + 1];
+  }
+  return result + str.substring(index);
+}
+
+@reflectiveTest
+class FuzzyMapTest {
+  static MatchStyle FILE = MatchStyle.FILENAME;
+  static MatchStyle SYM = MatchStyle.SYMBOL;
+
+  void map(
+      {@required String str,
+      @required String want,
+      MatchStyle matchStyle = MatchStyle.TEXT}) {
+//    test('maps characters of $str', () {
+    var out = List<CharRole>.filled(str.length, CharRole.NONE);
+    var matcher = FuzzyMatcher('', matchStyle: matchStyle);
+    matcher.fuzzyMap(str, out);
+    var result = '';
+    var map = ' /cuC';
+    for (var i = 0; i < str.length; i++) {
+      result += map[out[i].index];
+    }
+    expect(result, want);
+//    });
+  }
+
+  void test_map() {
+    // Text
+    map(str: 'abc', want: 'Ccc');
+    map(str: '.abc', want: ' Ccc');
+    map(str: 'abc def', want: 'Ccc Ccc');
+    map(str: 'SWT MyID', want: 'Cuu CcCu');
+    map(str: 'ID', want: 'Cu');
+    map(str: ' ID ', want: ' Cu ');
+    map(str: 'IDSome', want: 'CuCccc');
+    map(str: '0123456789', want: 'Cccccccccc');
+    map(str: 'abcdefghigklmnopqrstuvwxyz', want: 'Cccccccccccccccccccccccccc');
+    map(str: 'ABCDEFGHIGKLMNOPQRSTUVWXYZ', want: 'Cuuuuuuuuuuuuuuuuuuuuuuuuu');
+    map(str: 'こんにちは', want: 'Ccccc');
+    map(str: ':/.', want: '   ');
+
+    // File names
+    map(str: 'abc/def', want: 'Ccc/Ccc', matchStyle: FILE);
+    map(str: ' abc_def', want: ' Ccc Ccc', matchStyle: FILE);
+    map(str: ' abc_DDf', want: ' Ccc CCc', matchStyle: FILE);
+    map(str: ':.', want: '  ', matchStyle: FILE);
+
+    // Symbols
+    map(str: 'abc::def::goo', want: 'Ccc//Ccc//Ccc', matchStyle: SYM);
+    map(str: 'proto::Message', want: 'Ccccc//Ccccccc', matchStyle: SYM);
+    map(str: 'AbstractSWTFactory', want: 'CcccccccCuuCcccccc', matchStyle: SYM);
+    map(str: 'Abs012', want: 'Cccccc', matchStyle: SYM);
+    map(str: 'public setFoo', want: 'Cccccc/CccCcc', matchStyle: SYM);
+    map(str: '/', want: ' ', matchStyle: SYM);
+  }
+}
+
+@reflectiveTest
+class FuzzyMatcherTest {
+  void expectMatch(FuzzyMatcher matcher, String str, String expected) {
+    expect(matcher.score(str), greaterThan(0));
+    expect(highlightMatches(str, matcher), expected);
+  }
+
+  void test_considersTheEmptyStringToMatchAll() {
+    var matcher = FuzzyMatcher('');
+    expect(matcher.score('def'), greaterThan(0));
+    expect(matcher.getMatchedRanges(), []);
+    expect(matcher.score('Ab stuff c'), greaterThan(0));
+    expect(matcher.getMatchedRanges(), []);
+  }
+
+  void test_ranksActions() {
+    var matcher = FuzzyMatcher('jade', matchStyle: MatchStyle.TEXT);
+    // Full word matches score higher than subsequence matches.
+    expect(
+        matcher.score('jump to a directory in tree'),
+        lessThan(matcher
+            .score('fix imports and dependencies using jade (java only)')));
+
+    matcher = FuzzyMatcher('unedit', matchStyle: MatchStyle.TEXT);
+    expect(matcher.score('Undo an edit'),
+        lessThan(matcher.score('Close unedited tabs')));
+
+    matcher = FuzzyMatcher('fix', matchStyle: MatchStyle.TEXT);
+    expect(
+        matcher.score('find next match'),
+        lessThan(
+            matcher.score('format edited lines in workspace files (g4 fix)')));
+  }
+
+  void test_ranksFileNames() {
+    var matcher = FuzzyMatcher('aa', matchStyle: MatchStyle.FILENAME);
+    // Full word matches scores higher than subsequence matches.
+    expect(matcher.score('a/a/a'), lessThan(matcher.score('b/aa')));
+    // Matches starting at the word boundary score higher.
+    expect(matcher.score('baab'), lessThan(matcher.score('aabb')));
+    // First word scores higher than later ones.
+    expect(matcher.score('bb_aa'), lessThan(matcher.score('aa_bb')));
+    // Tails don't matter.
+    expect(matcher.score('aa_b'), matcher.score('aab'));
+  }
+
+  void test_ranksSymbols() {
+    var matcher = FuzzyMatcher('Foo', matchStyle: MatchStyle.SYMBOL);
+    // Prefix and complete matches are the same.
+    expect(matcher.score('FooA'), matcher.score('Foo'));
+    // First word scores higher than later ones.
+    expect(matcher.score('BarFoo'), lessThan(matcher.score('FooBar')));
+    // Aligned matches score higher.
+    expect(matcher.score('Barfoo'), lessThan(matcher.score('BarFoo')));
+    expect(matcher.score('F__oo'), matcher.score('F_oo'));
+    expect(matcher.score('F_o_o'), lessThan(matcher.score('F_oo')));
+    // Missed word vs a match in the middle.
+    expect(matcher.score('BarFaoo'), lessThan(matcher.score('BarFaoFooa')));
+
+    matcher = FuzzyMatcher('FooBar', matchStyle: MatchStyle.SYMBOL);
+    // Ignores incomplete matches
+    expect(matcher.score('FooaBar'), lessThan(matcher.score('FooBar')));
+    expect(matcher.score('FooBara'), matcher.score('FooBar'));
+    // Less words in the middle is better.
+    expect(matcher.score('FooAtBaBar'), lessThan(matcher.score('FooAtBar')));
+    expectMatch(matcher, 'FooAtBaBar', '[Foo]AtBa[Bar]');
+  }
+
+  void test_respectsTheBasename() {
+    var matcher = FuzzyMatcher('subs', matchStyle: MatchStyle.FILENAME);
+    expect(matcher.score('sub/seq'), greaterThanOrEqualTo(0));
+    expect(matcher.score('sub/seq/end'), -1);
+    expect(matcher.score('sub/seq'), greaterThanOrEqualTo(0));
+    expect(matcher.score('sub/seq/base'), greaterThanOrEqualTo(0));
+  }
+
+  void test_worksWithDepotPaths() {
+    var matcher = FuzzyMatcher('subs', matchStyle: MatchStyle.FILENAME);
+    expect(matcher.score('//sub/seq'), greaterThanOrEqualTo(0));
+    expect(matcher.score('//sub/seq/end'), -1);
+    expect(matcher.score('//sub/seq'), greaterThanOrEqualTo(0));
+    expect(matcher.score('//sub/seq/base'), greaterThanOrEqualTo(0));
+  }
+
+  void test_worksWithSimpleCases() {
+    var matcher = FuzzyMatcher('abc');
+    expect(matcher.score('def'), -1);
+    expect(matcher.score('abd'), -1);
+    expect(matcher.score('abc'), greaterThan(0));
+    expect(matcher.score('Abc'), greaterThan(0));
+    expect(matcher.score('Ab stuff c'), greaterThan(0));
+  }
+
+  void test_worksWithUpperCasePatterns() {
+    var matcher = FuzzyMatcher('Abc');
+    expect(matcher.score('def'), -1);
+    expect(matcher.score('abd'), -1);
+    expect(matcher.score('abc'), greaterThan(0));
+    expect(matcher.score('Abc'), greaterThan(0));
+    expect(matcher.score('Ab stuff c'), greaterThan(0));
+  }
+}
+
+@reflectiveTest
+class FuzzyScorerTest {
+  static MatchStyle FILE = MatchStyle.FILENAME;
+
+  static MatchStyle SYM = MatchStyle.SYMBOL;
+
+  void score(
+      {@required String p,
+      @required String str,
+      String want,
+      MatchStyle input = MatchStyle.TEXT}) {
+//    test('scores $str against $p', () {
+    var matcher = FuzzyMatcher(p, matchStyle: input);
+    if (want != null) {
+      expect(matcher.score(str), greaterThanOrEqualTo(0));
+      expect(highlightMatches(str, matcher), want);
+    } else {
+      expect(matcher.score(str), -1);
+    }
+//    });
+  }
+
+  void test_scorer() {
+    // Text
+    score(p: 'a', str: 'abc', want: '[a]bc');
+    score(p: 'aaa', str: 'aaa', want: '[aaa]');
+    score(p: 'aaa', str: 'abab');
+    score(p: 'aaba', str: 'abababa', want: '[a]b[aba]ba');
+    score(p: 'cabaa', str: 'c_babababa', want: '[c]_b[aba]b[a]ba');
+    score(p: 'caaa', str: 'c_babababaaa', want: '[c]_bababab[aaa]');
+    score(p: 'aaa', str: 'aaababababaaa', want: '[aaa]babababaaa');
+    score(
+        p: 'unedit', str: 'Close unedited tabs', want: 'Close [unedit]ed tabs');
+    // Forward slashes are ignored in the non-filename mode.
+    score(p: 'aaa', str: 'aaabab/ababaaa', want: '[aaa]bab/ababaaa');
+    score(p: 'aaa', str: 'baaabab/abab_aaa', want: 'baaabab/abab_[aaa]');
+
+    // Filenames.
+    score(p: 'aa', str: 'a_a/a_a', want: '[a]_a/[a]_a', input: FILE);
+    score(p: 'aaaa', str: 'a_a/a_a', want: '[a]_[a]/[a]_[a]', input: FILE);
+    score(p: 'aaaa', str: 'aaaa', want: '[aaaa]', input: FILE);
+    score(p: 'aaaa', str: 'a_a/a_aaaa', want: 'a_a/[a]_[aaa]a', input: FILE);
+    score(p: 'aaaa', str: 'a_a/aaaaa', want: 'a_a/[aaaa]a', input: FILE);
+    score(p: 'aaaa', str: 'aabaaa', want: '[aa]b[aa]a', input: FILE);
+    score(p: 'aaaa', str: 'a/baaa', want: '[a]/b[aaa]', input: FILE);
+    score(p: 'aaaa', str: 'a/baaa/', want: '[a]/b[aaa]/', input: FILE);
+    score(
+        p: 'abcxz',
+        str: 'd/abc/abcd/oxz',
+        want: 'd/[abc]/abcd/o[xz]',
+        input: FILE);
+    score(
+        p: 'abcxz',
+        str: 'd/abcd/abc/oxz',
+        want: 'd/[abc]d/abc/o[xz]',
+        input: FILE);
+
+    // Symbols
+    score(p: 'foo', str: 'abc::foo', want: 'abc::[foo]', input: SYM);
+    score(p: 'foo', str: 'abc::foo::', want: 'abc::[foo]::', input: SYM);
+    score(p: 'foo', str: 'foo.foo', want: 'foo.[foo]', input: SYM);
+    score(p: 'foo', str: 'fo_oo.oo_oo', want: '[f]o_oo.[oo]_oo', input: SYM);
+    score(p: 'foo', str: 'fo_oo.fo_oo', want: 'fo_oo.[fo]_[o]o', input: SYM);
+    score(p: 'fo_o', str: 'fo_oo.o_oo', want: '[f]o_oo.[o_o]o', input: SYM);
+    score(p: 'fOO', str: 'fo_oo.o_oo', want: '[f]o_oo.[o]_[o]o', input: SYM);
+    score(
+        p: 'tedit', str: 'foo.TextEdit', want: 'foo.[T]ext[Edit]', input: SYM);
+    score(
+        p: 'tedit',
+        str: '*foo.TextEdit',
+        want: '*foo.[T]ext[Edit]',
+        input: SYM);
+    score(
+        p: 'TEdit', str: 'foo.TextEdit', want: 'foo.[T]ext[Edit]', input: SYM);
+    score(
+        p: 'Tedit', str: 'foo.TextEdit', want: 'foo.[T]ext[Edit]', input: SYM);
+    score(
+        p: 'Tedit', str: 'foo.Textedit', want: 'foo.[Te]xte[dit]', input: SYM);
+    score(p: 'TEdit', str: 'foo.Textedit', input: SYM);
+    score(p: 'te', str: 'foo.Textedit', want: 'foo.[Te]xtedit', input: SYM);
+    score(p: 'ee', str: 'foo.Textedit', input: SYM);
+    score(p: 'ex', str: 'foo.Textedit', want: 'foo.T[ex]tedit', input: SYM);
+    score(p: 'exdi', str: 'foo.Textedit', input: SYM);
+    score(p: 'exdit', str: 'foo.Textedit', input: SYM);
+    score(
+        p: 'extdit', str: 'foo.Textedit', want: 'foo.T[ext]e[dit]', input: SYM);
+    score(p: 'e', str: 'foo.Textedit', want: 'foo.T[e]xtedit', input: SYM);
+    score(p: 'ed', str: 'foo.Textedit', want: 'foo.Text[ed]it', input: SYM);
+    score(p: 'edt', str: 'foo.Textedit', input: SYM);
+    score(p: 'edit', str: 'foo.Textedit', want: 'foo.Text[edit]', input: SYM);
+    score(
+        p: 'pub', str: 'public setPubl', want: 'public set[Pub]l', input: SYM);
+    score(
+        p: 'mod',
+        str: 'public List<AbstractModule> getMods',
+        want: 'public List<AbstractModule> get[Mod]s',
+        input: SYM);
+    score(
+        p: 'm',
+        str: 'public List<AbstractModule> getMods',
+        want: 'public List<AbstractModule> get[M]ods',
+        input: SYM);
+    score(p: 'f', str: '[]foo.Foo', want: '[]foo.[F]oo', input: SYM);
+    score(
+        p: 'edin',
+        str: 'foo.TexteditNum',
+        want: 'foo.Text[edi]t[N]um',
+        input: SYM);
+  }
+}
+
+@reflectiveTest
+class ScoringFunctionTest {
+  ///
+  void score({@required String p, @required String str, double want}) {
+//    test('scores $str against $p', () {
+    var matcher = FuzzyMatcher(p, matchStyle: MatchStyle.SYMBOL);
+    expect(
+        matcher
+            .score(str)
+            .toStringAsFixed(4)
+            .startsWith(want.toStringAsFixed(4)),
+        true);
+//    });
+  }
+
+  void test_score() {
+    // This is a regression test. Feel free to update numbers below if the new
+    // ones are reasonable. Use 5 digits after the period.
+    score(p: 'abc', str: 'abc', want: 1); // perfect
+    score(p: 'abc', str: 'Abc', want: 1); // almost perfect
+    score(p: 'abc', str: 'Abcdef', want: 1);
+    score(p: 'strc', str: 'StrCat', want: 1);
+    score(p: 'abc_def', str: 'abc_def_xyz', want: 1);
+    score(p: 'abcdef', str: 'abc_def_xyz', want: 0.91667);
+    score(p: 'abcxyz', str: 'abc_def_xyz', want: 0.875);
+    score(p: 'sc', str: 'StrCat', want: 0.75);
+    score(p: 'abc', str: 'AbstrBasicCtor', want: 0.75);
+    // Qualified symbols.
+    score(p: 'foo', str: 'abc::foo', want: 1);
+    score(p: 'afoo', str: 'abc::foo', want: 0.9375);
+    score(p: 'abr', str: 'abc::bar', want: 0.5);
+    score(p: 'br', str: 'abc::bar', want: 0.375);
+    score(p: 'aar', str: 'abc::bar', want: 0.16667);
+    score(p: 'edin', str: 'foo.TexteditNum', want: 0.0625); // poor match
+    score(p: 'ediu', str: 'foo.TexteditNum', want: 0); // poor match
+    // We want the next two items to have roughly similar scores.
+    score(p: 'up', str: 'unique_ptr', want: 0.75);
+    score(p: 'up', str: 'upper_bound', want: 1);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/completion/filtering/test_all.dart b/pkg/analysis_server/test/src/services/completion/filtering/test_all.dart
new file mode 100644
index 0000000..ffc9b80
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/completion/filtering/test_all.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.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fuzzy_matcher_test.dart' as fuzzy_matcher;
+
+void main() {
+  defineReflectiveSuite(() {
+    fuzzy_matcher.main();
+  }, name: 'filtering');
+}
diff --git a/pkg/analysis_server/test/src/services/completion/test_all.dart b/pkg/analysis_server/test/src/services/completion/test_all.dart
new file mode 100644
index 0000000..1d82ee2
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/completion/test_all.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.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'filtering/test_all.dart' as filtering;
+
+void main() {
+  defineReflectiveSuite(() {
+    filtering.main();
+  }, name: 'completion');
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart
index fb81386..fce863a 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_remove_widget_test.dart
@@ -25,7 +25,7 @@
 import 'package:flutter/material.dart';
 main() {
   Column(
-    children: <Widget>[
+    children: [
       Center(
         child: /*caret*/Padding(
           padding: const EdgeInsets.all(8.0),
@@ -43,7 +43,7 @@
 import 'package:flutter/material.dart';
 main() {
   Column(
-    children: <Widget>[
+    children: [
       Center(
         child: Center(
           heightFactor: 0.5,
@@ -87,7 +87,7 @@
 import 'package:flutter/material.dart';
 main() {
   Column(
-    children: <Widget>[
+    children: [
       Text('foo'),
       /*caret*/Center(
         heightFactor: 0.5,
@@ -105,7 +105,7 @@
 import 'package:flutter/material.dart';
 main() {
   Column(
-    children: <Widget>[
+    children: [
       Text('foo'),
       Padding(
         padding: const EdgeInsets.all(8.0),
@@ -186,7 +186,7 @@
 import 'package:flutter/material.dart';
 main() {
   Column(
-    children: <Widget>[
+    children: [
       Text('aaa'),
       /*caret*/Column(
         children: [
@@ -213,7 +213,7 @@
 import 'package:flutter/material.dart';
 main() {
   Column(
-    children: <Widget>[
+    children: [
       Text('aaa'),
       Row(
         children: [
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
index 629ebde..ce2a3ba 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
@@ -42,7 +42,7 @@
     children: [
       Text('aaa'),
       if (b) Column(
-        children: <Widget>[
+        children: [
           Text('bbb'),
         ],
       ),
@@ -73,7 +73,7 @@
   main() {
     return Container(
       child: Column(
-        children: <Widget>[
+        children: [
           Text('aaa'),
         ],
       ),
@@ -109,7 +109,7 @@
     return Row(children: [
       Text('aaa'),
       Column(
-        children: <Widget>[
+        children: [
           Text('bbb'),
           Text('ccc'),
         ],
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
index 6905f54..794cc11 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
@@ -94,7 +94,7 @@
     return Container(
       child: /*caret*/DefaultTextStyle(
         child: Row(
-          children: <Widget>[
+          children: [
             Container(
             ),
           ],
@@ -112,7 +112,7 @@
       child: widget(
         child: DefaultTextStyle(
           child: Row(
-            children: <Widget>[
+            children: [
               Container(
               ),
             ],
@@ -134,7 +134,7 @@
     return Container(\r
       child: /*caret*/DefaultTextStyle(\r
         child: Row(\r
-          children: <Widget>[\r
+          children: [\r
             Container(\r
             ),\r
           ],\r
@@ -152,7 +152,7 @@
       child: widget(\r
         child: DefaultTextStyle(\r
           child: Row(\r
-            children: <Widget>[\r
+            children: [\r
               Container(\r
               ),\r
             ],\r
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_row_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_row_test.dart
index fe71efc..2325c8c 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_row_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_row_test.dart
@@ -45,7 +45,7 @@
     return Column(children: [
       Text('aaa'),
       Row(
-        children: <Widget>[
+        children: [
           Text('bbb'),
           Text('ccc'),
         ],
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 b471caa..49a5dcf 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
@@ -43,7 +43,7 @@
 }
 
 build() {
-  return new MyWidget(children: <Widget>[],);
+  return new MyWidget(children: [],);
 }
 ''');
   }
@@ -241,7 +241,7 @@
 import 'package:test/a.dart';
 
 main() {
-  A a = new A(names: <String>[]);
+  A a = new A(names: []);
   print(a);
 }
 ''');
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart
index c7f6976..c6c1814 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_return_type_future_test.dart
@@ -39,9 +39,7 @@
 ''');
     await assertHasFix('''
 var v;Future<int> main() async => 0;
-''', errorFilter: (error) {
-      return error.errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE;
-    });
+''');
   }
 
   Future<void> test_complexTypeName_withImport() async {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/sort_directives_test.dart b/pkg/analysis_server/test/src/services/correction/fix/sort_directives_test.dart
new file mode 100644
index 0000000..903e00e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/sort_directives_test.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.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.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(SortDirectivesTest);
+  });
+}
+
+@reflectiveTest
+class SortDirectivesTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.SORT_DIRECTIVES;
+
+  @override
+  String get lintCode => LintNames.directives_ordering;
+
+  Future<void> test_sortDirectives() async {
+    await resolveTestUnit('''
+//ignore_for_file: unused_import
+import 'dart:io';
+
+import 'dart:async';
+
+void main(Stream<String> args) { }
+''');
+    await assertHasFix('''
+//ignore_for_file: unused_import
+import 'dart:async';
+import 'dart:io';
+
+void main(Stream<String> args) { }
+''');
+  }
+}
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 9fdf630..af23d15 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
@@ -145,6 +145,7 @@
 import 'replace_with_tear_off_test.dart' as replace_with_tear_off;
 import 'replace_with_var_test.dart' as replace_with_var;
 import 'sort_child_property_last_test.dart' as sort_properties_last;
+import 'sort_directives_test.dart' as sort_directives;
 import 'update_sdk_constraints_test.dart' as update_sdk_constraints;
 import 'use_const_test.dart' as use_const;
 import 'use_effective_integer_division_test.dart'
@@ -283,6 +284,7 @@
     replace_with_null_aware.main();
     replace_with_tear_off.main();
     replace_with_var.main();
+    sort_directives.main();
     sort_properties_last.main();
     update_sdk_constraints.main();
     use_const.main();
diff --git a/pkg/analysis_server/test/src/services/test_all.dart b/pkg/analysis_server/test/src/services/test_all.dart
index a2c9b81..e5d8aa0 100644
--- a/pkg/analysis_server/test/src/services/test_all.dart
+++ b/pkg/analysis_server/test/src/services/test_all.dart
@@ -4,12 +4,14 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'correction/test_all.dart' as correction_all;
-import 'flutter/test_all.dart' as flutter_all;
+import 'completion/test_all.dart' as completion;
+import 'correction/test_all.dart' as correction;
+import 'flutter/test_all.dart' as flutter;
 
 void main() {
   defineReflectiveSuite(() {
-    correction_all.main();
-    flutter_all.main();
+    completion.main();
+    correction.main();
+    flutter.main();
   }, name: 'services');
 }
diff --git a/pkg/analysis_server/test/tool/lsp_spec/generated_classes_test.dart b/pkg/analysis_server/test/tool/lsp_spec/generated_classes_test.dart
new file mode 100644
index 0000000..ca011cc
--- /dev/null
+++ b/pkg/analysis_server/test/tool/lsp_spec/generated_classes_test.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.
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('generated classes', () {
+    test('can be checked for equality', () {
+      final a = TextDocumentIdentifier('/a');
+      final b = TextDocumentIdentifier('/a');
+
+      expect(a, equals(b));
+    });
+
+    test('with list fields can be checked for equality', () {
+      final a = TextDocumentClientCapabilitiesCodeActionKind(
+          [CodeActionKind.QuickFix]);
+      final b = TextDocumentClientCapabilitiesCodeActionKind(
+          [CodeActionKind.QuickFix]);
+
+      expect(a, equals(b));
+    });
+
+    test('with aliased list fields can be checked for equality', () {
+      final a = TextDocumentRegistrationOptions(
+          [DocumentFilter('dart', 'file', null)]);
+      final b = TextDocumentRegistrationOptions(
+          [DocumentFilter('dart', 'file', null)]);
+
+      expect(a, equals(b));
+    });
+
+    test('with map fields can be checked for equality', () {
+      final a = WorkspaceEdit({
+        'a': [TextEdit(Range(Position(0, 0), Position(0, 0)), 'a')]
+      }, null);
+      final b = WorkspaceEdit({
+        'a': [TextEdit(Range(Position(0, 0), Position(0, 0)), 'a')]
+      }, null);
+
+      expect(a, equals(b));
+    });
+
+    test('with union fields can be checked for equality', () {
+      final a =
+          SignatureInformation('a', Either2<String, MarkupContent>.t1('a'), []);
+      final b =
+          SignatureInformation('a', Either2<String, MarkupContent>.t1('a'), []);
+
+      expect(a, equals(b));
+    });
+
+    test('consider subclasses when checking for equality', () {
+      final a = TextDocumentRegistrationOptions(
+          [DocumentFilter('dart', 'file', null)]);
+      final b = TextDocumentSaveRegistrationOptions(
+          true, [DocumentFilter('dart', 'file', null)]);
+
+      expect(a, isNot(equals(b)));
+      expect(b, isNot(equals(a)));
+    });
+  });
+}
diff --git a/pkg/analysis_server/test/tool/lsp_spec/test_all.dart b/pkg/analysis_server/test/tool/lsp_spec/test_all.dart
index 1717817..07a4247 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/test_all.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/test_all.dart
@@ -5,6 +5,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'dart_test.dart' as dart_test;
+import 'generated_classes_test.dart' as generated_classes_test;
 import 'json_test.dart' as json_test;
 import 'markdown_test.dart' as markdown_test;
 import 'typescript_test.dart' as typescript_test;
@@ -12,6 +13,7 @@
 void main() {
   defineReflectiveSuite(() {
     dart_test.main();
+    generated_classes_test.main();
     json_test.main();
     markdown_test.main();
     typescript_test.main();
diff --git a/pkg/analysis_server/tool/completion_metrics/code_metrics.dart b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
index 47af3b7..cd29795 100644
--- a/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
@@ -6,6 +6,7 @@
 import 'dart:io' as io;
 
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -321,6 +322,8 @@
   @override
   void visitClassTypeAlias(ClassTypeAlias node) {
     _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
       'abstractKeyword': node.abstractKeyword,
       'name': node.name,
       'typeParameters': node.typeParameters,
@@ -694,7 +697,10 @@
   @override
   void visitFunctionTypeAlias(FunctionTypeAlias node) {
     _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
       'returnType': node.returnType,
+      'name': node.name,
       'typeParameters': node.typeParameters,
       'parameters': node.parameters,
     });
@@ -929,6 +935,7 @@
       'documentationComment': node.documentationComment,
       'metadata': node.metadata,
       'name': node.name,
+      'typeParameters': node.typeParameters,
       'onClause': node.onClause,
       'implementsClause': node.implementsClause,
       'members': node.members,
@@ -1138,6 +1145,7 @@
   @override
   void visitSwitchCase(SwitchCase node) {
     _visitChildren(node, {
+      'labels': node.labels,
       'expression': node.expression,
       'statements': node.statements,
     });
@@ -1352,36 +1360,8 @@
       resourceProvider: PhysicalResourceProvider.INSTANCE,
     );
     final collector = CodeShapeDataCollector(data);
-
     for (var context in collection.contexts) {
-      for (var filePath in context.contextRoot.analyzedFiles()) {
-        if (AnalysisEngine.isDartFileName(filePath)) {
-          try {
-            var resolvedUnitResult =
-                await context.currentSession.getResolvedUnit(filePath);
-            //
-            // Check for errors that cause the file to be skipped.
-            //
-            if (resolvedUnitResult.state != ResultState.VALID) {
-              print('File $filePath skipped because it could not be analyzed.');
-              print('');
-              continue;
-            } else if (hasError(resolvedUnitResult)) {
-              print('File $filePath skipped due to errors:');
-              for (var error in resolvedUnitResult.errors) {
-                print('  ${error.toString()}');
-              }
-              print('');
-              continue;
-            }
-
-            resolvedUnitResult.unit.accept(collector);
-          } catch (exception) {
-            print('Exception caught analyzing: "$filePath"');
-            print(exception.toString());
-          }
-        }
-      }
+      await _computeInContext(context.contextRoot, collector);
     }
   }
 
@@ -1394,6 +1374,49 @@
     _writeChildData(sink);
   }
 
+  /// Compute the metrics for the files in the context [root], creating a
+  /// 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, CodeShapeDataCollector collector) async {
+    // Create a new collection to avoid consuming large quantities of memory.
+    final collection = AnalysisContextCollection(
+      includedPaths: root.includedPaths.toList(),
+      excludedPaths: root.excludedPaths.toList(),
+      resourceProvider: PhysicalResourceProvider.INSTANCE,
+    );
+    var context = collection.contexts[0];
+    for (var filePath in context.contextRoot.analyzedFiles()) {
+      if (AnalysisEngine.isDartFileName(filePath)) {
+        try {
+          var resolvedUnitResult =
+              await context.currentSession.getResolvedUnit(filePath);
+          //
+          // Check for errors that cause the file to be skipped.
+          //
+          if (resolvedUnitResult.state != ResultState.VALID) {
+            print('File $filePath skipped because it could not be analyzed.');
+            print('');
+            continue;
+          } else if (hasError(resolvedUnitResult)) {
+            print('File $filePath skipped due to errors:');
+            for (var error in resolvedUnitResult.errors) {
+              print('  ${error.toString()}');
+            }
+            print('');
+            continue;
+          }
+
+          resolvedUnitResult.unit.accept(collector);
+        } catch (exception) {
+          print('Exception caught analyzing: "$filePath"');
+          print(exception.toString());
+        }
+      }
+    }
+  }
+
   /// Convert the contents of a single [map] into the values for each row in the
   /// column occupied by the map.
   List<String> _convertMap<T extends Object>(String context, Map<T, int> map) {
diff --git a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
index be513c6..9fea6b2 100644
--- a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
@@ -15,7 +15,9 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart' as err;
+import 'package:analyzer/file_system/overlay_file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:args/args.dart';
 
@@ -30,10 +32,12 @@
   if (!validArguments(parser, result)) {
     return io.exit(1);
   }
+
   var root = result.rest[0];
   print('Analyzing root: "$root"');
   var stopwatch = Stopwatch()..start();
-  var code = await CompletionMetricsComputer(root, verbose: result['verbose'])
+  var code = await CompletionMetricsComputer(root,
+          verbose: result['verbose'], overlay: result['overlay'])
       .compute();
   stopwatch.stop();
 
@@ -43,6 +47,12 @@
   return io.exit(code);
 }
 
+const String OVERLAY_NONE = 'none';
+
+const String OVERLAY_REMOVE_REST_OF_FILE = 'remove-rest-of-file';
+
+const String OVERLAY_REMOVE_TOKEN = 'remove-token';
+
 /// Create a parser that can be used to parse the command-line arguments.
 ArgParser createArgParser() {
   var parser = ArgParser();
@@ -57,6 +67,17 @@
     help: 'Print additional information about the analysis',
     negatable: false,
   );
+  parser.addOption('overlay',
+      allowed: [
+        OVERLAY_NONE,
+        OVERLAY_REMOVE_TOKEN,
+        OVERLAY_REMOVE_REST_OF_FILE
+      ],
+      defaultsTo: OVERLAY_NONE,
+      help: 'Before attempting a completion at the location of each token, the '
+          'token can be removed, or the rest of the file can be removed to test '
+          'code completion with diverse methods. The default mode is to '
+          'complete at the start of the token without modifying the file.');
   return parser;
 }
 
@@ -94,6 +115,9 @@
 /// A wrapper for the collection of [Counter] and [MeanReciprocalRankComputer]
 /// objects for a run of [CompletionMetricsComputer].
 class CompletionMetrics {
+  /// The maximum number of worst results to collect.
+  static const maxWorstResults = 10;
+
   /// The name associated with this set of metrics.
   final String name;
 
@@ -126,7 +150,32 @@
   MeanReciprocalRankComputer nonTypeMemberMrrComputer =
       MeanReciprocalRankComputer('non-type member completions');
 
+  ArithmeticMeanComputer charsBeforeTop =
+      ArithmeticMeanComputer('chars_before_top');
+
+  ArithmeticMeanComputer charsBeforeTopFive =
+      ArithmeticMeanComputer('chars_before_top_five');
+
+  ArithmeticMeanComputer insertionLengthTheoretical =
+      ArithmeticMeanComputer('insertion_length_theoretical');
+
+  /// A list of the top [maxWorstResults] completion results with the highest
+  /// (worst) ranks.
+  List<CompletionResult> worstResults = [];
+
   CompletionMetrics(this.name);
+
+  /// If the [result] is worse than any previously recorded results, record it.
+  void recordCompletionResult(CompletionResult result) {
+    if (worstResults.length >= maxWorstResults) {
+      if (result.place.rank <= worstResults.last.place.rank) {
+        return;
+      }
+      worstResults.removeLast();
+    }
+    worstResults.add(result);
+    worstResults.sort((first, second) => second.place.rank - first.place.rank);
+  }
 }
 
 /// This is the main metrics computer class for code completions. After the
@@ -137,7 +186,7 @@
 
   final bool verbose;
 
-  String _currentFilePath;
+  final String overlay;
 
   ResolvedUnitResult _resolvedUnitResult;
 
@@ -148,10 +197,15 @@
 
   CompletionMetrics metricsNewMode;
 
-  CompletionMetricsComputer(this.rootPath, {this.verbose});
+  final OverlayResourceProvider _provider =
+      OverlayResourceProvider(PhysicalResourceProvider.INSTANCE);
 
-  /// The path to the current file.
-  String get currentFilePath => _currentFilePath;
+  int overlayModificationStamp = 0;
+
+  CompletionMetricsComputer(this.rootPath, {this.verbose, this.overlay})
+      : assert(overlay == OVERLAY_NONE ||
+            overlay == OVERLAY_REMOVE_TOKEN ||
+            overlay == OVERLAY_REMOVE_REST_OF_FILE);
 
   Future<int> compute() async {
     resultCode = 0;
@@ -166,21 +220,34 @@
     }
     printMetrics(metricsOldMode);
     printMetrics(metricsNewMode);
+    if (verbose) {
+      printWorstResults(metricsNewMode);
+    }
     return resultCode;
   }
 
-  void forEachExpectedCompletion(ExpectedCompletion expectedCompletion,
-      List<CompletionSuggestion> suggestions, CompletionMetrics metrics) {
+  bool forEachExpectedCompletion(
+      ExpectedCompletion expectedCompletion,
+      List<CompletionSuggestion> suggestions,
+      CompletionMetrics metrics,
+      bool doPrintMissedCompletions) {
     assert(suggestions != null);
 
+    var successfulCompletion;
+
     var place = placementInSuggestionList(suggestions, expectedCompletion);
 
     metrics.mrrComputer.addRank(place.rank);
 
     if (place.denominator != 0) {
+      successfulCompletion = true;
+
       metrics.successfulMrrComputer.addRank(place.rank);
       metrics.completionCounter.count('successful');
 
+      metrics.recordCompletionResult(
+          CompletionResult(place, suggestions, expectedCompletion));
+
       var element = getElement(expectedCompletion.syntacticEntity);
       if (isInstanceMember(element)) {
         metrics.instanceMemberMrrComputer.addRank(place.rank);
@@ -189,7 +256,17 @@
       } else {
         metrics.nonTypeMemberMrrComputer.addRank(place.rank);
       }
+
+      var charsBeforeTop =
+          _computeCharsBeforeTop(expectedCompletion, suggestions);
+      metrics.charsBeforeTop.addValue(charsBeforeTop);
+      metrics.charsBeforeTopFive.addValue(
+          _computeCharsBeforeTop(expectedCompletion, suggestions, minRank: 5));
+      metrics.insertionLengthTheoretical
+          .addValue(expectedCompletion.completion.length - charsBeforeTop);
     } else {
+      successfulCompletion = false;
+
       metrics.completionCounter.count('unsuccessful');
 
       metrics.completionMissedTokenCounter.count(expectedCompletion.completion);
@@ -197,18 +274,24 @@
       metrics.completionElementKindCounter
           .count(expectedCompletion.elementKind.toString());
 
-      if (verbose) {
-        // The format "/file/path/foo.dart:3:4" makes for easier input
-        // with the Files dialog in IntelliJ.
-        var lineNumber = expectedCompletion.lineNumber;
-        var columnNumber = expectedCompletion.columnNumber;
-        print('$currentFilePath:$lineNumber:$columnNumber');
-        print('  missing completion: "${expectedCompletion.completion}"');
-        print('  completion kind: ${expectedCompletion.kind}');
-        print('  element kind: ${expectedCompletion.elementKind}');
+      if (doPrintMissedCompletions) {
+        var closeMatchSuggestion;
+        for (var suggestion in suggestions) {
+          if (suggestion.completion == expectedCompletion.completion) {
+            closeMatchSuggestion = suggestion;
+          }
+        }
+
+        print('missing completion (`useNewRelevance = true`):');
+        print('$expectedCompletion');
+        if (closeMatchSuggestion != null) {
+          print('    close matching completion that was in the list:');
+          print('    $closeMatchSuggestion');
+        }
         print('');
       }
     }
+    return successfulCompletion;
   }
 
   void printMetrics(CompletionMetrics metrics) {
@@ -242,12 +325,62 @@
     metrics.nonTypeMemberMrrComputer.printMean();
     print('');
 
+    metrics.charsBeforeTop.printMean();
+    metrics.charsBeforeTopFive.printMean();
+    metrics.insertionLengthTheoretical.printMean();
+    print('');
+
     print('Summary for $rootPath:');
     metrics.meanCompletionMS.printMean();
     metrics.completionCounter.printCounterValues();
     print('====================');
   }
 
+  void printWorstResults(CompletionMetrics metrics) {
+    print('');
+    print('====================');
+    print('The worst completion results:');
+    for (var result in metrics.worstResults) {
+      var rank = result.place.rank;
+      var expected = result.expectedCompletion;
+      var suggestions = result.suggestions;
+      var preceeding = StringBuffer();
+      for (var i = 0; i < rank - 1; i++) {
+        if (i > 0) {
+          preceeding.write(', ');
+        }
+        preceeding.write(suggestions[i].relevance);
+      }
+      print('');
+      print('Rank: $rank');
+      print('Completion: ${expected.completion}');
+      print('Completion kind: ${expected.kind}');
+      print('Element kind: ${expected.elementKind}');
+      print('Offset: ${expected.offset}');
+      print('Preceeding: $preceeding');
+      print('Suggestion: ${suggestions[rank - 1]}');
+    }
+  }
+
+  int _computeCharsBeforeTop(
+      ExpectedCompletion target, List<CompletionSuggestion> suggestions,
+      {int minRank = 1}) {
+    var rank = placementInSuggestionList(suggestions, target).rank;
+    if (rank <= minRank) {
+      return 0;
+    }
+    var expected = target.completion;
+    for (var i = 1; i < expected.length + 1; i++) {
+      var prefix = expected.substring(0, i);
+      var filteredSuggestions = _filterSuggestions(prefix, suggestions);
+      rank = placementInSuggestionList(filteredSuggestions, target).rank;
+      if (rank <= minRank) {
+        return i;
+      }
+    }
+    return expected.length;
+  }
+
   Future<List<CompletionSuggestion>> _computeCompletionSuggestions(
       ResolvedUnitResult resolvedUnitResult,
       int offset,
@@ -305,8 +438,9 @@
     final collection = AnalysisContextCollection(
       includedPaths: root.includedPaths.toList(),
       excludedPaths: root.excludedPaths.toList(),
-      resourceProvider: PhysicalResourceProvider.INSTANCE,
+      resourceProvider: _provider,
     );
+
     var context = collection.contexts[0];
 //    // Set the DeclarationsTracker, only call doWork to build up the available
 //    // suggestions if doComputeCompletionsFromAnalysisServer is true.
@@ -323,7 +457,6 @@
     // forEachExpectedCompletion
     for (var filePath in context.contextRoot.analyzedFiles()) {
       if (AnalysisEngine.isDartFileName(filePath)) {
-        _currentFilePath = filePath;
         try {
           _resolvedUnitResult =
               await context.currentSession.getResolvedUnit(filePath);
@@ -339,10 +472,28 @@
 
           // Use the ExpectedCompletionsVisitor to compute the set of expected
           // completions for this CompilationUnit.
-          final visitor = ExpectedCompletionsVisitor();
+          final visitor = ExpectedCompletionsVisitor(filePath);
           _resolvedUnitResult.unit.accept(visitor);
 
           for (var expectedCompletion in visitor.expectedCompletions) {
+            var resolvedUnitResultWithOverlay = _resolvedUnitResult;
+
+            // If an overlay option is being used, compute the overlay file, and
+            // have the context reanalyze the file
+            if (overlay != OVERLAY_NONE) {
+              var overlayContents = _getOverlayContents(
+                  _resolvedUnitResult.content, expectedCompletion, overlay);
+
+              _provider.setOverlay(filePath,
+                  content: overlayContents,
+                  modificationStamp: overlayModificationStamp++);
+              (context as DriverBasedAnalysisContext)
+                  .driver
+                  .changeFile(filePath);
+              resolvedUnitResultWithOverlay =
+                  await context.currentSession.getResolvedUnit(filePath);
+            }
+
             // As this point the completion suggestions are computed,
             // and results are collected with varying settings for
             // comparison:
@@ -350,23 +501,50 @@
             // First we compute the completions useNewRelevance set to
             // false:
             var suggestions = await _computeCompletionSuggestions(
-                _resolvedUnitResult,
+                resolvedUnitResultWithOverlay,
                 expectedCompletion.offset,
                 metricsOldMode,
                 false);
 
-            forEachExpectedCompletion(
-                expectedCompletion, suggestions, metricsOldMode);
+            var successfulnessUseOldRelevance = forEachExpectedCompletion(
+                expectedCompletion, suggestions, metricsOldMode, false);
 
             // And again here with useNewRelevance set to true:
             suggestions = await _computeCompletionSuggestions(
-                _resolvedUnitResult,
+                resolvedUnitResultWithOverlay,
                 expectedCompletion.offset,
                 metricsNewMode,
                 true);
 
-            forEachExpectedCompletion(
-                expectedCompletion, suggestions, metricsNewMode);
+            var successfulnessUseNewRelevance = forEachExpectedCompletion(
+                expectedCompletion, suggestions, metricsNewMode, verbose);
+
+            if (verbose &&
+                successfulnessUseOldRelevance !=
+                    successfulnessUseNewRelevance) {
+              if (successfulnessUseNewRelevance &&
+                  !successfulnessUseOldRelevance) {
+                print('    ===========');
+                print(
+                    '    The `useNewRelevance = true` generated a completion that `useNewRelevance = false` did not:');
+                print('    $expectedCompletion');
+                print('    ===========');
+                print('');
+              } else {
+                print('    ===========');
+                print(
+                    '    The `useNewRelevance = false` generated a completion that `useNewRelevance = true` did not:');
+                print('    $expectedCompletion');
+                print('    ===========');
+                print('');
+              }
+            }
+
+            // If an overlay option is being used, remove the overlay applied
+            // earlier
+            if (overlay != OVERLAY_NONE) {
+              _provider.removeOverlay(filePath);
+            }
           }
         } catch (e) {
           print('Exception caught analyzing: $filePath');
@@ -377,6 +555,32 @@
     }
   }
 
+  List<CompletionSuggestion> _filterSuggestions(
+      String prefix, List<CompletionSuggestion> suggestions) {
+    // TODO(brianwilkerson) Replace this with a more realistic filtering algorithm.
+    return suggestions
+        .where((suggestion) => suggestion.completion.startsWith(prefix))
+        .toList();
+  }
+
+  String _getOverlayContents(String contents,
+      ExpectedCompletion expectedCompletion, String overlayMode) {
+    assert(contents.isNotEmpty);
+    var offset = expectedCompletion.offset;
+    var length = expectedCompletion.syntacticEntity.length;
+    assert(offset >= 0);
+    assert(length > 0);
+    if (overlayMode == OVERLAY_REMOVE_TOKEN) {
+      return contents.substring(0, offset) +
+          contents.substring(offset + length);
+    } else if (overlayMode == OVERLAY_REMOVE_REST_OF_FILE) {
+      return contents.substring(0, offset);
+    } else {
+      throw Exception('\'_getOverlayContents\' called with option other than'
+          '$OVERLAY_REMOVE_TOKEN and $OVERLAY_REMOVE_REST_OF_FILE: $overlayMode');
+    }
+  }
+
   /// Given some [ResolvedUnitResult] return the first error of high severity
   /// if such an error exists, `null` otherwise.
   static err.AnalysisError getFirstErrorOrNull(
@@ -401,3 +605,14 @@
     return Place.none();
   }
 }
+
+/// The result of a single completion.
+class CompletionResult {
+  final Place place;
+
+  final List<CompletionSuggestion> suggestions;
+
+  final ExpectedCompletion expectedCompletion;
+
+  CompletionResult(this.place, this.suggestions, this.expectedCompletion);
+}
diff --git a/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
new file mode 100644
index 0000000..f1cd4e2
--- /dev/null
+++ b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
@@ -0,0 +1,1558 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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' as io;
+
+import 'package:_fe_analyzer_shared/src/base/syntactic_entity.dart';
+import 'package:analysis_server/src/protocol_server.dart'
+    show convertElementToElementKind, ElementKind;
+import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analysis_tool/tools.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/context_root.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+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'
+    show ClassElement, Element, LibraryElement;
+import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/dart/element/type_system.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:args/args.dart';
+import 'package:meta/meta.dart';
+
+import '../../test/utils/package_root.dart' as package_root;
+
+/// Compute metrics to determine whether they should be used to compute a
+/// relevance score for completion suggestions.
+Future<void> main(List<String> args) async {
+  var parser = createArgParser();
+  var result = parser.parse(args);
+
+  if (validArguments(parser, result)) {
+    var rootPath = result.rest[0];
+    print('Analyzing root: "$rootPath"');
+
+    var provider = PhysicalResourceProvider.INSTANCE;
+    var packageRoot = provider.pathContext.normalize(package_root.packageRoot);
+    var generatedFilePath = provider.pathContext.join(
+        packageRoot,
+        'analysis_server',
+        'lib',
+        'src',
+        'services',
+        'completion',
+        'dart',
+        'relevance_tables.g.dart');
+    var generatedFile = provider.getFile(generatedFilePath);
+
+    var computer = RelevanceMetricsComputer();
+    var stopwatch = Stopwatch();
+    stopwatch.start();
+    await computer.compute(rootPath, verbose: result['verbose']);
+    var buffer = StringBuffer();
+    var writer = RelevanceTableWriter(buffer);
+    writer.write(computer.data);
+    generatedFile.writeAsStringSync(buffer.toString());
+    DartFormat.formatFile(io.File(generatedFile.path));
+    stopwatch.stop();
+
+    var duration = Duration(milliseconds: stopwatch.elapsedMilliseconds);
+    print('Tables generated in $duration');
+  }
+}
+
+/// Create a parser that can be used to parse the command-line arguments.
+ArgParser createArgParser() {
+  var parser = ArgParser();
+  parser.addFlag(
+    'help',
+    abbr: 'h',
+    help: 'Print this help message.',
+  );
+  parser.addFlag(
+    'verbose',
+    abbr: 'v',
+    help: 'Print additional information about the analysis',
+    negatable: false,
+  );
+  return parser;
+}
+
+/// Print usage information for this tool.
+void printUsage(ArgParser parser, {String error}) {
+  if (error != null) {
+    print(error);
+    print('');
+  }
+  print('usage: dart relevance_table_generator.dart [options] packagePath');
+  print('');
+  print('Generate the tables used to compute the values of certain features.');
+  print('');
+  print(parser.usage);
+}
+
+/// Return `true` if the command-line arguments (represented by the [result] and
+/// parsed by the [parser]) are valid.
+bool validArguments(ArgParser parser, ArgResults result) {
+  if (result.wasParsed('help')) {
+    printUsage(parser);
+    return false;
+  } else if (result.rest.length != 1) {
+    printUsage(parser, error: 'No package path specified.');
+    return false;
+  }
+  var rootPath = result.rest[0];
+  if (!PhysicalResourceProvider.INSTANCE.pathContext.isAbsolute(rootPath)) {
+    printUsage(parser, error: 'The package path must be an absolute path.');
+    return false;
+  }
+  if (!io.Directory(rootPath).existsSync()) {
+    printUsage(parser, error: 'The directory "$rootPath" does not exist.');
+    return false;
+  }
+  return true;
+}
+
+/// An object that records the data used to compute the tables.
+class RelevanceData {
+  /// A table mapping element kinds to counts by context.
+  Map<String, Map<String, int>> byElementKind = {};
+
+  /// A table mapping token types to counts by context.
+  Map<String, Map<String, int>> byTokenType = {};
+
+  /// Initialize a newly created set of relevance data to be empty.
+  RelevanceData();
+
+  /// Add the data from the given relevance [data] to this set of data.
+  void addDataFrom(RelevanceData data) {
+    _addToMap(byElementKind, data.byElementKind);
+    _addToMap(byTokenType, data.byTokenType);
+  }
+
+  /// Record that an element of the given [kind] was found in the given
+  /// [context].
+  void recordElementKind(String context, ElementKind kind) {
+    var contextMap = byElementKind.putIfAbsent(context, () => {});
+    var key = kind.name;
+    contextMap[key] = (contextMap[key] ?? 0) + 1;
+  }
+
+  /// Record that a token of the given [type] was found in the given [context].
+  void recordTokenType(String context, TokenType type) {
+    var contextMap = byTokenType.putIfAbsent(context, () => {});
+    var key = type.name;
+    contextMap[key] = (contextMap[key] ?? 0) + 1;
+  }
+
+  /// Add the data in the [source] map to the [target] map.
+  void _addToMap<K>(Map<K, Map<K, int>> target, Map<K, Map<K, int>> source) {
+    for (var outerEntry in source.entries) {
+      var innerTarget = target.putIfAbsent(outerEntry.key, () => {});
+      for (var innerEntry in outerEntry.value.entries) {
+        var innerKey = innerEntry.key;
+        innerTarget[innerKey] = (innerTarget[innerKey] ?? 0) + innerEntry.value;
+      }
+    }
+  }
+}
+
+/// An object that visits a compilation unit in order to record the data used to
+/// compute the metrics.
+class RelevanceDataCollector extends RecursiveAstVisitor<void> {
+  static const List<Keyword> declarationKeywords = [
+    Keyword.MIXIN,
+    Keyword.TYPEDEF
+  ];
+
+  static const List<Keyword> directiveKeywords = [
+    Keyword.EXPORT,
+    Keyword.IMPORT,
+    Keyword.LIBRARY,
+    Keyword.PART
+  ];
+
+  static const List<Keyword> exportKeywords = [
+    Keyword.AS,
+    Keyword.HIDE,
+    Keyword.SHOW
+  ];
+
+  static const List<Keyword> expressionKeywords = [
+    Keyword.AWAIT,
+    Keyword.SUPER
+  ];
+
+  static const List<Keyword> functionBodyKeywords = [
+    Keyword.ASYNC,
+    Keyword.SYNC
+  ];
+
+  static const List<Keyword> importKeywords = [
+    Keyword.AS,
+    Keyword.HIDE,
+    Keyword.SHOW
+  ];
+
+  static const List<Keyword> memberKeywords = [
+    Keyword.FACTORY,
+    Keyword.GET,
+    Keyword.OPERATOR,
+    Keyword.SET,
+    Keyword.STATIC
+  ];
+
+  static const List<Keyword> noKeywords = [];
+
+  static const List<Keyword> statementKeywords = [Keyword.AWAIT, Keyword.YIELD];
+
+  /// The relevance data being collected.
+  final RelevanceData data;
+
+  /// The compilation unit in which data is currently being collected.
+  CompilationUnit unit;
+
+  /// The object used to determine Flutter-specific features.
+  Flutter flutter;
+
+  InheritanceManager3 inheritanceManager = InheritanceManager3();
+
+  /// The library containing the compilation unit being visited.
+  LibraryElement enclosingLibrary;
+
+  /// The type provider associated with the current compilation unit.
+  TypeProvider typeProvider;
+
+  /// The type system associated with the current compilation unit.
+  TypeSystem typeSystem;
+
+  /// The object used to compute the values of features.
+  FeatureComputer featureComputer;
+
+  /// Initialize a newly created collector to add data points to the given
+  /// [data].
+  RelevanceDataCollector(this.data);
+
+  /// Initialize this collector prior to visiting the unit in the [result].
+  void initializeFrom(ResolvedUnitResult result) {
+    unit = result.unit;
+    flutter = Flutter.of(result);
+  }
+
+  @override
+  void visitAdjacentStrings(AdjacentStrings node) {
+    // There are no completions.
+    super.visitAdjacentStrings(node);
+  }
+
+  @override
+  void visitAnnotation(Annotation node) {
+    _recordDataForNode('Annotation_name', node.name);
+    super.visitAnnotation(node);
+  }
+
+  @override
+  void visitArgumentList(ArgumentList node) {
+    var context = _argumentListContext(node);
+    for (var argument in node.arguments) {
+      var realArgument = argument;
+      var argumentKind = 'unnamed';
+      if (argument is NamedExpression) {
+        realArgument = argument.expression;
+        argumentKind = 'named';
+      }
+      _recordDataForNode('ArgumentList_${context}_$argumentKind', realArgument,
+          allowedKeywords: expressionKeywords);
+    }
+    super.visitArgumentList(node);
+  }
+
+  @override
+  void visitAsExpression(AsExpression node) {
+    _recordDataForNode('AsExpression_type', node.type);
+    super.visitAsExpression(node);
+  }
+
+  @override
+  void visitAssertInitializer(AssertInitializer node) {
+    _recordDataForNode('AssertInitializer_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    _recordDataForNode('AssertInitializer_message', node.message,
+        allowedKeywords: expressionKeywords);
+    super.visitAssertInitializer(node);
+  }
+
+  @override
+  void visitAssertStatement(AssertStatement node) {
+    _recordDataForNode('AssertStatement_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    _recordDataForNode('AssertStatement_message', node.message,
+        allowedKeywords: expressionKeywords);
+    super.visitAssertStatement(node);
+  }
+
+  @override
+  void visitAssignmentExpression(AssignmentExpression node) {
+    _recordDataForNode('AssignmentExpression_rightHandSide', node.rightHandSide,
+        allowedKeywords: expressionKeywords);
+    super.visitAssignmentExpression(node);
+  }
+
+  @override
+  void visitAwaitExpression(AwaitExpression node) {
+    _recordDataForNode('AwaitExpression_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitAwaitExpression(node);
+  }
+
+  @override
+  void visitBinaryExpression(BinaryExpression node) {
+    _recordDataForNode(
+        'BinaryExpression_${node.operator}_rightOperand', node.rightOperand,
+        allowedKeywords: expressionKeywords);
+    super.visitBinaryExpression(node);
+  }
+
+  @override
+  void visitBlock(Block node) {
+    for (var statement in node.statements) {
+      // Function declaration statements that have no return type begin with an
+      // identifier but don't have an element kind associated with the
+      // identifier.
+      _recordDataForNode('Block_statement', statement,
+          allowedKeywords: statementKeywords);
+    }
+    super.visitBlock(node);
+  }
+
+  @override
+  void visitBlockFunctionBody(BlockFunctionBody node) {
+    _recordTokenType('BlockFunctionBody_start', node,
+        allowedKeywords: functionBodyKeywords);
+    super.visitBlockFunctionBody(node);
+  }
+
+  @override
+  void visitBooleanLiteral(BooleanLiteral node) {
+    _recordTokenType('BooleanLiteral_start', node);
+    super.visitBooleanLiteral(node);
+  }
+
+  @override
+  void visitBreakStatement(BreakStatement node) {
+    // The token following the `break` (if there is one) is always a label.
+    super.visitBreakStatement(node);
+  }
+
+  @override
+  void visitCascadeExpression(CascadeExpression node) {
+    for (var cascade in node.cascadeSections) {
+      _recordDataForNode('CascadeExpression_cascadeSection', cascade);
+    }
+    super.visitCascadeExpression(node);
+  }
+
+  @override
+  void visitCatchClause(CatchClause node) {
+    _recordDataForNode('CatchClause_exceptionType', node.exceptionType);
+    super.visitCatchClause(node);
+  }
+
+  @override
+  void visitClassDeclaration(ClassDeclaration node) {
+    var context = 'name';
+    if (node.extendsClause != null) {
+      _recordTokenType('ClassDeclaration_$context', node.extendsClause,
+          allowedKeywords: [Keyword.EXTENDS]);
+      context = 'extends';
+    }
+    if (node.withClause != null) {
+      _recordTokenType('ClassDeclaration_$context', node.withClause);
+      context = 'with';
+    }
+    _recordTokenType('ClassDeclaration_$context', node.implementsClause,
+        allowedKeywords: [Keyword.IMPLEMENTS]);
+
+    for (var member in node.members) {
+      _recordDataForNode('ClassDeclaration_member', member,
+          allowedKeywords: memberKeywords);
+    }
+    super.visitClassDeclaration(node);
+  }
+
+  @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    _recordDataForNode('ClassTypeAlias_superclass', node.superclass);
+    var context = 'superclass';
+    if (node.withClause != null) {
+      _recordTokenType('ClassTypeAlias_$context', node.withClause);
+      context = 'with';
+    }
+    _recordTokenType('ClassTypeAlias_$context', node.implementsClause);
+    super.visitClassTypeAlias(node);
+  }
+
+  @override
+  void visitComment(Comment node) {
+    // There are no completions.
+    super.visitComment(node);
+  }
+
+  @override
+  void visitCommentReference(CommentReference node) {
+    void recordDataForCommentReference(String context, AstNode node) {
+      _recordElementKind(context, node);
+      _recordTokenType(context, node);
+    }
+
+    recordDataForCommentReference(
+        'CommentReference_identifier', node.identifier);
+    super.visitCommentReference(node);
+  }
+
+  @override
+  void visitCompilationUnit(CompilationUnit node) {
+    enclosingLibrary = node.declaredElement.library;
+    typeProvider = enclosingLibrary.typeProvider;
+    typeSystem = enclosingLibrary.typeSystem;
+    inheritanceManager = InheritanceManager3();
+    featureComputer = FeatureComputer(typeSystem, typeProvider);
+
+    for (var directive in node.directives) {
+      _recordTokenType('CompilationUnit_directive', directive,
+          allowedKeywords: directiveKeywords);
+    }
+    for (var declaration in node.declarations) {
+      _recordDataForNode('CompilationUnit_declaration', declaration,
+          allowedKeywords: declarationKeywords);
+    }
+    super.visitCompilationUnit(node);
+
+    featureComputer = null;
+    inheritanceManager = null;
+    typeSystem = null;
+    typeProvider = null;
+    enclosingLibrary = null;
+  }
+
+  @override
+  void visitConditionalExpression(ConditionalExpression node) {
+    _recordDataForNode(
+        'ConditionalExpression_thenExpression', node.thenExpression,
+        allowedKeywords: expressionKeywords);
+    _recordDataForNode(
+        'ConditionalExpression_elseExpression', node.elseExpression,
+        allowedKeywords: expressionKeywords);
+    super.visitConditionalExpression(node);
+  }
+
+  @override
+  void visitConfiguration(Configuration node) {
+    // There are no completions.
+    super.visitConfiguration(node);
+  }
+
+  @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    _recordDataForNode('ConstructorDeclaration_returnType', node.returnType);
+    for (var initializer in node.initializers) {
+      _recordDataForNode('ConstructorDeclaration_initializer', initializer);
+    }
+    super.visitConstructorDeclaration(node);
+  }
+
+  @override
+  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    _recordDataForNode(
+        'ConstructorFieldInitializer_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitConstructorFieldInitializer(node);
+  }
+
+  @override
+  void visitConstructorName(ConstructorName node) {
+    // The token following the `.` is always the name of a constructor.
+    super.visitConstructorName(node);
+  }
+
+  @override
+  void visitContinueStatement(ContinueStatement node) {
+    // The token following the `continue` (if there is one) is always a label.
+    super.visitContinueStatement(node);
+  }
+
+  @override
+  void visitDeclaredIdentifier(DeclaredIdentifier node) {
+    // There are no completions.
+    super.visitDeclaredIdentifier(node);
+  }
+
+  @override
+  void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    _recordDataForNode('DefaultFormalParameter_defaultValue', node.defaultValue,
+        allowedKeywords: expressionKeywords);
+    super.visitDefaultFormalParameter(node);
+  }
+
+  @override
+  void visitDoStatement(DoStatement node) {
+    _recordDataForNode('DoStatement_body', node.body,
+        allowedKeywords: statementKeywords);
+    _recordDataForNode('DoStatement_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    super.visitDoStatement(node);
+  }
+
+  @override
+  void visitDottedName(DottedName node) {
+    // The components are always identifiers.
+    super.visitDottedName(node);
+  }
+
+  @override
+  void visitDoubleLiteral(DoubleLiteral node) {
+    // There are no completions.
+    super.visitDoubleLiteral(node);
+  }
+
+  @override
+  void visitEmptyFunctionBody(EmptyFunctionBody node) {
+    // There are no completions.
+    super.visitEmptyFunctionBody(node);
+  }
+
+  @override
+  void visitEmptyStatement(EmptyStatement node) {
+    // There are no completions.
+    super.visitEmptyStatement(node);
+  }
+
+  @override
+  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    // There are no completions.
+    super.visitEnumConstantDeclaration(node);
+  }
+
+  @override
+  void visitEnumDeclaration(EnumDeclaration node) {
+    // There are no completions.
+    super.visitEnumDeclaration(node);
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    var context = 'uri';
+    if (node.configurations.isNotEmpty) {
+      _recordTokenType('ImportDirective_$context', node.configurations[0],
+          allowedKeywords: exportKeywords);
+      context = 'configurations';
+    }
+    if (node.combinators.isNotEmpty) {
+      _recordTokenType('ImportDirective_$context', node.combinators[0],
+          allowedKeywords: exportKeywords);
+    }
+    for (var combinator in node.combinators) {
+      _recordTokenType('ImportDirective_combinator', combinator,
+          allowedKeywords: exportKeywords);
+    }
+    super.visitExportDirective(node);
+  }
+
+  @override
+  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    _recordTokenType('ExpressionFunctionBody_start', node,
+        allowedKeywords: functionBodyKeywords);
+    _recordDataForNode('ExpressionFunctionBody_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitExpressionFunctionBody(node);
+  }
+
+  @override
+  void visitExpressionStatement(ExpressionStatement node) {
+    _recordDataForNode('ExpressionStatement_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitExpressionStatement(node);
+  }
+
+  @override
+  void visitExtendsClause(ExtendsClause node) {
+    _recordDataForNode('ExtendsClause_superclass', node.superclass);
+    super.visitExtendsClause(node);
+  }
+
+  @override
+  void visitExtensionDeclaration(ExtensionDeclaration node) {
+    _recordDataForNode('ExtensionDeclaration_extendedType', node.extendedType);
+    for (var member in node.members) {
+      _recordDataForNode('ExtensionDeclaration_member', member,
+          allowedKeywords: memberKeywords);
+    }
+    super.visitExtensionDeclaration(node);
+  }
+
+  @override
+  void visitExtensionOverride(ExtensionOverride node) {
+    // There are no completions.
+    super.visitExtensionOverride(node);
+  }
+
+  @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    // There are no completions.
+    super.visitFieldDeclaration(node);
+  }
+
+  @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    // The completions after `this.` are always existing fields.
+    super.visitFieldFormalParameter(node);
+  }
+
+  @override
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+    _recordDataForNode(
+        'ForEachPartsWithDeclaration_loopVariable', node.loopVariable);
+    _recordDataForNode('ForEachPartsWithDeclaration_iterable', node.iterable,
+        allowedKeywords: expressionKeywords);
+    super.visitForEachPartsWithDeclaration(node);
+  }
+
+  @override
+  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+    _recordDataForNode(
+        'ForEachPartsWithIdentifier_identifier', node.identifier);
+    _recordDataForNode('ForEachPartsWithIdentifier_iterable', node.iterable,
+        allowedKeywords: expressionKeywords);
+    super.visitForEachPartsWithIdentifier(node);
+  }
+
+  @override
+  void visitForElement(ForElement node) {
+    _recordTokenType('ForElement_parts', node.forLoopParts);
+    _recordDataForNode('ForElement_body', node.body);
+    super.visitForElement(node);
+  }
+
+  @override
+  void visitFormalParameterList(FormalParameterList node) {
+    for (var parameter in node.parameters) {
+      _recordDataForNode('FormalParameterList_parameter', parameter,
+          allowedKeywords: [Keyword.COVARIANT]);
+    }
+    super.visitFormalParameterList(node);
+  }
+
+  @override
+  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
+    _recordDataForNode('ForParts_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    for (var updater in node.updaters) {
+      _recordDataForNode('ForParts_updater', updater,
+          allowedKeywords: expressionKeywords);
+    }
+    super.visitForPartsWithDeclarations(node);
+  }
+
+  @override
+  void visitForPartsWithExpression(ForPartsWithExpression node) {
+    _recordDataForNode('ForParts_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    for (var updater in node.updaters) {
+      _recordDataForNode('ForParts_updater', updater,
+          allowedKeywords: expressionKeywords);
+    }
+    super.visitForPartsWithExpression(node);
+  }
+
+  @override
+  void visitForStatement(ForStatement node) {
+    _recordTokenType('ForElement_parts', node.forLoopParts);
+    _recordDataForNode('ForElement_body', node.body,
+        allowedKeywords: statementKeywords);
+    super.visitForStatement(node);
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    // There are no completions.
+    super.visitFunctionDeclaration(node);
+  }
+
+  @override
+  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    // There are no completions.
+    super.visitFunctionDeclarationStatement(node);
+  }
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    // There are no completions.
+    super.visitFunctionExpression(node);
+  }
+
+  @override
+  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    // There are no completions.
+    super.visitFunctionExpressionInvocation(node);
+  }
+
+  @override
+  void visitFunctionTypeAlias(FunctionTypeAlias node) {
+    // There are no completions.
+    super.visitFunctionTypeAlias(node);
+  }
+
+  @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    // There are no completions.
+    super.visitFunctionTypedFormalParameter(node);
+  }
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    // There are no completions.
+    super.visitGenericFunctionType(node);
+  }
+
+  @override
+  void visitGenericTypeAlias(GenericTypeAlias node) {
+    _recordDataForNode('GenericTypeAlias_functionType', node.functionType,
+        allowedKeywords: [Keyword.FUNCTION]);
+    super.visitGenericTypeAlias(node);
+  }
+
+  @override
+  void visitHideCombinator(HideCombinator node) {
+    for (var hiddenName in node.hiddenNames) {
+      _recordDataForNode('HideCombinator_hiddenName', hiddenName);
+    }
+    super.visitHideCombinator(node);
+  }
+
+  @override
+  void visitIfElement(IfElement node) {
+    _recordDataForNode('IfElement_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    _recordDataForNode('IfElement_thenElement', node.thenElement);
+    _recordDataForNode('IfElement_elseElement', node.elseElement);
+    super.visitIfElement(node);
+  }
+
+  @override
+  void visitIfStatement(IfStatement node) {
+    _recordDataForNode('IfStatement_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    _recordDataForNode('IfStatement_then', node.thenStatement,
+        allowedKeywords: statementKeywords);
+    _recordDataForNode('IfStatement_else', node.elseStatement,
+        allowedKeywords: statementKeywords);
+    super.visitIfStatement(node);
+  }
+
+  @override
+  void visitImplementsClause(ImplementsClause node) {
+    // At the start of each type name.
+    for (var typeName in node.interfaces) {
+      _recordDataForNode('ImplementsClause_interface', typeName);
+    }
+    super.visitImplementsClause(node);
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    var context = 'uri';
+    if (node.deferredKeyword != null) {
+      data.recordTokenType(
+          'ImportDirective_$context', node.deferredKeyword.type);
+      context = 'deferred';
+    }
+    if (node.asKeyword != null) {
+      data.recordTokenType('ImportDirective_$context', node.asKeyword.type);
+      context = 'prefix';
+    }
+    if (node.configurations.isNotEmpty) {
+      _recordTokenType('ImportDirective_$context', node.configurations[0],
+          allowedKeywords: importKeywords);
+      context = 'configurations';
+    }
+    if (node.combinators.isNotEmpty) {
+      _recordTokenType('ImportDirective_$context', node.combinators[0],
+          allowedKeywords: importKeywords);
+    }
+    for (var combinator in node.combinators) {
+      _recordTokenType('ImportDirective_combinator', combinator,
+          allowedKeywords: importKeywords);
+    }
+    super.visitImportDirective(node);
+  }
+
+  @override
+  void visitIndexExpression(IndexExpression node) {
+    _recordDataForNode('IndexExpression_index', node.index,
+        allowedKeywords: expressionKeywords);
+    super.visitIndexExpression(node);
+  }
+
+  @override
+  void visitInstanceCreationExpression(InstanceCreationExpression node) {
+    // There are no completions.
+    super.visitInstanceCreationExpression(node);
+  }
+
+  @override
+  void visitIntegerLiteral(IntegerLiteral node) {
+    // There are no completions.
+    super.visitIntegerLiteral(node);
+  }
+
+  @override
+  void visitInterpolationExpression(InterpolationExpression node) {
+    // TODO(brianwilkerson) Consider splitting this based on whether the
+    //  expression is a simple identifier ('$') or a full expression ('${').
+    _recordDataForNode('InterpolationExpression_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitInterpolationExpression(node);
+  }
+
+  @override
+  void visitInterpolationString(InterpolationString node) {
+    // There are no completions.
+    super.visitInterpolationString(node);
+  }
+
+  @override
+  void visitIsExpression(IsExpression node) {
+    _recordDataForNode('IsExpression_type', node.type);
+    super.visitIsExpression(node);
+  }
+
+  @override
+  void visitLabel(Label node) {
+    // There are no completions.
+    super.visitLabel(node);
+  }
+
+  @override
+  void visitLabeledStatement(LabeledStatement node) {
+    _recordDataForNode('LabeledStatement_statement', node.statement,
+        allowedKeywords: statementKeywords);
+    super.visitLabeledStatement(node);
+  }
+
+  @override
+  void visitLibraryDirective(LibraryDirective node) {
+    // There are no completions.
+    super.visitLibraryDirective(node);
+  }
+
+  @override
+  void visitLibraryIdentifier(LibraryIdentifier node) {
+    // There are no completions.
+    super.visitLibraryIdentifier(node);
+  }
+
+  @override
+  void visitListLiteral(ListLiteral node) {
+    for (var element in node.elements) {
+      _recordDataForNode('ListLiteral_element', element,
+          allowedKeywords: expressionKeywords);
+    }
+    super.visitListLiteral(node);
+  }
+
+  @override
+  void visitMapLiteralEntry(MapLiteralEntry node) {
+    _recordDataForNode('MapLiteralEntry_value', node.value,
+        allowedKeywords: expressionKeywords);
+    super.visitMapLiteralEntry(node);
+  }
+
+  @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    // There are no completions.
+    super.visitMethodDeclaration(node);
+  }
+
+  @override
+  void visitMethodInvocation(MethodInvocation node) {
+    // There are no completions.
+    super.visitMethodInvocation(node);
+  }
+
+  @override
+  void visitMixinDeclaration(MixinDeclaration node) {
+    var context = 'name';
+    if (node.onClause != null) {
+      _recordTokenType('MixinDeclaration_$context', node.onClause,
+          allowedKeywords: [Keyword.ON]);
+      context = 'on';
+    }
+    _recordTokenType('MixinDeclaration_$context', node.implementsClause,
+        allowedKeywords: [Keyword.IMPLEMENTS]);
+
+    for (var member in node.members) {
+      _recordDataForNode('MixinDeclaration_member', member,
+          allowedKeywords: memberKeywords);
+    }
+    super.visitMixinDeclaration(node);
+  }
+
+  @override
+  void visitNamedExpression(NamedExpression node) {
+    // Named expressions only occur in argument lists and are handled there.
+    super.visitNamedExpression(node);
+  }
+
+  @override
+  void visitNativeClause(NativeClause node) {
+    // There are no completions.
+    super.visitNativeClause(node);
+  }
+
+  @override
+  void visitNativeFunctionBody(NativeFunctionBody node) {
+    // There are no completions.
+    super.visitNativeFunctionBody(node);
+  }
+
+  @override
+  void visitNullLiteral(NullLiteral node) {
+    // There are no completions.
+    super.visitNullLiteral(node);
+  }
+
+  @override
+  void visitOnClause(OnClause node) {
+    for (var constraint in node.superclassConstraints) {
+      _recordDataForNode('OnClause_superclassConstraint', constraint);
+    }
+    super.visitOnClause(node);
+  }
+
+  @override
+  void visitParenthesizedExpression(ParenthesizedExpression node) {
+    _recordDataForNode('ParenthesizedExpression_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitParenthesizedExpression(node);
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    // There are no completions.
+    super.visitPartDirective(node);
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    // There are no completions.
+    super.visitPartOfDirective(node);
+  }
+
+  @override
+  void visitPostfixExpression(PostfixExpression node) {
+    // There are no completions.
+    super.visitPostfixExpression(node);
+  }
+
+  @override
+  void visitPrefixedIdentifier(PrefixedIdentifier node) {
+    // There are no completions.
+    super.visitPrefixedIdentifier(node);
+  }
+
+  @override
+  void visitPrefixExpression(PrefixExpression node) {
+    _recordDataForNode(
+        'PrefixExpression_${node.operator}_operand', node.operand,
+        allowedKeywords: expressionKeywords);
+    super.visitPrefixExpression(node);
+  }
+
+  @override
+  void visitPropertyAccess(PropertyAccess node) {
+    _recordDataForNode('PropertyAccess_propertyName', node.propertyName);
+    super.visitPropertyAccess(node);
+  }
+
+  @override
+  void visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    // There are no completions.
+    super.visitRedirectingConstructorInvocation(node);
+  }
+
+  @override
+  void visitRethrowExpression(RethrowExpression node) {
+    // There are no completions.
+    super.visitRethrowExpression(node);
+  }
+
+  @override
+  void visitReturnStatement(ReturnStatement node) {
+    _recordDataForNode('ReturnStatement_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    if (node.expression == null) {
+      data.recordTokenType('ReturnStatement_expression', node.semicolon.type);
+    }
+    super.visitReturnStatement(node);
+  }
+
+  @override
+  void visitScriptTag(ScriptTag node) {
+    // There are no completions.
+    super.visitScriptTag(node);
+  }
+
+  @override
+  void visitSetOrMapLiteral(SetOrMapLiteral node) {
+    for (var element in node.elements) {
+      _recordDataForNode('SetOrMapLiteral_element', element,
+          allowedKeywords: expressionKeywords);
+    }
+    super.visitSetOrMapLiteral(node);
+  }
+
+  @override
+  void visitShowCombinator(ShowCombinator node) {
+    for (var name in node.shownNames) {
+      _recordDataForNode('ShowCombinator_shownName', name);
+    }
+    super.visitShowCombinator(node);
+  }
+
+  @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    // There are no completions.
+    super.visitSimpleFormalParameter(node);
+  }
+
+  @override
+  void visitSimpleStringLiteral(SimpleStringLiteral node) {
+    // There are no completions.
+    super.visitSimpleStringLiteral(node);
+  }
+
+  @override
+  void visitSpreadElement(SpreadElement node) {
+    _recordDataForNode('SpreadElement_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitSpreadElement(node);
+  }
+
+  @override
+  void visitStringInterpolation(StringInterpolation node) {
+    // There are no completions.
+    super.visitStringInterpolation(node);
+  }
+
+  @override
+  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    // There are no completions.
+    super.visitSuperConstructorInvocation(node);
+  }
+
+  @override
+  void visitSuperExpression(SuperExpression node) {
+    // There are no completions.
+    super.visitSuperExpression(node);
+  }
+
+  @override
+  void visitSwitchCase(SwitchCase node) {
+    _recordDataForNode('SwitchCase_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    for (var statement in node.statements) {
+      _recordDataForNode('SwitchMember_statement', statement,
+          allowedKeywords: statementKeywords);
+    }
+    super.visitSwitchCase(node);
+  }
+
+  @override
+  void visitSwitchDefault(SwitchDefault node) {
+    for (var statement in node.statements) {
+      _recordDataForNode('SwitchMember_statement', statement,
+          allowedKeywords: statementKeywords);
+    }
+    super.visitSwitchDefault(node);
+  }
+
+  @override
+  void visitSwitchStatement(SwitchStatement node) {
+    _recordDataForNode('SwitchStatement_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitSwitchStatement(node);
+  }
+
+  @override
+  void visitSymbolLiteral(SymbolLiteral node) {
+    // There are no completions.
+    super.visitSymbolLiteral(node);
+  }
+
+  @override
+  void visitThisExpression(ThisExpression node) {
+    // There are no completions.
+    super.visitThisExpression(node);
+  }
+
+  @override
+  void visitThrowExpression(ThrowExpression node) {
+    _recordDataForNode('ThrowExpression_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitThrowExpression(node);
+  }
+
+  @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    // There are no completions.
+    super.visitTopLevelVariableDeclaration(node);
+  }
+
+  @override
+  void visitTryStatement(TryStatement node) {
+    var context = 'try';
+    for (var clause in node.catchClauses) {
+      _recordTokenType('TryStatement_$context', clause,
+          allowedKeywords: [Keyword.ON]);
+      context = 'catch';
+    }
+    if (node.finallyKeyword != null) {
+      data.recordTokenType('TryStatement_$context', node.finallyKeyword.type);
+    }
+    super.visitTryStatement(node);
+  }
+
+  @override
+  void visitTypeArgumentList(TypeArgumentList node) {
+    for (var typeArgument in node.arguments) {
+      _recordDataForNode('TypeArgumentList_argument', typeArgument);
+    }
+    super.visitTypeArgumentList(node);
+  }
+
+  @override
+  void visitTypeName(TypeName node) {
+    // There are no completions.
+    super.visitTypeName(node);
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    if (node.bound != null) {
+      _recordDataForNode('TypeParameter_bound', node.bound);
+    }
+    super.visitTypeParameter(node);
+  }
+
+  @override
+  void visitTypeParameterList(TypeParameterList node) {
+    // There are no completions.
+    super.visitTypeParameterList(node);
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    var keywords = node.parent.parent is FieldDeclaration
+        ? [Keyword.COVARIANT, ...expressionKeywords]
+        : expressionKeywords;
+    _recordDataForNode('VariableDeclaration_initializer', node.initializer,
+        allowedKeywords: keywords);
+    super.visitVariableDeclaration(node);
+  }
+
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    // There are no completions.
+    super.visitVariableDeclarationList(node);
+  }
+
+  @override
+  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    // There are no completions.
+    super.visitVariableDeclarationStatement(node);
+  }
+
+  @override
+  void visitWhileStatement(WhileStatement node) {
+    _recordDataForNode('WhileStatement_condition', node.condition,
+        allowedKeywords: expressionKeywords);
+    _recordDataForNode('WhileStatement_body', node.body,
+        allowedKeywords: statementKeywords);
+    super.visitWhileStatement(node);
+  }
+
+  @override
+  void visitWithClause(WithClause node) {
+    for (var typeName in node.mixinTypes) {
+      _recordDataForNode('WithClause_mixinType', typeName);
+    }
+    super.visitWithClause(node);
+  }
+
+  @override
+  void visitYieldStatement(YieldStatement node) {
+    _recordDataForNode('YieldStatement_expression', node.expression,
+        allowedKeywords: expressionKeywords);
+    super.visitYieldStatement(node);
+  }
+
+  /// Return the context in which the [node] occurs. The [node] is expected to
+  /// be the parent of the argument expression.
+  String _argumentListContext(AstNode node) {
+    if (node is ArgumentList) {
+      var parent = node.parent;
+      if (parent is InstanceCreationExpression) {
+        if (flutter.isWidgetType(parent.staticType)) {
+          return 'widgetConstructor';
+        }
+        return 'constructor';
+      } else if (parent is MethodInvocation) {
+        return 'method';
+      } else if (parent is FunctionExpressionInvocation) {
+        return 'function';
+      } else if (parent is SuperConstructorInvocation ||
+          parent is RedirectingConstructorInvocation) {
+        return 'constructorRedirect';
+      } else if (parent is Annotation) {
+        return 'annotation';
+      }
+    } else if (node is IndexExpression) {
+      return 'index';
+    } else if (node is AssignmentExpression ||
+        node is BinaryExpression ||
+        node is PrefixExpression ||
+        node is PostfixExpression) {
+      return 'operator';
+    }
+    throw ArgumentError('Unknown parent of ${node.runtimeType}');
+  }
+
+  /// Return the first child of the [node] that is neither a comment nor an
+  /// annotation.
+  SyntacticEntity _firstChild(AstNode node) {
+    var children = node.childEntities.toList();
+    for (var i = 0; i < children.length; i++) {
+      var child = children[i];
+      if (child is! Comment && child is! Annotation) {
+        return child;
+      }
+    }
+    return null;
+  }
+
+  /// Return the element associated with the left-most identifier that is a
+  /// child of the [node].
+  Element _leftMostElement(AstNode node) =>
+      _leftMostIdentifier(node)?.staticElement;
+
+  /// Return the left-most child of the [node] if it is a simple identifier, or
+  /// `null` if the left-most child is not a simple identifier. Comments and
+  /// annotations are ignored for this purpose.
+  SimpleIdentifier _leftMostIdentifier(AstNode node) {
+    var currentNode = node;
+    while (currentNode != null && currentNode is! SimpleIdentifier) {
+      var firstChild = _firstChild(currentNode);
+      if (firstChild is AstNode) {
+        currentNode = firstChild;
+      } else {
+        currentNode = null;
+      }
+    }
+    if (currentNode is SimpleIdentifier && currentNode.inDeclarationContext()) {
+      return null;
+    }
+    return currentNode;
+  }
+
+  /// Return the element kind of the element associated with the left-most
+  /// identifier that is a child of the [node].
+  ElementKind _leftMostKind(AstNode node) {
+    if (node is InstanceCreationExpression) {
+      return convertElementToElementKind(node.staticElement);
+    }
+    var element = _leftMostElement(node);
+    if (element == null) {
+      return null;
+    }
+    if (element is ClassElement) {
+      var parent = node.parent;
+      if (parent is Annotation && parent.arguments != null) {
+        element = parent.element;
+      }
+    }
+    return convertElementToElementKind(element);
+  }
+
+  /// Return the left-most token that is a child of the [node].
+  Token _leftMostToken(AstNode node) {
+    SyntacticEntity entity = node;
+    while (entity is AstNode) {
+      entity = _firstChild(entity as AstNode);
+    }
+    if (entity is Token) {
+      return entity;
+    }
+    return null;
+  }
+
+  /// Record information about the given [node] occurring in the given
+  /// [context].
+  void _recordDataForNode(String context, AstNode node,
+      {List<Keyword> allowedKeywords = noKeywords}) {
+    _recordElementKind(context, node);
+    _recordTokenType(context, node, allowedKeywords: allowedKeywords);
+  }
+
+  /// Record the element kind of the element associated with the left-most
+  /// identifier that is a child of the [node] in the given [context].
+  void _recordElementKind(String context, AstNode node) {
+    if (node != null) {
+      var kind = _leftMostKind(node);
+      if (kind != null) {
+        data.recordElementKind(context, kind);
+        if (node is Expression) {
+          data.recordElementKind('Expression', kind);
+        } else if (node is Statement) {
+          data.recordElementKind('Statement', kind);
+        }
+      }
+    }
+  }
+
+  /// Record the token type of the left-most token that is a child of the
+  /// [node] in the given [context].
+  void _recordTokenType(String context, AstNode node,
+      {List<Keyword> allowedKeywords = noKeywords}) {
+    if (node != null) {
+      var token = _leftMostToken(node);
+      if (token != null) {
+        var type = token.type;
+        if (token.isKeyword && token.keyword.isBuiltInOrPseudo) {
+          // These keywords can be used as identifiers, so determine whether it
+          // is being used as a keyword or an identifier.
+          if (!allowedKeywords.contains(token.keyword)) {
+            type = TokenType.IDENTIFIER;
+          }
+        }
+        data.recordTokenType(context, type);
+        if (node is Expression) {
+          data.recordTokenType('Expression', type);
+        } else if (node is Statement) {
+          data.recordTokenType('Statement', type);
+        }
+      }
+    }
+  }
+}
+
+/// An object used to compute metrics for a single file or directory.
+class RelevanceMetricsComputer {
+  /// The metrics data that was computed.
+  final RelevanceData data = RelevanceData();
+
+  /// Initialize a newly created metrics computer that can compute the metrics
+  /// in one or more files and directories.
+  RelevanceMetricsComputer();
+
+  /// 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 {
+    final collection = AnalysisContextCollection(
+      includedPaths: [rootPath],
+      resourceProvider: PhysicalResourceProvider.INSTANCE,
+    );
+    final collector = RelevanceDataCollector(data);
+    for (var context in collection.contexts) {
+      await _computeInContext(context.contextRoot, collector, verbose: verbose);
+    }
+  }
+
+  /// Compute the metrics for the files in the context [root], creating a
+  /// 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,
+      {@required bool verbose}) async {
+    // Create a new collection to avoid consuming large quantities of memory.
+    final collection = AnalysisContextCollection(
+      includedPaths: root.includedPaths.toList(),
+      excludedPaths: root.excludedPaths.toList(),
+      resourceProvider: PhysicalResourceProvider.INSTANCE,
+    );
+    var context = collection.contexts[0];
+    for (var filePath in context.contextRoot.analyzedFiles()) {
+      if (AnalysisEngine.isDartFileName(filePath)) {
+        try {
+          var resolvedUnitResult =
+              await context.currentSession.getResolvedUnit(filePath);
+          //
+          // Check for errors that cause the file to be skipped.
+          //
+          if (resolvedUnitResult == null) {
+            print('File $filePath skipped because resolved unit was null.');
+            if (verbose) {
+              print('');
+            }
+            continue;
+          } else if (resolvedUnitResult.state != ResultState.VALID) {
+            print('File $filePath skipped because it could not be analyzed.');
+            if (verbose) {
+              print('');
+            }
+            continue;
+          } else if (hasError(resolvedUnitResult)) {
+            if (verbose) {
+              print('File $filePath skipped due to errors:');
+              for (var error in resolvedUnitResult.errors
+                  .where((e) => e.severity == Severity.error)) {
+                print('  ${error.toString()}');
+              }
+              print('');
+            } else {
+              print('File $filePath skipped due to analysis errors.');
+            }
+            continue;
+          }
+
+          collector.initializeFrom(resolvedUnitResult);
+          resolvedUnitResult.unit.accept(collector);
+        } catch (exception, stacktrace) {
+          print('Exception caught analyzing: "$filePath"');
+          print(exception);
+          print(stacktrace);
+        }
+      }
+    }
+  }
+
+  /// Return `true` if the [result] contains an error.
+  static bool hasError(ResolvedUnitResult result) {
+    for (var error in result.errors) {
+      if (error.severity == Severity.error) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
+
+/// A class used to write relevance data as a set of tables in a generated Dart
+/// file.
+class RelevanceTableWriter {
+  final StringSink sink;
+
+  RelevanceTableWriter(this.sink);
+
+  int totalCount(Map<String, int> counts) {
+    return counts.values
+        .fold(0, (previousValue, value) => previousValue + value);
+  }
+
+  void write(RelevanceData data) {
+    writeFileHeader();
+    writeElementKindTable(data);
+  }
+
+  void writeElementKindTable(RelevanceData data) {
+    var byTokenType = data.byTokenType;
+    var byElementKind = data.byElementKind;
+
+    sink.writeln();
+    sink.write('''
+/// A table keyed by completion location and element kind whose values are the
+/// ranges of the relevance of those element kinds in those locations.
+const elementKindRelevance = {
+''');
+
+    var completionLocations = byElementKind.keys.toList()..sort();
+    for (var completionLocation in completionLocations) {
+      var elementCounts = byElementKind[completionLocation];
+      var identifierPercent = 1.0;
+      var tokenCounts = byTokenType[completionLocation];
+      if (tokenCounts != null) {
+        var identifierCount = tokenCounts['IDENTIFIER'];
+        if (identifierCount != null) {
+          var totalTokenCount = totalCount(tokenCounts);
+          identifierPercent = identifierCount / totalTokenCount;
+        }
+      }
+      // TODO(brianwilkerson) This incorrectly assumes that identifiers are
+      //  always the most common first token in a completion location.
+      var startOfBand = 1.0 - identifierPercent;
+      sink.write("  '");
+      sink.write(completionLocation);
+      sink.writeln("': {");
+      var totalElementCount = totalCount(elementCounts);
+      var cumulativeCount = 0;
+      // TODO(brianwilkerson) If two element kinds have the same count they
+      //  ought to have the same probability. This doesn't correctly do that.
+      var entries = elementCounts.entries.toList()
+        ..sort((first, second) => first.value.compareTo(second.value));
+      var lowerBound = 0.0;
+      for (var entry in entries) {
+        var elementKind = entry.key;
+        cumulativeCount += entry.value;
+        var percentInBand = cumulativeCount / totalElementCount;
+        var upperBound = (percentInBand * identifierPercent) + startOfBand;
+        sink.write('    ElementKind.');
+        sink.write(elementKind);
+        sink.write(': ProbabilityRange(lower: ');
+        sink.write(lowerBound.toStringAsFixed(3));
+        sink.write(', upper: ');
+        sink.write(upperBound.toStringAsFixed(3));
+        sink.writeln('),');
+        lowerBound = upperBound;
+      }
+      sink.writeln('  },');
+    }
+    sink.writeln('};');
+  }
+
+  void writeFileHeader() {
+    sink.write('''
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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 has been automatically generated. Please do not edit it manually.
+// To regenerate the file, use the script
+// "pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart",
+// passing it the location of a corpus of code that is large enough for the
+// computed values to be statistically meaningful.
+
+import 'package:analysis_server/src/services/completion/dart/probability_range.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+''');
+  }
+}
+
+class Timer {
+  Stopwatch stopwatch = Stopwatch();
+
+  int count = 0;
+
+  Timer();
+
+  double get averageTime => count == 0 ? 0 : totalTime / count;
+
+  int get totalTime => stopwatch.elapsedMilliseconds;
+
+  void start() {
+    stopwatch.start();
+  }
+
+  void stop() {
+    stopwatch.stop();
+    count++;
+  }
+}
diff --git a/pkg/analysis_server/tool/completion_metrics/visitors.dart b/pkg/analysis_server/tool/completion_metrics/visitors.dart
index dcb21a8..7bacd2c 100644
--- a/pkg/analysis_server/tool/completion_metrics/visitors.dart
+++ b/pkg/analysis_server/tool/completion_metrics/visitors.dart
@@ -11,6 +11,8 @@
 import 'package:analyzer/dart/element/element.dart' as element;
 
 class ExpectedCompletion {
+  final String _filePath;
+
   final SyntacticEntity _entity;
 
   /// Some completions are special cased from the DAS "import" for instance is
@@ -26,11 +28,12 @@
 
   final protocol.ElementKind _elementKind;
 
-  ExpectedCompletion(this._entity, this._lineNumber, this._columnNumber,
-      this._kind, this._elementKind)
+  ExpectedCompletion(this._filePath, this._entity, this._lineNumber,
+      this._columnNumber, this._kind, this._elementKind)
       : _completionString = null;
 
   ExpectedCompletion.specialCompletionString(
+      this._filePath,
       this._entity,
       this._lineNumber,
       this._columnNumber,
@@ -68,11 +71,17 @@
     }
     return false;
   }
+
+  @override
+  String toString() =>
+      "'$completion', kind = $kind, elementKind = $elementKind, $_filePath:$lineNumber:$columnNumber";
 }
 
 class ExpectedCompletionsVisitor extends RecursiveAstVisitor<void> {
   final List<ExpectedCompletion> expectedCompletions;
 
+  final String filePath;
+
   CompilationUnit _enclosingCompilationUnit;
 
   /// This boolean is set to enable whether or not we should assert that some
@@ -88,7 +97,9 @@
   /// comment don't yield an error like Dart syntax mistakes would yield.
   final bool _doExpectCommentRefs = false;
 
-  ExpectedCompletionsVisitor() : expectedCompletions = <ExpectedCompletion>[];
+  ExpectedCompletionsVisitor(this.filePath)
+      : expectedCompletions = <ExpectedCompletion>[],
+        assert(filePath != null);
 
   void safelyRecordEntity(SyntacticEntity entity,
       {protocol.CompletionSuggestionKind kind,
@@ -108,9 +119,16 @@
       // DAS is "import '';" which we want to be sure to match.
       if (entity.toString() == 'async') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
-            entity, lineNumber, columnNumber, ASYNC_STAR, kind, elementKind));
+            filePath,
+            entity,
+            lineNumber,
+            columnNumber,
+            ASYNC_STAR,
+            kind,
+            elementKind));
       } else if (entity.toString() == 'default') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            filePath,
             entity,
             lineNumber,
             columnNumber,
@@ -119,9 +137,16 @@
             elementKind));
       } else if (entity.toString() == 'deferred') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
-            entity, lineNumber, columnNumber, DEFERRED_AS, kind, elementKind));
+            filePath,
+            entity,
+            lineNumber,
+            columnNumber,
+            DEFERRED_AS,
+            kind,
+            elementKind));
       } else if (entity.toString() == 'export') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            filePath,
             entity,
             lineNumber,
             columnNumber,
@@ -130,6 +155,7 @@
             elementKind));
       } else if (entity.toString() == 'import') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            filePath,
             entity,
             lineNumber,
             columnNumber,
@@ -138,6 +164,7 @@
             elementKind));
       } else if (entity.toString() == 'part') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            filePath,
             entity,
             lineNumber,
             columnNumber,
@@ -146,13 +173,25 @@
             elementKind));
       } else if (entity.toString() == 'sync') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
-            entity, lineNumber, columnNumber, SYNC_STAR, kind, elementKind));
+            filePath,
+            entity,
+            lineNumber,
+            columnNumber,
+            SYNC_STAR,
+            kind,
+            elementKind));
       } else if (entity.toString() == 'yield') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
-            entity, lineNumber, columnNumber, YIELD_STAR, kind, elementKind));
+            filePath,
+            entity,
+            lineNumber,
+            columnNumber,
+            YIELD_STAR,
+            kind,
+            elementKind));
       } else {
         expectedCompletions.add(ExpectedCompletion(
-            entity, lineNumber, columnNumber, kind, elementKind));
+            filePath, entity, lineNumber, columnNumber, kind, elementKind));
       }
     }
   }
@@ -528,7 +567,7 @@
     if (_doIncludeSimpleIdentifier(node)) {
       var elementKind;
       if (node.staticElement?.kind != null) {
-        elementKind = protocol.convertElementKind(node.staticElement?.kind);
+        elementKind = protocol.convertElementKind(node.staticElement.kind);
 
         // If the completed element kind is a getter or setter set the element
         // kind to null as the exact kind from the DAS is unknown at this
@@ -551,6 +590,27 @@
         if (node.parent is FieldFormalParameter) {
           elementKind = protocol.ElementKind.FIELD;
         }
+
+        // Class references that are constructor calls are constructor kinds,
+        // unless either:
+        //   1) the constructor is a named constructor, i.e. some "Foo.bar()",
+        //      the "Foo" in this case is a class,
+        //   2) or, there is an explicit const or new keyword before the
+        //      constructor invocation in which case the "Foo" above is
+        //      considered a constructor still
+        if (elementKind == protocol.ElementKind.CLASS) {
+          if (node.parent?.parent is ConstructorName) {
+            var constructorName = node.parent.parent as ConstructorName;
+            var instanceCreationExpression = constructorName.parent;
+            if (instanceCreationExpression is InstanceCreationExpression &&
+                constructorName.type.name == node) {
+              if (instanceCreationExpression.keyword != null ||
+                  constructorName.name == null) {
+                elementKind = protocol.ElementKind.CONSTRUCTOR;
+              }
+            }
+          }
+        }
       }
       safelyRecordEntity(node, elementKind: elementKind);
     }
@@ -644,6 +704,12 @@
     if (node == null || node.isSynthetic || node.inDeclarationContext()) {
       return false;
     }
+
+    // If the type of the SimpleIdentifier is dynamic, don't include.
+    if (node.staticType != null && node.staticType.isDynamic) {
+      return false;
+    }
+
     // If we are in a comment reference context, return if we should include
     // such identifiers.
     if (node.thisOrAncestorOfType<CommentReference>() != null) {
@@ -661,16 +727,17 @@
     // Named arguments, i.e. the 'foo' in 'method_call(foo: 1)' should not be
     // included, by design, the completion engine won't suggest named arguments
     // already it the source.
-    if (node.staticElement?.kind == element.ElementKind.PARAMETER &&
+    //
+    // The null check, node.staticElement == null, handles the cases where the
+    // invocation is unknown, i.e. the 'arg' in 'foo.bar(arg: 1)', where foo is
+    // dynamic.
+    if ((node.staticElement == null ||
+            node.staticElement?.kind == element.ElementKind.PARAMETER) &&
         node.parent is Label &&
         node.thisOrAncestorOfType<ArgumentList>() != null) {
       return false;
     }
 
-    // If the type of the SimpleIdentifier is dynamic, don't include.
-    if (node.staticType != null && node.staticType.isDynamic) {
-      return false;
-    }
     return true;
   }
 }
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index 4533588..23df9cc 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -348,24 +348,16 @@
     ..writeIndentedln('@override')
     ..writeIndentedln('bool operator ==(Object other) {')
     ..indent()
-    ..writeIndentedln('if (other is ${interface.name}) {')
+    // We want an exact type match, but also need `is` to have the analyzer
+    // promote the type to allow access to the fields on `other`.
+    ..writeIndentedln(
+        'if (other is ${interface.name} && other.runtimeType == ${interface.name}) {')
     ..indent()
     ..writeIndented('return ');
   for (var field in _getAllFields(interface)) {
-    final type = field.type;
-    if (type is ArrayType) {
-      final elementType = type.elementType;
-      final elementDartType = elementType.dartTypeWithTypeArgs;
-      buffer.write(
-          'listEqual(${field.name}, other.${field.name}, ($elementDartType a, $elementDartType b) => a == b) && ');
-    } else if (type is MapType) {
-      final valueType = type.valueType;
-      final valueDartType = valueType.dartTypeWithTypeArgs;
-      buffer.write(
-          'mapEqual(${field.name}, other.${field.name}, ($valueDartType a, $valueDartType b) => a == b) && ');
-    } else {
-      buffer.write('${field.name} == other.${field.name} && ');
-    }
+    final type = resolveTypeAlias(field.type);
+    _writeEqualsExpression(buffer, type, field.name, 'other.${field.name}');
+    buffer.write(' && ');
   }
   buffer
     ..writeln('true;')
@@ -376,6 +368,27 @@
     ..writeIndentedln('}');
 }
 
+void _writeEqualsExpression(IndentableStringBuffer buffer, TypeBase type,
+    String thisName, String otherName) {
+  if (type is ArrayType) {
+    final elementType = type.elementType;
+    final elementDartType = elementType.dartTypeWithTypeArgs;
+    buffer.write(
+        'listEqual($thisName, $otherName, ($elementDartType a, $elementDartType b) => ');
+    _writeEqualsExpression(buffer, elementType, 'a', 'b');
+    buffer.write(')');
+  } else if (type is MapType) {
+    final valueType = type.valueType;
+    final valueDartType = valueType.dartTypeWithTypeArgs;
+    buffer.write(
+        'mapEqual($thisName, $otherName, ($valueDartType a, $valueDartType b) => ');
+    _writeEqualsExpression(buffer, valueType, 'a', 'b');
+    buffer.write(')');
+  } else {
+    buffer.write('$thisName == $otherName');
+  }
+}
+
 void _writeField(IndentableStringBuffer buffer, Field field) {
   _writeDocCommentsAndAnnotations(buffer, field);
   buffer
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 59f2af9..058ac50 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -1002,7 +1002,7 @@
       </field>
     </params>
   </notification>
-  <notification event="closingLabels" experimental="true">
+  <notification event="closingLabels">
     <p>
       Reports closing labels relevant to a given file.
     </p>
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 743a14a..3e0c73e 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,12 +1,66 @@
-## 0.39.5-dev
+## 0.39.7
+* Added new error codes: ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING and
+  THROW_OF_INVALID_TYPE.
+* Changed error code NULLABLE_TYPE_IN_CATCH_CLAUSE to a hint.
+* Bug fixes: #40554, #41378, #41399, #41412, and, #41470.
+
+## 0.39.6
+* Added Window and DocumentFragment to analyzer's mock SDK.  These are required
+  for upcoming changes to the unsafe_html lint.
+
+## 0.39.5
 * Deprecated `ClassElement.instantiateToBounds()` and
   `FunctionTypeAliasElement.instantiateToBounds()`. With the null-safety
   feature, type arguments derived from type parameter bounds cannot be used as
   is, and might require erasing nullability, when the element is instantiated
   from a legacy library. Use `TypeSystem.instantiateToBounds2()` instead.
-* Deprecated `DeclaredVariables.getBool/getInt/getString()`. These methods
-  are used internally for constants computation, and should not be used by
-  clients.
+* Deprecated `DeclaredVariables.getBool/getInt/getString()` and
+  `TypeProvider.nullObject`. These methods are used internally for constants
+  computation, and should not be used by clients.
+* Deprecated `AstFactory.indexExpressionForCascade()`.  Please use
+  `indexExpressionForCascade2` instead.
+* Deprecated `AstFactory.indexExpressionForTarget()`.  Please use
+  `indexExpressionForTarget2` instead.
+* Deprecated `ClassElement.isOrInheritsProxy` and `ClassElement.isProxy`.  The
+  `@proxy` annotation is deprecated in the langauge, and will be removed.
+* Added new error codes: BODY_MIGHT_COMPLETE_NORMALLY,
+  CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE,
+  DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE, LATE_FINAL_LOCAL_ALREADY_ASSIGNED,
+  SWITCH_CASE_COMPLETES_NORMALLY, EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER,
+  FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER, GETTER_CONSTRUCTOR,
+  MEMBER_WITH_CLASS_NAME, SETTER_CONSTRUCTOR, TYPE_PARAMETER_ON_OPERATOR, and
+  VOID_WITH_TYPE_ARGUMENTS.
+* Renamed error code DEFAULT_LIST_CONSTRUCTOR_MISMATCH to
+  DEFAULT_LIST_CONSTRUCTOR.  This reflects a spec change: after null safety is
+  enabled, it will be an error to call the default `List` constructor under all
+  circumstances.
+* Added new warning code: INVALID_NULL_AWARE_OPERATOR.
+* Renamed warning code DEAD_NULL_COALESCE to DEAD_NULL_AWARE_EXPRESSION, to
+  reflect the fact that it applies both to if-null expressions (`??`) and
+  if-null compound assignment expressions (`??=`).
+* Split warning code MISMATCHED_GETTER_AND_SETTER_TYPES into two codes:
+  GETTER_NOT_ASSIGNABLE_SETTER_TYPES and GETTER_NOT_SUBTYPE_SETTER_TYPES.
+* Coalesced warning codes UNNECESSARY_NULL_AWARE_CALL and
+  UNNECESSARY_NULL_AWARE_SPREAD into one warning code:
+  INVALID_NULL_AWARE_OPERATOR.
+* Added new hint codes: EQUAL_ELEMENTS_IN_SET, EQUAL_KEYS_IN_MAP,
+  INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION, UNNECESSARY_NULL_COMPARISON_FALSE,
+  and UNNECESSARY_NULL_COMPARISON_TRUE.
+* Downgraded warning INVALID_USE_OF_NEVER_VALUE to hint RECEIVER_OF_TYPE_NEVER.
+* Re-introduced strong mode codes: DYNAMIC_INVOKE, IMPLICIT_DYNAMIC_FIELD,
+  IMPLICIT_DYNAMIC_FUNCTION, IMPLICIT_DYNAMIC_INVOKE,
+  IMPLICIT_DYNAMIC_LIST_LITERAL, IMPLICIT_DYNAMIC_MAP_LITERAL,
+  IMPLICIT_DYNAMIC_METHOD, IMPLICIT_DYNAMIC_PARAMETER, IMPLICIT_DYNAMIC_RETURN,
+  IMPLICIT_DYNAMIC_TYPE, and IMPLICIT_DYNAMIC_VARIABLE.  These were removed in
+  version 0.39.3, but it turns out they are actually needed (see
+  https://github.com/dart-lang/sdk/issues/40129).
+* Fixed bugs 35940, 37122, 38554, 38666, 38791, 38990, 39059, 39597, 39694,
+  39762, 39791, 39833, 39875, 39876, 39917, 39939, 39976, 40033, 40055, 40057,
+  40110, 40129, 40221, 40279, 40283, 40287, 40299, 40304, 40316, 40333, 40392,
+  40394, 40396, 40398, 40413, 40414, 40460, 40482, 40500, 40538, 40546, 40547,
+  40572, 40578, 40603, 40609, 40677, 40689, 40701, 40704, 40734, 40764, 40837,
+  40865, 40915, 40931, 40941, 40955, 40956, 40958, 40959, 41019, 41036, 41050,
+  41095, 41130, and 41180.
 
 ## 0.39.4
 * Deprecated `DartType.name`, use `element` or `getDisplayString()` instead.
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index bbcdc16..a9efa56 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -137,6 +137,7 @@
   CompileTimeErrorCode.DUPLICATE_DEFINITION,
   CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT,
   CompileTimeErrorCode.DUPLICATE_PART,
+  CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
   CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET,
   CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP,
   CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
@@ -269,7 +270,6 @@
   CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
   CompileTimeErrorCode.NOT_MAP_SPREAD,
   CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD,
-  CompileTimeErrorCode.NULLABLE_TYPE_IN_CATCH_CLAUSE,
   CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE,
   CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE,
   CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE,
@@ -308,6 +308,7 @@
   CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
   CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT,
   CompileTimeErrorCode.SWITCH_CASE_COMPLETES_NORMALLY,
+  CompileTimeErrorCode.THROW_OF_INVALID_TYPE,
   CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
   CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
   // ignore: deprecated_member_use_from_same_package
@@ -420,6 +421,7 @@
   HintCode.NULL_AWARE_BEFORE_OPERATOR,
   HintCode.NULL_AWARE_IN_CONDITION,
   HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR,
+  HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE,
   HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE,
   HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD,
   HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER,
diff --git a/pkg/analyzer/lib/src/command_line/arguments.dart b/pkg/analyzer/lib/src/command_line/arguments.dart
index 8d313c8..5d5bf1a 100644
--- a/pkg/analyzer/lib/src/command_line/arguments.dart
+++ b/pkg/analyzer/lib/src/command_line/arguments.dart
@@ -57,11 +57,9 @@
 }
 
 /**
- * Use the given [resourceProvider], [contentCache] and command-line [args] to
- * create a context builder.
+ * Use the command-line [args] to create a context builder.
  */
-ContextBuilderOptions createContextBuilderOptions(ArgResults args,
-    {bool trackCacheDependencies}) {
+ContextBuilderOptions createContextBuilderOptions(ArgResults args) {
   ContextBuilderOptions builderOptions = ContextBuilderOptions();
   builderOptions.argResults = args;
   //
@@ -77,9 +75,6 @@
   //
   AnalysisOptionsImpl defaultOptions = AnalysisOptionsImpl();
   applyAnalysisOptionFlags(defaultOptions, args);
-  if (trackCacheDependencies != null) {
-    defaultOptions.trackCacheDependencies = trackCacheDependencies;
-  }
   builderOptions.defaultOptions = defaultOptions;
   //
   // Declared variables.
diff --git a/pkg/analyzer/lib/src/context/packages.dart b/pkg/analyzer/lib/src/context/packages.dart
index 8d79d78..8ea6b3b 100644
--- a/pkg/analyzer/lib/src/context/packages.dart
+++ b/pkg/analyzer/lib/src/context/packages.dart
@@ -158,4 +158,20 @@
 
   /// Return the [Package] with the given [name], or `null`.
   Package operator [](String name) => _map[name];
+
+  /// Return the inner-most [Package] that contains  the [path], `null` if none.
+  Package packageForPath(String path) {
+    Package result;
+    int resultPathLength;
+    for (var package in packages) {
+      if (package.rootFolder.contains(path)) {
+        var packagePathLength = package.rootFolder.path.length;
+        if (result == null || resultPathLength < packagePathLength) {
+          result = package;
+          resultPathLength = packagePathLength;
+        }
+      }
+    }
+    return result;
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 1066383..0ece485 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -91,7 +91,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 = 100;
+  static const int DATA_VERSION = 101;
 
   /// The length of the list returned by [_computeDeclaredVariablesSignature].
   static const int _declaredVariablesSignatureLength = 4;
@@ -445,7 +445,7 @@
         _unitElementRequestedParts.isNotEmpty) {
       return AnalysisDriverPriority.general;
     }
-    _libraryContext = null;
+    _clearLibraryContext();
     return AnalysisDriverPriority.nothing;
   }
 
@@ -1173,7 +1173,7 @@
     _throwIfNotAbsolutePath(path);
     _throwIfChangesAreNotAllowed();
     _fileTracker.removeFile(path);
-    _libraryContext = null;
+    _clearLibraryContext();
     _priorityResults.clear();
   }
 
@@ -1188,7 +1188,7 @@
   /// Implementation for [changeFile].
   void _changeFile(String path) {
     _fileTracker.changeFile(path);
-    _libraryContext = null;
+    _clearLibraryContext();
     _priorityResults.clear();
   }
 
@@ -1196,17 +1196,27 @@
   /// of state.
   void _changeHook(String path) {
     _createNewSession(path);
-    _libraryContext = null;
+    _clearLibraryContext();
     _priorityResults.clear();
     _scheduler.notify(this);
   }
 
+  /// Clear the library context and any related data structures. Mostly we do
+  /// this to reduce memory consumption. The library context holds to every
+  /// library that was resynthesized, but after some initial analysis we might
+  /// not get again to many of these libraries. So, we should clear the context
+  /// periodically.
+  void _clearLibraryContext() {
+    _libraryContext = null;
+    _currentSession.clearHierarchies();
+  }
+
   /// There was an exception during a file analysis, we don't know why.
   /// But it might have been caused by an inconsistency of files state, and
   /// the library context state. Reset the library context, and hope that
   /// we will solve the inconsistency while loading / building summaries.
   void _clearLibraryContextAfterException() {
-    _libraryContext = null;
+    _clearLibraryContext();
   }
 
   /// Return the cached or newly computed analysis result of the file with the
@@ -1497,7 +1507,7 @@
   LibraryContext _createLibraryContext(FileState library) {
     if (_libraryContext != null) {
       if (_libraryContext.pack()) {
-        _libraryContext = null;
+        _clearLibraryContext();
       }
     }
 
@@ -1588,35 +1598,9 @@
       FileState file, List<AnalysisDriverUnitError> serialized) {
     List<AnalysisError> errors = <AnalysisError>[];
     for (AnalysisDriverUnitError error in serialized) {
-      String errorName = error.uniqueName;
-      ErrorCode errorCode =
-          errorCodeByUniqueName(errorName) ?? _lintCodeByUniqueName(errorName);
-      if (errorCode == null) {
-        // This could fail because the error code is no longer defined, or, in
-        // the case of a lint rule, if the lint rule has been disabled since the
-        // errors were written.
-        AnalysisEngine.instance.instrumentationService
-            .logError('No error code for "$error" in "$file"');
-      } else {
-        List<DiagnosticMessageImpl> contextMessages;
-        if (error.contextMessages.isNotEmpty) {
-          contextMessages = <DiagnosticMessageImpl>[];
-          for (var message in error.contextMessages) {
-            contextMessages.add(DiagnosticMessageImpl(
-                filePath: message.filePath,
-                length: message.length,
-                message: message.message,
-                offset: message.offset));
-          }
-        }
-        errors.add(AnalysisError.forValues(
-            file.source,
-            error.offset,
-            error.length,
-            errorCode,
-            error.message,
-            error.correction.isEmpty ? null : error.correction,
-            contextMessages: contextMessages ?? const []));
+      var analysisError = ErrorEncoding.decode(file.source, error);
+      if (analysisError != null) {
+        errors.add(analysisError);
       }
     }
     return errors;
@@ -1637,24 +1621,6 @@
     return signature.toHex();
   }
 
-  /// Return the lint code with the given [errorName], or `null` if there is no
-  /// lint registered with that name.
-  ErrorCode _lintCodeByUniqueName(String errorName) {
-    const String lintPrefix = 'LintCode.';
-    if (errorName.startsWith(lintPrefix)) {
-      String lintName = errorName.substring(lintPrefix.length);
-      return linter.Registry.ruleRegistry.getRule(lintName)?.lintCode;
-    }
-
-    const String lintPrefixOld = '_LintCode.';
-    if (errorName.startsWith(lintPrefixOld)) {
-      String lintName = errorName.substring(lintPrefixOld.length);
-      return linter.Registry.ruleRegistry.getRule(lintName)?.lintCode;
-    }
-
-    return null;
-  }
-
   /// We detected that one of the required `dart` libraries is missing.
   /// Return the empty analysis result with the error.
   AnalysisResult _newMissingDartLibraryResult(
@@ -1705,24 +1671,7 @@
         : AnalysisDriverUnitIndexBuilder();
     return AnalysisDriverResolvedUnitBuilder(
             errors: errors.map((error) {
-              List<DiagnosticMessageBuilder> contextMessages;
-              if (error.contextMessages != null) {
-                contextMessages = <DiagnosticMessageBuilder>[];
-                for (var message in error.contextMessages) {
-                  contextMessages.add(DiagnosticMessageBuilder(
-                      filePath: message.filePath,
-                      length: message.length,
-                      message: message.message,
-                      offset: message.offset));
-                }
-              }
-              return AnalysisDriverUnitErrorBuilder(
-                  offset: error.offset,
-                  length: error.length,
-                  uniqueName: error.errorCode.uniqueName,
-                  message: error.message,
-                  correction: error.correction,
-                  contextMessages: contextMessages);
+              return ErrorEncoding.encode(error);
             }).toList(),
             index: index)
         .toBuffer();
@@ -2117,6 +2066,94 @@
   void removedDriver(AnalysisDriver driver);
 }
 
+class ErrorEncoding {
+  static AnalysisError decode(
+    Source source,
+    AnalysisDriverUnitError error,
+  ) {
+    String errorName = error.uniqueName;
+    ErrorCode errorCode =
+        errorCodeByUniqueName(errorName) ?? _lintCodeByUniqueName(errorName);
+    if (errorCode == null) {
+      // This could fail because the error code is no longer defined, or, in
+      // the case of a lint rule, if the lint rule has been disabled since the
+      // errors were written.
+      AnalysisEngine.instance.instrumentationService
+          .logError('No error code for "$error" in "$source"');
+      return null;
+    }
+
+    List<DiagnosticMessageImpl> contextMessages;
+    if (error.contextMessages.isNotEmpty) {
+      contextMessages = <DiagnosticMessageImpl>[];
+      for (var message in error.contextMessages) {
+        contextMessages.add(
+          DiagnosticMessageImpl(
+            filePath: message.filePath,
+            length: message.length,
+            message: message.message,
+            offset: message.offset,
+          ),
+        );
+      }
+    }
+
+    return AnalysisError.forValues(
+      source,
+      error.offset,
+      error.length,
+      errorCode,
+      error.message,
+      error.correction.isEmpty ? null : error.correction,
+      contextMessages: contextMessages ?? const [],
+    );
+  }
+
+  static AnalysisDriverUnitErrorBuilder encode(AnalysisError error) {
+    List<DiagnosticMessageBuilder> contextMessages;
+    if (error.contextMessages != null) {
+      contextMessages = <DiagnosticMessageBuilder>[];
+      for (var message in error.contextMessages) {
+        contextMessages.add(
+          DiagnosticMessageBuilder(
+            filePath: message.filePath,
+            length: message.length,
+            message: message.message,
+            offset: message.offset,
+          ),
+        );
+      }
+    }
+
+    return AnalysisDriverUnitErrorBuilder(
+      offset: error.offset,
+      length: error.length,
+      uniqueName: error.errorCode.uniqueName,
+      message: error.message,
+      correction: error.correction,
+      contextMessages: contextMessages,
+    );
+  }
+
+  /// Return the lint code with the given [errorName], or `null` if there is no
+  /// lint registered with that name.
+  static ErrorCode _lintCodeByUniqueName(String errorName) {
+    const String lintPrefix = 'LintCode.';
+    if (errorName.startsWith(lintPrefix)) {
+      String lintName = errorName.substring(lintPrefix.length);
+      return linter.Registry.ruleRegistry.getRule(lintName)?.lintCode;
+    }
+
+    const String lintPrefixOld = '_LintCode.';
+    if (errorName.startsWith(lintPrefixOld)) {
+      String lintName = errorName.substring(lintPrefixOld.length);
+      return linter.Registry.ruleRegistry.getRule(lintName)?.lintCode;
+    }
+
+    return null;
+  }
+}
+
 /// Exception that happened during analysis.
 class ExceptionResult {
   /// The path of the file being analyzed when the [exception] happened.
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index 55646c1..aad02df 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.8.0';
+const _currentVersion = '2.9.0';
 
 /// A map containing information about all known experimental flags.
 const _knownFeatures = <String, 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 f062dd9..ae462be 100644
--- a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
@@ -35,15 +35,14 @@
       return _sdkFeatureSet;
     }
 
-    for (var package in _packages.packages) {
-      if (package.rootFolder.contains(path)) {
-        var languageVersion = package.languageVersion;
-        if (languageVersion == null ||
-            languageVersion == ExperimentStatus.currentVersion) {
-          return _packageDefaultFeatureSet;
-        } else {
-          return _packageDefaultFeatureSet.restrictToVersion(languageVersion);
-        }
+    var package = _packages.packageForPath(path);
+    if (package != null) {
+      var languageVersion = package.languageVersion;
+      if (languageVersion == null ||
+          languageVersion == ExperimentStatus.currentVersion) {
+        return _packageDefaultFeatureSet;
+      } else {
+        return _packageDefaultFeatureSet.restrictToVersion(languageVersion);
       }
     }
 
@@ -52,13 +51,11 @@
 
   /// Return the language version configured for the file.
   Version getLanguageVersion(String path, Uri uri) {
-    for (var package in _packages.packages) {
-      if (package.rootFolder.contains(path)) {
-        var languageVersion = package.languageVersion;
-        if (languageVersion != null) {
-          return languageVersion;
-        }
-        break;
+    var package = _packages.packageForPath(path);
+    if (package != null) {
+      var languageVersion = package.languageVersion;
+      if (languageVersion != null) {
+        return languageVersion;
       }
     }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 4ab24f0..fd5f01c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -239,12 +239,20 @@
       unit.accept(Dart2JSVerifier(errorReporter));
     }
 
-    unit.accept(BestPracticesVerifier(
-        errorReporter, _typeProvider, _libraryElement, unit, file.content,
+    unit.accept(
+      BestPracticesVerifier(
+        errorReporter,
+        _typeProvider,
+        _libraryElement,
+        unit,
+        file.content,
+        declaredVariables: _declaredVariables,
         typeSystem: _typeSystem,
         inheritanceManager: _inheritance,
         resourceProvider: _resourceProvider,
-        analysisOptions: _context.analysisOptions));
+        analysisOptions: _context.analysisOptions,
+      ),
+    );
 
     unit.accept(OverrideVerifier(
       _inheritance,
@@ -403,12 +411,46 @@
     LineInfo lineInfo = _fileToLineInfo[file];
 
     bool isIgnored(AnalysisError error) {
+      var code = error.errorCode;
+      // Don't allow error severity issues to be ignored.
+      if (!code.isIgnorable) {
+        // The [code] is not ignorable, but we've allowed a few "privileged"
+        // cases. Each is annotated with an issue which represents technical
+        // debt. Once cleaned up, we may remove this notion of "privileged".
+        // In the case of [CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY], we may
+        // just decide that it happens enough in tests that it can be declared
+        // an ignorable error, and in practice other back ends will prevent
+        // non-internal code from importing internal code.
+        bool privileged = false;
+
+        if (code == StaticTypeWarningCode.UNDEFINED_FUNCTION ||
+            code == StaticTypeWarningCode.UNDEFINED_PREFIXED_NAME) {
+          // Special case a small number of errors in Flutter code which are
+          // ignored. The erroneous code is found in a conditionally imported
+          // library, which uses a special version of the "dart:ui" library
+          // which the Analyzer does not use during analysis. See
+          // https://github.com/flutter/flutter/issues/52899.
+          if (file.path.contains('flutter')) {
+            privileged = true;
+          }
+        }
+
+        if (code == CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY &&
+            file.path.contains('tests/compiler/dart2js')) {
+          // Special case the dart2js language tests. Some of these import
+          // various internal libraries.
+          privileged = true;
+        }
+
+        if (!privileged) return false;
+      }
+
       int errorLine = lineInfo.getLocation(error.offset).lineNumber;
-      String name = error.errorCode.name.toLowerCase();
+      String name = code.name.toLowerCase();
       if (ignoreInfo.ignoredAt(name, errorLine)) {
         return true;
       }
-      String uniqueName = error.errorCode.uniqueName;
+      String uniqueName = code.uniqueName;
       int period = uniqueName.indexOf('.');
       if (period >= 0) {
         uniqueName = uniqueName.substring(period + 1);
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 066e416..d34a7ce 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -39,8 +39,8 @@
   /// The cache of libraries for URIs.
   final Map<String, LibraryElement> _uriToLibraryCache = {};
 
-  final ClassHierarchy classHierarchy = ClassHierarchy();
-  final InheritanceManager3 inheritanceManager = InheritanceManager3();
+  ClassHierarchy classHierarchy = ClassHierarchy();
+  InheritanceManager3 inheritanceManager = InheritanceManager3();
 
   /// Initialize a newly created analysis session.
   AnalysisSessionImpl(this._driver);
@@ -94,6 +94,12 @@
     return _uriConverter ??= DriverBasedUriConverter(_driver);
   }
 
+  /// Clear hierarchies, to reduce memory consumption.
+  void clearHierarchies() {
+    classHierarchy = ClassHierarchy();
+    inheritanceManager = InheritanceManager3();
+  }
+
   @deprecated
   driver.AnalysisDriver getDriver() => _driver;
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 8c31220..8bac535 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -2031,18 +2031,6 @@
   int languageVersionMinor;
 
   @override
-  LanguageVersionToken get languageVersionToken {
-    CommentToken comment = beginToken.precedingComments;
-    while (comment != null) {
-      if (comment is LanguageVersionToken) {
-        return comment;
-      }
-      comment = comment.next;
-    }
-    return null;
-  }
-
-  @override
   final FeatureSet featureSet;
 
   /// Initialize a newly created compilation unit to have the given directives
@@ -2085,6 +2073,18 @@
   }
 
   @override
+  LanguageVersionToken get languageVersionToken {
+    CommentToken comment = beginToken.precedingComments;
+    while (comment != null) {
+      if (comment is LanguageVersionToken) {
+        return comment;
+      }
+      comment = comment.next;
+    }
+    return null;
+  }
+
+  @override
   int get length {
     Token endToken = this.endToken;
     if (endToken == null) {
@@ -2385,6 +2385,10 @@
         case CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL:
         case CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL:
         case CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL:
+        case CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT:
+        case CompileTimeErrorCode.NON_CONSTANT_MAP_KEY:
+        case CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE:
+        case CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT:
           hasConstError = true;
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index f5af931..189fe9f 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -380,7 +380,10 @@
   }
 
   void _reportNotPotentialConstants(AstNode node) {
-    var notPotentiallyConstants = getNotPotentiallyConstants(node);
+    var notPotentiallyConstants = getNotPotentiallyConstants(
+      node,
+      isNonNullableByDefault: _isNonNullableByDefault,
+    );
     if (notPotentiallyConstants.isEmpty) return;
 
     for (var notConst in notPotentiallyConstants) {
@@ -750,7 +753,10 @@
 
   /// Return `true` if the [node] is a potential constant.
   bool _reportNotPotentialConstants(AstNode node) {
-    var notPotentiallyConstants = getNotPotentiallyConstants(node);
+    var notPotentiallyConstants = getNotPotentiallyConstants(
+      node,
+      isNonNullableByDefault: verifier._isNonNullableByDefault,
+    );
     if (notPotentiallyConstants.isEmpty) return true;
 
     for (var notConst in notPotentiallyConstants) {
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 3c58f20..7d7607e 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -19,12 +19,12 @@
 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';
 import 'package:analyzer/src/dart/constant/utilities.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/element/type_visitor.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -251,11 +251,11 @@
       Annotation constNode = constant.annotationAst;
       Element element = constant.element;
       if (element is PropertyAccessorElement &&
-          element.variable is VariableElementImpl) {
+          element.variable is VariableElement) {
         // The annotation is a reference to a compile-time constant variable.
         // Just copy the evaluation result.
         VariableElementImpl variableElement =
-            element.variable as VariableElementImpl;
+            element.variable.declaration as VariableElementImpl;
         if (variableElement.evaluationResult != null) {
           constant.evaluationResult = variableElement.evaluationResult;
         } else {
@@ -381,14 +381,14 @@
       Annotation constNode = constant.annotationAst;
       Element element = constant.element;
       if (element is PropertyAccessorElement &&
-          element.variable is VariableElementImpl) {
+          element.variable is VariableElement) {
         // The annotation is a reference to a compile-time constant variable,
         // so it depends on the variable.
-        callback(element.variable);
-      } else if (element is ConstructorElementImpl) {
+        callback(element.variable.declaration);
+      } else if (element is ConstructorElement) {
         // The annotation is a constructor invocation, so it depends on the
         // constructor.
-        callback(element);
+        callback(element.declaration);
       } else {
         // This could happen in the event of invalid code.  The error will be
         // reported at constant evaluation time.
@@ -981,6 +981,8 @@
   /// Convenience getter to gain access to the [evaluationEngine]'s type system.
   TypeSystemImpl get typeSystem => evaluationEngine.typeSystem;
 
+  bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
+
   /// Convenience getter to gain access to the [evaluationEngine]'s type
   /// provider.
   TypeProvider get _typeProvider => evaluationEngine.typeProvider;
@@ -1468,7 +1470,7 @@
   @override
   DartObjectImpl visitTypeName(TypeName node) {
     var type = node.type;
-    if (_hasTypeParameterReference(type)) {
+    if (!_isNonNullableByDefault && hasTypeParameterReference(type)) {
       return super.visitTypeName(node);
     }
     return DartObjectImpl(
@@ -1637,7 +1639,7 @@
         element is PropertyAccessorElement ? element.variable : element;
 
     if (node is SimpleIdentifier &&
-        (node.tearOffTypeArgumentTypes?.any(_hasAppliedTypeParameters) ??
+        (node.tearOffTypeArgumentTypes?.any(hasTypeParameterReference) ??
             false)) {
       _error(node, null);
     }
@@ -1707,13 +1709,6 @@
     return null;
   }
 
-  /// Check if any type parameters are referenced by [type], which is an error.
-  bool _hasAppliedTypeParameters(DartType type) {
-    final visitor = _ReferencesTypeParameterVisitor();
-    DartTypeVisitor.visit(type, visitor);
-    return visitor.result;
-  }
-
   /// Return `true` if the given [targetResult] represents a string and the
   /// [identifier] is "length".
   bool _isStringLength(
@@ -1726,7 +1721,10 @@
   }
 
   void _reportNotPotentialConstants(AstNode node) {
-    var notPotentiallyConstants = getNotPotentiallyConstants(node);
+    var notPotentiallyConstants = getNotPotentiallyConstants(
+      node,
+      isNonNullableByDefault: _isNonNullableByDefault,
+    );
     if (notPotentiallyConstants.isEmpty) return;
 
     for (var notConst in notPotentiallyConstants) {
@@ -1746,18 +1744,6 @@
     }
     return evaluationEngine._nullObject;
   }
-
-  /// Return `true` if the [type] has a type parameter reference, so is not
-  /// valid in a constant context.
-  static bool _hasTypeParameterReference(DartType type) {
-    if (type is TypeParameterType) {
-      return true;
-    }
-    if (type is ParameterizedType) {
-      return type.typeArguments.any(_hasTypeParameterReference);
-    }
-    return false;
-  }
 }
 
 /// A utility class that contains methods for manipulating instances of a Dart
@@ -2255,24 +2241,3 @@
     return value.toString();
   }
 }
-
-/// A visitor to find if a type contains any [TypeParameterType]s.
-///
-/// To find the result, check [result] on this instance after visiting the tree.
-/// The actual value returned by the visit methods is merely used so that
-/// [RecursiveTypeVisitor] stops visiting the type once the first type parameter
-/// type is found.
-class _ReferencesTypeParameterVisitor extends RecursiveTypeVisitor {
-  /// The result of whether any type parameters were found.
-  bool result = false;
-
-  @override
-  bool defaultDartType(_) => true;
-
-  @override
-  bool visitTypeParameterType(_) {
-    result = true;
-    // Stop visiting at this point.
-    return false;
-  } // Continue visiting in this case.
-}
diff --git a/pkg/analyzer/lib/src/dart/constant/has_type_parameter_reference.dart b/pkg/analyzer/lib/src/dart/constant/has_type_parameter_reference.dart
new file mode 100644
index 0000000..0aa6243
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/has_type_parameter_reference.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:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_visitor.dart';
+
+/// Return `true` if the [type] has a type parameter reference.
+bool hasTypeParameterReference(DartType type) {
+  var visitor = _ReferencesTypeParameterVisitor();
+  DartTypeVisitor.visit(type, visitor);
+  return visitor.result;
+}
+
+/// A visitor to find if a type contains any [TypeParameterType]s.
+///
+/// To find the result, check [result] on this instance after visiting the tree.
+///
+/// The actual value returned by the visit methods is merely used so that
+/// [RecursiveTypeVisitor] stops visiting the type once the first type parameter
+/// type is found.
+class _ReferencesTypeParameterVisitor extends RecursiveTypeVisitor {
+  /// The result of whether any type parameters were found.
+  bool result = false;
+
+  @override
+  bool defaultDartType(_) => true;
+
+  @override
+  bool visitTypeParameterType(_) {
+    result = true;
+    // Stop visiting at this point.
+    return false;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
index ba05758..82bbe07 100644
--- a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
+++ b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:meta/meta.dart';
 
 /// Some [ConstructorElement]s can be temporary marked as "const" to check
 /// if doing this is valid.
@@ -14,8 +15,13 @@
 /// Check if the [node] and all its sub-nodes are potentially constant.
 ///
 /// Return the list of nodes that are not potentially constant.
-List<AstNode> getNotPotentiallyConstants(AstNode node) {
-  var collector = _Collector();
+List<AstNode> getNotPotentiallyConstants(
+  AstNode node, {
+  @required bool isNonNullableByDefault,
+}) {
+  var collector = _Collector(
+    isNonNullableByDefault: isNonNullableByDefault,
+  );
   collector.collect(node);
   return collector.nodes;
 }
@@ -78,6 +84,18 @@
   return false;
 }
 
+/// Return `true` if the [node] is a potentially constant type expression.
+bool isPotentiallyConstantTypeExpression(TypeAnnotation node) {
+  if (node is TypeName) {
+    var element = node.name.staticElement;
+    if (element is TypeParameterElement) {
+      return true;
+    }
+  }
+
+  return isConstantTypeExpression(node);
+}
+
 bool _isConstantTypeName(Identifier name) {
   var element = name.staticElement;
   if (element is ClassElement || element is GenericTypeAliasElement) {
@@ -92,8 +110,11 @@
 }
 
 class _Collector {
+  final bool isNonNullableByDefault;
   final List<AstNode> nodes = [];
 
+  _Collector({@required this.isNonNullableByDefault});
+
   void collect(AstNode node) {
     if (node is BooleanLiteral ||
         node is DoubleLiteral ||
@@ -178,16 +199,28 @@
     }
 
     if (node is AsExpression) {
-      if (!isConstantTypeExpression(node.type)) {
-        nodes.add(node.type);
+      if (isNonNullableByDefault) {
+        if (!isPotentiallyConstantTypeExpression(node.type)) {
+          nodes.add(node.type);
+        }
+      } else {
+        if (!isConstantTypeExpression(node.type)) {
+          nodes.add(node.type);
+        }
       }
       collect(node.expression);
       return;
     }
 
     if (node is IsExpression) {
-      if (!isConstantTypeExpression(node.type)) {
-        nodes.add(node.type);
+      if (isNonNullableByDefault) {
+        if (!isPotentiallyConstantTypeExpression(node.type)) {
+          nodes.add(node.type);
+        }
+      } else {
+        if (!isConstantTypeExpression(node.type)) {
+          nodes.add(node.type);
+        }
       }
       collect(node.expression);
       return;
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index fcaf659..2e000e5 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/constant/has_type_parameter_reference.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
@@ -262,7 +263,16 @@
     if (isNull) {
       return this;
     }
-    if (!typeSystem.isSubtypeOf2(type, (castType._state as TypeState)._type)) {
+
+    var resultType = (castType._state as TypeState)._type;
+
+    // We don't know the actual value of a type parameter.
+    // So, the object type might be a subtype of the result type.
+    if (hasTypeParameterReference(resultType)) {
+      return this;
+    }
+
+    if (!typeSystem.isSubtypeOf2(type, resultType)) {
       throw EvaluationException(
           CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
     }
diff --git a/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart b/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
index a02599d..543e4ba 100644
--- a/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
+++ b/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
@@ -7,18 +7,32 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:meta/meta.dart';
 
 class ClassHierarchy {
   final Map<ClassElement, _Hierarchy> _map = {};
 
+  List<ClassHierarchyError> errors(ClassElement element) {
+    return _getHierarchy(element).errors;
+  }
+
   List<InterfaceType> implementedInterfaces(ClassElement element) {
+    return _getHierarchy(element).interfaces;
+  }
+
+  void remove(ClassElement element) {
+    _map.remove(element);
+  }
+
+  _Hierarchy _getHierarchy(ClassElement element) {
     var hierarchy = _map[element];
 
     if (hierarchy != null) {
-      return hierarchy.interfaces;
+      return hierarchy;
     }
 
     hierarchy = _Hierarchy(
+      errors: const <ClassHierarchyError>[],
       interfaces: const <InterfaceType>[],
     );
     _map[element] = hierarchy;
@@ -29,16 +43,12 @@
 
     void appendOne(InterfaceType type) {
       var element = type.element;
-      if (library.isNonNullableByDefault) {
-        var classResult = map[element];
-        if (classResult == null) {
-          classResult = _ClassInterfaceType(typeSystem);
-          map[element] = classResult;
-        }
-        classResult.update(type);
-      } else {
-        map[element] ??= _ClassInterfaceType(typeSystem)..update(type);
+      var classResult = map[element];
+      if (classResult == null) {
+        classResult = _ClassInterfaceType(typeSystem);
+        map[element] = classResult;
       }
+      classResult.update(type);
     }
 
     void append(InterfaceType type) {
@@ -68,43 +78,101 @@
       append(type);
     }
 
-    var result = map.values.map((e) => e.type).toList(growable: false);
-    hierarchy.interfaces = result;
-    return result;
+    var errors = <ClassHierarchyError>[];
+    var interfaces = <InterfaceType>[];
+    for (var collector in map.values) {
+      if (collector._error != null) {
+        errors.add(collector._error);
+      }
+      interfaces.add(collector.type);
+    }
+
+    hierarchy.errors = errors;
+    hierarchy.interfaces = interfaces;
+
+    return hierarchy;
   }
 }
 
+abstract class ClassHierarchyError {}
+
+/// This error is recorded when the same generic class is found in the
+/// hierarchy of a class, and the type arguments are not compatible. What it
+/// means to be compatible depends on whether the class is declared in a
+/// legacy, or an opted-in library.
+///
+/// In legacy libraries LEGACY_ERASURE of the interfaces must be syntactically
+/// equal.
+///
+/// In opted-in libraries NNBD_TOP_MERGE of NORM of the interfaces must be
+/// successful.
+class IncompatibleInterfacesClassHierarchyError extends ClassHierarchyError {
+  final InterfaceType first;
+  final InterfaceType second;
+
+  IncompatibleInterfacesClassHierarchyError(this.first, this.second);
+}
+
 class _ClassInterfaceType {
   final TypeSystemImpl _typeSystem;
 
-  InterfaceType _notNormalized;
-  InterfaceType _currentMerge;
+  ClassHierarchyError _error;
+
+  InterfaceType _singleType;
+  InterfaceType _currentResult;
 
   _ClassInterfaceType(this._typeSystem);
 
-  InterfaceType get type => _currentMerge ?? _notNormalized;
+  InterfaceType get type => _currentResult ?? _singleType;
 
   void update(InterfaceType type) {
-    if (_currentMerge == null) {
-      if (_notNormalized == null) {
-        _notNormalized = type;
-        return;
-      } else {
-        _currentMerge = _typeSystem.normalize(_notNormalized);
-      }
+    if (_error != null) {
+      return;
     }
 
-    var normType = _typeSystem.normalize(type);
-    try {
-      _currentMerge = _typeSystem.topMerge(_currentMerge, normType);
-    } catch (e) {
-      // ignored
+    if (_typeSystem.isNonNullableByDefault) {
+      if (_currentResult == null) {
+        if (_singleType == null) {
+          _singleType = type;
+          return;
+        } else if (type == _singleType) {
+          return;
+        } else {
+          _currentResult = _typeSystem.normalize(_singleType);
+        }
+      }
+
+      var normType = _typeSystem.normalize(type);
+      try {
+        _currentResult = _typeSystem.topMerge(_currentResult, normType);
+      } catch (e) {
+        _error = IncompatibleInterfacesClassHierarchyError(
+          _currentResult,
+          type,
+        );
+      }
+    } else {
+      var legacyType = _typeSystem.toLegacyType(type);
+      if (_currentResult == null) {
+        _currentResult = legacyType;
+      } else {
+        if (legacyType != _currentResult) {
+          _error = IncompatibleInterfacesClassHierarchyError(
+            _currentResult,
+            legacyType,
+          );
+        }
+      }
     }
   }
 }
 
 class _Hierarchy {
+  List<ClassHierarchyError> errors;
   List<InterfaceType> interfaces;
 
-  _Hierarchy({this.interfaces});
+  _Hierarchy({
+    @required this.errors,
+    @required this.interfaces,
+  });
 }
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
new file mode 100644
index 0000000..076a6f4
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -0,0 +1,990 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+import 'dart:math' as math;
+
+import 'package:analyzer/dart/ast/ast.dart' show AstNode, ConstructorName;
+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/error/listener.dart' show ErrorReporter;
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/nullability_eliminator.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_schema.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/error/codes.dart' show HintCode, StrongModeCode;
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:meta/meta.dart';
+
+bool _isBottom(DartType t) {
+  return (t.isBottom && t.nullabilitySuffix != NullabilitySuffix.question) ||
+      identical(t, UnknownInferredType.instance);
+}
+
+/// Is [t] the bottom of the legacy type hierarchy.
+bool _isLegacyBottom(DartType t, {@required bool orTrueBottom}) {
+  return (t.isBottom && t.nullabilitySuffix == NullabilitySuffix.question) ||
+      t.isDartCoreNull ||
+      (orTrueBottom ? _isBottom(t) : false);
+}
+
+/// Is [t] the top of the legacy type hierarch.
+bool _isLegacyTop(DartType t, {@required bool orTrueTop}) {
+  if (t.isDartAsyncFutureOr) {
+    return _isLegacyTop((t as InterfaceType).typeArguments[0],
+        orTrueTop: orTrueTop);
+  }
+  if (t.isObject && t.nullabilitySuffix == NullabilitySuffix.none) {
+    return true;
+  }
+  return orTrueTop ? _isTop(t) : false;
+}
+
+bool _isTop(DartType t) {
+  if (t.isDartAsyncFutureOr) {
+    return _isTop((t as InterfaceType).typeArguments[0]);
+  }
+  return t.isDynamic ||
+      (t.isObject && t.nullabilitySuffix != NullabilitySuffix.none) ||
+      t.isVoid ||
+      identical(t, UnknownInferredType.instance);
+}
+
+/// Tracks upper and lower type bounds for a set of type parameters.
+///
+/// This class is used by calling [isSubtypeOf]. When it encounters one of
+/// the type parameters it is inferring, it will record the constraint, and
+/// optimistically assume the constraint will be satisfied.
+///
+/// For example if we are inferring type parameter A, and we ask if
+/// `A <: num`, this will record that A must be a subytpe of `num`. It also
+/// handles cases when A appears as part of the structure of another type, for
+/// example `Iterable<A> <: Iterable<num>` would infer the same constraint
+/// (due to covariant generic types) as would `() -> A <: () -> num`. In
+/// contrast `(A) -> void <: (num) -> void`.
+///
+/// Once the lower/upper bounds are determined, [infer] should be called to
+/// finish the inference. It will instantiate a generic function type with the
+/// inferred types for each type parameter.
+///
+/// It can also optionally compute a partial solution, in case some of the type
+/// parameters could not be inferred (because the constraints cannot be
+/// satisfied), or bail on the inference when this happens.
+///
+/// As currently designed, an instance of this class should only be used to
+/// infer a single call and discarded immediately afterwards.
+class GenericInferrer {
+  final TypeSystemImpl _typeSystem;
+  final Map<TypeParameterElement, List<_TypeConstraint>> constraints = {};
+
+  /// Buffer recording constraints recorded while performing a recursive call to
+  /// [_matchSubtypeOf] that might fail, so that any constraints recorded during
+  /// the failed match can be rewound.
+  final _undoBuffer = <_TypeConstraint>[];
+
+  GenericInferrer(
+    this._typeSystem,
+    Iterable<TypeParameterElement> typeFormals,
+  ) {
+    for (var formal in typeFormals) {
+      constraints[formal] = [];
+    }
+  }
+
+  bool get isNonNullableByDefault => _typeSystem.isNonNullableByDefault;
+
+  TypeProvider get typeProvider => _typeSystem.typeProvider;
+
+  /// Apply an argument constraint, which asserts that the [argument] staticType
+  /// is a subtype of the [parameterType].
+  void constrainArgument(
+      DartType argumentType, DartType parameterType, String parameterName,
+      {ClassElement genericClass}) {
+    var origin = _TypeConstraintFromArgument(
+      argumentType,
+      parameterType,
+      parameterName,
+      genericClass: genericClass,
+      isNonNullableByDefault: isNonNullableByDefault,
+    );
+    tryMatchSubtypeOf(argumentType, parameterType, origin, covariant: false);
+  }
+
+  /// Constrain a universal function type [fnType] used in a context
+  /// [contextType].
+  void constrainGenericFunctionInContext(
+      FunctionType fnType, DartType contextType) {
+    var origin = _TypeConstraintFromFunctionContext(
+      fnType,
+      contextType,
+      isNonNullableByDefault: isNonNullableByDefault,
+    );
+
+    // Since we're trying to infer the instantiation, we want to ignore type
+    // formals as we check the parameters and return type.
+    var inferFnType = FunctionTypeImpl(
+      typeFormals: const [],
+      parameters: fnType.parameters,
+      returnType: fnType.returnType,
+      nullabilitySuffix: fnType.nullabilitySuffix,
+    );
+    tryMatchSubtypeOf(inferFnType, contextType, origin, covariant: true);
+  }
+
+  /// Apply a return type constraint, which asserts that the [declaredType]
+  /// is a subtype of the [contextType].
+  void constrainReturnType(DartType declaredType, DartType contextType) {
+    var origin = _TypeConstraintFromReturnType(
+      declaredType,
+      contextType,
+      isNonNullableByDefault: isNonNullableByDefault,
+    );
+    tryMatchSubtypeOf(declaredType, contextType, origin, covariant: true);
+  }
+
+  /// Given the constraints that were given by calling [constrainArgument] and
+  /// [constrainReturnType], find the type arguments for the [typeFormals] that
+  /// satisfies these constraints.
+  ///
+  /// If [downwardsInferPhase] is set, we are in the first pass of inference,
+  /// pushing context types down. At that point we are allowed to push down
+  /// `?` to precisely represent an unknown type. If [downwardsInferPhase] is
+  /// false, we are on our final inference pass, have all available information
+  /// including argument types, and must not conclude `?` for any type formal.
+  List<DartType> infer(List<TypeParameterElement> typeFormals,
+      {bool considerExtendsClause = true,
+      ErrorReporter errorReporter,
+      AstNode errorNode,
+      bool failAtError = false,
+      bool downwardsInferPhase = false}) {
+    // Initialize the inferred type array.
+    //
+    // In the downwards phase, they all start as `?` to offer reasonable
+    // degradation for f-bounded type parameters.
+    var inferredTypes =
+        List<DartType>.filled(typeFormals.length, UnknownInferredType.instance);
+
+    for (int i = 0; i < typeFormals.length; i++) {
+      // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+      // variance is added to the interface.
+      TypeParameterElementImpl typeParam = typeFormals[i];
+      _TypeConstraint extendsClause;
+      if (considerExtendsClause && typeParam.bound != null) {
+        extendsClause = _TypeConstraint.fromExtends(
+          typeParam,
+          Substitution.fromPairs(typeFormals, inferredTypes)
+              .substituteType(typeParam.bound),
+          isNonNullableByDefault: isNonNullableByDefault,
+        );
+      }
+
+      inferredTypes[i] = downwardsInferPhase
+          ? _inferTypeParameterFromContext(
+              constraints[typeParam], extendsClause,
+              isContravariant: typeParam.variance.isContravariant)
+          : _inferTypeParameterFromAll(constraints[typeParam], extendsClause,
+              isContravariant: typeParam.variance.isContravariant,
+              preferUpwardsInference: !typeParam.isLegacyCovariant);
+    }
+
+    // If the downwards infer phase has failed, we'll catch this in the upwards
+    // phase later on.
+    if (downwardsInferPhase) {
+      return inferredTypes;
+    }
+
+    // Check the inferred types against all of the constraints.
+    var knownTypes = <TypeParameterElement, DartType>{};
+    for (int i = 0; i < typeFormals.length; i++) {
+      TypeParameterElement typeParam = typeFormals[i];
+      var constraints = this.constraints[typeParam];
+      var typeParamBound = typeParam.bound != null
+          ? Substitution.fromPairs(typeFormals, inferredTypes)
+              .substituteType(typeParam.bound)
+          : typeProvider.dynamicType;
+
+      var inferred = inferredTypes[i];
+      bool success =
+          constraints.every((c) => c.isSatisifedBy(_typeSystem, inferred));
+      if (success && !typeParamBound.isDynamic) {
+        // If everything else succeeded, check the `extends` constraint.
+        var extendsConstraint = _TypeConstraint.fromExtends(
+          typeParam,
+          typeParamBound,
+          isNonNullableByDefault: isNonNullableByDefault,
+        );
+        constraints.add(extendsConstraint);
+        success = extendsConstraint.isSatisifedBy(_typeSystem, inferred);
+      }
+
+      if (!success) {
+        if (failAtError) return null;
+        errorReporter?.reportErrorForNode(
+            StrongModeCode.COULD_NOT_INFER,
+            errorNode,
+            [typeParam.name, _formatError(typeParam, inferred, constraints)]);
+
+        // Heuristic: even if we failed, keep the erroneous type.
+        // It should satisfy at least some of the constraints (e.g. the return
+        // context). If we fall back to instantiateToBounds, we'll typically get
+        // more errors (e.g. because `dynamic` is the most common bound).
+      }
+
+      if (inferred is FunctionType && inferred.typeFormals.isNotEmpty) {
+        if (failAtError) return null;
+        var typeFormals = (inferred as FunctionType).typeFormals;
+        var typeFormalsStr = typeFormals.map(_elementStr).join(', ');
+        errorReporter
+            ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
+          typeParam.name,
+          ' Inferred candidate type ${_typeStr(inferred)} has type parameters'
+              ' [$typeFormalsStr], but a function with'
+              ' type parameters cannot be used as a type argument.'
+        ]);
+
+        // Heuristic: Using a generic function type as a bound makes subtyping
+        // undecidable. Therefore, we cannot keep [inferred] unless we wish to
+        // generate bogus subtyping errors. Instead generate plain [Function],
+        // which is the most general function type.
+        inferred = typeProvider.functionType;
+      }
+
+      if (UnknownInferredType.isKnown(inferred)) {
+        knownTypes[typeParam] = inferred;
+      } else if (_typeSystem.strictInference) {
+        // [typeParam] could not be inferred. A result will still be returned
+        // by [infer], with [typeParam] filled in as its bounds. This is
+        // considered a failure of inference, under the "strict-inference"
+        // mode.
+        if (errorNode is ConstructorName) {
+          String constructorName = '${errorNode.type}.${errorNode.name}';
+          errorReporter?.reportErrorForNode(
+              HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,
+              errorNode,
+              [constructorName]);
+        }
+        // TODO(srawlins): More inference failure cases, like functions, and
+        // function expressions.
+      }
+    }
+
+    // Use instantiate to bounds to finish things off.
+    var hasError = List<bool>.filled(typeFormals.length, false);
+    var result = _typeSystem.instantiateTypeFormalsToBounds(typeFormals,
+        hasError: hasError, knownTypes: knownTypes);
+
+    // Report any errors from instantiateToBounds.
+    for (int i = 0; i < hasError.length; i++) {
+      if (hasError[i]) {
+        if (failAtError) return null;
+        TypeParameterElement typeParam = typeFormals[i];
+        var typeParamBound = Substitution.fromPairs(typeFormals, inferredTypes)
+            .substituteType(typeParam.bound ?? typeProvider.objectType);
+        // TODO(jmesserly): improve this error message.
+        errorReporter
+            ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
+          typeParam.name,
+          "\nRecursive bound cannot be instantiated: '$typeParamBound'."
+              "\nConsider passing explicit type argument(s) "
+              "to the generic.\n\n'"
+        ]);
+      }
+    }
+
+    return result;
+  }
+
+  /// Tries to make [i1] a subtype of [i2] and accumulate constraints as needed.
+  ///
+  /// The return value indicates whether the match was successful.  If it was
+  /// unsuccessful, any constraints that were accumulated during the match
+  /// attempt have been rewound (see [_rewindConstraints]).
+  bool tryMatchSubtypeOf(DartType t1, DartType t2, _TypeConstraintOrigin origin,
+      {@required bool covariant}) {
+    int previousRewindBufferLength = _undoBuffer.length;
+    bool success = _matchSubtypeOf(t1, t2, null, origin, covariant: covariant);
+    if (!success) {
+      _rewindConstraints(previousRewindBufferLength);
+    }
+    return success;
+  }
+
+  /// Choose the bound that was implied by the return type, if any.
+  ///
+  /// Which bound this is depends on what positions the type parameter
+  /// appears in. If the type only appears only in a contravariant position,
+  /// we will choose the lower bound instead.
+  ///
+  /// For example given:
+  ///
+  ///     Func1<T, bool> makeComparer<T>(T x) => (T y) => x() == y;
+  ///
+  ///     main() {
+  ///       Func1<num, bool> t = makeComparer/* infer <num> */(42);
+  ///       print(t(42.0)); /// false, no error.
+  ///     }
+  ///
+  /// The constraints we collect are:
+  ///
+  /// * `num <: T`
+  /// * `int <: T`
+  ///
+  /// ... and no upper bound. Therefore the lower bound is the best choice.
+  ///
+  /// If [isContravariant] is `true`, then we are solving for a contravariant
+  /// type parameter which means we choose the upper bound rather than the
+  /// lower bound for normally covariant type parameters.
+  DartType _chooseTypeFromConstraints(Iterable<_TypeConstraint> constraints,
+      {bool toKnownType = false, @required bool isContravariant}) {
+    DartType lower = UnknownInferredType.instance;
+    DartType upper = UnknownInferredType.instance;
+    for (var constraint in constraints) {
+      // Given constraints:
+      //
+      //     L1 <: T <: U1
+      //     L2 <: T <: U2
+      //
+      // These can be combined to produce:
+      //
+      //     LUB(L1, L2) <: T <: GLB(U1, U2).
+      //
+      // This can then be done for all constraints in sequence.
+      //
+      // This resulting constraint may be unsatisfiable; in that case inference
+      // will fail.
+      upper = _typeSystem.getGreatestLowerBound(upper, constraint.upperBound);
+      lower = _typeSystem.getLeastUpperBound(lower, constraint.lowerBound);
+      upper = _toLegacyType(upper);
+      lower = _toLegacyType(lower);
+    }
+
+    // Prefer the known bound, if any.
+    // Otherwise take whatever bound has partial information, e.g. `Iterable<?>`
+    //
+    // For both of those, prefer the lower bound (arbitrary heuristic) or upper
+    // bound if [isContravariant] is `true`
+    if (isContravariant) {
+      if (UnknownInferredType.isKnown(upper)) {
+        return upper;
+      }
+      if (UnknownInferredType.isKnown(lower)) {
+        return lower;
+      }
+      if (!identical(UnknownInferredType.instance, upper)) {
+        return toKnownType ? _typeSystem.greatestClosure(upper) : upper;
+      }
+      if (!identical(UnknownInferredType.instance, lower)) {
+        return toKnownType ? _typeSystem.leastClosure(lower) : lower;
+      }
+      return upper;
+    } else {
+      if (UnknownInferredType.isKnown(lower)) {
+        return lower;
+      }
+      if (UnknownInferredType.isKnown(upper)) {
+        return upper;
+      }
+      if (!identical(UnknownInferredType.instance, lower)) {
+        return toKnownType ? _typeSystem.leastClosure(lower) : lower;
+      }
+      if (!identical(UnknownInferredType.instance, upper)) {
+        return toKnownType ? _typeSystem.greatestClosure(upper) : upper;
+      }
+      return lower;
+    }
+  }
+
+  String _elementStr(Element element) {
+    return element.getDisplayString(withNullability: isNonNullableByDefault);
+  }
+
+  String _formatError(TypeParameterElement typeParam, DartType inferred,
+      Iterable<_TypeConstraint> constraints) {
+    var inferredStr = inferred.getDisplayString(
+      withNullability: isNonNullableByDefault,
+    );
+    var intro = "Tried to infer '$inferredStr' for '${typeParam.name}'"
+        " which doesn't work:";
+
+    var constraintsByOrigin = <_TypeConstraintOrigin, List<_TypeConstraint>>{};
+    for (var c in constraints) {
+      constraintsByOrigin.putIfAbsent(c.origin, () => []).add(c);
+    }
+
+    // Only report unique constraint origins.
+    Iterable<_TypeConstraint> isSatisified(bool expected) => constraintsByOrigin
+        .values
+        .where((l) =>
+            l.every((c) => c.isSatisifedBy(_typeSystem, inferred)) == expected)
+        .expand((i) => i);
+
+    String unsatisified = _formatConstraints(isSatisified(false));
+    String satisified = _formatConstraints(isSatisified(true));
+
+    assert(unsatisified.isNotEmpty);
+    if (satisified.isNotEmpty) {
+      satisified = "\nThe type '$inferredStr' was inferred from:\n$satisified";
+    }
+
+    return '\n\n$intro\n$unsatisified$satisified\n\n'
+        'Consider passing explicit type argument(s) to the generic.\n\n';
+  }
+
+  DartType _inferTypeParameterFromAll(
+      List<_TypeConstraint> constraints, _TypeConstraint extendsClause,
+      {@required bool isContravariant, @required bool preferUpwardsInference}) {
+    // See if we already fixed this type from downwards inference.
+    // If so, then we aren't allowed to change it based on argument types unless
+    // [preferUpwardsInference] is true.
+    DartType t = _inferTypeParameterFromContext(
+        constraints.where((c) => c.isDownwards), extendsClause,
+        isContravariant: isContravariant);
+    if (!preferUpwardsInference && UnknownInferredType.isKnown(t)) {
+      // Remove constraints that aren't downward ones; we'll ignore these for
+      // error reporting, because inference already succeeded.
+      constraints.removeWhere((c) => !c.isDownwards);
+      return t;
+    }
+
+    if (extendsClause != null) {
+      constraints = constraints.toList()..add(extendsClause);
+    }
+
+    var choice = _chooseTypeFromConstraints(constraints,
+        toKnownType: true, isContravariant: isContravariant);
+    return choice;
+  }
+
+  DartType _inferTypeParameterFromContext(
+      Iterable<_TypeConstraint> constraints, _TypeConstraint extendsClause,
+      {@required bool isContravariant}) {
+    DartType t = _chooseTypeFromConstraints(constraints,
+        isContravariant: isContravariant);
+    if (UnknownInferredType.isUnknown(t)) {
+      return t;
+    }
+
+    // If we're about to make our final choice, apply the extends clause.
+    // This gives us a chance to refine the choice, in case it would violate
+    // the `extends` clause. For example:
+    //
+    //     Object obj = math.min/*<infer Object, error>*/(1, 2);
+    //
+    // If we consider the `T extends num` we conclude `<num>`, which works.
+    if (extendsClause != null) {
+      constraints = constraints.toList()..add(extendsClause);
+      return _chooseTypeFromConstraints(constraints,
+          isContravariant: isContravariant);
+    }
+    return t;
+  }
+
+  /// Tries to make [i1] a subtype of [i2] and accumulate constraints as needed.
+  ///
+  /// The return value indicates whether the match was successful.  If it was
+  /// unsuccessful, the caller is responsible for ignoring any constraints that
+  /// were accumulated (see [_rewindConstraints]).
+  bool _matchInterfaceSubtypeOf(InterfaceType i1, InterfaceType i2,
+      Set<Element> visited, _TypeConstraintOrigin origin,
+      {@required bool covariant}) {
+    if (identical(i1, i2)) {
+      return true;
+    }
+
+    if (i1.element == i2.element) {
+      return _matchInterfaceSubtypeOf2(i1, i2, origin, covariant);
+    }
+
+    for (var interface in i1.element.allSupertypes) {
+      if (interface.element == i2.element) {
+        var substitution = Substitution.fromInterfaceType(i1);
+        var substitutedInterface = substitution.substituteType(interface);
+        return _matchInterfaceSubtypeOf2(
+            substitutedInterface, i2, origin, covariant);
+      }
+    }
+    return false;
+  }
+
+  /// Tries to make [i1] a subtype of [i2] and accumulate constraints as needed.
+  ///
+  /// The return value indicates whether the match was successful.  If it was
+  /// unsuccessful, the caller is responsible for ignoring any constraints that
+  /// were accumulated (see [_rewindConstraints]).
+  ///
+  /// Interfaces [i1] and [i2] are instantiations of the same class element.
+  bool _matchInterfaceSubtypeOf2(InterfaceType i1, InterfaceType i2,
+      _TypeConstraintOrigin origin, bool covariant) {
+    List<DartType> tArgs1 = i1.typeArguments;
+    List<DartType> tArgs2 = i2.typeArguments;
+    List<TypeParameterElement> tParams = i1.element.typeParameters;
+    assert(tArgs1.length == tArgs2.length);
+    assert(tArgs1.length == tParams.length);
+    for (int i = 0; i < tArgs1.length; i++) {
+      TypeParameterElement typeParameterElement = tParams[i];
+
+      // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+      // variance is added to the interface.
+      Variance parameterVariance =
+          (typeParameterElement as TypeParameterElementImpl).variance;
+      if (parameterVariance.isCovariant) {
+        if (!_matchSubtypeOf(tArgs1[i], tArgs2[i], HashSet<Element>(), origin,
+            covariant: covariant)) {
+          return false;
+        }
+      } else if (parameterVariance.isContravariant) {
+        if (!_matchSubtypeOf(tArgs2[i], tArgs1[i], HashSet<Element>(), origin,
+            covariant: !covariant)) {
+          return false;
+        }
+      } else if (parameterVariance.isInvariant) {
+        if (!_matchSubtypeOf(tArgs1[i], tArgs2[i], HashSet<Element>(), origin,
+                covariant: covariant) ||
+            !_matchSubtypeOf(tArgs2[i], tArgs1[i], HashSet<Element>(), origin,
+                covariant: !covariant)) {
+          return false;
+        }
+      } else {
+        throw StateError("Type parameter ${tParams[i]} has unknown "
+            "variance $parameterVariance for inference.");
+      }
+    }
+    return true;
+  }
+
+  /// Assert that [t1] will be a subtype of [t2], and returns if the constraint
+  /// can be satisfied.
+  ///
+  /// [covariant] must be true if [t1] is a declared type of the generic
+  /// function and [t2] is the context type, or false if the reverse. For
+  /// example [covariant] is used when [t1] is the declared return type
+  /// and [t2] is the context type. Contravariant would be used if [t1] is the
+  /// argument type (i.e. passed in to the generic function) and [t2] is the
+  /// declared parameter type.
+  ///
+  /// [origin] indicates where the constraint came from, for example an argument
+  /// or return type.
+  bool _matchSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
+      _TypeConstraintOrigin origin,
+      {@required bool covariant}) {
+    if (covariant && t1 is TypeParameterType) {
+      var constraints = this.constraints[t1.element];
+      if (constraints != null) {
+        if (!identical(t2, UnknownInferredType.instance)) {
+          if (t1.nullabilitySuffix == NullabilitySuffix.question) {
+            t2 = _typeSystem.promoteToNonNull(t2);
+          }
+          var constraint = _TypeConstraint(origin, t1.element, upper: t2);
+          constraints.add(constraint);
+          _undoBuffer.add(constraint);
+        }
+        return true;
+      }
+    }
+    if (!covariant && t2 is TypeParameterType) {
+      var constraints = this.constraints[t2.element];
+      if (constraints != null) {
+        if (!identical(t1, UnknownInferredType.instance)) {
+          if (t2.nullabilitySuffix == NullabilitySuffix.question) {
+            t1 = _typeSystem.promoteToNonNull(t1);
+          }
+          var constraint = _TypeConstraint(origin, t2.element, lower: t1);
+          constraints.add(constraint);
+          _undoBuffer.add(constraint);
+        }
+        return true;
+      }
+    }
+
+    if (identical(t1, t2)) {
+      return true;
+    }
+
+    // TODO(jmesserly): this logic is taken from subtype.
+    bool matchSubtype(DartType t1, DartType t2) {
+      return _matchSubtypeOf(t1, t2, null, origin, covariant: covariant);
+    }
+
+    // Handle FutureOr<T> union type.
+    if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
+      var t1TypeArg = t1.typeArguments[0];
+      if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+        var t2TypeArg = t2.typeArguments[0];
+        // FutureOr<A> <: FutureOr<B> iff A <: B
+        return matchSubtype(t1TypeArg, t2TypeArg);
+      }
+
+      // given t1 is Future<A> | A, then:
+      // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
+      var t1Future = typeProvider.futureType2(t1TypeArg);
+      return matchSubtype(t1Future, t2) && matchSubtype(t1TypeArg, t2);
+    }
+
+    if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+      // given t2 is Future<A> | A, then:
+      // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
+      var t2TypeArg = t2.typeArguments[0];
+      var t2Future = typeProvider.futureType2(t2TypeArg);
+
+      // First we try matching `t1 <: Future<A>`.  If that succeeds *and*
+      // records at least one constraint, then we proceed using that constraint.
+      var previousRewindBufferLength = _undoBuffer.length;
+      var success =
+          tryMatchSubtypeOf(t1, t2Future, origin, covariant: covariant);
+
+      if (_undoBuffer.length != previousRewindBufferLength) {
+        // Trying to match `t1 <: Future<A>` succeeded and recorded constraints,
+        // so those are the constraints we want.
+        return true;
+      } else {
+        // Either `t1 <: Future<A>` failed to match, or it matched trivially
+        // without recording any constraints (e.g. because t1 is `Null`).  We
+        // want constraints, because they let us do more precise inference, so
+        // go ahead and try matching `t1 <: A` to see if it records any
+        // constraints.
+        if (tryMatchSubtypeOf(t1, t2TypeArg, origin, covariant: covariant)) {
+          // Trying to match `t1 <: A` succeeded.  If it recorded constraints,
+          // those are the constraints we want.  If it didn't, then there's no
+          // way we're going to get any constraints.  So either way, we want to
+          // return `true` since the match suceeded and the constraints we want
+          // (if any) have been recorded.
+          return true;
+        } else {
+          // Trying to match `t1 <: A` failed.  So there's no way we are going
+          // to get any constraints.  Just return `success` to indicate whether
+          // the match succeeded.
+          return success;
+        }
+      }
+    }
+
+    // S <: T where S is a type variable
+    //  T is not dynamic or object (handled above)
+    //  True if T == S
+    //  Or true if bound of S is S' and S' <: T
+
+    if (t1 is TypeParameterType) {
+      // Guard against recursive type parameters
+      //
+      // TODO(jmesserly): this function isn't guarding against anything (it's
+      // not passsing down `visitedSet`, so adding the element has no effect).
+      bool guardedSubtype(DartType t1, DartType t2) {
+        var visitedSet = visited ?? HashSet<Element>();
+        if (visitedSet.add(t1.element)) {
+          bool matched = matchSubtype(t1, t2);
+          visitedSet.remove(t1.element);
+          return matched;
+        } else {
+          // In the case of a recursive type parameter, consider the subtype
+          // match to have failed.
+          return false;
+        }
+      }
+
+      if (t2 is TypeParameterType && t1.definition == t2.definition) {
+        return guardedSubtype(t1.bound, t2.bound);
+      }
+      return guardedSubtype(t1.bound, t2);
+    }
+    if (t2 is TypeParameterType) {
+      return false;
+    }
+
+    // TODO(mfairhurst): switch legacy Bottom checks to true Bottom checks
+    // TODO(mfairhurst): switch legacy Top checks to true Top checks
+    if (_isLegacyBottom(t1, orTrueBottom: true) ||
+        _isLegacyTop(t2, orTrueTop: true)) return true;
+
+    if (t1 is InterfaceType && t2 is InterfaceType) {
+      return _matchInterfaceSubtypeOf(t1, t2, visited, origin,
+          covariant: covariant);
+    }
+
+    if (t1 is FunctionType && t2 is FunctionType) {
+      return FunctionTypeImpl.relate(t1, t2, matchSubtype,
+          parameterRelation: (p1, p2) {
+            return _matchSubtypeOf(p2.type, p1.type, null, origin,
+                covariant: !covariant);
+          },
+          // Type parameter bounds are invariant.
+          boundsRelation: (t1, t2, p1, p2) =>
+              matchSubtype(t1, t2) && matchSubtype(t2, t1));
+    }
+
+    if (t1 is FunctionType && t2 == typeProvider.functionType) {
+      return true;
+    }
+
+    return false;
+  }
+
+  /// Un-does constraints that were gathered by a failed match attempt, until
+  /// [_undoBuffer] has length [previousRewindBufferLength].
+  ///
+  /// The intended usage is that the caller should record the length of
+  /// [_undoBuffer] before attempting to make a match.  Then, if the match
+  /// fails, pass the recorded length to this method to erase any constraints
+  /// that were recorded during the failed match.
+  void _rewindConstraints(int previousRewindBufferLength) {
+    while (_undoBuffer.length > previousRewindBufferLength) {
+      var constraint = _undoBuffer.removeLast();
+      var element = constraint.typeParameter;
+      assert(identical(constraints[element].last, constraint));
+      constraints[element].removeLast();
+    }
+  }
+
+  /// If in a legacy library, return the legacy version of the [type].
+  /// Otherwise, return the original type.
+  DartType _toLegacyType(DartType type) {
+    if (isNonNullableByDefault) return type;
+    return NullabilityEliminator.perform(typeProvider, type);
+  }
+
+  String _typeStr(DartType type) {
+    return type.getDisplayString(withNullability: isNonNullableByDefault);
+  }
+
+  static String _formatConstraints(Iterable<_TypeConstraint> constraints) {
+    List<List<String>> lineParts =
+        Set<_TypeConstraintOrigin>.from(constraints.map((c) => c.origin))
+            .map((o) => o.formatError())
+            .toList();
+
+    int prefixMax = lineParts.map((p) => p[0].length).fold(0, math.max);
+
+    // Use a set to prevent identical message lines.
+    // (It's not uncommon for the same constraint to show up in a few places.)
+    var messageLines = Set<String>.from(lineParts.map((parts) {
+      var prefix = parts[0];
+      var middle = parts[1];
+      var prefixPad = ' ' * (prefixMax - prefix.length);
+      var middlePad = ' ' * (prefixMax);
+      var end = "";
+      if (parts.length > 2) {
+        end = '\n  $middlePad ${parts[2]}';
+      }
+      return '  $prefix$prefixPad $middle$end';
+    }));
+
+    return messageLines.join('\n');
+  }
+}
+
+/// A constraint on a type parameter that we're inferring.
+class _TypeConstraint extends _TypeRange {
+  /// The type parameter that is constrained by [lowerBound] or [upperBound].
+  final TypeParameterElement typeParameter;
+
+  /// Where this constraint comes from, used for error messages.
+  ///
+  /// See [toString].
+  final _TypeConstraintOrigin origin;
+
+  _TypeConstraint(this.origin, this.typeParameter,
+      {DartType upper, DartType lower})
+      : super(upper: upper, lower: lower);
+
+  _TypeConstraint.fromExtends(
+      TypeParameterElement element, DartType extendsType,
+      {@required bool isNonNullableByDefault})
+      : this(
+            _TypeConstraintFromExtendsClause(
+              element,
+              extendsType,
+              isNonNullableByDefault: isNonNullableByDefault,
+            ),
+            element,
+            upper: extendsType);
+
+  bool get isDownwards => origin is! _TypeConstraintFromArgument;
+
+  bool isSatisifedBy(TypeSystemImpl ts, DartType type) =>
+      ts.isSubtypeOf2(lowerBound, type) && ts.isSubtypeOf2(type, upperBound);
+
+  /// Converts this constraint to a message suitable for a type inference error.
+  @override
+  String toString() => !identical(upperBound, UnknownInferredType.instance)
+      ? "'$typeParameter' must extend '$upperBound'"
+      : "'$lowerBound' must extend '$typeParameter'";
+}
+
+class _TypeConstraintFromArgument extends _TypeConstraintOrigin {
+  final DartType argumentType;
+  final DartType parameterType;
+  final String parameterName;
+  final ClassElement genericClass;
+
+  _TypeConstraintFromArgument(
+      this.argumentType, this.parameterType, this.parameterName,
+      {this.genericClass, @required bool isNonNullableByDefault})
+      : super(isNonNullableByDefault: isNonNullableByDefault);
+
+  @override
+  formatError() {
+    // TODO(jmesserly): we should highlight the span. That would be more useful.
+    // However in summary code it doesn't look like the AST node with span is
+    // available.
+    String prefix;
+    if (genericClass != null &&
+        (genericClass.name == "List" || genericClass.name == "Map") &&
+        genericClass.library.isDartCore == true) {
+      // This will become:
+      //     "List element"
+      //     "Map key"
+      //     "Map value"
+      prefix = "${genericClass.name} $parameterName";
+    } else {
+      prefix = "Parameter '$parameterName'";
+    }
+
+    return [
+      prefix,
+      "declared as     '${_typeStr(parameterType)}'",
+      "but argument is '${_typeStr(argumentType)}'."
+    ];
+  }
+}
+
+class _TypeConstraintFromExtendsClause extends _TypeConstraintOrigin {
+  final TypeParameterElement typeParam;
+  final DartType extendsType;
+
+  _TypeConstraintFromExtendsClause(this.typeParam, this.extendsType,
+      {@required bool isNonNullableByDefault})
+      : super(isNonNullableByDefault: isNonNullableByDefault);
+
+  @override
+  formatError() {
+    return [
+      "Type parameter '${typeParam.name}'",
+      "declared to extend '${_typeStr(extendsType)}'."
+    ];
+  }
+}
+
+class _TypeConstraintFromFunctionContext extends _TypeConstraintOrigin {
+  final DartType contextType;
+  final DartType functionType;
+
+  _TypeConstraintFromFunctionContext(this.functionType, this.contextType,
+      {@required bool isNonNullableByDefault})
+      : super(isNonNullableByDefault: isNonNullableByDefault);
+
+  @override
+  formatError() {
+    return [
+      "Function type",
+      "declared as '${_typeStr(functionType)}'",
+      "used where  '${_typeStr(contextType)}' is required."
+    ];
+  }
+}
+
+class _TypeConstraintFromReturnType extends _TypeConstraintOrigin {
+  final DartType contextType;
+  final DartType declaredType;
+
+  _TypeConstraintFromReturnType(this.declaredType, this.contextType,
+      {@required bool isNonNullableByDefault})
+      : super(isNonNullableByDefault: isNonNullableByDefault);
+
+  @override
+  formatError() {
+    return [
+      "Return type",
+      "declared as '${_typeStr(declaredType)}'",
+      "used where  '${_typeStr(contextType)}' is required."
+    ];
+  }
+}
+
+/// The origin of a type constraint, for the purposes of producing a human
+/// readable error message during type inference as well as determining whether
+/// the constraint was used to fix the type parameter or not.
+abstract class _TypeConstraintOrigin {
+  final bool isNonNullableByDefault;
+
+  _TypeConstraintOrigin({@required this.isNonNullableByDefault});
+
+  List<String> formatError();
+
+  String _typeStr(DartType type) {
+    return type.getDisplayString(withNullability: isNonNullableByDefault);
+  }
+}
+
+class _TypeRange {
+  /// The upper bound of the type parameter. In other words, T <: upperBound.
+  ///
+  /// In Dart this can be written as `<T extends UpperBoundType>`.
+  ///
+  /// In inference, this can happen as a result of parameters of function type.
+  /// For example, consider a signature like:
+  ///
+  ///     T reduce<T>(List<T> values, T f(T x, T y));
+  ///
+  /// and a call to it like:
+  ///
+  ///     reduce(values, (num x, num y) => ...);
+  ///
+  /// From the function expression's parameters, we conclude `T <: num`. We may
+  /// still be able to conclude a different [lower] based on `values` or
+  /// the type of the elided `=> ...` body. For example:
+  ///
+  ///      reduce(['x'], (num x, num y) => 'hi');
+  ///
+  /// Here the [lower] will be `String` and the upper bound will be `num`,
+  /// which cannot be satisfied, so this is ill typed.
+  final DartType upperBound;
+
+  /// The lower bound of the type parameter. In other words, lowerBound <: T.
+  ///
+  /// This kind of constraint cannot be expressed in Dart, but it applies when
+  /// we're doing inference. For example, consider a signature like:
+  ///
+  ///     T pickAtRandom<T>(T x, T y);
+  ///
+  /// and a call to it like:
+  ///
+  ///     pickAtRandom(1, 2.0)
+  ///
+  /// when we see the first parameter is an `int`, we know that `int <: T`.
+  /// When we see `double` this implies `double <: T`.
+  /// Combining these constraints results in a lower bound of `num`.
+  ///
+  /// In general, we choose the lower bound as our inferred type, so we can
+  /// offer the most constrained (strongest) result type.
+  final DartType lowerBound;
+
+  _TypeRange({DartType lower, DartType upper})
+      : lowerBound = lower ?? UnknownInferredType.instance,
+        upperBound = upper ?? UnknownInferredType.instance;
+
+  /// Formats the typeRange as a string suitable for unit testing.
+  ///
+  /// For example, if [typeName] is 'T' and the range has bounds int and Object
+  /// respectively, the returned string will be 'int <: T <: Object'.
+  @visibleForTesting
+  String format(String typeName, {@required bool withNullability}) {
+    String typeStr(DartType type) {
+      return type.getDisplayString(withNullability: withNullability);
+    }
+
+    var lowerString = identical(lowerBound, UnknownInferredType.instance)
+        ? ''
+        : '${typeStr(lowerBound)} <: ';
+    var upperString = identical(upperBound, UnknownInferredType.instance)
+        ? ''
+        : ' <: ${typeStr(upperBound)}';
+    return '$lowerString$typeName$upperString';
+  }
+
+  @override
+  String toString() => format('(type)', withNullability: true);
+}
diff --git a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
new file mode 100644
index 0000000..1085211
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
@@ -0,0 +1,411 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/dart/element/nullability_suffix.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/element/type_schema.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+
+class GreatestLowerBoundHelper {
+  final TypeSystemImpl _typeSystem;
+
+  GreatestLowerBoundHelper(this._typeSystem);
+
+  InterfaceTypeImpl get _nullNone => _typeSystem.nullNone;
+
+  TypeProviderImpl get _typeProvider => _typeSystem.typeProvider;
+
+  /// Computes the greatest lower bound of [T1] and [T2].
+  ///
+  /// https://github.com/dart-lang/language
+  /// See `resources/type-system/upper-lower-bounds.md`
+  DartType getGreatestLowerBound(DartType T1, DartType T2) {
+    // DOWN(T, T) = T
+    if (identical(T1, T2)) {
+      return T1;
+    }
+
+    // For any type T, DOWN(?, T) == T.
+    if (identical(T1, UnknownInferredType.instance)) {
+      return T2;
+    }
+    if (identical(T2, UnknownInferredType.instance)) {
+      return T1;
+    }
+
+    var T1_isTop = _typeSystem.isTop(T1);
+    var T2_isTop = _typeSystem.isTop(T2);
+
+    // DOWN(T1, T2) where TOP(T1) and TOP(T2)
+    if (T1_isTop && T2_isTop) {
+      // * T1 if MORETOP(T2, T1)
+      // * T2 otherwise
+      if (_typeSystem.isMoreTop(T2, T1)) {
+        return T1;
+      } else {
+        return T2;
+      }
+    }
+
+    // DOWN(T1, T2) = T2 if TOP(T1)
+    if (T1_isTop) {
+      return T2;
+    }
+
+    // DOWN(T1, T2) = T1 if TOP(T2)
+    if (T2_isTop) {
+      return T1;
+    }
+
+    var T1_isBottom = _typeSystem.isBottom(T1);
+    var T2_isBottom = _typeSystem.isBottom(T2);
+
+    // DOWN(T1, T2) where BOTTOM(T1) and BOTTOM(T2)
+    if (T1_isBottom && T2_isBottom) {
+      // * T1 if MOREBOTTOM(T1, T2)
+      // * T2 otherwise
+      if (_typeSystem.isMoreBottom(T1, T2)) {
+        return T1;
+      } else {
+        return T2;
+      }
+    }
+
+    // DOWN(T1, T2) = T1 if BOTTOM(T1)
+    if (T1_isBottom) {
+      return T1;
+    }
+
+    // DOWN(T1, T2) = T2 if BOTTOM(T2)
+    if (T2_isBottom) {
+      return T2;
+    }
+
+    var T1_isNull = _typeSystem.isNull(T1);
+    var T2_isNull = _typeSystem.isNull(T2);
+
+    // DOWN(T1, T2) where NULL(T1) and NULL(T2)
+    if (T1_isNull && T2_isNull) {
+      // * T1 if MOREBOTTOM(T1, T2)
+      // * T2 otherwise
+      if (_typeSystem.isMoreBottom(T1, T2)) {
+        return T1;
+      } else {
+        return T2;
+      }
+    }
+
+    var T1_impl = T1 as TypeImpl;
+    var T2_impl = T2 as TypeImpl;
+
+    var T1_nullability = T1_impl.nullabilitySuffix;
+    var T2_nullability = T2_impl.nullabilitySuffix;
+
+    // DOWN(Null, T2)
+    if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull) {
+      // * Null if Null <: T2
+      // * Never otherwise
+      if (_typeSystem.isSubtypeOf2(_nullNone, T2)) {
+        return _nullNone;
+      } else {
+        return NeverTypeImpl.instance;
+      }
+    }
+
+    // DOWN(T1, Null)
+    if (T2_nullability == NullabilitySuffix.none && T2.isDartCoreNull) {
+      // * Null if Null <: T1
+      // * Never otherwise
+      if (_typeSystem.isSubtypeOf2(_nullNone, T1)) {
+        return _nullNone;
+      } else {
+        return NeverTypeImpl.instance;
+      }
+    }
+
+    var T1_isObject = _typeSystem.isObject(T1);
+    var T2_isObject = _typeSystem.isObject(T2);
+
+    // DOWN(T1, T2) where OBJECT(T1) and OBJECT(T2)
+    if (T1_isObject && T2_isObject) {
+      // * T1 if MORETOP(T2, T1)
+      // * T2 otherwise
+      if (_typeSystem.isMoreTop(T2, T1)) {
+        return T1;
+      } else {
+        return T2;
+      }
+    }
+
+    // DOWN(T1, T2) where OBJECT(T1)
+    if (T1_isObject) {
+      // * T2 if T2 is non-nullable
+      if (_typeSystem.isNonNullable(T2)) {
+        return T2;
+      }
+
+      // * NonNull(T2) if NonNull(T2) is non-nullable
+      var T2_nonNull = _typeSystem.promoteToNonNull(T2_impl);
+      if (_typeSystem.isNonNullable(T2_nonNull)) {
+        return T2_nonNull;
+      }
+
+      // * Never otherwise
+      return NeverTypeImpl.instance;
+    }
+
+    // DOWN(T1, T2) where OBJECT(T2)
+    if (T2_isObject) {
+      // * T1 if T1 is non-nullable
+      if (_typeSystem.isNonNullable(T1)) {
+        return T1;
+      }
+
+      // * NonNull(T1) if NonNull(T1) is non-nullable
+      var T1_nonNull = _typeSystem.promoteToNonNull(T1_impl);
+      if (_typeSystem.isNonNullable(T1_nonNull)) {
+        return T1_nonNull;
+      }
+
+      // * Never otherwise
+      return NeverTypeImpl.instance;
+    }
+
+    // DOWN(T1*, T2*) = S* where S is DOWN(T1, T2)
+    // DOWN(T1*, T2?) = S* where S is DOWN(T1, T2)
+    // DOWN(T1?, T2*) = S* where S is DOWN(T1, T2)
+    // DOWN(T1*, T2) = S where S is DOWN(T1, T2)
+    // DOWN(T1, T2*) = S where S is DOWN(T1, T2)
+    // DOWN(T1?, T2?) = S? where S is DOWN(T1, T2)
+    // DOWN(T1?, T2) = S where S is DOWN(T1, T2)
+    // DOWN(T1, T2?) = S where S is DOWN(T1, T2)
+    if (T1_nullability != NullabilitySuffix.none ||
+        T2_nullability != NullabilitySuffix.none) {
+      var resultNullability = NullabilitySuffix.question;
+      if (T1_nullability == NullabilitySuffix.none ||
+          T2_nullability == NullabilitySuffix.none) {
+        resultNullability = NullabilitySuffix.none;
+      } else if (T1_nullability == NullabilitySuffix.star ||
+          T2_nullability == NullabilitySuffix.star) {
+        resultNullability = NullabilitySuffix.star;
+      }
+      var T1_none = T1_impl.withNullability(NullabilitySuffix.none);
+      var T2_none = T2_impl.withNullability(NullabilitySuffix.none);
+      var S = getGreatestLowerBound(T1_none, T2_none);
+      return (S as TypeImpl).withNullability(resultNullability);
+    }
+
+    assert(T1_nullability == NullabilitySuffix.none);
+    assert(T2_nullability == NullabilitySuffix.none);
+
+    if (T1 is FunctionType && T2 is FunctionType) {
+      return _functionType(T1, T2);
+    }
+
+    // DOWN(T1, T2) = T1 if T1 <: T2
+    if (_typeSystem.isSubtypeOf2(T1, T2)) {
+      return T1;
+    }
+
+    // DOWN(T1, T2) = T2 if T2 <: T1
+    if (_typeSystem.isSubtypeOf2(T2, T1)) {
+      return T2;
+    }
+
+    // FutureOr<S1>
+    if (T1 is InterfaceType && T1.isDartAsyncFutureOr) {
+      var S1 = T1.typeArguments[0];
+      // DOWN(FutureOr<S1>, FutureOr<S2>) = FutureOr(S)
+      //   S = DOWN(S1, S2)
+      if (T2 is InterfaceType && T2.isDartAsyncFutureOr) {
+        var S2 = T2.typeArguments[0];
+        var S = getGreatestLowerBound(S1, S2);
+        return _typeProvider.futureOrType2(S);
+      }
+      // DOWN(FutureOr<S1>, Future<S2>) = Future(S)
+      //   S = DOWN(S1, S2)
+      if (T2 is InterfaceType && T2.isDartAsyncFuture) {
+        var S2 = T2.typeArguments[0];
+        var S = getGreatestLowerBound(S1, S2);
+        return _typeProvider.futureType2(S);
+      }
+      // DOWN(FutureOr<S1>, T2) = DOWN(S1, T2)
+      return getGreatestLowerBound(S1, T2);
+    }
+
+    // FutureOr<S2>
+    if (T2 is InterfaceType && T2.isDartAsyncFutureOr) {
+      var S2 = T2.typeArguments[0];
+      // DOWN(Future<S1>, FutureOr<S2>) = Future<S>
+      //   S = DOWN(S1, S2)
+      if (T1 is InterfaceType && T1.isDartAsyncFuture) {
+        var S1 = T1.typeArguments[0];
+        var S = getGreatestLowerBound(S1, S2);
+        return _typeProvider.futureType2(S);
+      }
+      // DOWN(T1, FutureOr<S2>) = DOWN(T1, S2)
+      return getGreatestLowerBound(T1, S2);
+    }
+
+    // DOWN(T1, T2) = Never otherwise
+    return NeverTypeImpl.instance;
+  }
+
+  /**
+   * Compute the greatest lower bound of function types [f] and [g].
+   *
+   * https://github.com/dart-lang/language
+   * See `resources/type-system/upper-lower-bounds.md`
+   */
+  DartType _functionType(FunctionType f, FunctionType g) {
+    var fTypeFormals = f.typeFormals;
+    var gTypeFormals = g.typeFormals;
+
+    // The number of type parameters must be the same.
+    // Otherwise the result is `Never`.
+    if (fTypeFormals.length != gTypeFormals.length) {
+      return NeverTypeImpl.instance;
+    }
+
+    // The bounds of type parameters must be equal.
+    // Otherwise the result is `Never`.
+    var freshTypeFormalTypes =
+        FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
+    if (freshTypeFormalTypes == null) {
+      return NeverTypeImpl.instance;
+    }
+
+    var typeFormals = freshTypeFormalTypes
+        .map<TypeParameterElement>((t) => t.element)
+        .toList();
+
+    f = f.instantiate(freshTypeFormalTypes);
+    g = g.instantiate(freshTypeFormalTypes);
+
+    var fParameters = f.parameters;
+    var gParameters = g.parameters;
+
+    var parameters = <ParameterElement>[];
+    var fIndex = 0;
+    var gIndex = 0;
+    while (fIndex < fParameters.length && gIndex < gParameters.length) {
+      var fParameter = fParameters[fIndex];
+      var gParameter = gParameters[gIndex];
+      if (fParameter.isPositional) {
+        if (gParameter.isPositional) {
+          fIndex++;
+          gIndex++;
+          parameters.add(
+            ParameterElementImpl.synthetic(
+              fParameter.name,
+              _typeSystem.getLeastUpperBound(fParameter.type, gParameter.type),
+              fParameter.isOptional || gParameter.isOptional
+                  ? ParameterKind.POSITIONAL
+                  : ParameterKind.REQUIRED,
+            ),
+          );
+        } else {
+          return NeverTypeImpl.instance;
+        }
+      } else if (fParameter.isNamed) {
+        if (gParameter.isNamed) {
+          var compareNames = fParameter.name.compareTo(gParameter.name);
+          if (compareNames == 0) {
+            fIndex++;
+            gIndex++;
+            parameters.add(
+              ParameterElementImpl.synthetic(
+                fParameter.name,
+                _typeSystem.getLeastUpperBound(
+                    fParameter.type, gParameter.type),
+                fParameter.isRequiredNamed && gParameter.isRequiredNamed
+                    ? ParameterKind.NAMED_REQUIRED
+                    : ParameterKind.NAMED,
+              ),
+            );
+          } else if (compareNames < 0) {
+            fIndex++;
+            parameters.add(
+              ParameterElementImpl.synthetic(
+                fParameter.name,
+                fParameter.type,
+                ParameterKind.NAMED,
+              ),
+            );
+          } else {
+            assert(compareNames > 0);
+            gIndex++;
+            parameters.add(
+              ParameterElementImpl.synthetic(
+                gParameter.name,
+                gParameter.type,
+                ParameterKind.NAMED,
+              ),
+            );
+          }
+        } else {
+          return NeverTypeImpl.instance;
+        }
+      }
+    }
+
+    while (fIndex < fParameters.length) {
+      var fParameter = fParameters[fIndex++];
+      if (fParameter.isPositional) {
+        parameters.add(
+          ParameterElementImpl.synthetic(
+            fParameter.name,
+            fParameter.type,
+            ParameterKind.POSITIONAL,
+          ),
+        );
+      } else {
+        assert(fParameter.isNamed);
+        parameters.add(
+          ParameterElementImpl.synthetic(
+            fParameter.name,
+            fParameter.type,
+            ParameterKind.NAMED,
+          ),
+        );
+      }
+    }
+
+    while (gIndex < gParameters.length) {
+      var gParameter = gParameters[gIndex++];
+      if (gParameter.isPositional) {
+        parameters.add(
+          ParameterElementImpl.synthetic(
+            gParameter.name,
+            gParameter.type,
+            ParameterKind.POSITIONAL,
+          ),
+        );
+      } else {
+        assert(gParameter.isNamed);
+        parameters.add(
+          ParameterElementImpl.synthetic(
+            gParameter.name,
+            gParameter.type,
+            ParameterKind.NAMED,
+          ),
+        );
+      }
+    }
+
+    var returnType = getGreatestLowerBound(f.returnType, g.returnType);
+
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index bf23dce..d599435 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -75,6 +75,7 @@
         type.element,
         interface._inheritedMap,
         interface._overridden,
+        doTopMerge: false,
       );
     }
     return interface._inheritedMap;
@@ -106,20 +107,12 @@
     Map<Name, ExecutableElement> declared;
     Interface superInterface;
     Map<Name, ExecutableElement> implemented;
+    List<List<Conflict>> mixinsConflicts = [];
     try {
       // If a class declaration has a member declaration, the signature of that
       // member declaration becomes the signature in the interface.
       declared = _getTypeMembers(type);
 
-      for (var interface in type.interfaces.reversed) {
-        var interfaceObj = getInterface(interface);
-        _addCandidates(
-          namedCandidates,
-          interfaceObj,
-          isNonNullableByDefault: isNonNullableByDefault,
-        );
-      }
-
       if (classElement.isMixin) {
         var superClassCandidates = <Name, List<ExecutableElement>>{};
         for (var constraint in type.superclassConstraints) {
@@ -145,6 +138,7 @@
           classElement,
           superClass,
           superClassCandidates,
+          doTopMerge: true,
         );
         superImplemented.add(superClass);
       } else {
@@ -162,13 +156,70 @@
           implemented = {};
         }
 
+        // TODO(scheglov) Handling of members for super and mixins is not
+        // optimal. We always have just one member for each name in super,
+        // multiple candidates happen only when we merge super and multiple
+        // interfaces. Consider using `Map<Name, ExecutableElement>` here.
         for (var mixin in type.mixins) {
+          var mixinElement = mixin.element;
           var interfaceObj = getInterface(mixin);
-          _addCandidates(
-            namedCandidates,
-            interfaceObj,
-            isNonNullableByDefault: isNonNullableByDefault,
-          );
+          // `class X extends S with M1, M2 {}` is semantically a sequence of:
+          //     class S&M1 extends S implements M1 {
+          //       // declared M1 members
+          //     }
+          //     class S&M2 extends S&M1 implements M2 {
+          //       // declared M2 members
+          //     }
+          //     class X extends S&M2 {
+          //       // declared X members
+          //     }
+          // So, each mixin always replaces members in the interface.
+          // And there are individual override conflicts for each mixin.
+          var candidatesFromSuperAndMixin = <Name, List<ExecutableElement>>{};
+          var mixinConflicts = <Conflict>[];
+          for (var name in interfaceObj.map.keys) {
+            var candidate = interfaceObj.map[name];
+
+            var currentList = namedCandidates[name];
+            if (currentList == null) {
+              namedCandidates[name] = [candidate];
+              continue;
+            }
+
+            var current = currentList.single;
+            if (candidate.enclosingElement == mixinElement) {
+              namedCandidates[name] = [candidate];
+              if (current.kind != candidate.kind) {
+                var currentIsGetter = current.kind == ElementKind.GETTER;
+                mixinConflicts.add(
+                  Conflict(
+                    name,
+                    [current, candidate],
+                    currentIsGetter ? current : candidate,
+                    currentIsGetter ? candidate : current,
+                  ),
+                );
+              }
+            } else {
+              candidatesFromSuperAndMixin[name] = [current, candidate];
+            }
+          }
+
+          // Merge members from the superclass and the mixin interface.
+          {
+            var map = <Name, ExecutableElement>{};
+            _findMostSpecificFromNamedCandidates(
+              classElement,
+              map,
+              candidatesFromSuperAndMixin,
+              doTopMerge: true,
+            );
+            for (var entry in map.entries) {
+              namedCandidates[entry.key] = [entry.value];
+            }
+          }
+
+          mixinsConflicts.add(mixinConflicts);
 
           implemented = <Name, ExecutableElement>{}..addAll(implemented);
           implemented.addEntries(
@@ -185,6 +236,15 @@
           superImplemented.add(implemented);
         }
       }
+
+      for (var interface in type.interfaces) {
+        var interfaceObj = getInterface(interface);
+        _addCandidates(
+          namedCandidates,
+          interfaceObj,
+          isNonNullableByDefault: isNonNullableByDefault,
+        );
+      }
     } finally {
       _processingClasses.remove(classElement);
     }
@@ -203,6 +263,7 @@
       classElement,
       map,
       namedCandidates,
+      doTopMerge: true,
     );
 
     var noSuchMethodForwarders = <Name>{};
@@ -224,6 +285,15 @@
       }
     }
 
+    /// TODO(scheglov) Instead of merging conflicts we could report them on
+    /// the corresponding mixins applied in the class.
+    for (var mixinConflicts in mixinsConflicts) {
+      if (mixinConflicts.isNotEmpty) {
+        conflicts ??= [];
+        conflicts.addAll(mixinConflicts);
+      }
+    }
+
     var interface = Interface._(
       map,
       declared,
@@ -380,9 +450,11 @@
   /// such single most specific signature (i.e. no valid override), then add a
   /// new conflict description.
   List<Conflict> _findMostSpecificFromNamedCandidates(
-      ClassElement targetClass,
-      Map<Name, ExecutableElement> map,
-      Map<Name, List<ExecutableElement>> namedCandidates) {
+    ClassElement targetClass,
+    Map<Name, ExecutableElement> map,
+    Map<Name, List<ExecutableElement>> namedCandidates, {
+    @required bool doTopMerge,
+  }) {
     TypeSystemImpl typeSystem = targetClass.library.typeSystem;
 
     List<Conflict> conflicts;
@@ -407,13 +479,8 @@
         conflicts.add(conflict);
       }
 
-      // Candidates are recorded in forward order, so
-      // `class X extends S with M1, M2 implements I1, I2 {}` will record
-      // candidates from [I1, I2, S, M1, M2]. But during method lookup
-      // candidates should be considered in backward order, i.e. from `M2`,
-      // then from `M1`, then from `S`.
       var validOverrides = <ExecutableElement>[];
-      for (var i = candidates.length - 1; i >= 0; i--) {
+      for (var i = 0; i < candidates.length; i++) {
         var validOverride = candidates[i];
         var overrideHelper = CorrectOverrideHelper(
           library: targetClass.library,
@@ -437,7 +504,11 @@
         continue;
       }
 
-      map[name] = _topMerge(typeSystem, targetClass, validOverrides);
+      if (doTopMerge) {
+        map[name] = _topMerge(typeSystem, targetClass, validOverrides);
+      } else {
+        map[name] = validOverrides.first;
+      }
     }
 
     return conflicts;
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
new file mode 100644
index 0000000..21fe0b0
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -0,0 +1,818 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/dart/element/nullability_suffix.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_algebra.dart';
+import 'package:analyzer/src/dart/element/type_schema.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
+
+/// The instantiation of a [ClassElement] with type arguments.
+///
+/// It is not a [DartType] itself, because it does not have nullability.
+/// But it should be used where nullability does not make sense - to specify
+/// superclasses, mixins, and implemented interfaces.
+class InstantiatedClass {
+  final ClassElement element;
+  final List<DartType> arguments;
+
+  final Substitution _substitution;
+
+  InstantiatedClass(this.element, this.arguments)
+      : _substitution = Substitution.fromPairs(
+          element.typeParameters,
+          arguments,
+        );
+
+  /// Return the [InstantiatedClass] that corresponds to the [type] - with the
+  /// same element and type arguments, ignoring its nullability suffix.
+  factory InstantiatedClass.of(InterfaceType type) {
+    return InstantiatedClass(type.element, type.typeArguments);
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0x3fffffff & element.hashCode;
+    for (var i = 0; i < arguments.length; i++) {
+      hash = 0x3fffffff & (hash * 31 + (hash ^ arguments[i].hashCode));
+    }
+    return hash;
+  }
+
+  /// Return the interfaces that are directly implemented by this class.
+  List<InstantiatedClass> get interfaces {
+    var interfaces = element.interfaces;
+
+    var result = List<InstantiatedClass>(interfaces.length);
+    for (var i = 0; i < interfaces.length; i++) {
+      var interface = interfaces[i];
+      var substituted = _substitution.substituteType(interface);
+      result[i] = InstantiatedClass.of(substituted);
+    }
+
+    return result;
+  }
+
+  /// Return `true` if this type represents the type 'Function' defined in the
+  /// dart:core library.
+  bool get isDartCoreFunction {
+    return element.name == 'Function' && element.library.isDartCore;
+  }
+
+  /// Return the superclass of this type, or `null` if this type represents
+  /// the class 'Object'.
+  InstantiatedClass get superclass {
+    var supertype = element.supertype;
+    if (supertype == null) return null;
+
+    supertype = _substitution.substituteType(supertype);
+    return InstantiatedClass.of(supertype);
+  }
+
+  /// Return a list containing all of the superclass constraints defined for
+  /// this class. The list will be empty if this class does not represent a
+  /// mixin declaration. If this class _does_ represent a mixin declaration but
+  /// the declaration does not have an `on` clause, then the list will contain
+  /// the type for the class `Object`.
+  List<InstantiatedClass> get superclassConstraints {
+    var constraints = element.superclassConstraints;
+
+    var result = List<InstantiatedClass>(constraints.length);
+    for (var i = 0; i < constraints.length; i++) {
+      var constraint = constraints[i];
+      var substituted = _substitution.substituteType(constraint);
+      result[i] = InstantiatedClass.of(substituted);
+    }
+
+    return result;
+  }
+
+  @visibleForTesting
+  InterfaceType get withNullabilitySuffixNone {
+    return withNullability(NullabilitySuffix.none);
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+
+    if (other is InstantiatedClass) {
+      if (element != other.element) return false;
+      if (arguments.length != other.arguments.length) return false;
+      for (var i = 0; i < arguments.length; i++) {
+        if (arguments[i] != other.arguments[i]) return false;
+      }
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  String toString() {
+    var buffer = StringBuffer();
+    buffer.write(element.name);
+    if (arguments.isNotEmpty) {
+      buffer.write('<');
+      buffer.write(arguments.join(', '));
+      buffer.write('>');
+    }
+    return buffer.toString();
+  }
+
+  InterfaceType withNullability(NullabilitySuffix nullability) {
+    return InterfaceTypeImpl(
+      element: element,
+      typeArguments: arguments,
+      nullabilitySuffix: nullability,
+    );
+  }
+}
+
+class InterfaceLeastUpperBoundHelper {
+  final TypeSystemImpl typeSystem;
+
+  InterfaceLeastUpperBoundHelper(this.typeSystem);
+
+  /// This currently does not implement a very complete least upper bound
+  /// algorithm, but handles a couple of the very common cases that are
+  /// causing pain in real code.  The current algorithm is:
+  /// 1. If either of the types is a supertype of the other, return it.
+  ///    This is in fact the best result in this case.
+  /// 2. If the two types have the same class element and are implicitly or
+  ///    explicitly covariant, then take the pointwise least upper bound of
+  ///    the type arguments. This is again the best result, except that the
+  ///    recursive calls may not return the true least upper bounds. The
+  ///    result is guaranteed to be a well-formed type under the assumption
+  ///    that the input types were well-formed (and assuming that the
+  ///    recursive calls return well-formed types).
+  ///    If the variance of the type parameter is contravariant, we take the
+  ///    greatest lower bound of the type arguments. If the variance of the
+  ///    type parameter is invariant, we verify if the type arguments satisfy
+  ///    subtyping in both directions, then choose a bound.
+  /// 3. Otherwise return the spec-defined least upper bound.  This will
+  ///    be an upper bound, might (or might not) be least, and might
+  ///    (or might not) be a well-formed type.
+  ///
+  /// TODO(leafp): Use matchTypes or something similar here to handle the
+  ///  case where one of the types is a superclass (but not supertype) of
+  ///  the other, e.g. LUB(Iterable<double>, List<int>) = Iterable<num>
+  /// TODO(leafp): Figure out the right final algorithm and implement it.
+  InterfaceTypeImpl compute(InterfaceTypeImpl type1, InterfaceTypeImpl type2) {
+    var nullability = _chooseNullability(type1, type2);
+
+    // Strip off nullability.
+    type1 = type1.withNullability(NullabilitySuffix.none);
+    type2 = type2.withNullability(NullabilitySuffix.none);
+
+    if (typeSystem.isSubtypeOf2(type1, type2)) {
+      return type2.withNullability(nullability);
+    }
+    if (typeSystem.isSubtypeOf2(type2, type1)) {
+      return type1.withNullability(nullability);
+    }
+
+    if (type1.element == type2.element) {
+      var args1 = type1.typeArguments;
+      var args2 = type2.typeArguments;
+      var params = type1.element.typeParameters;
+      assert(args1.length == args2.length);
+      assert(args1.length == params.length);
+
+      var args = List<DartType>(args1.length);
+      for (int i = 0; i < args1.length; i++) {
+        // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+        // variance is added to the interface.
+        Variance parameterVariance =
+            (params[i] as TypeParameterElementImpl).variance;
+        if (parameterVariance.isCovariant) {
+          args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
+        } else if (parameterVariance.isContravariant) {
+          if (typeSystem is TypeSystemImpl) {
+            args[i] = typeSystem.getGreatestLowerBound(args1[i], args2[i]);
+          } else {
+            args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
+          }
+        } else if (parameterVariance.isInvariant) {
+          if (!typeSystem.isSubtypeOf2(args1[i], args2[i]) ||
+              !typeSystem.isSubtypeOf2(args2[i], args1[i])) {
+            // No bound will be valid, find bound at the interface level.
+            return _computeLeastUpperBound(
+              InstantiatedClass.of(type1),
+              InstantiatedClass.of(type2),
+            ).withNullability(nullability);
+          }
+          // TODO (kallentu) : Fix asymmetric bounds behavior for invariant type
+          //  parameters.
+          args[i] = args1[i];
+        } else {
+          throw StateError('Type parameter ${params[i]} has unknown '
+              'variance $parameterVariance for bounds calculation.');
+        }
+      }
+
+      return InterfaceTypeImpl(
+        element: type1.element,
+        typeArguments: args,
+        nullabilitySuffix: nullability,
+      );
+    }
+
+    var result = _computeLeastUpperBound(
+      InstantiatedClass.of(type1),
+      InstantiatedClass.of(type2),
+    );
+    return result.withNullability(nullability);
+  }
+
+  /// Compute the least upper bound of types [i] and [j], both of which are
+  /// known to be interface types.
+  ///
+  /// In the event that the algorithm fails (which might occur due to a bug in
+  /// the analyzer), `null` is returned.
+  InstantiatedClass _computeLeastUpperBound(
+    InstantiatedClass i,
+    InstantiatedClass j,
+  ) {
+    // compute set of supertypes
+    var si = computeSuperinterfaceSet(i);
+    var sj = computeSuperinterfaceSet(j);
+
+    // union si with i and sj with j
+    si.add(i);
+    sj.add(j);
+
+    // compute intersection, reference as set 's'
+    var s = _intersection(si, sj);
+    return _computeTypeAtMaxUniqueDepth(s);
+  }
+
+  /**
+   * Return the length of the longest inheritance path from the [element] to
+   * Object.
+   */
+  @visibleForTesting
+  static int computeLongestInheritancePathToObject(ClassElement element) {
+    return _computeLongestInheritancePathToObject(
+      element,
+      0,
+      <ClassElement>{},
+    );
+  }
+
+  /// Return all of the superinterfaces of the given [type].
+  @visibleForTesting
+  static Set<InstantiatedClass> computeSuperinterfaceSet(
+      InstantiatedClass type) {
+    var result = <InstantiatedClass>{};
+    _addSuperinterfaces(result, type);
+    return result;
+  }
+
+  /// Add all of the superinterfaces of the given [type] to the given [set].
+  static void _addSuperinterfaces(
+      Set<InstantiatedClass> set, InstantiatedClass type) {
+    for (var interface in type.interfaces) {
+      if (!interface.isDartCoreFunction) {
+        if (set.add(interface)) {
+          _addSuperinterfaces(set, interface);
+        }
+      }
+    }
+
+    for (var constraint in type.superclassConstraints) {
+      if (!constraint.isDartCoreFunction) {
+        if (set.add(constraint)) {
+          _addSuperinterfaces(set, constraint);
+        }
+      }
+    }
+
+    var supertype = type.superclass;
+    if (supertype != null && !supertype.isDartCoreFunction) {
+      if (set.add(supertype)) {
+        _addSuperinterfaces(set, supertype);
+      }
+    }
+  }
+
+  static NullabilitySuffix _chooseNullability(
+    InterfaceTypeImpl type1,
+    InterfaceTypeImpl type2,
+  ) {
+    var nullability1 = type1.nullabilitySuffix;
+    var nullability2 = type2.nullabilitySuffix;
+    if (nullability1 == NullabilitySuffix.question ||
+        nullability2 == NullabilitySuffix.question) {
+      return NullabilitySuffix.question;
+    } else if (nullability1 == NullabilitySuffix.star ||
+        nullability2 == NullabilitySuffix.star) {
+      return NullabilitySuffix.star;
+    }
+    return NullabilitySuffix.none;
+  }
+
+  /// Return the length of the longest inheritance path from a subtype of the
+  /// given [element] to Object, where the given [depth] is the length of the
+  /// longest path from the subtype to this type. The set of [visitedElements]
+  /// is used to prevent infinite recursion in the case of a cyclic type
+  /// structure.
+  static int _computeLongestInheritancePathToObject(
+      ClassElement element, int depth, Set<ClassElement> visitedElements) {
+    // Object case
+    if (element.isDartCoreObject || visitedElements.contains(element)) {
+      return depth;
+    }
+    int longestPath = 1;
+    try {
+      visitedElements.add(element);
+      int pathLength;
+
+      // loop through each of the superinterfaces recursively calling this
+      // method and keeping track of the longest path to return
+      for (InterfaceType interface in element.superclassConstraints) {
+        pathLength = _computeLongestInheritancePathToObject(
+            interface.element, depth + 1, visitedElements);
+        if (pathLength > longestPath) {
+          longestPath = pathLength;
+        }
+      }
+
+      // loop through each of the superinterfaces recursively calling this
+      // method and keeping track of the longest path to return
+      for (InterfaceType interface in element.interfaces) {
+        pathLength = _computeLongestInheritancePathToObject(
+            interface.element, depth + 1, visitedElements);
+        if (pathLength > longestPath) {
+          longestPath = pathLength;
+        }
+      }
+
+      // finally, perform this same check on the super type
+      // TODO(brianwilkerson) Does this also need to add in the number of mixin
+      // classes?
+      InterfaceType supertype = element.supertype;
+      if (supertype != null) {
+        pathLength = _computeLongestInheritancePathToObject(
+            supertype.element, depth + 1, visitedElements);
+        if (pathLength > longestPath) {
+          longestPath = pathLength;
+        }
+      }
+    } finally {
+      visitedElements.remove(element);
+    }
+    return longestPath;
+  }
+
+  /// Return the type from the [types] list that has the longest inheritance
+  /// path to Object of unique length.
+  static InstantiatedClass _computeTypeAtMaxUniqueDepth(
+    List<InstantiatedClass> types,
+  ) {
+    // for each element in Set s, compute the largest inheritance path to Object
+    List<int> depths = List<int>.filled(types.length, 0);
+    int maxDepth = 0;
+    for (int i = 0; i < types.length; i++) {
+      depths[i] = computeLongestInheritancePathToObject(types[i].element);
+      if (depths[i] > maxDepth) {
+        maxDepth = depths[i];
+      }
+    }
+    // ensure that the currently computed maxDepth is unique,
+    // otherwise, decrement and test for uniqueness again
+    for (; maxDepth >= 0; maxDepth--) {
+      int indexOfLeastUpperBound = -1;
+      int numberOfTypesAtMaxDepth = 0;
+      for (int m = 0; m < depths.length; m++) {
+        if (depths[m] == maxDepth) {
+          numberOfTypesAtMaxDepth++;
+          indexOfLeastUpperBound = m;
+        }
+      }
+      if (numberOfTypesAtMaxDepth == 1) {
+        return types[indexOfLeastUpperBound];
+      }
+    }
+    // Should be impossible--there should always be exactly one type with the
+    // maximum depth.
+    assert(false);
+    return null;
+  }
+
+  /**
+   * Return the intersection of the [first] and [second] sets of types, where
+   * intersection is based on the equality of the types themselves.
+   */
+  static List<InstantiatedClass> _intersection(
+    Set<InstantiatedClass> first,
+    Set<InstantiatedClass> second,
+  ) {
+    var result = first.toSet();
+    result.retainAll(second);
+    return result.toList();
+  }
+}
+
+class LeastUpperBoundHelper {
+  final TypeSystemImpl _typeSystem;
+
+  LeastUpperBoundHelper(this._typeSystem);
+
+  InterfaceType get _interfaceTypeFunctionNone {
+    return _typeSystem.typeProvider.functionType.element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get _objectType => _typeSystem.typeProvider.objectType;
+
+  /**
+   * Compute the least upper bound of two types.
+   *
+   * https://github.com/dart-lang/language
+   * See `resources/type-system/upper-lower-bounds.md`
+   */
+  DartType getLeastUpperBound(DartType T1, DartType T2) {
+    // UP(T, T) = T
+    if (identical(T1, T2)) {
+      return T1;
+    }
+
+    // For any type T, UP(?, T) == T.
+    if (identical(T1, UnknownInferredType.instance)) {
+      return T2;
+    }
+    if (identical(T2, UnknownInferredType.instance)) {
+      return T1;
+    }
+
+    var T1_isTop = _typeSystem.isTop(T1);
+    var T2_isTop = _typeSystem.isTop(T2);
+
+    // UP(T1, T2) where TOP(T1) and TOP(T2)
+    if (T1_isTop && T2_isTop) {
+      // * T1 if MORETOP(T1, T2)
+      // * T2 otherwise
+      if (_typeSystem.isMoreTop(T1, T2)) {
+        return T1;
+      } else {
+        return T2;
+      }
+    }
+
+    // UP(T1, T2) = T1 if TOP(T1)
+    if (T1_isTop) {
+      return T1;
+    }
+
+    // UP(T1, T2) = T2 if TOP(T2)
+    if (T2_isTop) {
+      return T2;
+    }
+
+    var T1_isBottom = _typeSystem.isBottom(T1);
+    var T2_isBottom = _typeSystem.isBottom(T2);
+
+    // UP(T1, T2) where BOTTOM(T1) and BOTTOM(T2)
+    if (T1_isBottom && T2_isBottom) {
+      // * T2 if MOREBOTTOM(T1, T2)
+      // * T1 otherwise
+      if (_typeSystem.isMoreBottom(T1, T2)) {
+        return T2;
+      } else {
+        return T1;
+      }
+    }
+
+    // UP(T1, T2) = T2 if BOTTOM(T1)
+    if (T1_isBottom) {
+      return T2;
+    }
+
+    // UP(T1, T2) = T1 if BOTTOM(T2)
+    if (T2_isBottom) {
+      return T1;
+    }
+
+    var T1_isNull = _typeSystem.isNull(T1);
+    var T2_isNull = _typeSystem.isNull(T2);
+
+    // UP(T1, T2) where NULL(T1) and NULL(T2)
+    if (T1_isNull && T2_isNull) {
+      // * T2 if MOREBOTTOM(T1, T2)
+      // * T1 otherwise
+      if (_typeSystem.isMoreBottom(T1, T2)) {
+        return T2;
+      } else {
+        return T1;
+      }
+    }
+
+    var T1_impl = T1 as TypeImpl;
+    var T2_impl = T2 as TypeImpl;
+
+    var T1_nullability = T1_impl.nullabilitySuffix;
+    var T2_nullability = T2_impl.nullabilitySuffix;
+
+    // UP(T1, T2) where NULL(T1)
+    if (T1_isNull) {
+      // * T2 if T2 is nullable
+      // * T2* if Null <: T2 or T1 <: Object (that is, T1 or T2 is legacy)
+      // * T2? otherwise
+      if (_typeSystem.isNullable(T2)) {
+        return T2;
+      } else if (T1_nullability == NullabilitySuffix.star ||
+          T2_nullability == NullabilitySuffix.star) {
+        return T2_impl.withNullability(NullabilitySuffix.star);
+      } else {
+        return _typeSystem.makeNullable(T2);
+      }
+    }
+
+    // UP(T1, T2) where NULL(T2)
+    if (T2_isNull) {
+      // * T1 if T1 is nullable
+      // * T1* if Null <: T1 or T2 <: Object (that is, T1 or T2 is legacy)
+      // * T1? otherwise
+      if (_typeSystem.isNullable(T1)) {
+        return T1;
+      } else if (T1_nullability == NullabilitySuffix.star ||
+          T2_nullability == NullabilitySuffix.star) {
+        return T1_impl.withNullability(NullabilitySuffix.star);
+      } else {
+        return _typeSystem.makeNullable(T1);
+      }
+    }
+
+    var T1_isObject = _typeSystem.isObject(T1);
+    var T2_isObject = _typeSystem.isObject(T2);
+
+    // UP(T1, T2) where OBJECT(T1) and OBJECT(T2)
+    if (T1_isObject && T2_isObject) {
+      // * T1 if MORETOP(T1, T2)
+      // * T2 otherwise
+      if (_typeSystem.isMoreTop(T1, T2)) {
+        return T1;
+      } else {
+        return T2;
+      }
+    }
+
+    // UP(T1, T2) where OBJECT(T1)
+    if (T1_isObject) {
+      // * T1 if T2 is non-nullable
+      // * T1? otherwise
+      if (_typeSystem.isNonNullable(T2)) {
+        return T1;
+      } else {
+        return _typeSystem.makeNullable(T1);
+      }
+    }
+
+    // UP(T1, T2) where OBJECT(T2)
+    if (T2_isObject) {
+      // * T2 if T1 is non-nullable
+      // * T2? otherwise
+      if (_typeSystem.isNonNullable(T1)) {
+        return T2;
+      } else {
+        return _typeSystem.makeNullable(T2);
+      }
+    }
+
+    // UP(T1*, T2*) = S* where S is UP(T1, T2)
+    // UP(T1*, T2?) = S? where S is UP(T1, T2)
+    // UP(T1?, T2*) = S? where S is UP(T1, T2)
+    // UP(T1*, T2) = S* where S is UP(T1, T2)
+    // UP(T1, T2*) = S* where S is UP(T1, T2)
+    // UP(T1?, T2?) = S? where S is UP(T1, T2)
+    // UP(T1?, T2) = S? where S is UP(T1, T2)
+    // UP(T1, T2?) = S? where S is UP(T1, T2)
+    if (T1_nullability != NullabilitySuffix.none ||
+        T2_nullability != NullabilitySuffix.none) {
+      var resultNullability = NullabilitySuffix.none;
+      if (T1_nullability == NullabilitySuffix.question ||
+          T2_nullability == NullabilitySuffix.question) {
+        resultNullability = NullabilitySuffix.question;
+      } else if (T1_nullability == NullabilitySuffix.star ||
+          T2_nullability == NullabilitySuffix.star) {
+        resultNullability = NullabilitySuffix.star;
+      }
+      var T1_none = T1_impl.withNullability(NullabilitySuffix.none);
+      var T2_none = T2_impl.withNullability(NullabilitySuffix.none);
+      var S = getLeastUpperBound(T1_none, T2_none);
+      return (S as TypeImpl).withNullability(resultNullability);
+    }
+
+    assert(T1_nullability == NullabilitySuffix.none);
+    assert(T2_nullability == NullabilitySuffix.none);
+
+    // UP(X1 extends B1, T2)
+    // UP(X1 & B1, T2)
+    if (T1 is TypeParameterType) {
+      // T2 if X1 <: T2
+      if (_typeSystem.isSubtypeOf2(T1, T2)) {
+        return T2;
+      }
+      // otherwise X1 if T2 <: X1
+      if (_typeSystem.isSubtypeOf2(T2, T1)) {
+        return T1;
+      }
+      // otherwise UP(B1[Object/X1], T2)
+      var T1_toObject = _typeParameterResolveToObjectBounds(T1);
+      return getLeastUpperBound(T1_toObject, T2);
+    }
+
+    // UP(T1, X2 extends B2)
+    // UP(T1, X2 & B2)
+    if (T2 is TypeParameterType) {
+      // X2 if T1 <: X2
+      if (_typeSystem.isSubtypeOf2(T1, T2)) {
+        // TODO(scheglov) How to get here?
+        return T2;
+      }
+      // otherwise T1 if X2 <: T1
+      if (_typeSystem.isSubtypeOf2(T2, T1)) {
+        return T1;
+      }
+      // otherwise UP(T1, B2[Object/X2])
+      var T2_toObject = _typeParameterResolveToObjectBounds(T2);
+      return getLeastUpperBound(T1, T2_toObject);
+    }
+
+    // UP(T Function<...>(...), Function) = Function
+    if (T1 is FunctionType && T2.isDartCoreFunction) {
+      return T2;
+    }
+
+    // UP(Function, T Function<...>(...)) = Function
+    if (T1.isDartCoreFunction && T2 is FunctionType) {
+      return T1;
+    }
+
+    // UP(T Function<...>(...), S Function<...>(...)) = Function
+    // And other, more interesting variants.
+    if (T1 is FunctionType && T2 is FunctionType) {
+      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(T1, T2) = T2 if T1 <: T2
+    // UP(T1, T2) = T1 if T2 <: T1
+    // And other, more complex variants of interface types.
+    var helper = InterfaceLeastUpperBoundHelper(_typeSystem);
+    return helper.compute(T1, T2);
+  }
+
+  /**
+   * Compute the least upper bound of function types [f] and [g].
+   *
+   * https://github.com/dart-lang/language
+   * See `resources/type-system/upper-lower-bounds.md`
+   */
+  DartType _functionType(FunctionType f, FunctionType g) {
+    var fTypeFormals = f.typeFormals;
+    var gTypeFormals = g.typeFormals;
+
+    // The number of type parameters must be the same.
+    // Otherwise the result is `Function`.
+    if (fTypeFormals.length != gTypeFormals.length) {
+      return _interfaceTypeFunctionNone;
+    }
+
+    // The bounds of type parameters must be equal.
+    // Otherwise the result is `Function`.
+    var freshTypeFormalTypes =
+        FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
+    if (freshTypeFormalTypes == null) {
+      return _interfaceTypeFunctionNone;
+    }
+
+    var typeFormals = freshTypeFormalTypes
+        .map<TypeParameterElement>((t) => t.element)
+        .toList();
+
+    f = f.instantiate(freshTypeFormalTypes);
+    g = g.instantiate(freshTypeFormalTypes);
+
+    var fParameters = f.parameters;
+    var gParameters = g.parameters;
+
+    var parameters = <ParameterElement>[];
+    var fIndex = 0;
+    var gIndex = 0;
+    while (fIndex < fParameters.length && gIndex < gParameters.length) {
+      var fParameter = fParameters[fIndex];
+      var gParameter = gParameters[gIndex];
+      if (fParameter.isRequiredPositional) {
+        if (gParameter.isRequiredPositional) {
+          fIndex++;
+          gIndex++;
+          parameters.add(
+            ParameterElementImpl.synthetic(
+              fParameter.name,
+              _parameterType(fParameter, gParameter),
+              ParameterKind.REQUIRED,
+            ),
+          );
+        } else {
+          break;
+        }
+      } else if (fParameter.isOptionalPositional) {
+        if (gParameter.isOptionalPositional) {
+          fIndex++;
+          gIndex++;
+          parameters.add(
+            ParameterElementImpl.synthetic(
+              fParameter.name,
+              _parameterType(fParameter, gParameter),
+              ParameterKind.POSITIONAL,
+            ),
+          );
+        } else {
+          break;
+        }
+      } else if (fParameter.isNamed) {
+        if (gParameter.isNamed) {
+          var compareNames = fParameter.name.compareTo(gParameter.name);
+          if (compareNames == 0) {
+            fIndex++;
+            gIndex++;
+            parameters.add(
+              ParameterElementImpl.synthetic(
+                fParameter.name,
+                _parameterType(fParameter, gParameter),
+                fParameter.isRequiredNamed || gParameter.isRequiredNamed
+                    ? ParameterKind.NAMED_REQUIRED
+                    : ParameterKind.NAMED,
+              ),
+            );
+          } else if (compareNames < 0) {
+            if (fParameter.isRequiredNamed) {
+              // We cannot skip required named.
+              return _interfaceTypeFunctionNone;
+            } else {
+              fIndex++;
+            }
+          } else {
+            assert(compareNames > 0);
+            if (gParameter.isRequiredNamed) {
+              // We cannot skip required named.
+              return _interfaceTypeFunctionNone;
+            } else {
+              gIndex++;
+            }
+          }
+        } else {
+          break;
+        }
+      }
+    }
+
+    while (fIndex < fParameters.length) {
+      var fParameter = fParameters[fIndex++];
+      if (fParameter.isNotOptional) {
+        return _interfaceTypeFunctionNone;
+      }
+    }
+
+    while (gIndex < gParameters.length) {
+      var gParameter = gParameters[gIndex++];
+      if (gParameter.isNotOptional) {
+        return _interfaceTypeFunctionNone;
+      }
+    }
+
+    var returnType = getLeastUpperBound(f.returnType, g.returnType);
+
+    return FunctionTypeImpl(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  DartType _parameterType(ParameterElement a, ParameterElement b) {
+    return _typeSystem.getGreatestLowerBound(a.type, b.type);
+  }
+
+  DartType _typeParameterResolveToObjectBounds(DartType type) {
+    var element = type.element;
+    type = type.resolveToBound(_objectType);
+    return Substitution.fromMap({element: _objectType}).substituteType(type);
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
index 25887d8..83c3c78 100644
--- a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
@@ -8,9 +8,8 @@
 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/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/type_system.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';
diff --git a/pkg/analyzer/lib/src/dart/element/subtype.dart b/pkg/analyzer/lib/src/dart/element/subtype.dart
new file mode 100644
index 0000000..77eef3a
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/subtype.dart
@@ -0,0 +1,508 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/dart/element/nullability_suffix.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_algebra.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/element/type_schema.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+
+/// Helper for checking the subtype relation.
+///
+/// https://github.com/dart-lang/language
+/// See `resources/type-system/subtyping.md`
+class SubtypeHelper {
+  final TypeProviderImpl _typeProvider;
+  final InterfaceTypeImpl _nullNone;
+  final InterfaceTypeImpl _objectNone;
+  final InterfaceTypeImpl _objectQuestion;
+
+  SubtypeHelper(TypeSystemImpl typeSystem)
+      : _typeProvider = typeSystem.typeProvider,
+        _nullNone = typeSystem.nullNone,
+        _objectNone = typeSystem.objectNone,
+        _objectQuestion = typeSystem.objectQuestion;
+
+  /// Return `true` if [_T0] is a subtype of [_T1].
+  bool isSubtypeOf(DartType _T0, DartType _T1) {
+    // Reflexivity: if `T0` and `T1` are the same type then `T0 <: T1`.
+    if (identical(_T0, _T1)) {
+      return true;
+    }
+
+    // `?` is treated as a top and a bottom type during inference.
+    if (identical(_T0, UnknownInferredType.instance) ||
+        identical(_T1, UnknownInferredType.instance)) {
+      return true;
+    }
+
+    var T0 = _T0 as TypeImpl;
+    var T1 = _T1 as TypeImpl;
+
+    var T1_nullability = T1.nullabilitySuffix;
+    var T0_nullability = T0.nullabilitySuffix;
+
+    // Right Top: if `T1` is a top type (i.e. `dynamic`, or `void`, or
+    // `Object?`) then `T0 <: T1`.
+    if (identical(T1, DynamicTypeImpl.instance) ||
+        identical(T1, VoidTypeImpl.instance) ||
+        T1_nullability == NullabilitySuffix.question && T1.isDartCoreObject) {
+      return true;
+    }
+
+    // Left Top: if `T0` is `dynamic` or `void`,
+    //   then `T0 <: T1` if `Object? <: T1`.
+    if (identical(T0, DynamicTypeImpl.instance) ||
+        identical(T0, VoidTypeImpl.instance)) {
+      if (isSubtypeOf(_objectQuestion, T1)) {
+        return true;
+      }
+    }
+
+    // Left Bottom: if `T0` is `Never`, then `T0 <: T1`.
+    if (identical(T0, NeverTypeImpl.instance)) {
+      return true;
+    }
+
+    // Right Object: if `T1` is `Object` then:
+    if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreObject) {
+      // * if `T0` is an unpromoted type variable with bound `B`,
+      //   then `T0 <: T1` iff `B <: Object`.
+      // * if `T0` is a promoted type variable `X & S`,
+      //   then `T0 <: T1` iff `S <: Object`.
+      if (T0_nullability == NullabilitySuffix.none &&
+          T0 is TypeParameterTypeImpl) {
+        var S = T0.promotedBound;
+        var B = T0.element.bound;
+        if (S == null && B != null) {
+          return isSubtypeOf(B, _objectNone);
+        }
+        if (S != null) {
+          return isSubtypeOf(S, _objectNone);
+        }
+      }
+      // * if `T0` is `FutureOr<S>` for some `S`,
+      //   then `T0 <: T1` iff `S <: Object`
+      if (T0_nullability == NullabilitySuffix.none &&
+          T0 is InterfaceTypeImpl &&
+          T0.isDartAsyncFutureOr) {
+        return isSubtypeOf(T0.typeArguments[0], T1);
+      }
+      // * if `T0` is `S*` for any `S`, then `T0 <: T1` iff `S <: T1`
+      if (T0_nullability == NullabilitySuffix.star) {
+        return isSubtypeOf(
+          T0.withNullability(NullabilitySuffix.none),
+          T1,
+        );
+      }
+      // * if `T0` is `Null`, `dynamic`, `void`, or `S?` for any `S`,
+      //   then the subtyping does not hold, the result is false.
+      if (T0_nullability == NullabilitySuffix.none && T0.isDartCoreNull ||
+          identical(T0, DynamicTypeImpl.instance) ||
+          identical(T0, VoidTypeImpl.instance) ||
+          T0_nullability == NullabilitySuffix.question) {
+        return false;
+      }
+      // Otherwise `T0 <: T1` is true.
+      return true;
+    }
+
+    // Left Null: if `T0` is `Null` then:
+    if (T0_nullability == NullabilitySuffix.none && T0.isDartCoreNull) {
+      // * If `T1` is `FutureOr<S>` for some `S`, then the query is true iff
+      // `Null <: S`.
+      if (T1_nullability == NullabilitySuffix.none &&
+          T1 is InterfaceTypeImpl &&
+          T1.isDartAsyncFutureOr) {
+        var S = T1.typeArguments[0];
+        return isSubtypeOf(_nullNone, S);
+      }
+      // If `T1` is `Null`, `S?` or `S*` for some `S`, then the query is true.
+      if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull ||
+          T1_nullability == NullabilitySuffix.question ||
+          T1_nullability == NullabilitySuffix.star) {
+        return true;
+      }
+      // * if `T1` is a type variable (promoted or not) the query is false
+      if (T1 is TypeParameterTypeImpl) {
+        return false;
+      }
+      // Otherwise, the query is false.
+      return false;
+    }
+
+    // Left Legacy if `T0` is `S0*` then:
+    if (T0_nullability == NullabilitySuffix.star) {
+      // * `T0 <: T1` iff `S0 <: T1`.
+      var S0 = T0.withNullability(NullabilitySuffix.none);
+      return isSubtypeOf(S0, T1);
+    }
+
+    // Right Legacy `T1` is `S1*` then:
+    //   * `T0 <: T1` iff `T0 <: S1?`.
+    if (T1_nullability == NullabilitySuffix.star) {
+      if (T1 is FunctionType && _isFunctionTypeWithNamedRequired(T0)) {
+        T1 = _functionTypeWithNamedRequired(T1 as FunctionType);
+      }
+      var S1 = T1.withNullability(NullabilitySuffix.question);
+      return isSubtypeOf(T0, S1);
+    }
+
+    // Left FutureOr: if `T0` is `FutureOr<S0>` then:
+    if (T0_nullability == NullabilitySuffix.none &&
+        T0 is InterfaceTypeImpl &&
+        T0.isDartAsyncFutureOr) {
+      var S0 = T0.typeArguments[0];
+      // * `T0 <: T1` iff `Future<S0> <: T1` and `S0 <: T1`
+      if (isSubtypeOf(S0, T1)) {
+        var FutureS0 = _typeProvider.futureElement.instantiate(
+          typeArguments: [S0],
+          nullabilitySuffix: NullabilitySuffix.none,
+        );
+        return isSubtypeOf(FutureS0, T1);
+      }
+      return false;
+    }
+
+    // Left Nullable: if `T0` is `S0?` then:
+    //   * `T0 <: T1` iff `S0 <: T1` and `Null <: T1`.
+    if (T0_nullability == NullabilitySuffix.question) {
+      var S0 = T0.withNullability(NullabilitySuffix.none);
+      return isSubtypeOf(S0, T1) && isSubtypeOf(_nullNone, T1);
+    }
+
+    // Type Variable Reflexivity 1: if T0 is a type variable X0 or a promoted
+    // type variables X0 & S0 and T1 is X0 then:
+    //   * T0 <: T1
+    if (T0 is TypeParameterTypeImpl &&
+        T1 is TypeParameterTypeImpl &&
+        T1.promotedBound == null &&
+        T0.element == T1.element) {
+      return true;
+    }
+
+    // Right Promoted Variable: if `T1` is a promoted type variable `X1 & S1`:
+    //   * `T0 <: T1` iff `T0 <: X1` and `T0 <: S1`
+    if (T1 is TypeParameterTypeImpl && T1.promotedBound != null) {
+      var X1 = TypeParameterTypeImpl(
+        element: T1.element,
+        nullabilitySuffix: T1.nullabilitySuffix,
+      );
+      return isSubtypeOf(T0, X1) && isSubtypeOf(T0, T1.promotedBound);
+    }
+
+    // Right FutureOr: if `T1` is `FutureOr<S1>` then:
+    if (T1_nullability == NullabilitySuffix.none &&
+        T1 is InterfaceTypeImpl &&
+        T1.isDartAsyncFutureOr) {
+      var S1 = T1.typeArguments[0];
+      // `T0 <: T1` iff any of the following hold:
+      // * either `T0 <: Future<S1>`
+      var FutureS1 = _typeProvider.futureElement.instantiate(
+        typeArguments: [S1],
+        nullabilitySuffix: NullabilitySuffix.none,
+      );
+      if (isSubtypeOf(T0, FutureS1)) {
+        return true;
+      }
+      // * or `T0 <: S1`
+      if (isSubtypeOf(T0, S1)) {
+        return true;
+      }
+      // * or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
+      // * or `T0` is `X0 & S0` and `S0 <: T1`
+      if (T0 is TypeParameterTypeImpl) {
+        var S0 = T0.promotedBound;
+        if (S0 != null && isSubtypeOf(S0, T1)) {
+          return true;
+        }
+        var B0 = T0.element.bound;
+        if (B0 != null && isSubtypeOf(B0, T1)) {
+          return true;
+        }
+      }
+      // iff
+      return false;
+    }
+
+    // Right Nullable: if `T1` is `S1?` then:
+    if (T1_nullability == NullabilitySuffix.question) {
+      var S1 = T1.withNullability(NullabilitySuffix.none);
+      // `T0 <: T1` iff any of the following hold:
+      // * either `T0 <: S1`
+      if (isSubtypeOf(T0, S1)) {
+        return true;
+      }
+      // * or `T0 <: Null`
+      if (isSubtypeOf(T0, _nullNone)) {
+        return true;
+      }
+      // or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
+      // or `T0` is `X0 & S0` and `S0 <: T1`
+      if (T0 is TypeParameterTypeImpl) {
+        var S0 = T0.promotedBound;
+        if (S0 != null && isSubtypeOf(S0, T1)) {
+          return true;
+        }
+        var B0 = T0.element.bound;
+        if (B0 != null && isSubtypeOf(B0, T1)) {
+          return true;
+        }
+      }
+      // iff
+      return false;
+    }
+
+    // Super-Interface: `T0` is an interface type with super-interfaces
+    // `S0,...Sn`:
+    //   * and `Si <: T1` for some `i`.
+    if (T0 is InterfaceTypeImpl && T1 is InterfaceTypeImpl) {
+      return _isInterfaceSubtypeOf(T0, T1);
+    }
+
+    // Left Promoted Variable: `T0` is a promoted type variable `X0 & S0`
+    //   * and `S0 <: T1`
+    // Left Type Variable Bound: `T0` is a type variable `X0` with bound `B0`
+    //   * and `B0 <: T1`
+    if (T0 is TypeParameterTypeImpl) {
+      var S0 = T0.promotedBound;
+      if (S0 != null && isSubtypeOf(S0, T1)) {
+        return true;
+      }
+
+      var B0 = T0.element.bound;
+      if (B0 != null && isSubtypeOf(B0, T1)) {
+        return true;
+      }
+    }
+
+    if (T0 is FunctionTypeImpl) {
+      // Function Type/Function: `T0` is a function type and `T1` is `Function`.
+      if (T1.isDartCoreFunction) {
+        return true;
+      }
+      if (T1 is FunctionTypeImpl) {
+        return _isFunctionSubtypeOf(T0, T1);
+      }
+    }
+
+    return false;
+  }
+
+  bool _interfaceArguments(
+    ClassElement element,
+    InterfaceType subType,
+    InterfaceType superType,
+  ) {
+    List<TypeParameterElement> parameters = element.typeParameters;
+    List<DartType> subArguments = subType.typeArguments;
+    List<DartType> superArguments = superType.typeArguments;
+
+    assert(subArguments.length == superArguments.length);
+    assert(parameters.length == subArguments.length);
+
+    for (int i = 0; i < subArguments.length; i++) {
+      var parameter = parameters[i] as TypeParameterElementImpl;
+      var subArgument = subArguments[i];
+      var superArgument = superArguments[i];
+
+      Variance variance = parameter.variance;
+      if (variance.isCovariant) {
+        if (!isSubtypeOf(subArgument, superArgument)) {
+          return false;
+        }
+      } else if (variance.isContravariant) {
+        if (!isSubtypeOf(superArgument, subArgument)) {
+          return false;
+        }
+      } else if (variance.isInvariant) {
+        if (!isSubtypeOf(subArgument, superArgument) ||
+            !isSubtypeOf(superArgument, subArgument)) {
+          return false;
+        }
+      } else {
+        throw StateError(
+          'Type parameter $parameter has unknown '
+          'variance $variance for subtype checking.',
+        );
+      }
+    }
+    return true;
+  }
+
+  /// Check that [f] is a subtype of [g].
+  bool _isFunctionSubtypeOf(FunctionType f, FunctionType g) {
+    var fTypeFormals = f.typeFormals;
+    var gTypeFormals = g.typeFormals;
+
+    // The number of type parameters must be the same.
+    if (fTypeFormals.length != gTypeFormals.length) {
+      return false;
+    }
+
+    // The bounds of type parameters must be equal.
+    var freshTypeFormalTypes =
+        FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) {
+      return isSubtypeOf(t, s) && isSubtypeOf(s, t);
+    });
+    if (freshTypeFormalTypes == null) {
+      return false;
+    }
+
+    f = f.instantiate(freshTypeFormalTypes);
+    g = g.instantiate(freshTypeFormalTypes);
+
+    if (!isSubtypeOf(f.returnType, g.returnType)) {
+      return false;
+    }
+
+    var fParameters = f.parameters;
+    var gParameters = g.parameters;
+
+    var fIndex = 0;
+    var gIndex = 0;
+    while (fIndex < fParameters.length && gIndex < gParameters.length) {
+      var fParameter = fParameters[fIndex];
+      var gParameter = gParameters[gIndex];
+      if (fParameter.isRequiredPositional) {
+        if (gParameter.isRequiredPositional) {
+          if (isSubtypeOf(gParameter.type, fParameter.type)) {
+            fIndex++;
+            gIndex++;
+          } else {
+            return false;
+          }
+        } else {
+          return false;
+        }
+      } else if (fParameter.isOptionalPositional) {
+        if (gParameter.isPositional) {
+          if (isSubtypeOf(gParameter.type, fParameter.type)) {
+            fIndex++;
+            gIndex++;
+          } else {
+            return false;
+          }
+        } else {
+          return false;
+        }
+      } else if (fParameter.isNamed) {
+        if (gParameter.isNamed) {
+          var compareNames = fParameter.name.compareTo(gParameter.name);
+          if (compareNames == 0) {
+            var gIsRequiredOrLegacy = gParameter.isRequiredNamed ||
+                g.nullabilitySuffix == NullabilitySuffix.star;
+            if (fParameter.isRequiredNamed && !gIsRequiredOrLegacy) {
+              return false;
+            } else if (isSubtypeOf(gParameter.type, fParameter.type)) {
+              fIndex++;
+              gIndex++;
+            } else {
+              return false;
+            }
+          } else if (compareNames < 0) {
+            if (fParameter.isRequiredNamed) {
+              return false;
+            } else {
+              fIndex++;
+            }
+          } else {
+            assert(compareNames > 0);
+            // The subtype must accept all parameters of the supertype.
+            return false;
+          }
+        } else {
+          break;
+        }
+      }
+    }
+
+    // The supertype must provide all required parameters to the subtype.
+    while (fIndex < fParameters.length) {
+      var fParameter = fParameters[fIndex++];
+      if (fParameter.isNotOptional) {
+        return false;
+      }
+    }
+
+    // The subtype must accept all parameters of the supertype.
+    assert(fIndex == fParameters.length);
+    if (gIndex < gParameters.length) {
+      return false;
+    }
+
+    return true;
+  }
+
+  bool _isInterfaceSubtypeOf(InterfaceType subType, InterfaceType superType) {
+    // Note: we should never reach `_isInterfaceSubtypeOf` with `i2 == Object`,
+    // because top types are eliminated before `isSubtypeOf` calls this.
+    // TODO(scheglov) Replace with assert().
+    if (identical(subType, superType) || superType.isObject) {
+      return true;
+    }
+
+    // Object cannot subtype anything but itself (handled above).
+    if (subType.isObject) {
+      return false;
+    }
+
+    var subElement = subType.element;
+    var superElement = superType.element;
+    if (subElement == superElement) {
+      return _interfaceArguments(superElement, subType, superType);
+    }
+
+    // Classes types cannot subtype `Function` or vice versa.
+    if (subType.isDartCoreFunction || superType.isDartCoreFunction) {
+      return false;
+    }
+
+    for (var interface in subElement.allSupertypes) {
+      if (interface.element == superElement) {
+        var substitution = Substitution.fromInterfaceType(subType);
+        var substitutedInterface = substitution.substituteType(interface);
+        return _interfaceArguments(
+          superElement,
+          substitutedInterface,
+          superType,
+        );
+      }
+    }
+
+    return false;
+  }
+
+  static FunctionTypeImpl _functionTypeWithNamedRequired(FunctionType type) {
+    return FunctionTypeImpl(
+      typeFormals: type.typeFormals,
+      parameters: type.parameters.map((e) {
+        if (e.isNamed) {
+          return ParameterElementImpl.synthetic(
+            e.name,
+            e.type,
+            ParameterKind.NAMED_REQUIRED,
+          );
+        } else {
+          return e;
+        }
+      }).toList(growable: false),
+      returnType: type.returnType,
+      nullabilitySuffix: type.nullabilitySuffix,
+    );
+  }
+
+  static bool _isFunctionTypeWithNamedRequired(DartType type) {
+    if (type is FunctionType) {
+      return type.parameters.any((e) => e.isRequiredNamed);
+    }
+    return false;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/top_merge.dart b/pkg/analyzer/lib/src/dart/element/top_merge.dart
index 2db7d00..d166d7f 100644
--- a/pkg/analyzer/lib/src/dart/element/top_merge.dart
+++ b/pkg/analyzer/lib/src/dart/element/top_merge.dart
@@ -51,26 +51,26 @@
       return VoidTypeImpl.instance;
     }
 
-    // NNBD_TOP_MERGE(void, Object?) = void
     // NNBD_TOP_MERGE(Object?, void) = void
-    if (T_isVoid && S_isObjectQuestion || T_isObjectQuestion && S_isVoid) {
-      return VoidTypeImpl.instance;
+    // NNBD_TOP_MERGE(void, Object?) = void
+    if (T_isObjectQuestion && S_isVoid || T_isVoid && S_isObjectQuestion) {
+      return typeSystem.objectQuestion;
     }
 
-    // NNBD_TOP_MERGE(void, Object*) = void
     // NNBD_TOP_MERGE(Object*, void) = void
+    // NNBD_TOP_MERGE(void, Object*) = void
     var T_isObjectStar =
         T_nullability == NullabilitySuffix.star && T.isDartCoreObject;
     var S_isObjectStar =
         S_nullability == NullabilitySuffix.star && S.isDartCoreObject;
-    if (T_isVoid && S_isObjectStar || T_isObjectStar && S_isVoid) {
-      return VoidTypeImpl.instance;
+    if (T_isObjectStar && S_isVoid || T_isVoid && S_isObjectStar) {
+      return typeSystem.objectQuestion;
     }
 
-    // NNBD_TOP_MERGE(void, dynamic) = void
     // NNBD_TOP_MERGE(dynamic, void) = void
-    if (T_isVoid && S_isDynamic || T_isDynamic && S_isVoid) {
-      return VoidTypeImpl.instance;
+    // NNBD_TOP_MERGE(void, dynamic) = void
+    if (T_isDynamic && S_isVoid || T_isVoid && S_isDynamic) {
+      return typeSystem.objectQuestion;
     }
 
     // NNBD_TOP_MERGE(Object?, dynamic) = Object?
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 0b61689..9c209a2 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -977,7 +977,18 @@
    * return the type `A<String>`.
    */
   InterfaceType asInstanceOf(ClassElement targetElement) {
-    return _asInstanceOf(targetElement, <ClassElement>{});
+    if (element == targetElement) {
+      return this;
+    }
+
+    for (var rawInterface in element.allSupertypes) {
+      if (rawInterface.element == targetElement) {
+        var substitution = Substitution.fromInterfaceType(this);
+        return substitution.substituteType(rawInterface);
+      }
+    }
+
+    return null;
   }
 
   @override
@@ -1499,43 +1510,6 @@
     );
   }
 
-  /**
-   * Return  either this type or a supertype of this type that is defined by the
-   * [targetElement], or `null` if such a type does not exist. The set of
-   * [visitedClasses] is used to prevent infinite recursion.
-   */
-  InterfaceType _asInstanceOf(
-      ClassElement targetElement, Set<ClassElement> visitedClasses) {
-    ClassElement thisElement = element;
-    if (thisElement == targetElement) {
-      return this;
-    } else if (visitedClasses.add(thisElement)) {
-      InterfaceType type;
-      for (InterfaceType mixin in mixins) {
-        type = (mixin as InterfaceTypeImpl)
-            ._asInstanceOf(targetElement, visitedClasses);
-        if (type != null) {
-          return type;
-        }
-      }
-      if (superclass != null) {
-        type = (superclass as InterfaceTypeImpl)
-            ._asInstanceOf(targetElement, visitedClasses);
-        if (type != null) {
-          return type;
-        }
-      }
-      for (InterfaceType interface in interfaces) {
-        type = (interface as InterfaceTypeImpl)
-            ._asInstanceOf(targetElement, visitedClasses);
-        if (type != null) {
-          return type;
-        }
-      }
-    }
-    return null;
-  }
-
   List<InterfaceType> _instantiateSuperTypes(List<InterfaceType> defined) {
     if (defined.isEmpty) return defined;
 
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index d6635c0..4197381 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -7,8 +7,8 @@
 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_schema.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
-import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary2/function_type_builder.dart';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
 
diff --git a/pkg/analyzer/lib/src/dart/element/type_schema.dart b/pkg/analyzer/lib/src/dart/element/type_schema.dart
new file mode 100644
index 0000000..05469d8
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/type_schema.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/token.dart' show Keyword;
+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/type.dart';
+
+/// A type that is being inferred but is not currently known.
+///
+/// This type will only appear in a downward inference context for type
+/// parameters that we do not know yet. Notationally it is written `?`, for
+/// example `List<?>`. This is distinct from `List<dynamic>`. These types will
+/// never appear in the final resolved AST.
+class UnknownInferredType extends TypeImpl {
+  static final UnknownInferredType instance = UnknownInferredType._();
+
+  UnknownInferredType._() : super(UnknownInferredTypeElement.instance);
+
+  @override
+  int get hashCode => 1;
+
+  @override
+  bool get isDynamic => true;
+
+  @Deprecated('Check element, or use getDisplayString()')
+  @override
+  String get name => Keyword.DYNAMIC.lexeme;
+
+  @override
+  NullabilitySuffix get nullabilitySuffix => NullabilitySuffix.star;
+
+  @override
+  bool operator ==(Object object) => identical(object, this);
+
+  @override
+  void appendTo(ElementDisplayStringBuilder builder) {
+    builder.writeUnknownInferredType();
+  }
+
+  @override
+  DartType replaceTopAndBottom(TypeProvider typeProvider,
+      {bool isCovariant = true}) {
+    // In theory this should never happen, since we only need to do this
+    // replacement when checking super-boundedness of explicitly-specified
+    // types, or types produced by mixin inference or instantiate-to-bounds, and
+    // the unknown type can't occur in any of those cases.
+    assert(
+        false, 'Attempted to check super-boundedness of a type including "?"');
+    // But just in case it does, behave similar to `dynamic`.
+    if (isCovariant) {
+      return typeProvider.nullType;
+    } else {
+      return this;
+    }
+  }
+
+  @override
+  DartType substitute2(
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
+    int length = parameterTypes.length;
+    for (int i = 0; i < length; i++) {
+      if (parameterTypes[i] == this) {
+        return argumentTypes[i];
+      }
+    }
+    return this;
+  }
+
+  @override
+  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) => this;
+
+  /// Given a [type] T, return true if it does not have an unknown type `?`.
+  static bool isKnown(DartType type) => !isUnknown(type);
+
+  /// Given a [type] T, return true if it has an unknown type `?`.
+  static bool isUnknown(DartType type) {
+    if (identical(type, UnknownInferredType.instance)) {
+      return true;
+    }
+    if (type is InterfaceTypeImpl) {
+      return type.typeArguments.any(isUnknown);
+    }
+    if (type is FunctionType) {
+      return isUnknown(type.returnType) ||
+          type.parameters.any((p) => isUnknown(p.type));
+    }
+    return false;
+  }
+}
+
+/// The synthetic element for [UnknownInferredType].
+class UnknownInferredTypeElement extends ElementImpl
+    implements TypeDefiningElement {
+  static final UnknownInferredTypeElement instance =
+      UnknownInferredTypeElement._();
+
+  UnknownInferredTypeElement._() : super(Keyword.DYNAMIC.lexeme, -1) {
+    setModifier(Modifier.SYNTHETIC, true);
+  }
+
+  @override
+  ElementKind get kind => ElementKind.DYNAMIC;
+
+  @override
+  UnknownInferredType get type => UnknownInferredType.instance;
+
+  @override
+  T accept<T>(ElementVisitor visitor) => null;
+}
diff --git a/pkg/analyzer/lib/src/dart/element/type_schema_elimination.dart b/pkg/analyzer/lib/src/dart/element/type_schema_elimination.dart
index 2727d95..3fff1c1 100644
--- a/pkg/analyzer/lib/src/dart/element/type_schema_elimination.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_schema_elimination.dart
@@ -4,7 +4,7 @@
 
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/replacement_visitor.dart';
-import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:meta/meta.dart';
 
 /// Visitor that computes least and greatest closures of a type schema.
diff --git a/pkg/analyzer/lib/src/dart/element/type_visitor.dart b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
index 11ef758..714fac0 100644
--- a/pkg/analyzer/lib/src/dart/element/type_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
@@ -4,7 +4,7 @@
 
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/summary2/function_type_builder.dart';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
 
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 84df830..3128a5d 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -1306,6 +1306,16 @@
           "as an operand of a logical operator.");
 
   /**
+   * If it is not allowed to throw a nullable expression, there is not
+   * need to catch it.
+   */
+  static const HintCode NULLABLE_TYPE_IN_CATCH_CLAUSE = HintCode(
+      'NULLABLE_TYPE_IN_CATCH_CLAUSE',
+      "A potentially nullable type can't be used in an 'on' clause because it "
+          "isn't valid to throw a nullable expression.",
+      correction: "Try using a non-nullable type.");
+
+  /**
    * Hint for classes that override equals, but not hashCode.
    *
    * Parameters:
diff --git a/pkg/analyzer/lib/src/dart/error/lint_codes.dart b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
index 0a3659c..22c0965 100644
--- a/pkg/analyzer/lib/src/dart/error/lint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
@@ -4,13 +4,11 @@
 
 import 'package:analyzer/error/error.dart';
 
-/**
- * Defines style and best practice recommendations.
- *
- * Unlike [HintCode]s, which are akin to traditional static warnings from a
- * compiler, lint recommendations focus on matters of style and practices that
- * might aggregated to define a project's style guide.
- */
+/// Defines style and best practice recommendations.
+///
+/// Unlike [HintCode]s, which are akin to traditional static warnings from a
+/// compiler, lint recommendations focus on matters of style and practices that
+/// might aggregated to define a project's style guide.
 class LintCode extends ErrorCode {
   const LintCode(String name, String message, {String correction})
       : super.temporary(name, message, correction: correction);
@@ -27,14 +25,24 @@
   @override
   ErrorType get type => ErrorType.LINT;
 
-  /**
-   * Overridden so that [LintCode] and its subclasses share the same uniqueName
-   * pattern (we know how to identify a lint even if we don't know the specific
-   * subclass the lint's code is defined in.
-   */
+  /// Overridden so that [LintCode] and its subclasses share the same uniqueName
+  /// pattern (we know how to identify a lint even if we don't know the specific
+  /// subclass the lint's code is defined in.
   @override
   String get uniqueName => "LintCode.$name";
 
   @override
   String get url => 'https://dart-lang.github.io/linter/lints/$name.html';
 }
+
+/// Defines security-related best practice recommendations.
+///
+/// The primary difference from [LintCode]s is that these codes cannot be
+/// suppressed with `// ignore:` or `// ignore_for_file:` comments.
+class SecurityLintCode extends LintCode {
+  const SecurityLintCode(String name, String message, {String correction})
+      : super(name, message, correction: correction);
+
+  @override
+  bool get isIgnorable => false;
+}
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 6dda3a4..3accea6 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -269,12 +269,20 @@
     }
 
     var content = _getFileContent(file.path);
-    unit.accept(BestPracticesVerifier(
-        errorReporter, _typeProvider, _libraryElement, unit, content,
+    unit.accept(
+      BestPracticesVerifier(
+        errorReporter,
+        _typeProvider,
+        _libraryElement,
+        unit,
+        content,
+        declaredVariables: _declaredVariables,
         typeSystem: _typeSystem,
         inheritanceManager: _inheritance,
         resourceProvider: _resourceProvider,
-        analysisOptions: _context.analysisOptions));
+        analysisOptions: _context.analysisOptions,
+      ),
+    );
 
     unit.accept(OverrideVerifier(
       _inheritance,
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index 0409d1a..8875b3e 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -61,6 +61,7 @@
   final Set<FileState> directReferencedLibraries = Set();
   final List<FileState> libraryFiles = [];
 
+  List<int> _digest;
   bool _exists;
   List<int> _apiSignature;
   UnlinkedUnit2 unlinked2;
@@ -70,6 +71,8 @@
 
   List<int> get apiSignature => _apiSignature;
 
+  List<int> get digest => _digest;
+
   bool get exists => _exists;
 
   /// Return the [LibraryCycle] this file belongs to, even if it consists of
@@ -81,6 +84,8 @@
     return _libraryCycle;
   }
 
+  LineInfo get lineInfo => LineInfo(unlinked2.lineStarts);
+
   /// Return the [uri] string.
   String get uriStr => uri.toString();
 
@@ -123,8 +128,8 @@
   }
 
   void refresh() {
-    var digest = utf8.encode(_fsState.getFileDigest(path));
-    _exists = digest.isNotEmpty;
+    _digest = utf8.encode(_fsState.getFileDigest(path));
+    _exists = _digest.isNotEmpty;
     String unlinkedKey = path;
 
     // Prepare bytes of the unlinked bundle - existing or new.
@@ -136,7 +141,7 @@
       if (bytes != null) {
         var ciderUnlinkedUnit = CiderUnlinkedUnit.fromBuffer(bytes);
         if (!const ListEquality()
-            .equals(ciderUnlinkedUnit.contentDigest, digest)) {
+            .equals(ciderUnlinkedUnit.contentDigest, _digest)) {
           bytes = null;
         }
       }
@@ -150,7 +155,7 @@
         }
         var unit = parse(AnalysisErrorListener.NULL_LISTENER, content);
         _fsState._logger.run('Create unlinked for $path', () {
-          var unlinkedBuilder = serializeAstCiderUnlinked(digest, unit);
+          var unlinkedBuilder = serializeAstCiderUnlinked(_digest, unit);
           bytes = unlinkedBuilder.toBuffer();
           _fsState._byteStore.put(unlinkedKey, bytes);
         });
@@ -420,7 +425,7 @@
   /// files that [libraries] reference (but we don't compute these files).
   List<int> signature;
 
-  // The hash for all the paths of the files in this cycle.
+  /// The hash of all the paths of the files in this cycle.
   String cyclePathsHash;
 
   LibraryCycle();
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 401bbe7..1ce64a5 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -4,17 +4,19 @@
 
 import 'dart:typed_data';
 
-import 'package:analyzer/dart/analysis/context_locator.dart';
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/context/packages.dart';
 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/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/results.dart';
@@ -23,19 +25,22 @@
 import 'package:analyzer/src/dart/micro/analysis_context.dart';
 import 'package:analyzer/src/dart/micro/library_analyzer.dart';
 import 'package:analyzer/src/dart/micro/library_graph.dart';
+import 'package:analyzer/src/generated/engine.dart'
+    show AnalysisEngine, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/api_signature.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/link.dart' as link2;
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:collection/collection.dart';
+import 'package:meta/meta.dart';
+import 'package:yaml/yaml.dart';
 
-/*
- * Resolves a single file.
- */
 class FileResolver {
   final PerformanceLog logger;
   final ResourceProvider resourceProvider;
@@ -55,125 +60,265 @@
    */
   final void Function(List<String> paths) prefetchFiles;
 
-  Workspace workspace;
+  final Workspace workspace;
+
+  /// This field gets value only during testing.
+  FileResolverTestView testView;
 
   MicroAnalysisContextImpl analysisContext;
 
+  FileSystemState fsState;
+
+  _LibraryContext libraryContext;
+
   FileResolver(this.logger, this.resourceProvider, this.byteStore,
       this.sourceFactory, this.getFileDigest, this.prefetchFiles,
-      {Workspace workspace})
+      {@required Workspace workspace})
       : this.workspace = workspace;
 
   FeatureSet get defaultFeatureSet => FeatureSet.fromEnableFlags([]);
 
+  ErrorsResult getErrors(String path) {
+    _throwIfNotAbsoluteNormalizedPath(path);
+
+    return logger.run('Get errors for $path', () {
+      var fileContext = _createFileContext(path);
+      var file = fileContext.file;
+
+      var errorsSignatureBuilder = ApiSignature();
+      errorsSignatureBuilder.addBytes(file.libraryCycle.signature);
+      errorsSignatureBuilder.addBytes(file.digest);
+      var errorsSignature = errorsSignatureBuilder.toByteList();
+
+      var errorsKey = file.path + '.errors';
+      var bytes = byteStore.get(errorsKey);
+
+      List<AnalysisError> errors;
+      if (bytes != null) {
+        var data = CiderUnitErrors.fromBuffer(bytes);
+        if (const ListEquality().equals(data.signature, errorsSignature)) {
+          errors = data.errors.map((error) {
+            return ErrorEncoding.decode(file.source, error);
+          }).toList();
+        }
+      }
+
+      if (errors == null) {
+        var unitResult = resolve(path);
+        errors = unitResult.errors;
+
+        bytes = CiderUnitErrorsBuilder(
+          signature: errorsSignature,
+          errors: errors.map((ErrorEncoding.encode)).toList(),
+        ).toBuffer();
+        byteStore.put(errorsKey, bytes);
+      }
+
+      return ErrorsResultImpl(
+        libraryContext.analysisSession,
+        path,
+        file.uri,
+        file.lineInfo,
+        false, // isPart
+        errors,
+      );
+    });
+  }
+
   ResolvedUnitResult resolve(String path) {
     _throwIfNotAbsoluteNormalizedPath(path);
 
     return logger.run('Resolve $path', () {
+      var fileContext = _createFileContext(path);
+      var file = fileContext.file;
+
+      libraryContext.load2(file);
+
+      testView?.addResolvedFile(path);
+
+      var errorListener = RecordingErrorListener();
+      var content = resourceProvider.getFile(path).readAsStringSync();
+      var unit = file.parse(errorListener, content);
+
+      Map<FileState, UnitAnalysisResult> results;
+      logger.run('Compute analysis results', () {
+        var libraryAnalyzer = LibraryAnalyzer(
+          fileContext.analysisOptions,
+          analysisContext.declaredVariables,
+          sourceFactory,
+          (_) => true,
+          // _isLibraryUri
+          libraryContext.analysisContext,
+          libraryContext.elementFactory,
+          libraryContext.inheritanceManager,
+          file,
+          resourceProvider,
+          (String path) => resourceProvider.getFile(path).readAsStringSync(),
+        );
+
+        results = libraryAnalyzer.analyzeSync();
+      });
+      UnitAnalysisResult fileResult = results[file];
+
+      return ResolvedUnitResultImpl(
+        analysisContext.currentSession,
+        path,
+        file.uri,
+        file.exists,
+        content,
+        unit.lineInfo,
+        false, // isPart
+        fileResult.unit,
+        fileResult.errors,
+      );
+    });
+  }
+
+  /// Make sure that [analysisContext], [fsState] and [libraryContext] are
+  /// compatible with the given [fileAnalysisOptions].
+  ///
+  /// Specifically we check that `implicit-casts` and `strict-inference`
+  /// flags are the same, so the type systems would be the same.
+  void _createContext(AnalysisOptionsImpl fileAnalysisOptions) {
+    if (analysisContext != null) {
+      var analysisOptions = analysisContext.analysisOptions;
+      var analysisOptionsImpl = analysisOptions as AnalysisOptionsImpl;
+      if (analysisOptionsImpl.implicitCasts !=
+              fileAnalysisOptions.implicitCasts ||
+          analysisOptionsImpl.strictInference !=
+              fileAnalysisOptions.strictInference) {
+        logger.writeln(
+          'Reset the context, different type system affecting options.',
+        );
+        fsState = null; // TODO(scheglov) don't do this
+        analysisContext = null;
+        libraryContext = null;
+      }
+    }
+
+    var analysisOptions = AnalysisOptionsImpl()
+      ..implicitCasts = fileAnalysisOptions.implicitCasts
+      ..strictInference = fileAnalysisOptions.strictInference;
+
+    if (fsState == null) {
+      var featureSetProvider = FeatureSetProvider.build(
+        resourceProvider: resourceProvider,
+        packages: Packages.empty,
+        packageDefaultFeatureSet: analysisOptions.contextFeatures,
+        nonPackageDefaultFeatureSet: analysisOptions.nonPackageFeatureSet,
+      );
+
+      fsState = FileSystemState(
+        logger,
+        resourceProvider,
+        byteStore,
+        sourceFactory,
+        analysisOptions,
+        Uint32List(0), // linkedSalt
+        featureSetProvider,
+        getFileDigest,
+        prefetchFiles,
+      );
+    }
+
+    if (analysisContext == null) {
       logger.run('Create AnalysisContext', () {
-        var contextLocator = ContextLocator(
-          resourceProvider: this.resourceProvider,
+        var root = ContextRootImpl(
+          resourceProvider,
+          resourceProvider.getFolder(workspace.root),
         );
 
-        var roots = contextLocator.locateRoots(
-          includedPaths: [path],
-          excludedPaths: [],
-        );
-        if (roots.length != 1) {
-          throw StateError('Exactly one root expected: $roots');
-        }
-        var root = roots[0];
-
-        var analysisOptions = AnalysisOptionsImpl();
-        var declaredVariables = DeclaredVariables();
-
         analysisContext = MicroAnalysisContextImpl(
           this,
           root,
           analysisOptions,
-          declaredVariables,
+          DeclaredVariables(),
           sourceFactory,
           resourceProvider,
           workspace: workspace,
         );
       });
+    }
 
-      return _resolve(path);
-    });
+    if (libraryContext == null) {
+      libraryContext = _LibraryContext(
+        logger,
+        resourceProvider,
+        byteStore,
+        analysisContext.currentSession,
+        analysisContext.analysisOptions,
+        sourceFactory,
+        analysisContext.declaredVariables,
+      );
+    }
   }
 
-  ResolvedUnitResultImpl _resolve(String path) {
-    var options = analysisContext.analysisOptions;
-    var featureSetProvider = FeatureSetProvider.build(
-      resourceProvider: resourceProvider,
-      packages: Packages.empty,
-      packageDefaultFeatureSet: analysisContext.analysisOptions.contextFeatures,
-      nonPackageDefaultFeatureSet:
-          (options as AnalysisOptionsImpl).nonPackageFeatureSet,
-    );
+  _FileContext _createFileContext(String path) {
+    var analysisOptions = _getAnalysisOptions(path);
 
-    var fsState = FileSystemState(
-      logger,
-      resourceProvider,
-      byteStore,
-      analysisContext.sourceFactory,
-      analysisContext.analysisOptions,
-      Uint32List(0), // linkedSalt
-      featureSetProvider,
-      getFileDigest,
-      prefetchFiles,
-    );
+    _createContext(analysisOptions);
 
-    FileState file;
-    logger.run('Get file $path', () {
-      file = fsState.getFileForPath(path);
+    var file = logger.run('Get file $path', () {
+      return fsState.getFileForPath(path);
     });
 
-    var errorListener = RecordingErrorListener();
-    var content = resourceProvider.getFile(path).readAsStringSync();
-    var unit = file.parse(errorListener, content);
+    return _FileContext(analysisOptions, file);
+  }
 
-    _LibraryContext libraryContext = _LibraryContext(
-      logger,
-      resourceProvider,
-      byteStore,
-      analysisContext.currentSession,
-      analysisContext.analysisOptions,
-      analysisContext.sourceFactory,
-      analysisContext.declaredVariables,
-    );
-    libraryContext.load2(file);
+  File _findOptionsFile(Folder folder) {
+    while (folder != null) {
+      File packagesFile =
+          _getFile(folder, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
+      if (packagesFile != null) {
+        return packagesFile;
+      }
+      folder = folder.parent;
+    }
+    return null;
+  }
 
-    Map<FileState, UnitAnalysisResult> results;
-    logger.run('Compute analysis results', () {
-      var libraryAnalyzer = LibraryAnalyzer(
-        analysisContext.analysisOptions,
-        analysisContext.declaredVariables,
-        analysisContext.sourceFactory,
-        (_) => true, // _isLibraryUri
-        libraryContext.analysisContext,
-        libraryContext.elementFactory,
-        libraryContext.inheritanceManager,
-        file,
-        resourceProvider,
-        (String path) => resourceProvider.getFile(path).readAsStringSync(),
-      );
+  /// Return the analysis options.
+  ///
+  /// If the [optionsFile] is not `null`, read it.
+  ///
+  /// If the [workspace] is a [WorkspaceWithDefaultAnalysisOptions], get the
+  /// default options, if the file exists.
+  ///
+  /// Otherwise, return the default options.
+  AnalysisOptionsImpl _getAnalysisOptions(String path) {
+    YamlMap optionMap;
+    var folder = resourceProvider.getFile(path).parent;
+    var optionsFile = _findOptionsFile(folder);
+    if (optionsFile != null) {
+      try {
+        var optionsProvider = AnalysisOptionsProvider(sourceFactory);
+        optionMap = optionsProvider.getOptionsFromFile(optionsFile);
+      } catch (e) {
+        // ignored
+      }
+    } else {
+      Source source;
+      if (workspace is WorkspaceWithDefaultAnalysisOptions) {
+        source = sourceFactory.forUri(WorkspaceWithDefaultAnalysisOptions.uri);
+      }
 
-      results = libraryAnalyzer.analyzeSync();
-    });
-    UnitAnalysisResult fileResult = results[file];
+      if (source != null && source.exists()) {
+        try {
+          var optionsProvider = AnalysisOptionsProvider(sourceFactory);
+          optionMap = optionsProvider.getOptionsFromSource(source);
+        } catch (e) {
+          // ignored
+        }
+      }
+    }
 
-    return ResolvedUnitResultImpl(
-      analysisContext.currentSession,
-      path,
-      file.uri,
-      file.exists,
-      content,
-      unit.lineInfo,
-      false, // isPart
-      fileResult.unit,
-      fileResult.errors,
-    );
+    var options = AnalysisOptionsImpl();
+
+    if (optionMap != null) {
+      applyToAnalysisOptions(options, optionMap);
+    }
+
+    return options;
   }
 
   void _throwIfNotAbsoluteNormalizedPath(String path) {
@@ -184,6 +329,32 @@
       );
     }
   }
+
+  static File _getFile(Folder directory, String name) {
+    Resource resource = directory.getChild(name);
+    if (resource is File && resource.exists) {
+      return resource;
+    }
+    return null;
+  }
+}
+
+class FileResolverTestView {
+  /// The paths of files which were resolved.
+  ///
+  /// The file path is added every time when it is resolved.
+  final List<String> resolvedFiles = [];
+
+  void addResolvedFile(String path) {
+    resolvedFiles.add(path);
+  }
+}
+
+class _FileContext {
+  final AnalysisOptionsImpl analysisOptions;
+  final FileState file;
+
+  _FileContext(this.analysisOptions, this.file);
 }
 
 class _LibraryContext {
@@ -354,14 +525,6 @@
     inheritanceManager = InheritanceManager3();
   }
 
-  static CiderLinkedLibraryCycleBuilder serializeBundle(
-      List<int> signature, link2.LinkResult linkResult) {
-    return CiderLinkedLibraryCycleBuilder(
-      signature: signature,
-      bundle: linkResult.bundle,
-    );
-  }
-
   void _createElementFactory() {
     elementFactory = LinkedElementFactory(
       analysisContext,
@@ -378,4 +541,12 @@
       elementFactory.createTypeProviders(dartCore, dartAsync);
     }
   }
+
+  static CiderLinkedLibraryCycleBuilder serializeBundle(
+      List<int> signature, link2.LinkResult linkResult) {
+    return CiderLinkedLibraryCycleBuilder(
+      signature: signature,
+      bundle: linkResult.bundle,
+    );
+  }
 }
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 fd27511..f668b54 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -8,8 +8,10 @@
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/generic_inferrer.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/resolver/resolution_result.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
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 81ce4ed..e5a22d0 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -26,7 +26,7 @@
 
   /// The list of [Expression]s representing variable accesses that occur before
   /// the corresponding variable has been definitely assigned.
-  final List<AstNode> unassignedNodes = [];
+  final List<AstNode> potentiallyUnassignedNodes = [];
 
   /// The list of [SimpleIdentifier]s representing variable accesses that occur
   /// when the corresponding variable has been definitely unassigned.
@@ -181,12 +181,11 @@
     var element = node.staticElement;
     if (element is LocalVariableElement) {
       var typeSystem = _typeOperations.typeSystem;
+      var isUnassigned = !flow.isAssigned(element);
+      if (isUnassigned) {
+        dataForTesting?.potentiallyUnassignedNodes?.add(node);
+      }
       if (typeSystem.isPotentiallyNonNullable(element.type)) {
-        var isUnassigned = !flow.isAssigned(element);
-        if (isUnassigned) {
-          dataForTesting?.unassignedNodes?.add(node);
-        }
-
         // Note: in principle we could make this slightly more performant by
         // checking element.isLate earlier, but we would lose the ability to
         // test the flow analysis mechanism using late variables.  And it seems
diff --git a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
index efb83e0..030a398 100644
--- a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
@@ -8,9 +8,9 @@
 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/element/type_schema.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/type_system.dart';
 import 'package:meta/meta.dart';
 
 /// Helper for resolving [ForStatement]s and [ForElement]s.
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index dd3dbcd1..7382c03 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -178,6 +178,7 @@
 
         exceptionNode.staticElement = element;
 
+        element.isFinal = true;
         if (exceptionTypeNode == null) {
           element.hasImplicitType = true;
           element.type = _dynamicType;
@@ -201,6 +202,7 @@
 
         stackTraceNode.staticElement = element;
 
+        element.isFinal = true;
         element.type = _typeProvider.stackTraceType;
         stackTraceNode.staticType = _typeProvider.stackTraceType;
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index 238602d..b955c20 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -12,6 +12,7 @@
 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/element/type_schema.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 6c5f405..71bcb62 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -4,7 +4,6 @@
 
 import 'dart:collection';
 
-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';
@@ -85,21 +84,14 @@
     this._currentLibrary,
     CompilationUnit unit,
     String content, {
-    TypeSystemImpl typeSystem,
+    @required TypeSystemImpl typeSystem,
     @required InheritanceManager3 inheritanceManager,
-    ResourceProvider resourceProvider,
-    DeclaredVariables declaredVariables,
-    AnalysisOptions analysisOptions,
+    @required ResourceProvider resourceProvider,
+    @required DeclaredVariables declaredVariables,
+    @required AnalysisOptions analysisOptions,
   })  : _nullType = typeProvider.nullType,
-        _typeSystem = typeSystem ??
-            TypeSystemImpl(
-              implicitCasts: true,
-              isNonNullableByDefault: false,
-              strictInference: false,
-              typeProvider: typeProvider,
-            ),
-        _isNonNullableByDefault =
-            unit.featureSet.isEnabled(Feature.non_nullable),
+        _typeSystem = typeSystem,
+        _isNonNullableByDefault = typeSystem.isNonNullableByDefault,
         _strictInference =
             (analysisOptions as AnalysisOptionsImpl).strictInference,
         _inheritanceManager = inheritanceManager,
@@ -242,6 +234,12 @@
   }
 
   @override
+  void visitCatchClause(CatchClause node) {
+    super.visitCatchClause(node);
+    _checkForNullableTypeInCatchClause(node);
+  }
+
+  @override
   void visitClassDeclaration(ClassDeclaration node) {
     ClassElementImpl element = node.declaredElement;
     _enclosingClass = element;
@@ -1163,6 +1161,24 @@
     }
   }
 
+  void _checkForNullableTypeInCatchClause(CatchClause node) {
+    if (!_isNonNullableByDefault) {
+      return;
+    }
+
+    var type = node.exceptionType;
+    if (type == null) {
+      return;
+    }
+
+    if (_typeSystem.isPotentiallyNullable(type.type)) {
+      _errorReporter.reportErrorForNode(
+        HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE,
+        type,
+      );
+    }
+  }
+
   /// Produce several null-aware related hints.
   void _checkForNullAwareHints(Expression node, Token operator) {
     if (_isNonNullableByDefault) {
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 9ab905c..1f1150b 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1566,19 +1566,6 @@
       hasPublishedDocs: true);
 
   /**
-   * 18.3 Parts: It's a compile-time error if the same library contains two part
-   * directives with the same URI.
-   *
-   * Parameters:
-   * 0: the URI of the duplicate part
-   */
-  static const CompileTimeErrorCode DUPLICATE_PART = CompileTimeErrorCode(
-      'DUPLICATE_PART',
-      "The library already contains a part with the uri '{0}'.",
-      correction:
-          "Try removing all but one of the duplicated part directives.");
-
-  /**
    * Parameters:
    * 0: the name of the parameter that was duplicated
    */
@@ -1636,6 +1623,24 @@
           hasPublishedDocs: true);
 
   /**
+   * 18.3 Parts: It's a compile-time error if the same library contains two part
+   * directives with the same URI.
+   *
+   * Parameters:
+   * 0: the URI of the duplicate part
+   */
+  static const CompileTimeErrorCode DUPLICATE_PART = CompileTimeErrorCode(
+      'DUPLICATE_PART',
+      "The library already contains a part with the uri '{0}'.",
+      correction:
+          "Try removing all but one of the duplicated part directives.");
+
+  static const CompileTimeErrorCode ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING =
+      CompileTimeErrorCode('ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING',
+          "The name of the enum constant can't be the same as the enum's name.",
+          correction: "Try renaming the constant.");
+
+  /**
    * No parameters.
    */
   // #### Description
@@ -4551,17 +4556,6 @@
               "spread.");
 
   /**
-   * It is an error if the type `T` in the on-catch clause `on T catch` is
-   * potentially nullable.
-   */
-  static const CompileTimeErrorCode NULLABLE_TYPE_IN_CATCH_CLAUSE =
-      CompileTimeErrorCode(
-          'NULLABLE_TYPE_IN_CATCH_CLAUSE',
-          "A nullable type can't be used in an 'on' clause because it isn't "
-              "valid to throw 'null'.",
-          correction: "Try removing the question mark.");
-
-  /**
    * No parameters.
    */
   /* #### Description
@@ -5164,6 +5158,14 @@
           correction: "Try adding 'break', or 'return', etc.");
 
   /**
+   * It is an error if the static type of `e` in the expression `throw e` is
+   * not assignable to `Object`.
+   */
+  static const CompileTimeErrorCode THROW_OF_INVALID_TYPE = CompileTimeErrorCode(
+      'THROW_OF_INVALID_TYPE',
+      "The type '{0}' of the thrown expression must be assignable to Object.");
+
+  /**
    * Parameters:
    * 0: the name of the type used in the instance creation that should be
    *    limited by the bound as specified in the class declaration
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 8c8837f..dea3b72 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -42,24 +42,29 @@
     Map<String, Element> instanceGetters = HashMap<String, Element>();
     Map<String, Element> staticGetters = HashMap<String, Element>();
 
-    String indexName = 'index';
-    String valuesName = 'values';
-    instanceGetters[indexName] = element.getGetter(indexName);
-    staticGetters[valuesName] = element.getGetter(valuesName);
+    instanceGetters['index'] = element.getGetter('index');
+    instanceGetters['toString'] = element.getMethod('toString');
+    staticGetters['values'] = element.getGetter('values');
 
     for (EnumConstantDeclaration constant in node.constants) {
       _checkDuplicateIdentifier(staticGetters, constant.name);
     }
 
+    String enumName = element.name;
     for (EnumConstantDeclaration constant in node.constants) {
       SimpleIdentifier identifier = constant.name;
       String name = identifier.name;
-      if (instanceGetters.containsKey(name)) {
-        String enumName = element.displayName;
+      if (name == enumName) {
         _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
-            identifier,
-            [enumName, name, enumName]);
+          CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
+          identifier,
+        );
+      } else if (instanceGetters.containsKey(name)) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
+          identifier,
+          [enumName, name, enumName],
+        );
       }
     }
   }
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index 98e1df1..ac089e4 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/error/listener.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_schema.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart';
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index 1b84b71..94bd973 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -108,12 +108,21 @@
       }
     } else {
       _useIdentifierElement(node);
+      var enclosingElement = element?.enclosingElement;
       if (element == null) {
         if (isIdentifierRead) {
           usedElements.unresolvedReadMembers.add(node.name);
         }
-      } else if ((element.enclosingElement is ClassElement ||
-              element.enclosingElement is ExtensionElement) &&
+      } else if (enclosingElement is ClassElement &&
+          enclosingElement.isEnum &&
+          element.name == 'values') {
+        // If the 'values' static accessor of the enum is accessed, then all of
+        // the enum values have been read.
+        for (var value in enclosingElement.fields) {
+          usedElements.readMembers.add(value.getter);
+        }
+      } else if ((enclosingElement is ClassElement ||
+              enclosingElement is ExtensionElement) &&
           !identical(element, _enclosingExec)) {
         usedElements.members.add(element);
         if (isIdentifierRead) {
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 7828dae..770dd99 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -699,6 +699,8 @@
       prefixOrName = name.prefix;
       period = name.period;
       nameOrNull = name.identifier;
+    } else if (name is _OperatorName) {
+      prefixOrName = name.name;
     } else {
       throw UnimplementedError(
           'name is an instance of ${name.runtimeType} in endClassConstructor');
@@ -2259,6 +2261,14 @@
   }
 
   @override
+  void beginAsOperatorType(Token asOperator) {}
+
+  @override
+  void endAsOperatorType(Token asOperator) {
+    debugEvent("AsOperatorType");
+  }
+
+  @override
   void handleAsOperator(Token asOperator) {
     assert(optional('as', asOperator));
     debugEvent("AsOperator");
@@ -2817,6 +2827,14 @@
   }
 
   @override
+  void beginIsOperatorType(Token asOperator) {}
+
+  @override
+  void endIsOperatorType(Token asOperator) {
+    debugEvent("IsOperatorType");
+  }
+
+  @override
   void handleIsOperator(Token isOperator, Token not) {
     assert(optional('is', isOperator));
     assert(optionalOrNull('!', not));
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index cc87d16..22e20e2 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -703,15 +703,6 @@
       return;
     }
     //
-    // The name dynamic denotes a Type object even though dynamic is not a
-    // class.
-    //
-    if (node.name == 'dynamic') {
-      node.staticElement = _dynamicType.element;
-      node.staticType = _typeType;
-      return;
-    }
-    //
     // Otherwise, the node should be resolved.
     //
     Element element = _resolveSimpleIdentifier(node);
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index aa2c4e3..785ccbd 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -221,6 +221,7 @@
 
   /// Function that returns `true` if analysis is to parse and analyze function
   /// bodies for a given source.
+  @deprecated
   AnalyzeFunctionBodiesPredicate get analyzeFunctionBodiesPredicate;
 
   /// Return the maximum number of sources for which AST structures should be
@@ -247,6 +248,7 @@
   /// This option should not be used when the analyzer is part of a long running
   /// process (such as the analysis server) because it has the potential to
   /// prevent memory from being reclaimed.
+  @deprecated
   bool get disableCacheFlushing;
 
   /// Return `true` if the parser is to parse asserts in the initializer list of
@@ -281,6 +283,7 @@
 
   /// Return `true` to enable the lazy compound assignment operators '&&=' and
   /// '||='.
+  @deprecated
   bool get enableLazyAssignmentOperators;
 
   /// Return `true` if mixins are allowed to inherit from types other than
@@ -305,10 +308,12 @@
 
   /// Return `true` if errors, warnings and hints should be generated for sources
   /// that are implicitly being analyzed. The default value is `true`.
+  @deprecated
   bool get generateImplicitErrors;
 
   /// Return `true` if errors, warnings and hints should be generated for sources
   /// in the SDK. The default value is `false`.
+  @deprecated
   bool get generateSdkErrors;
 
   /// Return `true` if analysis is to generate hint results (e.g. type inference
@@ -324,9 +329,11 @@
 
   /// A mapping from Dart SDK library name (e.g. "dart:core") to a list of paths
   /// to patch files that should be applied to the library.
+  @deprecated
   Map<String, List<String>> get patchPaths;
 
   /// Return `true` if analysis is to parse comments.
+  @deprecated
   bool get preserveComments;
 
   /// Return `true` if analyzer should enable the use of Dart 2.0 features.
@@ -356,6 +363,7 @@
   /// by analysis cache.  This option should only be set to `false` if analysis
   /// is performed in such a way that none of the inputs is ever changed
   /// during the life time of the context.
+  @deprecated
   bool get trackCacheDependencies;
 
   /// Return `true` if analyzer should use the Dart 2.0 Front End parser.
@@ -365,6 +373,7 @@
   bool isLintEnabled(String name);
 
   /// Reset the state of this set of analysis options to its original state.
+  @deprecated
   void resetToDefaults();
 
   /// Set the values of the cross-context options to match those in the given set
@@ -403,6 +412,7 @@
 
   /// A predicate indicating whether analysis is to parse and analyze function
   /// bodies.
+  @deprecated
   AnalyzeFunctionBodiesPredicate _analyzeFunctionBodiesPredicate =
       _analyzeAllFunctionBodies;
 
@@ -434,6 +444,7 @@
   @override
   List<String> enabledPluginNames = const <String>[];
 
+  @deprecated
   @override
   bool enableLazyAssignmentOperators = false;
 
@@ -447,9 +458,11 @@
   /// A list of exclude patterns used to exclude some sources from analysis.
   List<String> _excludePatterns;
 
+  @deprecated
   @override
   bool generateImplicitErrors = true;
 
+  @deprecated
   @override
   bool generateSdkErrors = false;
 
@@ -463,18 +476,22 @@
   /// `true`.
   List<Linter> _lintRules;
 
+  @deprecated
   @override
   Map<String, List<String>> patchPaths = {};
 
+  @deprecated
   @override
   bool preserveComments = true;
 
+  @deprecated
   @override
   bool trackCacheDependencies = true;
 
   @override
   bool useFastaParser = true;
 
+  @deprecated
   @override
   bool disableCacheFlushing = false;
 
@@ -516,19 +533,24 @@
   /// Initialize a newly created set of analysis options to have the same values
   /// as those in the given set of analysis [options].
   AnalysisOptionsImpl.from(AnalysisOptions options) {
+    // ignore: deprecated_member_use_from_same_package
     analyzeFunctionBodiesPredicate = options.analyzeFunctionBodiesPredicate;
     dart2jsHint = options.dart2jsHint;
     contextFeatures = options.contextFeatures;
     enabledPluginNames = options.enabledPluginNames;
+    // ignore: deprecated_member_use_from_same_package
     enableLazyAssignmentOperators = options.enableLazyAssignmentOperators;
     enableTiming = options.enableTiming;
     errorProcessors = options.errorProcessors;
     excludePatterns = options.excludePatterns;
+    // ignore: deprecated_member_use_from_same_package
     generateImplicitErrors = options.generateImplicitErrors;
+    // ignore: deprecated_member_use_from_same_package
     generateSdkErrors = options.generateSdkErrors;
     hint = options.hint;
     lint = options.lint;
     lintRules = options.lintRules;
+    // ignore: deprecated_member_use_from_same_package
     preserveComments = options.preserveComments;
     useFastaParser = options.useFastaParser;
     if (options is AnalysisOptionsImpl) {
@@ -537,12 +559,16 @@
       strictInference = options.strictInference;
       strictRawTypes = options.strictRawTypes;
     }
+    // ignore: deprecated_member_use_from_same_package
     trackCacheDependencies = options.trackCacheDependencies;
+    // ignore: deprecated_member_use_from_same_package
     disableCacheFlushing = options.disableCacheFlushing;
+    // ignore: deprecated_member_use_from_same_package
     patchPaths = options.patchPaths;
     sdkVersionConstraint = options.sdkVersionConstraint;
   }
 
+  @deprecated
   bool get analyzeFunctionBodies {
     if (identical(analyzeFunctionBodiesPredicate, _analyzeAllFunctionBodies)) {
       return true;
@@ -554,6 +580,7 @@
     }
   }
 
+  @deprecated
   set analyzeFunctionBodies(bool value) {
     if (value) {
       analyzeFunctionBodiesPredicate = _analyzeAllFunctionBodies;
@@ -562,10 +589,12 @@
     }
   }
 
+  @deprecated
   @override
   AnalyzeFunctionBodiesPredicate get analyzeFunctionBodiesPredicate =>
       _analyzeFunctionBodiesPredicate;
 
+  @deprecated
   set analyzeFunctionBodiesPredicate(AnalyzeFunctionBodiesPredicate value) {
     if (value == null) {
       throw ArgumentError.notNull('analyzeFunctionBodiesPredicate');
@@ -701,6 +730,7 @@
       }
 
       // Append boolean flags.
+      // ignore: deprecated_member_use_from_same_package
       buffer.addBool(enableLazyAssignmentOperators);
       buffer.addBool(implicitCasts);
       buffer.addBool(implicitDynamic);
@@ -755,6 +785,7 @@
       ApiSignature buffer = ApiSignature();
 
       // Append boolean flags.
+      // ignore: deprecated_member_use_from_same_package
       buffer.addBool(enableLazyAssignmentOperators);
       buffer.addBool(useFastaParser);
 
@@ -780,6 +811,7 @@
     return lintRules.any((rule) => rule.name == name);
   }
 
+  @deprecated
   @override
   void resetToDefaults() {
     contextFeatures = ExperimentStatus();
@@ -826,10 +858,12 @@
 
   /// Predicate used for [analyzeFunctionBodiesPredicate] when
   /// [analyzeFunctionBodies] is set to `true`.
+  @deprecated
   static bool _analyzeAllFunctionBodies(Source _) => true;
 
   /// Predicate used for [analyzeFunctionBodiesPredicate] when
   /// [analyzeFunctionBodies] is set to `false`.
+  @deprecated
   static bool _analyzeNoFunctionBodies(Source _) => false;
 }
 
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 3336cd5..0a4d3d4 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -15,10 +15,11 @@
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/error/error.dart';
 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/element/class_hierarchy.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
@@ -238,14 +239,6 @@
 
   final _UninstantiatedBoundChecker _uninstantiatedBoundChecker;
 
-  /// Setting this flag to `true` disables the check for conflicting generics.
-  /// This is used when running with the old task model to work around
-  /// dartbug.com/32421.
-  ///
-  /// TODO(paulberry): remove this flag once dartbug.com/32421 is properly
-  /// fixed.
-  final bool disableConflictingGenericsCheck;
-
   /// The features enabled in the unit currently being checked for errors.
   FeatureSet _featureSet;
 
@@ -258,8 +251,7 @@
    * Initialize a newly created error verifier.
    */
   ErrorVerifier(ErrorReporter errorReporter, this._currentLibrary,
-      this._typeProvider, this._inheritanceManager, bool enableSuperMixins,
-      {this.disableConflictingGenericsCheck = false})
+      this._typeProvider, this._inheritanceManager, bool enableSuperMixins)
       : _errorReporter = errorReporter,
         _uninstantiatedBoundChecker =
             _UninstantiatedBoundChecker(errorReporter),
@@ -437,7 +429,6 @@
     try {
       _isInCatchClause = true;
       _checkForTypeAnnotationDeferredClass(node.exceptionType);
-      _checkForNullableTypeInCatchClause(node.exceptionType);
       super.visitCatchClause(node);
     } finally {
       _isInCatchClause = previousIsInCatchClause;
@@ -1212,6 +1203,7 @@
   void visitThrowExpression(ThrowExpression node) {
     _checkForConstEvalThrowsException(node);
     _checkForUseOfVoidResult(node.expression);
+    _checkForThrowOfInvalidType(node);
     super.visitThrowExpression(node);
   }
 
@@ -1332,9 +1324,7 @@
       _checkImplementsSuperClass(implementsClause);
       _checkMixinInference(node, withClause);
       _checkForMixinWithConflictingPrivateMember(withClause, superclass);
-      if (!disableConflictingGenericsCheck) {
-        _checkForConflictingGenerics(node);
-      }
+      _checkForConflictingGenerics(node);
     }
   }
 
@@ -1957,58 +1947,26 @@
   }
 
   void _checkForConflictingGenerics(NamedCompilationUnitMember node) {
-    var visitedClasses = <ClassElement>[];
-    var interfaces = <ClassElement, InterfaceType>{};
+    var element = node.declaredElement as ClassElement;
 
-    void visit(InterfaceType type) {
-      if (type == null) return;
+    var analysisSession = _currentLibrary.session as AnalysisSessionImpl;
+    var errors = analysisSession.classHierarchy.errors(element);
 
-      var element = type.element;
-      if (visitedClasses.contains(element)) return;
-      visitedClasses.add(element);
-
-      if (element.typeParameters.isNotEmpty) {
-        if (_typeSystem.isNonNullableByDefault) {
-          type = _typeSystem.normalize(type);
-          var oldType = interfaces[element];
-          if (oldType == null) {
-            interfaces[element] = type;
-          } else {
-            try {
-              var result = _typeSystem.topMerge(oldType, type);
-              interfaces[element] = result;
-            } catch (_) {
-              _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
-                node,
-                [_enclosingClass.name, oldType, type],
-              );
-            }
-          }
-        } else {
-          type = _toLegacyType(type);
-          var oldType = interfaces[element];
-          if (oldType == null) {
-            interfaces[element] = type;
-          } else if (type != oldType) {
-            _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
-              node,
-              [_enclosingClass.name, oldType, type],
-            );
-          }
-        }
+    for (var error in errors) {
+      if (error is IncompatibleInterfacesClassHierarchyError) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
+          node,
+          [
+            _enclosingClass.name,
+            error.first.getDisplayString(withNullability: true),
+            error.second.getDisplayString(withNullability: true),
+          ],
+        );
+      } else {
+        throw UnimplementedError('${error.runtimeType}');
       }
-
-      visit(type.superclass);
-      type.mixins.forEach(visit);
-      type.superclassConstraints.forEach(visit);
-      type.interfaces.forEach(visit);
-
-      visitedClasses.removeLast();
     }
-
-    visit(_enclosingClass.thisType);
   }
 
   /**
@@ -2554,6 +2512,10 @@
         NamespaceBuilder().createExportNamespaceForDirective(element);
 
     for (var element in namespace.definedNames.values) {
+      if (element == DynamicElementImpl.instance ||
+          element == NeverElementImpl.instance) {
+        continue;
+      }
       if (!element.library.isNonNullableByDefault) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.EXPORT_LEGACY_SYMBOL,
@@ -2872,35 +2834,12 @@
    * If the current function is async, async*, or sync*, verify that its
    * declared return type is assignable to Future, Stream, or Iterable,
    * respectively. This is called by [_checkForIllegalReturnType] to check if
-   * the declared [returnTypeName] is assignable to the required [expectedType]
-   * and if not report [errorCode].
+   * a value with the type of the declared [returnTypeName] is assignable to
+   * [expectedElement] and if not report [errorCode].
    */
   void _checkForIllegalReturnTypeCode(TypeAnnotation returnTypeName,
       ClassElement expectedElement, StaticTypeWarningCode errorCode) {
-    DartType returnType = _enclosingFunction.returnType;
-    //
-    // When checking an async/sync*/async* method, we know the exact type
-    // that will be returned (e.g. Future, Iterable, or Stream).
-    //
-    // For example an `async` function body will return a `Future<T>` for
-    // some `T` (possibly `dynamic`).
-    //
-    // We allow the declared return type to be a supertype of that
-    // (e.g. `dynamic`, `Object`), or Future<S> for some S.
-    // (We assume the T <: S relation is checked elsewhere.)
-    //
-    // We do not allow user-defined subtypes of Future, because an `async`
-    // method will never return those.
-    //
-    // To check for this, we ensure that `Future<bottom> <: returnType`.
-    //
-    // Similar logic applies for sync* and async*.
-    //
-    var lowerBound = expectedElement.instantiate(
-      typeArguments: [NeverTypeImpl.instance],
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
-    if (!_typeSystem.isSubtypeOf2(lowerBound, returnType)) {
+    if (!_isLegalReturnType(expectedElement)) {
       _errorReporter.reportErrorForNode(errorCode, returnTypeName);
     }
   }
@@ -3939,23 +3878,6 @@
     }
   }
 
-  void _checkForNullableTypeInCatchClause(TypeAnnotation type) {
-    if (!_isNonNullableByDefault) {
-      return;
-    }
-
-    if (type == null) {
-      return;
-    }
-
-    if (_typeSystem.isPotentiallyNullable(type.type)) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.NULLABLE_TYPE_IN_CATCH_CLAUSE,
-        type,
-      );
-    }
-  }
-
   /**
    * Verify that all classes of the given [onClause] are valid.
    *
@@ -4349,6 +4271,13 @@
     if (_inAsync) {
       toType = _typeSystem.flatten(toType);
       fromType = _typeSystem.flatten(fromType);
+      if (!_isLegalReturnType(_typeProvider.futureElement)) {
+        // ILLEGAL_ASYNC_RETURN_TYPE has already been reported, meaning the
+        // _declared_ return type is illegal; don't confuse by also reporting
+        // that the type being returned here does not match that illegal return
+        // type.
+        return;
+      }
     }
 
     void reportTypeError() {
@@ -4511,6 +4440,21 @@
     }
   }
 
+  void _checkForThrowOfInvalidType(ThrowExpression node) {
+    if (!_isNonNullableByDefault) return;
+
+    var expression = node.expression;
+    var type = node.expression.staticType;
+
+    if (!_typeSystem.isAssignableTo2(type, _typeSystem.objectNone)) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.THROW_OF_INVALID_TYPE,
+        expression,
+        [type],
+      );
+    }
+  }
+
   /**
    * Verify that the given [element] does not reference itself directly.
    * If it does, report the error on the [node].
@@ -5190,9 +5134,7 @@
         implementsClause?.interfaces,
         CompileTimeErrorCode.IMPLEMENTS_REPEATED,
       );
-      if (!disableConflictingGenericsCheck) {
-        _checkForConflictingGenerics(node);
-      }
+      _checkForConflictingGenerics(node);
     }
   }
 
@@ -5229,12 +5171,13 @@
     if (!_isNonNullableByDefault) return;
 
     var parent = node.parent;
-    var defaultValuesAreExpected = parent is ConstructorDeclaration ||
-        parent is FunctionExpression ||
-        parent is MethodDeclaration &&
-            !parent.isAbstract &&
-            parent.externalKeyword == null &&
-            parent.body is! NativeFunctionBody;
+    var defaultValuesAreExpected =
+        parent is ConstructorDeclaration && parent.externalKeyword == null ||
+            parent is FunctionExpression ||
+            parent is MethodDeclaration &&
+                !parent.isAbstract &&
+                parent.externalKeyword == null &&
+                parent.body is! NativeFunctionBody;
 
     for (var parameter in node.parameters) {
       if (parameter is DefaultFormalParameter) {
@@ -5482,6 +5425,35 @@
     return false;
   }
 
+  /// Returns whether a value with the type of the the enclosing function's
+  /// declared return type is assignable to [expectedElement].
+  bool _isLegalReturnType(ClassElement expectedElement) {
+    DartType returnType = _enclosingFunction.returnType;
+    //
+    // When checking an async/sync*/async* method, we know the exact type
+    // that will be returned (e.g. Future, Iterable, or Stream).
+    //
+    // For example an `async` function body will return a `Future<T>` for
+    // some `T` (possibly `dynamic`).
+    //
+    // We allow the declared return type to be a supertype of that
+    // (e.g. `dynamic`, `Object`), or Future<S> for some S.
+    // (We assume the T <: S relation is checked elsewhere.)
+    //
+    // We do not allow user-defined subtypes of Future, because an `async`
+    // method will never return those.
+    //
+    // To check for this, we ensure that `Future<bottom> <: returnType`.
+    //
+    // Similar logic applies for sync* and async*.
+    //
+    var lowerBound = expectedElement.instantiate(
+      typeArguments: [NeverTypeImpl.instance],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+    return _typeSystem.isSubtypeOf2(lowerBound, returnType);
+  }
+
   /**
    * Return `true` if the given 'this' [expression] is in a valid context.
    */
@@ -5552,13 +5524,6 @@
     return null;
   }
 
-  /// If in a legacy library, return the legacy version of the [type].
-  /// Otherwise, return the original type.
-  DartType _toLegacyType(DartType type) {
-    if (_isNonNullableByDefault) return type;
-    return NullabilityEliminator.perform(_typeProvider, type);
-  }
-
   /**
    * Return [FieldElement]s that are declared in the [ClassDeclaration] with
    * the given [constructor], but are not initialized.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3c731ff..4e7ee60 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -126,13 +126,15 @@
     if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) {
       // If NNBD, and the function body end is reachable, infer nullable.
       // If legacy, we consider the end as always reachable, and return Null.
-      if (_resolver._isNonNullableByDefault) {
-        var flow = _resolver._flowAnalysis?.flow;
-        if (flow != null && flow.isReachable) {
+      if (!node.isGenerator) {
+        if (_resolver._isNonNullableByDefault) {
+          var flow = _resolver._flowAnalysis?.flow;
+          if (flow != null && flow.isReachable) {
+            addReturnOrYieldType(_typeProvider.nullType);
+          }
+        } else {
           addReturnOrYieldType(_typeProvider.nullType);
         }
-      } else {
-        addReturnOrYieldType(_typeProvider.nullType);
       }
 
       DartType context = _returnStack.removeLast();
@@ -1628,7 +1630,6 @@
   @override
   void visitThrowExpression(ThrowExpression node) {
     super.visitThrowExpression(node);
-    nullableDereferenceVerifier.expression(node.expression);
     _flowAnalysis?.flow?.handleExit();
   }
 
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index b47e5e3..5ff6329 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -451,6 +451,11 @@
         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
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index 1d5a001..4ad4eae 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -3,7 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/element/class_hierarchy.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/source.dart' show Source;
@@ -18,11 +19,9 @@
   factory TestTypeProvider({
     bool isNonNullableByDefault = false,
   }) {
-    var context = _MockAnalysisContext();
-    var sdkElements = MockSdkElements(
-      context,
-      isNonNullableByDefault ? NullabilitySuffix.none : NullabilitySuffix.star,
-    );
+    var analysisContext = _MockAnalysisContext();
+    var analysisSession = _MockAnalysisSession();
+    var sdkElements = MockSdkElements(analysisContext, analysisSession);
     return TestTypeProvider._(
       sdkElements.coreLibrary,
       sdkElements.asyncLibrary,
@@ -37,7 +36,7 @@
   ) : super(
           coreLibrary: coreLibrary,
           asyncLibrary: asyncLibrary,
-          isNonNullableByDefault: isNonNullableByDefault,
+          isNonNullableByDefault: true,
         );
 }
 
@@ -49,6 +48,14 @@
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
+class _MockAnalysisSession implements AnalysisSessionImpl {
+  @override
+  final ClassHierarchy classHierarchy = ClassHierarchy();
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
 class _MockSource implements Source {
   @override
   final Uri uri;
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 3a57819..2636d14 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -3,10 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
-import 'dart:math' as math;
 
-import 'package:analyzer/dart/ast/ast.dart' show AstNode, ConstructorName;
-import 'package:analyzer/dart/ast/token.dart' show Keyword, TokenType;
+import 'package:analyzer/dart/ast/ast.dart' show AstNode;
+import 'package:analyzer/dart/ast/token.dart' show TokenType;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
@@ -14,1256 +13,21 @@
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/dart/element/type_system.dart' as public;
 import 'package:analyzer/error/listener.dart' show ErrorReporter;
-import 'package:analyzer/src/dart/element/display_string_builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/generic_inferrer.dart';
+import 'package:analyzer/src/dart/element/greatest_lower_bound.dart';
+import 'package:analyzer/src/dart/element/least_upper_bound.dart';
 import 'package:analyzer/src/dart/element/normalize.dart';
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/runtime_type_equality.dart';
+import 'package:analyzer/src/dart/element/subtype.dart';
 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_schema.dart';
 import 'package:analyzer/src/dart/element/type_schema_elimination.dart';
-import 'package:analyzer/src/dart/resolver/variance.dart';
-import 'package:analyzer/src/error/codes.dart' show HintCode, StrongModeCode;
-import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
 import 'package:meta/meta.dart';
 
-bool _isBottom(DartType t) {
-  return (t.isBottom && t.nullabilitySuffix != NullabilitySuffix.question) ||
-      identical(t, UnknownInferredType.instance);
-}
-
-/// Is [t] the bottom of the legacy type hierarchy.
-bool _isLegacyBottom(DartType t, {@required bool orTrueBottom}) {
-  return (t.isBottom && t.nullabilitySuffix == NullabilitySuffix.question) ||
-      t.isDartCoreNull ||
-      (orTrueBottom ? _isBottom(t) : false);
-}
-
-/// Is [t] the top of the legacy type hierarch.
-bool _isLegacyTop(DartType t, {@required bool orTrueTop}) {
-  if (t.isDartAsyncFutureOr) {
-    return _isLegacyTop((t as InterfaceType).typeArguments[0],
-        orTrueTop: orTrueTop);
-  }
-  if (t.isObject && t.nullabilitySuffix == NullabilitySuffix.none) {
-    return true;
-  }
-  return orTrueTop ? _isTop(t) : false;
-}
-
-bool _isTop(DartType t) {
-  if (t.isDartAsyncFutureOr) {
-    return _isTop((t as InterfaceType).typeArguments[0]);
-  }
-  return t.isDynamic ||
-      (t.isObject && t.nullabilitySuffix != NullabilitySuffix.none) ||
-      t.isVoid ||
-      identical(t, UnknownInferredType.instance);
-}
-
-/// Tracks upper and lower type bounds for a set of type parameters.
-///
-/// This class is used by calling [isSubtypeOf]. When it encounters one of
-/// the type parameters it is inferring, it will record the constraint, and
-/// optimistically assume the constraint will be satisfied.
-///
-/// For example if we are inferring type parameter A, and we ask if
-/// `A <: num`, this will record that A must be a subytpe of `num`. It also
-/// handles cases when A appears as part of the structure of another type, for
-/// example `Iterable<A> <: Iterable<num>` would infer the same constraint
-/// (due to covariant generic types) as would `() -> A <: () -> num`. In
-/// contrast `(A) -> void <: (num) -> void`.
-///
-/// Once the lower/upper bounds are determined, [infer] should be called to
-/// finish the inference. It will instantiate a generic function type with the
-/// inferred types for each type parameter.
-///
-/// It can also optionally compute a partial solution, in case some of the type
-/// parameters could not be inferred (because the constraints cannot be
-/// satisfied), or bail on the inference when this happens.
-///
-/// As currently designed, an instance of this class should only be used to
-/// infer a single call and discarded immediately afterwards.
-class GenericInferrer {
-  final TypeSystemImpl _typeSystem;
-  final Map<TypeParameterElement, List<_TypeConstraint>> constraints = {};
-
-  /// Buffer recording constraints recorded while performing a recursive call to
-  /// [_matchSubtypeOf] that might fail, so that any constraints recorded during
-  /// the failed match can be rewound.
-  final _undoBuffer = <_TypeConstraint>[];
-
-  GenericInferrer(
-    this._typeSystem,
-    Iterable<TypeParameterElement> typeFormals,
-  ) {
-    for (var formal in typeFormals) {
-      constraints[formal] = [];
-    }
-  }
-
-  bool get isNonNullableByDefault => _typeSystem.isNonNullableByDefault;
-
-  TypeProvider get typeProvider => _typeSystem.typeProvider;
-
-  /// Apply an argument constraint, which asserts that the [argument] staticType
-  /// is a subtype of the [parameterType].
-  void constrainArgument(
-      DartType argumentType, DartType parameterType, String parameterName,
-      {ClassElement genericClass}) {
-    var origin = _TypeConstraintFromArgument(
-      argumentType,
-      parameterType,
-      parameterName,
-      genericClass: genericClass,
-      isNonNullableByDefault: isNonNullableByDefault,
-    );
-    tryMatchSubtypeOf(argumentType, parameterType, origin, covariant: false);
-  }
-
-  /// Constrain a universal function type [fnType] used in a context
-  /// [contextType].
-  void constrainGenericFunctionInContext(
-      FunctionType fnType, DartType contextType) {
-    var origin = _TypeConstraintFromFunctionContext(
-      fnType,
-      contextType,
-      isNonNullableByDefault: isNonNullableByDefault,
-    );
-
-    // Since we're trying to infer the instantiation, we want to ignore type
-    // formals as we check the parameters and return type.
-    var inferFnType = FunctionTypeImpl(
-      typeFormals: const [],
-      parameters: fnType.parameters,
-      returnType: fnType.returnType,
-      nullabilitySuffix: fnType.nullabilitySuffix,
-    );
-    tryMatchSubtypeOf(inferFnType, contextType, origin, covariant: true);
-  }
-
-  /// Apply a return type constraint, which asserts that the [declaredType]
-  /// is a subtype of the [contextType].
-  void constrainReturnType(DartType declaredType, DartType contextType) {
-    var origin = _TypeConstraintFromReturnType(
-      declaredType,
-      contextType,
-      isNonNullableByDefault: isNonNullableByDefault,
-    );
-    tryMatchSubtypeOf(declaredType, contextType, origin, covariant: true);
-  }
-
-  /// Given the constraints that were given by calling [constrainArgument] and
-  /// [constrainReturnType], find the type arguments for the [typeFormals] that
-  /// satisfies these constraints.
-  ///
-  /// If [downwardsInferPhase] is set, we are in the first pass of inference,
-  /// pushing context types down. At that point we are allowed to push down
-  /// `?` to precisely represent an unknown type. If [downwardsInferPhase] is
-  /// false, we are on our final inference pass, have all available information
-  /// including argument types, and must not conclude `?` for any type formal.
-  List<DartType> infer(List<TypeParameterElement> typeFormals,
-      {bool considerExtendsClause = true,
-      ErrorReporter errorReporter,
-      AstNode errorNode,
-      bool failAtError = false,
-      bool downwardsInferPhase = false}) {
-    // Initialize the inferred type array.
-    //
-    // In the downwards phase, they all start as `?` to offer reasonable
-    // degradation for f-bounded type parameters.
-    var inferredTypes =
-        List<DartType>.filled(typeFormals.length, UnknownInferredType.instance);
-
-    for (int i = 0; i < typeFormals.length; i++) {
-      // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
-      // variance is added to the interface.
-      TypeParameterElementImpl typeParam = typeFormals[i];
-      _TypeConstraint extendsClause;
-      if (considerExtendsClause && typeParam.bound != null) {
-        extendsClause = _TypeConstraint.fromExtends(
-          typeParam,
-          Substitution.fromPairs(typeFormals, inferredTypes)
-              .substituteType(typeParam.bound),
-          isNonNullableByDefault: isNonNullableByDefault,
-        );
-      }
-
-      inferredTypes[i] = downwardsInferPhase
-          ? _inferTypeParameterFromContext(
-              constraints[typeParam], extendsClause,
-              isContravariant: typeParam.variance.isContravariant)
-          : _inferTypeParameterFromAll(constraints[typeParam], extendsClause,
-              isContravariant: typeParam.variance.isContravariant,
-              preferUpwardsInference: !typeParam.isLegacyCovariant);
-    }
-
-    // If the downwards infer phase has failed, we'll catch this in the upwards
-    // phase later on.
-    if (downwardsInferPhase) {
-      return inferredTypes;
-    }
-
-    // Check the inferred types against all of the constraints.
-    var knownTypes = <TypeParameterElement, DartType>{};
-    for (int i = 0; i < typeFormals.length; i++) {
-      TypeParameterElement typeParam = typeFormals[i];
-      var constraints = this.constraints[typeParam];
-      var typeParamBound = typeParam.bound != null
-          ? Substitution.fromPairs(typeFormals, inferredTypes)
-              .substituteType(typeParam.bound)
-          : typeProvider.dynamicType;
-
-      var inferred = inferredTypes[i];
-      bool success =
-          constraints.every((c) => c.isSatisifedBy(_typeSystem, inferred));
-      if (success && !typeParamBound.isDynamic) {
-        // If everything else succeeded, check the `extends` constraint.
-        var extendsConstraint = _TypeConstraint.fromExtends(
-          typeParam,
-          typeParamBound,
-          isNonNullableByDefault: isNonNullableByDefault,
-        );
-        constraints.add(extendsConstraint);
-        success = extendsConstraint.isSatisifedBy(_typeSystem, inferred);
-      }
-
-      if (!success) {
-        if (failAtError) return null;
-        errorReporter?.reportErrorForNode(
-            StrongModeCode.COULD_NOT_INFER,
-            errorNode,
-            [typeParam.name, _formatError(typeParam, inferred, constraints)]);
-
-        // Heuristic: even if we failed, keep the erroneous type.
-        // It should satisfy at least some of the constraints (e.g. the return
-        // context). If we fall back to instantiateToBounds, we'll typically get
-        // more errors (e.g. because `dynamic` is the most common bound).
-      }
-
-      if (inferred is FunctionType && inferred.typeFormals.isNotEmpty) {
-        if (failAtError) return null;
-        var typeFormals = (inferred as FunctionType).typeFormals;
-        var typeFormalsStr = typeFormals.map(_elementStr).join(', ');
-        errorReporter
-            ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
-          typeParam.name,
-          ' Inferred candidate type ${_typeStr(inferred)} has type parameters'
-              ' [$typeFormalsStr], but a function with'
-              ' type parameters cannot be used as a type argument.'
-        ]);
-
-        // Heuristic: Using a generic function type as a bound makes subtyping
-        // undecidable. Therefore, we cannot keep [inferred] unless we wish to
-        // generate bogus subtyping errors. Instead generate plain [Function],
-        // which is the most general function type.
-        inferred = typeProvider.functionType;
-      }
-
-      if (UnknownInferredType.isKnown(inferred)) {
-        knownTypes[typeParam] = inferred;
-      } else if (_typeSystem.strictInference) {
-        // [typeParam] could not be inferred. A result will still be returned
-        // by [infer], with [typeParam] filled in as its bounds. This is
-        // considered a failure of inference, under the "strict-inference"
-        // mode.
-        if (errorNode is ConstructorName) {
-          String constructorName = '${errorNode.type}.${errorNode.name}';
-          errorReporter?.reportErrorForNode(
-              HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,
-              errorNode,
-              [constructorName]);
-        }
-        // TODO(srawlins): More inference failure cases, like functions, and
-        // function expressions.
-      }
-    }
-
-    // Use instantiate to bounds to finish things off.
-    var hasError = List<bool>.filled(typeFormals.length, false);
-    var result = _typeSystem.instantiateTypeFormalsToBounds(typeFormals,
-        hasError: hasError, knownTypes: knownTypes);
-
-    // Report any errors from instantiateToBounds.
-    for (int i = 0; i < hasError.length; i++) {
-      if (hasError[i]) {
-        if (failAtError) return null;
-        TypeParameterElement typeParam = typeFormals[i];
-        var typeParamBound = Substitution.fromPairs(typeFormals, inferredTypes)
-            .substituteType(typeParam.bound ?? typeProvider.objectType);
-        // TODO(jmesserly): improve this error message.
-        errorReporter
-            ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
-          typeParam.name,
-          "\nRecursive bound cannot be instantiated: '$typeParamBound'."
-              "\nConsider passing explicit type argument(s) "
-              "to the generic.\n\n'"
-        ]);
-      }
-    }
-
-    return result;
-  }
-
-  /// Tries to make [i1] a subtype of [i2] and accumulate constraints as needed.
-  ///
-  /// The return value indicates whether the match was successful.  If it was
-  /// unsuccessful, any constraints that were accumulated during the match
-  /// attempt have been rewound (see [_rewindConstraints]).
-  bool tryMatchSubtypeOf(DartType t1, DartType t2, _TypeConstraintOrigin origin,
-      {bool covariant}) {
-    int previousRewindBufferLength = _undoBuffer.length;
-    bool success = _matchSubtypeOf(t1, t2, null, origin, covariant: covariant);
-    if (!success) {
-      _rewindConstraints(previousRewindBufferLength);
-    }
-    return success;
-  }
-
-  /// Choose the bound that was implied by the return type, if any.
-  ///
-  /// Which bound this is depends on what positions the type parameter
-  /// appears in. If the type only appears only in a contravariant position,
-  /// we will choose the lower bound instead.
-  ///
-  /// For example given:
-  ///
-  ///     Func1<T, bool> makeComparer<T>(T x) => (T y) => x() == y;
-  ///
-  ///     main() {
-  ///       Func1<num, bool> t = makeComparer/* infer <num> */(42);
-  ///       print(t(42.0)); /// false, no error.
-  ///     }
-  ///
-  /// The constraints we collect are:
-  ///
-  /// * `num <: T`
-  /// * `int <: T`
-  ///
-  /// ... and no upper bound. Therefore the lower bound is the best choice.
-  ///
-  /// If [isContravariant] is `true`, then we are solving for a contravariant
-  /// type parameter which means we choose the upper bound rather than the
-  /// lower bound for normally covariant type parameters.
-  DartType _chooseTypeFromConstraints(Iterable<_TypeConstraint> constraints,
-      {bool toKnownType = false, @required bool isContravariant}) {
-    DartType lower = UnknownInferredType.instance;
-    DartType upper = UnknownInferredType.instance;
-    for (var constraint in constraints) {
-      // Given constraints:
-      //
-      //     L1 <: T <: U1
-      //     L2 <: T <: U2
-      //
-      // These can be combined to produce:
-      //
-      //     LUB(L1, L2) <: T <: GLB(U1, U2).
-      //
-      // This can then be done for all constraints in sequence.
-      //
-      // This resulting constraint may be unsatisfiable; in that case inference
-      // will fail.
-      upper = _getGreatestLowerBound(upper, constraint.upperBound);
-      lower = _typeSystem.getLeastUpperBound(lower, constraint.lowerBound);
-      upper = _toLegacyType(upper);
-      lower = _toLegacyType(lower);
-    }
-
-    // Prefer the known bound, if any.
-    // Otherwise take whatever bound has partial information, e.g. `Iterable<?>`
-    //
-    // For both of those, prefer the lower bound (arbitrary heuristic) or upper
-    // bound if [isContravariant] is `true`
-    if (isContravariant) {
-      if (UnknownInferredType.isKnown(upper)) {
-        return upper;
-      }
-      if (UnknownInferredType.isKnown(lower)) {
-        return lower;
-      }
-      if (!identical(UnknownInferredType.instance, upper)) {
-        return toKnownType ? _typeSystem.greatestClosure(upper) : upper;
-      }
-      if (!identical(UnknownInferredType.instance, lower)) {
-        return toKnownType ? _typeSystem.leastClosure(lower) : lower;
-      }
-      return upper;
-    } else {
-      if (UnknownInferredType.isKnown(lower)) {
-        return lower;
-      }
-      if (UnknownInferredType.isKnown(upper)) {
-        return upper;
-      }
-      if (!identical(UnknownInferredType.instance, lower)) {
-        return toKnownType ? _typeSystem.leastClosure(lower) : lower;
-      }
-      if (!identical(UnknownInferredType.instance, upper)) {
-        return toKnownType ? _typeSystem.greatestClosure(upper) : upper;
-      }
-      return lower;
-    }
-  }
-
-  String _elementStr(Element element) {
-    return element.getDisplayString(withNullability: isNonNullableByDefault);
-  }
-
-  String _formatError(TypeParameterElement typeParam, DartType inferred,
-      Iterable<_TypeConstraint> constraints) {
-    var inferredStr = inferred.getDisplayString(
-      withNullability: isNonNullableByDefault,
-    );
-    var intro = "Tried to infer '$inferredStr' for '${typeParam.name}'"
-        " which doesn't work:";
-
-    var constraintsByOrigin = <_TypeConstraintOrigin, List<_TypeConstraint>>{};
-    for (var c in constraints) {
-      constraintsByOrigin.putIfAbsent(c.origin, () => []).add(c);
-    }
-
-    // Only report unique constraint origins.
-    Iterable<_TypeConstraint> isSatisified(bool expected) => constraintsByOrigin
-        .values
-        .where((l) =>
-            l.every((c) => c.isSatisifedBy(_typeSystem, inferred)) == expected)
-        .expand((i) => i);
-
-    String unsatisified = _formatConstraints(isSatisified(false));
-    String satisified = _formatConstraints(isSatisified(true));
-
-    assert(unsatisified.isNotEmpty);
-    if (satisified.isNotEmpty) {
-      satisified = "\nThe type '$inferredStr' was inferred from:\n$satisified";
-    }
-
-    return '\n\n$intro\n$unsatisified$satisified\n\n'
-        'Consider passing explicit type argument(s) to the generic.\n\n';
-  }
-
-  /// This is first calls strong mode's GLB, but if it fails to find anything
-  /// (i.e. returns the bottom type), we kick in a few additional rules:
-  ///
-  /// - `GLB(FutureOr<A>, B)` is defined as:
-  ///   - `GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>`
-  ///   - `GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>`
-  ///   - else `GLB(FutureOr<A>, B) == GLB(A, B)`
-  /// - `GLB(A, FutureOr<B>) ==  GLB(FutureOr<B>, A)` (defined above),
-  /// - else `GLB(A, B) == Null`
-  DartType _getGreatestLowerBound(DartType t1, DartType t2) {
-    var result = _typeSystem.getGreatestLowerBound(t1, t2);
-    if (result.isBottom) {
-      // See if we can do better by considering FutureOr rules.
-      if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
-        var t1TypeArg = t1.typeArguments[0];
-        if (t2 is InterfaceType) {
-          //  GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>
-          if (t2.isDartAsyncFutureOr) {
-            var t2TypeArg = t2.typeArguments[0];
-            return typeProvider
-                .futureOrType2(_getGreatestLowerBound(t1TypeArg, t2TypeArg));
-          }
-          // GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>
-          if (t2.isDartAsyncFuture) {
-            var t2TypeArg = t2.typeArguments[0];
-            return typeProvider
-                .futureType2(_getGreatestLowerBound(t1TypeArg, t2TypeArg));
-          }
-        }
-        // GLB(FutureOr<A>, B) == GLB(A, B)
-        return _getGreatestLowerBound(t1TypeArg, t2);
-      }
-      if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
-        // GLB(A, FutureOr<B>) ==  GLB(FutureOr<B>, A)
-        return _getGreatestLowerBound(t2, t1);
-      }
-    }
-    return result;
-  }
-
-  DartType _inferTypeParameterFromAll(
-      List<_TypeConstraint> constraints, _TypeConstraint extendsClause,
-      {@required bool isContravariant, @required bool preferUpwardsInference}) {
-    // See if we already fixed this type from downwards inference.
-    // If so, then we aren't allowed to change it based on argument types unless
-    // [preferUpwardsInference] is true.
-    DartType t = _inferTypeParameterFromContext(
-        constraints.where((c) => c.isDownwards), extendsClause,
-        isContravariant: isContravariant);
-    if (!preferUpwardsInference && UnknownInferredType.isKnown(t)) {
-      // Remove constraints that aren't downward ones; we'll ignore these for
-      // error reporting, because inference already succeeded.
-      constraints.removeWhere((c) => !c.isDownwards);
-      return t;
-    }
-
-    if (extendsClause != null) {
-      constraints = constraints.toList()..add(extendsClause);
-    }
-
-    var choice = _chooseTypeFromConstraints(constraints,
-        toKnownType: true, isContravariant: isContravariant);
-    return choice;
-  }
-
-  DartType _inferTypeParameterFromContext(
-      Iterable<_TypeConstraint> constraints, _TypeConstraint extendsClause,
-      {@required bool isContravariant}) {
-    DartType t = _chooseTypeFromConstraints(constraints,
-        isContravariant: isContravariant);
-    if (UnknownInferredType.isUnknown(t)) {
-      return t;
-    }
-
-    // If we're about to make our final choice, apply the extends clause.
-    // This gives us a chance to refine the choice, in case it would violate
-    // the `extends` clause. For example:
-    //
-    //     Object obj = math.min/*<infer Object, error>*/(1, 2);
-    //
-    // If we consider the `T extends num` we conclude `<num>`, which works.
-    if (extendsClause != null) {
-      constraints = constraints.toList()..add(extendsClause);
-      return _chooseTypeFromConstraints(constraints,
-          isContravariant: isContravariant);
-    }
-    return t;
-  }
-
-  /// Tries to make [i1] a subtype of [i2] and accumulate constraints as needed.
-  ///
-  /// The return value indicates whether the match was successful.  If it was
-  /// unsuccessful, the caller is responsible for ignoring any constraints that
-  /// were accumulated (see [_rewindConstraints]).
-  bool _matchInterfaceSubtypeOf(InterfaceType i1, InterfaceType i2,
-      Set<Element> visited, _TypeConstraintOrigin origin,
-      {bool covariant}) {
-    if (identical(i1, i2)) {
-      return true;
-    }
-
-    if (i1.element == i2.element) {
-      List<DartType> tArgs1 = i1.typeArguments;
-      List<DartType> tArgs2 = i2.typeArguments;
-      List<TypeParameterElement> tParams = i1.element.typeParameters;
-      assert(tArgs1.length == tArgs2.length);
-      assert(tArgs1.length == tParams.length);
-      for (int i = 0; i < tArgs1.length; i++) {
-        TypeParameterElement typeParameterElement = tParams[i];
-
-        // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
-        // variance is added to the interface.
-        Variance parameterVariance =
-            (typeParameterElement as TypeParameterElementImpl).variance;
-        if (parameterVariance.isCovariant) {
-          if (!_matchSubtypeOf(tArgs1[i], tArgs2[i], HashSet<Element>(), origin,
-              covariant: covariant)) {
-            return false;
-          }
-        } else if (parameterVariance.isContravariant) {
-          if (!_matchSubtypeOf(tArgs2[i], tArgs1[i], HashSet<Element>(), origin,
-              covariant: !covariant)) {
-            return false;
-          }
-        } else if (parameterVariance.isInvariant) {
-          if (!_matchSubtypeOf(tArgs1[i], tArgs2[i], HashSet<Element>(), origin,
-                  covariant: covariant) ||
-              !_matchSubtypeOf(tArgs2[i], tArgs1[i], HashSet<Element>(), origin,
-                  covariant: !covariant)) {
-            return false;
-          }
-        } else {
-          throw StateError("Type parameter ${tParams[i]} has unknown "
-              "variance $parameterVariance for inference.");
-        }
-      }
-      return true;
-    }
-    if (i1.isObject) {
-      return false;
-    }
-
-    // Guard against loops in the class hierarchy
-    bool guardedInterfaceSubtype(InterfaceType t1) {
-      visited ??= HashSet<Element>();
-      if (visited.add(t1.element)) {
-        bool matched = _matchInterfaceSubtypeOf(t1, i2, visited, origin,
-            covariant: covariant);
-        visited.remove(t1.element);
-        return matched;
-      } else {
-        // In the case of a recursive type parameter, consider the subtype
-        // match to have failed.
-        return false;
-      }
-    }
-
-    // We don't need to search the entire class hierarchy, since a given
-    // subclass can't appear multiple times with different generic parameters.
-    // So shortcut to the first match found.
-    //
-    // We don't need undo logic here because if the classes don't match, nothing
-    // is added to the constraint set.
-    var superclass = i1.superclass;
-    if (superclass != null && guardedInterfaceSubtype(superclass)) return true;
-    for (final parent in i1.interfaces) {
-      if (guardedInterfaceSubtype(parent)) return true;
-    }
-    for (final parent in i1.mixins) {
-      if (guardedInterfaceSubtype(parent)) return true;
-    }
-    for (final parent in i1.superclassConstraints) {
-      if (guardedInterfaceSubtype(parent)) return true;
-    }
-    return false;
-  }
-
-  /// Assert that [t1] will be a subtype of [t2], and returns if the constraint
-  /// can be satisfied.
-  ///
-  /// [covariant] must be true if [t1] is a declared type of the generic
-  /// function and [t2] is the context type, or false if the reverse. For
-  /// example [covariant] is used when [t1] is the declared return type
-  /// and [t2] is the context type. Contravariant would be used if [t1] is the
-  /// argument type (i.e. passed in to the generic function) and [t2] is the
-  /// declared parameter type.
-  ///
-  /// [origin] indicates where the constraint came from, for example an argument
-  /// or return type.
-  bool _matchSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
-      _TypeConstraintOrigin origin,
-      {bool covariant}) {
-    if (covariant && t1 is TypeParameterType) {
-      var constraints = this.constraints[t1.element];
-      if (constraints != null) {
-        if (!identical(t2, UnknownInferredType.instance)) {
-          var constraint = _TypeConstraint(origin, t1.element, upper: t2);
-          constraints.add(constraint);
-          _undoBuffer.add(constraint);
-        }
-        return true;
-      }
-    }
-    if (!covariant && t2 is TypeParameterType) {
-      var constraints = this.constraints[t2.element];
-      if (constraints != null) {
-        if (!identical(t1, UnknownInferredType.instance)) {
-          if (t2.nullabilitySuffix == NullabilitySuffix.question) {
-            t1 = _typeSystem.promoteToNonNull(t1);
-          }
-          var constraint = _TypeConstraint(origin, t2.element, lower: t1);
-          constraints.add(constraint);
-          _undoBuffer.add(constraint);
-        }
-        return true;
-      }
-    }
-
-    if (identical(t1, t2)) {
-      return true;
-    }
-
-    // TODO(jmesserly): this logic is taken from subtype.
-    bool matchSubtype(DartType t1, DartType t2) {
-      return _matchSubtypeOf(t1, t2, null, origin, covariant: covariant);
-    }
-
-    // Handle FutureOr<T> union type.
-    if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
-      var t1TypeArg = t1.typeArguments[0];
-      if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
-        var t2TypeArg = t2.typeArguments[0];
-        // FutureOr<A> <: FutureOr<B> iff A <: B
-        return matchSubtype(t1TypeArg, t2TypeArg);
-      }
-
-      // given t1 is Future<A> | A, then:
-      // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-      var t1Future = typeProvider.futureType2(t1TypeArg);
-      return matchSubtype(t1Future, t2) && matchSubtype(t1TypeArg, t2);
-    }
-
-    if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
-      // given t2 is Future<A> | A, then:
-      // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
-      var t2TypeArg = t2.typeArguments[0];
-      var t2Future = typeProvider.futureType2(t2TypeArg);
-
-      // First we try matching `t1 <: Future<A>`.  If that succeeds *and*
-      // records at least one constraint, then we proceed using that constraint.
-      var previousRewindBufferLength = _undoBuffer.length;
-      var success =
-          tryMatchSubtypeOf(t1, t2Future, origin, covariant: covariant);
-
-      if (_undoBuffer.length != previousRewindBufferLength) {
-        // Trying to match `t1 <: Future<A>` succeeded and recorded constraints,
-        // so those are the constraints we want.
-        return true;
-      } else {
-        // Either `t1 <: Future<A>` failed to match, or it matched trivially
-        // without recording any constraints (e.g. because t1 is `Null`).  We
-        // want constraints, because they let us do more precise inference, so
-        // go ahead and try matching `t1 <: A` to see if it records any
-        // constraints.
-        if (tryMatchSubtypeOf(t1, t2TypeArg, origin, covariant: covariant)) {
-          // Trying to match `t1 <: A` succeeded.  If it recorded constraints,
-          // those are the constraints we want.  If it didn't, then there's no
-          // way we're going to get any constraints.  So either way, we want to
-          // return `true` since the match suceeded and the constraints we want
-          // (if any) have been recorded.
-          return true;
-        } else {
-          // Trying to match `t1 <: A` failed.  So there's no way we are going
-          // to get any constraints.  Just return `success` to indicate whether
-          // the match succeeded.
-          return success;
-        }
-      }
-    }
-
-    // S <: T where S is a type variable
-    //  T is not dynamic or object (handled above)
-    //  True if T == S
-    //  Or true if bound of S is S' and S' <: T
-
-    if (t1 is TypeParameterType) {
-      // Guard against recursive type parameters
-      //
-      // TODO(jmesserly): this function isn't guarding against anything (it's
-      // not passsing down `visitedSet`, so adding the element has no effect).
-      bool guardedSubtype(DartType t1, DartType t2) {
-        var visitedSet = visited ?? HashSet<Element>();
-        if (visitedSet.add(t1.element)) {
-          bool matched = matchSubtype(t1, t2);
-          visitedSet.remove(t1.element);
-          return matched;
-        } else {
-          // In the case of a recursive type parameter, consider the subtype
-          // match to have failed.
-          return false;
-        }
-      }
-
-      if (t2 is TypeParameterType && t1.definition == t2.definition) {
-        return guardedSubtype(t1.bound, t2.bound);
-      }
-      return guardedSubtype(t1.bound, t2);
-    }
-    if (t2 is TypeParameterType) {
-      return false;
-    }
-
-    // TODO(mfairhurst): switch legacy Bottom checks to true Bottom checks
-    // TODO(mfairhurst): switch legacy Top checks to true Top checks
-    if (_isLegacyBottom(t1, orTrueBottom: true) ||
-        _isLegacyTop(t2, orTrueTop: true)) return true;
-
-    if (t1 is InterfaceType && t2 is InterfaceType) {
-      return _matchInterfaceSubtypeOf(t1, t2, visited, origin,
-          covariant: covariant);
-    }
-
-    if (t1 is FunctionType && t2 is FunctionType) {
-      return FunctionTypeImpl.relate(t1, t2, matchSubtype,
-          parameterRelation: (p1, p2) {
-            return _matchSubtypeOf(p2.type, p1.type, null, origin,
-                covariant: !covariant);
-          },
-          // Type parameter bounds are invariant.
-          boundsRelation: (t1, t2, p1, p2) =>
-              matchSubtype(t1, t2) && matchSubtype(t2, t1));
-    }
-
-    if (t1 is FunctionType && t2 == typeProvider.functionType) {
-      return true;
-    }
-
-    return false;
-  }
-
-  /// Un-does constraints that were gathered by a failed match attempt, until
-  /// [_undoBuffer] has length [previousRewindBufferLength].
-  ///
-  /// The intended usage is that the caller should record the length of
-  /// [_undoBuffer] before attempting to make a match.  Then, if the match
-  /// fails, pass the recorded length to this method to erase any constraints
-  /// that were recorded during the failed match.
-  void _rewindConstraints(int previousRewindBufferLength) {
-    while (_undoBuffer.length > previousRewindBufferLength) {
-      var constraint = _undoBuffer.removeLast();
-      var element = constraint.typeParameter;
-      assert(identical(constraints[element].last, constraint));
-      constraints[element].removeLast();
-    }
-  }
-
-  /// If in a legacy library, return the legacy version of the [type].
-  /// Otherwise, return the original type.
-  DartType _toLegacyType(DartType type) {
-    if (isNonNullableByDefault) return type;
-    return NullabilityEliminator.perform(typeProvider, type);
-  }
-
-  String _typeStr(DartType type) {
-    return type.getDisplayString(withNullability: isNonNullableByDefault);
-  }
-
-  static String _formatConstraints(Iterable<_TypeConstraint> constraints) {
-    List<List<String>> lineParts =
-        Set<_TypeConstraintOrigin>.from(constraints.map((c) => c.origin))
-            .map((o) => o.formatError())
-            .toList();
-
-    int prefixMax = lineParts.map((p) => p[0].length).fold(0, math.max);
-
-    // Use a set to prevent identical message lines.
-    // (It's not uncommon for the same constraint to show up in a few places.)
-    var messageLines = Set<String>.from(lineParts.map((parts) {
-      var prefix = parts[0];
-      var middle = parts[1];
-      var prefixPad = ' ' * (prefixMax - prefix.length);
-      var middlePad = ' ' * (prefixMax);
-      var end = "";
-      if (parts.length > 2) {
-        end = '\n  $middlePad ${parts[2]}';
-      }
-      return '  $prefix$prefixPad $middle$end';
-    }));
-
-    return messageLines.join('\n');
-  }
-}
-
-/// The instantiation of a [ClassElement] with type arguments.
-///
-/// It is not a [DartType] itself, because it does not have nullability.
-/// But it should be used where nullability does not make sense - to specify
-/// superclasses, mixins, and implemented interfaces.
-class InstantiatedClass {
-  final ClassElement element;
-  final List<DartType> arguments;
-
-  final Substitution _substitution;
-
-  InstantiatedClass(this.element, this.arguments)
-      : _substitution = Substitution.fromPairs(
-          element.typeParameters,
-          arguments,
-        );
-
-  /// Return the [InstantiatedClass] that corresponds to the [type] - with the
-  /// same element and type arguments, ignoring its nullability suffix.
-  factory InstantiatedClass.of(InterfaceType type) {
-    return InstantiatedClass(type.element, type.typeArguments);
-  }
-
-  @override
-  int get hashCode {
-    var hash = 0x3fffffff & element.hashCode;
-    for (var i = 0; i < arguments.length; i++) {
-      hash = 0x3fffffff & (hash * 31 + (hash ^ arguments[i].hashCode));
-    }
-    return hash;
-  }
-
-  /// Return the interfaces that are directly implemented by this class.
-  List<InstantiatedClass> get interfaces {
-    var interfaces = element.interfaces;
-
-    var result = List<InstantiatedClass>(interfaces.length);
-    for (var i = 0; i < interfaces.length; i++) {
-      var interface = interfaces[i];
-      var substituted = _substitution.substituteType(interface);
-      result[i] = InstantiatedClass.of(substituted);
-    }
-
-    return result;
-  }
-
-  /// Return `true` if this type represents the type 'Function' defined in the
-  /// dart:core library.
-  bool get isDartCoreFunction {
-    return element.name == 'Function' && element.library.isDartCore;
-  }
-
-  /// Return the superclass of this type, or `null` if this type represents
-  /// the class 'Object'.
-  InstantiatedClass get superclass {
-    var supertype = element.supertype;
-    if (supertype == null) return null;
-
-    supertype = _substitution.substituteType(supertype);
-    return InstantiatedClass.of(supertype);
-  }
-
-  /// Return a list containing all of the superclass constraints defined for
-  /// this class. The list will be empty if this class does not represent a
-  /// mixin declaration. If this class _does_ represent a mixin declaration but
-  /// the declaration does not have an `on` clause, then the list will contain
-  /// the type for the class `Object`.
-  List<InstantiatedClass> get superclassConstraints {
-    var constraints = element.superclassConstraints;
-
-    var result = List<InstantiatedClass>(constraints.length);
-    for (var i = 0; i < constraints.length; i++) {
-      var constraint = constraints[i];
-      var substituted = _substitution.substituteType(constraint);
-      result[i] = InstantiatedClass.of(substituted);
-    }
-
-    return result;
-  }
-
-  @visibleForTesting
-  InterfaceType get withNullabilitySuffixNone {
-    return withNullability(NullabilitySuffix.none);
-  }
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-
-    if (other is InstantiatedClass) {
-      if (element != other.element) return false;
-      if (arguments.length != other.arguments.length) return false;
-      for (var i = 0; i < arguments.length; i++) {
-        if (arguments[i] != other.arguments[i]) return false;
-      }
-      return true;
-    }
-    return false;
-  }
-
-  @override
-  String toString() {
-    var buffer = StringBuffer();
-    buffer.write(element.name);
-    if (arguments.isNotEmpty) {
-      buffer.write('<');
-      buffer.write(arguments.join(', '));
-      buffer.write('>');
-    }
-    return buffer.toString();
-  }
-
-  InterfaceType withNullability(NullabilitySuffix nullability) {
-    return InterfaceTypeImpl(
-      element: element,
-      typeArguments: arguments,
-      nullabilitySuffix: nullability,
-    );
-  }
-}
-
-class InterfaceLeastUpperBoundHelper {
-  final TypeSystemImpl typeSystem;
-
-  InterfaceLeastUpperBoundHelper(this.typeSystem);
-
-  /// This currently does not implement a very complete least upper bound
-  /// algorithm, but handles a couple of the very common cases that are
-  /// causing pain in real code.  The current algorithm is:
-  /// 1. If either of the types is a supertype of the other, return it.
-  ///    This is in fact the best result in this case.
-  /// 2. If the two types have the same class element and are implicitly or
-  ///    explicitly covariant, then take the pointwise least upper bound of
-  ///    the type arguments. This is again the best result, except that the
-  ///    recursive calls may not return the true least upper bounds. The
-  ///    result is guaranteed to be a well-formed type under the assumption
-  ///    that the input types were well-formed (and assuming that the
-  ///    recursive calls return well-formed types).
-  ///    If the variance of the type parameter is contravariant, we take the
-  ///    greatest lower bound of the type arguments. If the variance of the
-  ///    type parameter is invariant, we verify if the type arguments satisfy
-  ///    subtyping in both directions, then choose a bound.
-  /// 3. Otherwise return the spec-defined least upper bound.  This will
-  ///    be an upper bound, might (or might not) be least, and might
-  ///    (or might not) be a well-formed type.
-  ///
-  /// TODO(leafp): Use matchTypes or something similar here to handle the
-  ///  case where one of the types is a superclass (but not supertype) of
-  ///  the other, e.g. LUB(Iterable<double>, List<int>) = Iterable<num>
-  /// TODO(leafp): Figure out the right final algorithm and implement it.
-  InterfaceTypeImpl compute(InterfaceTypeImpl type1, InterfaceTypeImpl type2) {
-    var nullability = _chooseNullability(type1, type2);
-
-    // Strip off nullability.
-    type1 = type1.withNullability(NullabilitySuffix.none);
-    type2 = type2.withNullability(NullabilitySuffix.none);
-
-    if (typeSystem.isSubtypeOf2(type1, type2)) {
-      return type2.withNullability(nullability);
-    }
-    if (typeSystem.isSubtypeOf2(type2, type1)) {
-      return type1.withNullability(nullability);
-    }
-
-    if (type1.element == type2.element) {
-      var args1 = type1.typeArguments;
-      var args2 = type2.typeArguments;
-      var params = type1.element.typeParameters;
-      assert(args1.length == args2.length);
-      assert(args1.length == params.length);
-
-      var args = List<DartType>(args1.length);
-      for (int i = 0; i < args1.length; i++) {
-        // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
-        // variance is added to the interface.
-        Variance parameterVariance =
-            (params[i] as TypeParameterElementImpl).variance;
-        if (parameterVariance.isCovariant) {
-          args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
-        } else if (parameterVariance.isContravariant) {
-          if (typeSystem is TypeSystemImpl) {
-            args[i] = typeSystem.getGreatestLowerBound(args1[i], args2[i]);
-          } else {
-            args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
-          }
-        } else if (parameterVariance.isInvariant) {
-          if (!typeSystem.isSubtypeOf2(args1[i], args2[i]) ||
-              !typeSystem.isSubtypeOf2(args2[i], args1[i])) {
-            // No bound will be valid, find bound at the interface level.
-            return _computeLeastUpperBound(
-              InstantiatedClass.of(type1),
-              InstantiatedClass.of(type2),
-            ).withNullability(nullability);
-          }
-          // TODO (kallentu) : Fix asymmetric bounds behavior for invariant type
-          //  parameters.
-          args[i] = args1[i];
-        } else {
-          throw StateError('Type parameter ${params[i]} has unknown '
-              'variance $parameterVariance for bounds calculation.');
-        }
-      }
-
-      return InterfaceTypeImpl(
-        element: type1.element,
-        typeArguments: args,
-        nullabilitySuffix: nullability,
-      );
-    }
-
-    var result = _computeLeastUpperBound(
-      InstantiatedClass.of(type1),
-      InstantiatedClass.of(type2),
-    );
-    return result.withNullability(nullability);
-  }
-
-  /// Compute the least upper bound of types [i] and [j], both of which are
-  /// known to be interface types.
-  ///
-  /// In the event that the algorithm fails (which might occur due to a bug in
-  /// the analyzer), `null` is returned.
-  InstantiatedClass _computeLeastUpperBound(
-    InstantiatedClass i,
-    InstantiatedClass j,
-  ) {
-    // compute set of supertypes
-    var si = computeSuperinterfaceSet(i);
-    var sj = computeSuperinterfaceSet(j);
-
-    // union si with i and sj with j
-    si.add(i);
-    sj.add(j);
-
-    // compute intersection, reference as set 's'
-    var s = _intersection(si, sj);
-    return _computeTypeAtMaxUniqueDepth(s);
-  }
-
-  /**
-   * Return the length of the longest inheritance path from the [element] to
-   * Object.
-   */
-  @visibleForTesting
-  static int computeLongestInheritancePathToObject(ClassElement element) {
-    return _computeLongestInheritancePathToObject(
-      element,
-      0,
-      <ClassElement>{},
-    );
-  }
-
-  /// Return all of the superinterfaces of the given [type].
-  @visibleForTesting
-  static Set<InstantiatedClass> computeSuperinterfaceSet(
-      InstantiatedClass type) {
-    var result = <InstantiatedClass>{};
-    _addSuperinterfaces(result, type);
-    return result;
-  }
-
-  /// Add all of the superinterfaces of the given [type] to the given [set].
-  static void _addSuperinterfaces(
-      Set<InstantiatedClass> set, InstantiatedClass type) {
-    for (var interface in type.interfaces) {
-      if (!interface.isDartCoreFunction) {
-        if (set.add(interface)) {
-          _addSuperinterfaces(set, interface);
-        }
-      }
-    }
-
-    for (var constraint in type.superclassConstraints) {
-      if (!constraint.isDartCoreFunction) {
-        if (set.add(constraint)) {
-          _addSuperinterfaces(set, constraint);
-        }
-      }
-    }
-
-    var supertype = type.superclass;
-    if (supertype != null && !supertype.isDartCoreFunction) {
-      if (set.add(supertype)) {
-        _addSuperinterfaces(set, supertype);
-      }
-    }
-  }
-
-  static NullabilitySuffix _chooseNullability(
-    InterfaceTypeImpl type1,
-    InterfaceTypeImpl type2,
-  ) {
-    var nullability1 = type1.nullabilitySuffix;
-    var nullability2 = type2.nullabilitySuffix;
-    if (nullability1 == NullabilitySuffix.question ||
-        nullability2 == NullabilitySuffix.question) {
-      return NullabilitySuffix.question;
-    } else if (nullability1 == NullabilitySuffix.star ||
-        nullability2 == NullabilitySuffix.star) {
-      return NullabilitySuffix.star;
-    }
-    return NullabilitySuffix.none;
-  }
-
-  /// Return the length of the longest inheritance path from a subtype of the
-  /// given [element] to Object, where the given [depth] is the length of the
-  /// longest path from the subtype to this type. The set of [visitedElements]
-  /// is used to prevent infinite recursion in the case of a cyclic type
-  /// structure.
-  static int _computeLongestInheritancePathToObject(
-      ClassElement element, int depth, Set<ClassElement> visitedElements) {
-    // Object case
-    if (element.isDartCoreObject || visitedElements.contains(element)) {
-      return depth;
-    }
-    int longestPath = 1;
-    try {
-      visitedElements.add(element);
-      int pathLength;
-
-      // loop through each of the superinterfaces recursively calling this
-      // method and keeping track of the longest path to return
-      for (InterfaceType interface in element.superclassConstraints) {
-        pathLength = _computeLongestInheritancePathToObject(
-            interface.element, depth + 1, visitedElements);
-        if (pathLength > longestPath) {
-          longestPath = pathLength;
-        }
-      }
-
-      // loop through each of the superinterfaces recursively calling this
-      // method and keeping track of the longest path to return
-      for (InterfaceType interface in element.interfaces) {
-        pathLength = _computeLongestInheritancePathToObject(
-            interface.element, depth + 1, visitedElements);
-        if (pathLength > longestPath) {
-          longestPath = pathLength;
-        }
-      }
-
-      // finally, perform this same check on the super type
-      // TODO(brianwilkerson) Does this also need to add in the number of mixin
-      // classes?
-      InterfaceType supertype = element.supertype;
-      if (supertype != null) {
-        pathLength = _computeLongestInheritancePathToObject(
-            supertype.element, depth + 1, visitedElements);
-        if (pathLength > longestPath) {
-          longestPath = pathLength;
-        }
-      }
-    } finally {
-      visitedElements.remove(element);
-    }
-    return longestPath;
-  }
-
-  /// Return the type from the [types] list that has the longest inheritance
-  /// path to Object of unique length.
-  static InstantiatedClass _computeTypeAtMaxUniqueDepth(
-    List<InstantiatedClass> types,
-  ) {
-    // for each element in Set s, compute the largest inheritance path to Object
-    List<int> depths = List<int>.filled(types.length, 0);
-    int maxDepth = 0;
-    for (int i = 0; i < types.length; i++) {
-      depths[i] = computeLongestInheritancePathToObject(types[i].element);
-      if (depths[i] > maxDepth) {
-        maxDepth = depths[i];
-      }
-    }
-    // ensure that the currently computed maxDepth is unique,
-    // otherwise, decrement and test for uniqueness again
-    for (; maxDepth >= 0; maxDepth--) {
-      int indexOfLeastUpperBound = -1;
-      int numberOfTypesAtMaxDepth = 0;
-      for (int m = 0; m < depths.length; m++) {
-        if (depths[m] == maxDepth) {
-          numberOfTypesAtMaxDepth++;
-          indexOfLeastUpperBound = m;
-        }
-      }
-      if (numberOfTypesAtMaxDepth == 1) {
-        return types[indexOfLeastUpperBound];
-      }
-    }
-    // Should be impossible--there should always be exactly one type with the
-    // maximum depth.
-    assert(false);
-    return null;
-  }
-
-  /**
-   * Return the intersection of the [first] and [second] sets of types, where
-   * intersection is based on the equality of the types themselves.
-   */
-  static List<InstantiatedClass> _intersection(
-    Set<InstantiatedClass> first,
-    Set<InstantiatedClass> second,
-  ) {
-    var result = first.toSet();
-    result.retainAll(second);
-    return result.toList();
-  }
-}
-
-/// Used to check for infinite loops, if we repeat the same type comparison.
-class TypeComparison {
-  final DartType lhs;
-  final DartType rhs;
-
-  TypeComparison(this.lhs, this.rhs);
-
-  @override
-  int get hashCode => lhs.hashCode * 11 + rhs.hashCode;
-
-  @override
-  bool operator ==(Object other) {
-    if (other is TypeComparison) {
-      return lhs == other.lhs && rhs == other.rhs;
-    }
-
-    return false;
-  }
-
-  @override
-  String toString() => "$lhs vs $rhs";
-}
-
 /**
  * The interface `TypeSystem` defines the behavior of an object representing
  * the type system.  This provides a common location to put methods that act on
@@ -1723,47 +487,50 @@
   final TypeProvider typeProvider;
 
   /// The cached instance of `Object?`.
-  InterfaceTypeImpl _objectQuestionCached;
+  InterfaceTypeImpl _objectQuestion;
 
   /// The cached instance of `Object*`.
-  InterfaceTypeImpl _objectStarCached;
+  InterfaceTypeImpl _objectStar;
 
   /// The cached instance of `Object!`.
-  InterfaceTypeImpl _objectNoneCached;
+  InterfaceTypeImpl _objectNone;
 
   /// The cached instance of `Null!`.
-  InterfaceTypeImpl _nullNoneCached;
+  InterfaceTypeImpl _nullNone;
+
+  GreatestLowerBoundHelper _greatestLowerBoundHelper;
+  LeastUpperBoundHelper _leastUpperBoundHelper;
+
+  /// The implementation of the subtyping relation.
+  SubtypeHelper _subtypeHelper;
 
   TypeSystemImpl({
     @required this.implicitCasts,
     @required bool isNonNullableByDefault,
     @required this.strictInference,
     @required this.typeProvider,
-  }) : super(isNonNullableByDefault: isNonNullableByDefault);
+  }) : super(isNonNullableByDefault: isNonNullableByDefault) {
+    _greatestLowerBoundHelper = GreatestLowerBoundHelper(this);
+    _leastUpperBoundHelper = LeastUpperBoundHelper(this);
+    _subtypeHelper = SubtypeHelper(this);
+  }
 
   InterfaceTypeImpl get nullNone =>
-      _nullNoneCached ??= (typeProvider.nullType as TypeImpl)
+      _nullNone ??= (typeProvider.nullType as TypeImpl)
           .withNullability(NullabilitySuffix.none);
 
   InterfaceTypeImpl get objectNone =>
-      _objectNoneCached ??= (typeProvider.objectType as TypeImpl)
+      _objectNone ??= (typeProvider.objectType as TypeImpl)
           .withNullability(NullabilitySuffix.none);
 
   InterfaceTypeImpl get objectQuestion =>
-      _objectQuestionCached ??= (typeProvider.objectType as TypeImpl)
+      _objectQuestion ??= (typeProvider.objectType as TypeImpl)
           .withNullability(NullabilitySuffix.question);
 
   InterfaceTypeImpl get objectStar =>
-      _objectStarCached ??= (typeProvider.objectType as TypeImpl)
+      _objectStar ??= (typeProvider.objectType as TypeImpl)
           .withNullability(NullabilitySuffix.star);
 
-  InterfaceType get _interfaceTypeFunctionNone {
-    return typeProvider.functionType.element.instantiate(
-      typeArguments: const [],
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
-  }
-
   /// Returns true iff the type [t] accepts function types, and requires an
   /// implicit coercion if interface types with a `call` method are passed in.
   ///
@@ -1877,201 +644,7 @@
 
   /// Computes the greatest lower bound of [T1] and [T2].
   DartType getGreatestLowerBound(DartType T1, DartType T2) {
-    // DOWN(T, T) = T
-    if (identical(T1, T2)) {
-      return T1;
-    }
-
-    // For any type T, DOWN(?, T) == T.
-    if (identical(T1, UnknownInferredType.instance)) {
-      return T2;
-    }
-    if (identical(T2, UnknownInferredType.instance)) {
-      return T1;
-    }
-
-    var T1_isTop = isTop(T1);
-    var T2_isTop = isTop(T2);
-
-    // DOWN(T1, T2) where TOP(T1) and TOP(T2)
-    if (T1_isTop && T2_isTop) {
-      // * T1 if MORETOP(T2, T1)
-      // * T2 otherwise
-      if (isMoreTop(T2, T1)) {
-        return T1;
-      } else {
-        return T2;
-      }
-    }
-
-    // DOWN(T1, T2) = T2 if TOP(T1)
-    if (T1_isTop) {
-      return T2;
-    }
-
-    // DOWN(T1, T2) = T1 if TOP(T2)
-    if (T2_isTop) {
-      return T1;
-    }
-
-    var T1_isBottom = isBottom(T1);
-    var T2_isBottom = isBottom(T2);
-
-    // DOWN(T1, T2) where BOTTOM(T1) and BOTTOM(T2)
-    if (T1_isBottom && T2_isBottom) {
-      // * T1 if MOREBOTTOM(T1, T2)
-      // * T2 otherwise
-      if (isMoreBottom(T1, T2)) {
-        return T1;
-      } else {
-        return T2;
-      }
-    }
-
-    // DOWN(T1, T2) = T1 if BOTTOM(T1)
-    if (T1_isBottom) {
-      return T1;
-    }
-
-    // DOWN(T1, T2) = T2 if BOTTOM(T2)
-    if (T2_isBottom) {
-      return T2;
-    }
-
-    var T1_isNull = isNull(T1);
-    var T2_isNull = isNull(T2);
-
-    // DOWN(T1, T2) where NULL(T1) and NULL(T2)
-    if (T1_isNull && T2_isNull) {
-      // * T1 if MOREBOTTOM(T1, T2)
-      // * T2 otherwise
-      if (isMoreBottom(T1, T2)) {
-        return T1;
-      } else {
-        return T2;
-      }
-    }
-
-    var T1_impl = T1 as TypeImpl;
-    var T2_impl = T2 as TypeImpl;
-
-    var T1_nullability = T1_impl.nullabilitySuffix;
-    var T2_nullability = T2_impl.nullabilitySuffix;
-
-    // DOWN(Null, T2)
-    if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull) {
-      // * Null if Null <: T2
-      // * Never otherwise
-      if (isSubtypeOf2(nullNone, T2)) {
-        return nullNone;
-      } else {
-        return NeverTypeImpl.instance;
-      }
-    }
-
-    // DOWN(T1, Null)
-    if (T2_nullability == NullabilitySuffix.none && T2.isDartCoreNull) {
-      // * Null if Null <: T1
-      // * Never otherwise
-      if (isSubtypeOf2(nullNone, T1)) {
-        return nullNone;
-      } else {
-        return NeverTypeImpl.instance;
-      }
-    }
-
-    var T1_isObject = isObject(T1);
-    var T2_isObject = isObject(T2);
-
-    // DOWN(T1, T2) where OBJECT(T1) and OBJECT(T2)
-    if (T1_isObject && T2_isObject) {
-      // * T1 if MORETOP(T2, T1)
-      // * T2 otherwise
-      if (isMoreTop(T2, T1)) {
-        return T1;
-      } else {
-        return T2;
-      }
-    }
-
-    // DOWN(T1, T2) where OBJECT(T1)
-    if (T1_isObject) {
-      // * T2 if T2 is non-nullable
-      if (isNonNullable(T2)) {
-        return T2;
-      }
-
-      // * NonNull(T2) if NonNull(T2) is non-nullable
-      var T2_nonNull = promoteToNonNull(T2_impl);
-      if (isNonNullable(T2_nonNull)) {
-        return T2_nonNull;
-      }
-
-      // * Never otherwise
-      return NeverTypeImpl.instance;
-    }
-
-    // DOWN(T1, T2) where OBJECT(T2)
-    if (T2_isObject) {
-      // * T1 if T1 is non-nullable
-      if (isNonNullable(T1)) {
-        return T1;
-      }
-
-      // * NonNull(T1) if NonNull(T1) is non-nullable
-      var T1_nonNull = promoteToNonNull(T1_impl);
-      if (isNonNullable(T1_nonNull)) {
-        return T1_nonNull;
-      }
-
-      // * Never otherwise
-      return NeverTypeImpl.instance;
-    }
-
-    // DOWN(T1*, T2*) = S* where S is DOWN(T1, T2)
-    // DOWN(T1*, T2?) = S* where S is DOWN(T1, T2)
-    // DOWN(T1?, T2*) = S* where S is DOWN(T1, T2)
-    // DOWN(T1*, T2) = S where S is DOWN(T1, T2)
-    // DOWN(T1, T2*) = S where S is DOWN(T1, T2)
-    // DOWN(T1?, T2?) = S? where S is DOWN(T1, T2)
-    // DOWN(T1?, T2) = S where S is DOWN(T1, T2)
-    // DOWN(T1, T2?) = S where S is DOWN(T1, T2)
-    if (T1_nullability != NullabilitySuffix.none ||
-        T2_nullability != NullabilitySuffix.none) {
-      var resultNullability = NullabilitySuffix.question;
-      if (T1_nullability == NullabilitySuffix.none ||
-          T2_nullability == NullabilitySuffix.none) {
-        resultNullability = NullabilitySuffix.none;
-      } else if (T1_nullability == NullabilitySuffix.star ||
-          T2_nullability == NullabilitySuffix.star) {
-        resultNullability = NullabilitySuffix.star;
-      }
-      var T1_none = T1_impl.withNullability(NullabilitySuffix.none);
-      var T2_none = T2_impl.withNullability(NullabilitySuffix.none);
-      var S = getGreatestLowerBound(T1_none, T2_none);
-      return (S as TypeImpl).withNullability(resultNullability);
-    }
-
-    assert(T1_nullability == NullabilitySuffix.none);
-    assert(T2_nullability == NullabilitySuffix.none);
-
-    // TODO(scheglov) incomplete
-    if (T1 is FunctionType && T2 is FunctionType) {
-      return _functionGreatestLowerBound(T1, T2);
-    }
-
-    // DOWN(T1, T2) = T1 if T1 <: T2
-    if (isSubtypeOf2(T1, T2)) {
-      return T1;
-    }
-
-    // DOWN(T1, T2) = T2 if T2 <: T1
-    if (isSubtypeOf2(T2, T1)) {
-      return T2;
-    }
-
-    // DOWN(T1, T2) = Never otherwise
-    return NeverTypeImpl.instance;
+    return _greatestLowerBoundHelper.getGreatestLowerBound(T1, T2);
   }
 
   /**
@@ -2082,240 +655,7 @@
    */
   @override
   DartType getLeastUpperBound(DartType T1, DartType T2) {
-    // UP(T, T) = T
-    if (identical(T1, T2)) {
-      return T1;
-    }
-
-    // For any type T, UP(?, T) == T.
-    if (identical(T1, UnknownInferredType.instance)) {
-      return T2;
-    }
-    if (identical(T2, UnknownInferredType.instance)) {
-      return T1;
-    }
-
-    var T1_isTop = isTop(T1);
-    var T2_isTop = isTop(T2);
-
-    // UP(T1, T2) where TOP(T1) and TOP(T2)
-    if (T1_isTop && T2_isTop) {
-      // * T1 if MORETOP(T1, T2)
-      // * T2 otherwise
-      if (isMoreTop(T1, T2)) {
-        return T1;
-      } else {
-        return T2;
-      }
-    }
-
-    // UP(T1, T2) = T1 if TOP(T1)
-    if (T1_isTop) {
-      return T1;
-    }
-
-    // UP(T1, T2) = T2 if TOP(T2)
-    if (T2_isTop) {
-      return T2;
-    }
-
-    var T1_isBottom = isBottom(T1);
-    var T2_isBottom = isBottom(T2);
-
-    // UP(T1, T2) where BOTTOM(T1) and BOTTOM(T2)
-    if (T1_isBottom && T2_isBottom) {
-      // * T2 if MOREBOTTOM(T1, T2)
-      // * T1 otherwise
-      if (isMoreBottom(T1, T2)) {
-        return T2;
-      } else {
-        return T1;
-      }
-    }
-
-    // UP(T1, T2) = T2 if BOTTOM(T1)
-    if (T1_isBottom) {
-      return T2;
-    }
-
-    // UP(T1, T2) = T1 if BOTTOM(T2)
-    if (T2_isBottom) {
-      return T1;
-    }
-
-    var T1_isNull = isNull(T1);
-    var T2_isNull = isNull(T2);
-
-    // UP(T1, T2) where NULL(T1) and NULL(T2)
-    if (T1_isNull && T2_isNull) {
-      // * T2 if MOREBOTTOM(T1, T2)
-      // * T1 otherwise
-      if (isMoreBottom(T1, T2)) {
-        return T2;
-      } else {
-        return T1;
-      }
-    }
-
-    var T1_impl = T1 as TypeImpl;
-    var T2_impl = T2 as TypeImpl;
-
-    var T1_nullability = T1_impl.nullabilitySuffix;
-    var T2_nullability = T2_impl.nullabilitySuffix;
-
-    // UP(T1, T2) where NULL(T1)
-    if (T1_isNull) {
-      // * T2 if T2 is nullable
-      // * T2* if Null <: T2 or T1 <: Object (that is, T1 or T2 is legacy)
-      // * T2? otherwise
-      if (isNullable(T2)) {
-        return T2;
-      } else if (T1_nullability == NullabilitySuffix.star ||
-          T2_nullability == NullabilitySuffix.star) {
-        return T2_impl.withNullability(NullabilitySuffix.star);
-      } else {
-        return makeNullable(T2);
-      }
-    }
-
-    // UP(T1, T2) where NULL(T2)
-    if (T2_isNull) {
-      // * T1 if T1 is nullable
-      // * T1* if Null <: T1 or T2 <: Object (that is, T1 or T2 is legacy)
-      // * T1? otherwise
-      if (isNullable(T1)) {
-        return T1;
-      } else if (T1_nullability == NullabilitySuffix.star ||
-          T2_nullability == NullabilitySuffix.star) {
-        return T1_impl.withNullability(NullabilitySuffix.star);
-      } else {
-        return makeNullable(T1);
-      }
-    }
-
-    var T1_isObject = isObject(T1);
-    var T2_isObject = isObject(T2);
-
-    // UP(T1, T2) where OBJECT(T1) and OBJECT(T2)
-    if (T1_isObject && T2_isObject) {
-      // * T1 if MORETOP(T1, T2)
-      // * T2 otherwise
-      if (isMoreTop(T1, T2)) {
-        return T1;
-      } else {
-        return T2;
-      }
-    }
-
-    // UP(T1, T2) where OBJECT(T1)
-    if (T1_isObject) {
-      // * T1 if T2 is non-nullable
-      // * T1? otherwise
-      if (isNonNullable(T2)) {
-        return T1;
-      } else {
-        return makeNullable(T1);
-      }
-    }
-
-    // UP(T1, T2) where OBJECT(T2)
-    if (T2_isObject) {
-      // * T2 if T1 is non-nullable
-      // * T2? otherwise
-      if (isNonNullable(T1)) {
-        return T2;
-      } else {
-        return makeNullable(T2);
-      }
-    }
-
-    // UP(T1*, T2*) = S* where S is UP(T1, T2)
-    // UP(T1*, T2?) = S? where S is UP(T1, T2)
-    // UP(T1?, T2*) = S? where S is UP(T1, T2)
-    // UP(T1*, T2) = S* where S is UP(T1, T2)
-    // UP(T1, T2*) = S* where S is UP(T1, T2)
-    // UP(T1?, T2?) = S? where S is UP(T1, T2)
-    // UP(T1?, T2) = S? where S is UP(T1, T2)
-    // UP(T1, T2?) = S? where S is UP(T1, T2)
-    if (T1_nullability != NullabilitySuffix.none ||
-        T2_nullability != NullabilitySuffix.none) {
-      var resultNullability = NullabilitySuffix.none;
-      if (T1_nullability == NullabilitySuffix.question ||
-          T2_nullability == NullabilitySuffix.question) {
-        resultNullability = NullabilitySuffix.question;
-      } else if (T1_nullability == NullabilitySuffix.star ||
-          T2_nullability == NullabilitySuffix.star) {
-        resultNullability = NullabilitySuffix.star;
-      }
-      var T1_none = T1_impl.withNullability(NullabilitySuffix.none);
-      var T2_none = T2_impl.withNullability(NullabilitySuffix.none);
-      var S = getLeastUpperBound(T1_none, T2_none);
-      return (S as TypeImpl).withNullability(resultNullability);
-    }
-
-    assert(T1_nullability == NullabilitySuffix.none);
-    assert(T2_nullability == NullabilitySuffix.none);
-
-    // UP(X1 extends B1, T2)
-    // UP(X1 & B1, T2)
-    if (T1 is TypeParameterType) {
-      // T2 if X1 <: T2
-      if (isSubtypeOf2(T1, T2)) {
-        return T2;
-      }
-      // otherwise X1 if T2 <: X1
-      if (isSubtypeOf2(T2, T1)) {
-        return T1;
-      }
-      // otherwise UP(B1[Object/X1], T2)
-      var T1_toObject = _typeParameterResolveToObjectBounds(T1);
-      return getLeastUpperBound(T1_toObject, T2);
-    }
-
-    // UP(T1, X2 extends B2)
-    // UP(T1, X2 & B2)
-    if (T2 is TypeParameterType) {
-      // X2 if T1 <: X2
-      if (isSubtypeOf2(T1, T2)) {
-        // TODO(scheglov) How to get here?
-        return T2;
-      }
-      // otherwise T1 if X2 <: T1
-      if (isSubtypeOf2(T2, T1)) {
-        return T1;
-      }
-      // otherwise UP(T1, B2[Object/X2])
-      var T2_toObject = _typeParameterResolveToObjectBounds(T2);
-      return getLeastUpperBound(T1, T2_toObject);
-    }
-
-    // UP(T Function<...>(...), Function) = Function
-    if (T1 is FunctionType && T2.isDartCoreFunction) {
-      return T2;
-    }
-
-    // UP(Function, T Function<...>(...)) = Function
-    if (T1.isDartCoreFunction && T2 is FunctionType) {
-      return T1;
-    }
-
-    // UP(T Function<...>(...), S Function<...>(...)) = Function
-    // And other, more interesting variants.
-    if (T1 is FunctionType && T2 is FunctionType) {
-      return _functionLeastUpperBound(T1, T2);
-    }
-
-    // UP(T Function<...>(...), T2) = Object
-    // UP(T1, T Function<...>(...)) = Object
-    if (T1 is FunctionType || T2 is FunctionType) {
-      return objectNone;
-    }
-
-    // UP(T1, T2) = T2 if T1 <: T2
-    // UP(T1, T2) = T1 if T2 <: T1
-    // And other, more complex variants of interface types.
-    var helper = InterfaceLeastUpperBoundHelper(this);
-    return helper.compute(T1, T2);
+    return _leastUpperBoundHelper.getLeastUpperBound(T1, T2);
   }
 
   /// Returns the greatest closure of the given type [schema] with respect to `?`.
@@ -2954,282 +1294,22 @@
     return false;
   }
 
-  /// Check if [_T0] is a subtype of [_T1].
+  /// Check if [leftType] is a subtype of [rightType].
   ///
   /// Implements:
-  /// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md#rules
+  /// https://github.com/dart-lang/language
+  /// See `resources/type-system/subtyping.md`
   @override
-  bool isSubtypeOf(DartType _T0, DartType _T1) {
+  bool isSubtypeOf(DartType leftType, DartType rightType) {
     if (!NullSafetyUnderstandingFlag.isEnabled) {
-      _T0 = NullabilityEliminator.perform(typeProvider, _T0);
-      _T1 = NullabilityEliminator.perform(typeProvider, _T1);
+      leftType = NullabilityEliminator.perform(typeProvider, leftType);
+      rightType = NullabilityEliminator.perform(typeProvider, rightType);
     }
-    return isSubtypeOf2(_T0, _T1);
+    return isSubtypeOf2(leftType, rightType);
   }
 
-  bool isSubtypeOf2(DartType _T0, DartType _T1) {
-    // Reflexivity: if `T0` and `T1` are the same type then `T0 <: T1`.
-    if (identical(_T0, _T1)) {
-      return true;
-    }
-
-    // `?` is treated as a top and a bottom type during inference.
-    if (identical(_T0, UnknownInferredType.instance) ||
-        identical(_T1, UnknownInferredType.instance)) {
-      return true;
-    }
-
-    var T0 = _T0 as TypeImpl;
-    var T1 = _T1 as TypeImpl;
-
-    var T1_nullability = T1.nullabilitySuffix;
-    var T0_nullability = T0.nullabilitySuffix;
-
-    // Right Top: if `T1` is a top type (i.e. `dynamic`, or `void`, or
-    // `Object?`) then `T0 <: T1`.
-    if (identical(T1, DynamicTypeImpl.instance) ||
-        identical(T1, VoidTypeImpl.instance) ||
-        T1_nullability == NullabilitySuffix.question && T1.isDartCoreObject) {
-      return true;
-    }
-
-    // Left Top: if `T0` is `dynamic` or `void`,
-    //   then `T0 <: T1` if `Object? <: T1`.
-    if (identical(T0, DynamicTypeImpl.instance) ||
-        identical(T0, VoidTypeImpl.instance)) {
-      if (isSubtypeOf2(objectQuestion, T1)) {
-        return true;
-      }
-    }
-
-    // Left Bottom: if `T0` is `Never`, then `T0 <: T1`.
-    if (identical(T0, NeverTypeImpl.instance)) {
-      return true;
-    }
-
-    // Right Object: if `T1` is `Object` then:
-    if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreObject) {
-      // * if `T0` is an unpromoted type variable with bound `B`,
-      //   then `T0 <: T1` iff `B <: Object`.
-      // * if `T0` is a promoted type variable `X & S`,
-      //   then `T0 <: T1` iff `S <: Object`.
-      if (T0_nullability == NullabilitySuffix.none &&
-          T0 is TypeParameterTypeImpl) {
-        var S = T0.promotedBound;
-        var B = T0.element.bound;
-        if (S == null && B != null) {
-          return isSubtypeOf2(B, objectNone);
-        }
-        if (S != null) {
-          return isSubtypeOf2(S, objectNone);
-        }
-      }
-      // * if `T0` is `FutureOr<S>` for some `S`,
-      //   then `T0 <: T1` iff `S <: Object`
-      if (T0_nullability == NullabilitySuffix.none &&
-          T0 is InterfaceTypeImpl &&
-          T0.isDartAsyncFutureOr) {
-        return isSubtypeOf2(T0.typeArguments[0], T1);
-      }
-      // * if `T0` is `S*` for any `S`, then `T0 <: T1` iff `S <: T1`
-      if (T0_nullability == NullabilitySuffix.star) {
-        return isSubtypeOf2(
-          T0.withNullability(NullabilitySuffix.none),
-          T1,
-        );
-      }
-      // * if `T0` is `Null`, `dynamic`, `void`, or `S?` for any `S`,
-      //   then the subtyping does not hold, the result is false.
-      if (T0_nullability == NullabilitySuffix.none && T0.isDartCoreNull ||
-          identical(T0, DynamicTypeImpl.instance) ||
-          identical(T0, VoidTypeImpl.instance) ||
-          T0_nullability == NullabilitySuffix.question) {
-        return false;
-      }
-      // Otherwise `T0 <: T1` is true.
-      return true;
-    }
-
-    // Left Null: if `T0` is `Null` then:
-    if (T0_nullability == NullabilitySuffix.none && T0.isDartCoreNull) {
-      // * If `T1` is `FutureOr<S>` for some `S`, then the query is true iff
-      // `Null <: S`.
-      if (T1_nullability == NullabilitySuffix.none &&
-          T1 is InterfaceTypeImpl &&
-          T1.isDartAsyncFutureOr) {
-        var S = T1.typeArguments[0];
-        return isSubtypeOf2(nullNone, S);
-      }
-      // If `T1` is `Null`, `S?` or `S*` for some `S`, then the query is true.
-      if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull ||
-          T1_nullability == NullabilitySuffix.question ||
-          T1_nullability == NullabilitySuffix.star) {
-        return true;
-      }
-      // * if `T1` is a type variable (promoted or not) the query is false
-      if (T1 is TypeParameterTypeImpl) {
-        return false;
-      }
-      // Otherwise, the query is false.
-      return false;
-    }
-
-    // Left Legacy if `T0` is `S0*` then:
-    if (T0_nullability == NullabilitySuffix.star) {
-      // * `T0 <: T1` iff `S0 <: T1`.
-      var S0 = T0.withNullability(NullabilitySuffix.none);
-      return isSubtypeOf2(S0, T1);
-    }
-
-    // Right Legacy `T1` is `S1*` then:
-    //   * `T0 <: T1` iff `T0 <: S1?`.
-    if (T1_nullability == NullabilitySuffix.star) {
-      if (T1 is FunctionType && _isFunctionTypeWithNamedRequired(T0)) {
-        T1 = _functionTypeWithNamedRequired(T1 as FunctionType);
-      }
-      var S1 = T1.withNullability(NullabilitySuffix.question);
-      return isSubtypeOf2(T0, S1);
-    }
-
-    // Left FutureOr: if `T0` is `FutureOr<S0>` then:
-    if (T0_nullability == NullabilitySuffix.none &&
-        T0 is InterfaceTypeImpl &&
-        T0.isDartAsyncFutureOr) {
-      var S0 = T0.typeArguments[0];
-      // * `T0 <: T1` iff `Future<S0> <: T1` and `S0 <: T1`
-      if (isSubtypeOf2(S0, T1)) {
-        var FutureS0 = typeProvider.futureElement.instantiate(
-          typeArguments: [S0],
-          nullabilitySuffix: NullabilitySuffix.none,
-        );
-        return isSubtypeOf2(FutureS0, T1);
-      }
-      return false;
-    }
-
-    // Left Nullable: if `T0` is `S0?` then:
-    //   * `T0 <: T1` iff `S0 <: T1` and `Null <: T1`.
-    if (T0_nullability == NullabilitySuffix.question) {
-      var S0 = T0.withNullability(NullabilitySuffix.none);
-      return isSubtypeOf2(S0, T1) && isSubtypeOf2(nullNone, T1);
-    }
-
-    // Type Variable Reflexivity 1: if T0 is a type variable X0 or a promoted
-    // type variables X0 & S0 and T1 is X0 then:
-    //   * T0 <: T1
-    if (T0 is TypeParameterTypeImpl &&
-        T1 is TypeParameterTypeImpl &&
-        T1.promotedBound == null &&
-        T0.element == T1.element) {
-      return true;
-    }
-
-    // Right Promoted Variable: if `T1` is a promoted type variable `X1 & S1`:
-    //   * `T0 <: T1` iff `T0 <: X1` and `T0 <: S1`
-    if (T1 is TypeParameterTypeImpl && T1.promotedBound != null) {
-      var X1 = TypeParameterTypeImpl(
-        element: T1.element,
-        nullabilitySuffix: T1.nullabilitySuffix,
-      );
-      return isSubtypeOf2(T0, X1) && isSubtypeOf2(T0, T1.promotedBound);
-    }
-
-    // Right FutureOr: if `T1` is `FutureOr<S1>` then:
-    if (T1_nullability == NullabilitySuffix.none &&
-        T1 is InterfaceTypeImpl &&
-        T1.isDartAsyncFutureOr) {
-      var S1 = T1.typeArguments[0];
-      // `T0 <: T1` iff any of the following hold:
-      // * either `T0 <: Future<S1>`
-      var FutureS1 = typeProvider.futureElement.instantiate(
-        typeArguments: [S1],
-        nullabilitySuffix: NullabilitySuffix.none,
-      );
-      if (isSubtypeOf2(T0, FutureS1)) {
-        return true;
-      }
-      // * or `T0 <: S1`
-      if (isSubtypeOf2(T0, S1)) {
-        return true;
-      }
-      // * or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
-      // * or `T0` is `X0 & S0` and `S0 <: T1`
-      if (T0 is TypeParameterTypeImpl) {
-        var S0 = T0.promotedBound;
-        if (S0 != null && isSubtypeOf2(S0, T1)) {
-          return true;
-        }
-        var B0 = T0.element.bound;
-        if (B0 != null && isSubtypeOf2(B0, T1)) {
-          return true;
-        }
-      }
-      // iff
-      return false;
-    }
-
-    // Right Nullable: if `T1` is `S1?` then:
-    if (T1_nullability == NullabilitySuffix.question) {
-      var S1 = T1.withNullability(NullabilitySuffix.none);
-      // `T0 <: T1` iff any of the following hold:
-      // * either `T0 <: S1`
-      if (isSubtypeOf2(T0, S1)) {
-        return true;
-      }
-      // * or `T0 <: Null`
-      if (isSubtypeOf2(T0, nullNone)) {
-        return true;
-      }
-      // or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
-      // or `T0` is `X0 & S0` and `S0 <: T1`
-      if (T0 is TypeParameterTypeImpl) {
-        var S0 = T0.promotedBound;
-        if (S0 != null && isSubtypeOf2(S0, T1)) {
-          return true;
-        }
-        var B0 = T0.element.bound;
-        if (B0 != null && isSubtypeOf2(B0, T1)) {
-          return true;
-        }
-      }
-      // iff
-      return false;
-    }
-
-    // Super-Interface: `T0` is an interface type with super-interfaces
-    // `S0,...Sn`:
-    //   * and `Si <: T1` for some `i`.
-    if (T0 is InterfaceTypeImpl && T1 is InterfaceTypeImpl) {
-      return _isInterfaceSubtypeOf(T0, T1, null);
-    }
-
-    // Left Promoted Variable: `T0` is a promoted type variable `X0 & S0`
-    //   * and `S0 <: T1`
-    // Left Type Variable Bound: `T0` is a type variable `X0` with bound `B0`
-    //   * and `B0 <: T1`
-    if (T0 is TypeParameterTypeImpl) {
-      var S0 = T0.promotedBound;
-      if (S0 != null && isSubtypeOf2(S0, T1)) {
-        return true;
-      }
-
-      var B0 = T0.element.bound;
-      if (B0 != null && isSubtypeOf2(B0, T1)) {
-        return true;
-      }
-    }
-
-    if (T0 is FunctionTypeImpl) {
-      // Function Type/Function: `T0` is a function type and `T1` is `Function`.
-      if (T1.isDartCoreFunction) {
-        return true;
-      }
-      if (T1 is FunctionTypeImpl) {
-        return _isFunctionSubtypeOf(T0, T1);
-      }
-    }
-
-    return false;
+  bool isSubtypeOf2(DartType leftType, DartType rightType) {
+    return _subtypeHelper.isSubtypeOf(leftType, rightType);
   }
 
   /// Return `true` for any type which is in the equivalence class of top types.
@@ -3410,830 +1490,6 @@
       return typeParameterImpl.defaultType;
     }).toList();
   }
-
-  /**
-   * Compute the greatest lower bound of function types [f] and [g].
-   *
-   * https://github.com/dart-lang/language
-   * See `resources/type-system/upper-lower-bounds.md`
-   */
-  DartType _functionGreatestLowerBound(FunctionType f, FunctionType g) {
-    var fTypeFormals = f.typeFormals;
-    var gTypeFormals = g.typeFormals;
-
-    // The number of type parameters must be the same.
-    // Otherwise the result is `Never`.
-    if (fTypeFormals.length != gTypeFormals.length) {
-      return NeverTypeImpl.instance;
-    }
-
-    // The bounds of type parameters must be equal.
-    // Otherwise the result is `Never`.
-    var freshTypeFormalTypes =
-        FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
-    if (freshTypeFormalTypes == null) {
-      return NeverTypeImpl.instance;
-    }
-
-    var typeFormals = freshTypeFormalTypes
-        .map<TypeParameterElement>((t) => t.element)
-        .toList();
-
-    f = f.instantiate(freshTypeFormalTypes);
-    g = g.instantiate(freshTypeFormalTypes);
-
-    var fParameters = f.parameters;
-    var gParameters = g.parameters;
-
-    var parameters = <ParameterElement>[];
-    var fIndex = 0;
-    var gIndex = 0;
-    while (fIndex < fParameters.length && gIndex < gParameters.length) {
-      var fParameter = fParameters[fIndex];
-      var gParameter = gParameters[gIndex];
-      if (fParameter.isPositional) {
-        if (gParameter.isPositional) {
-          fIndex++;
-          gIndex++;
-          parameters.add(
-            ParameterElementImpl.synthetic(
-              fParameter.name,
-              getLeastUpperBound(fParameter.type, gParameter.type),
-              fParameter.isOptional || gParameter.isOptional
-                  ? ParameterKind.POSITIONAL
-                  : ParameterKind.REQUIRED,
-            ),
-          );
-        } else {
-          return NeverTypeImpl.instance;
-        }
-      } else if (fParameter.isNamed) {
-        if (gParameter.isNamed) {
-          var compareNames = fParameter.name.compareTo(gParameter.name);
-          if (compareNames == 0) {
-            fIndex++;
-            gIndex++;
-            parameters.add(
-              ParameterElementImpl.synthetic(
-                fParameter.name,
-                getLeastUpperBound(fParameter.type, gParameter.type),
-                fParameter.isRequiredNamed && gParameter.isRequiredNamed
-                    ? ParameterKind.NAMED_REQUIRED
-                    : ParameterKind.NAMED,
-              ),
-            );
-          } else if (compareNames < 0) {
-            fIndex++;
-            parameters.add(
-              ParameterElementImpl.synthetic(
-                fParameter.name,
-                fParameter.type,
-                ParameterKind.NAMED,
-              ),
-            );
-          } else {
-            assert(compareNames > 0);
-            gIndex++;
-            parameters.add(
-              ParameterElementImpl.synthetic(
-                gParameter.name,
-                gParameter.type,
-                ParameterKind.NAMED,
-              ),
-            );
-          }
-        } else {
-          return NeverTypeImpl.instance;
-        }
-      }
-    }
-
-    while (fIndex < fParameters.length) {
-      var fParameter = fParameters[fIndex++];
-      if (fParameter.isPositional) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            fParameter.name,
-            fParameter.type,
-            ParameterKind.POSITIONAL,
-          ),
-        );
-      } else {
-        assert(fParameter.isNamed);
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            fParameter.name,
-            fParameter.type,
-            ParameterKind.NAMED,
-          ),
-        );
-      }
-    }
-
-    while (gIndex < gParameters.length) {
-      var gParameter = gParameters[gIndex++];
-      if (gParameter.isPositional) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            gParameter.name,
-            gParameter.type,
-            ParameterKind.POSITIONAL,
-          ),
-        );
-      } else {
-        assert(gParameter.isNamed);
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            gParameter.name,
-            gParameter.type,
-            ParameterKind.NAMED,
-          ),
-        );
-      }
-    }
-
-    var returnType = getGreatestLowerBound(f.returnType, g.returnType);
-
-    return FunctionTypeImpl(
-      typeFormals: typeFormals,
-      parameters: parameters,
-      returnType: returnType,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
-  }
-
-  /**
-   * Compute the least upper bound of function types [f] and [g].
-   *
-   * https://github.com/dart-lang/language
-   * See `resources/type-system/upper-lower-bounds.md`
-   */
-  DartType _functionLeastUpperBound(FunctionType f, FunctionType g) {
-    var fTypeFormals = f.typeFormals;
-    var gTypeFormals = g.typeFormals;
-
-    // The number of type parameters must be the same.
-    // Otherwise the result is `Function`.
-    if (fTypeFormals.length != gTypeFormals.length) {
-      return _interfaceTypeFunctionNone;
-    }
-
-    // The bounds of type parameters must be equal.
-    // Otherwise the result is `Function`.
-    var freshTypeFormalTypes =
-        FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
-    if (freshTypeFormalTypes == null) {
-      return _interfaceTypeFunctionNone;
-    }
-
-    var typeFormals = freshTypeFormalTypes
-        .map<TypeParameterElement>((t) => t.element)
-        .toList();
-
-    f = f.instantiate(freshTypeFormalTypes);
-    g = g.instantiate(freshTypeFormalTypes);
-
-    var fParameters = f.parameters;
-    var gParameters = g.parameters;
-
-    var parameters = <ParameterElement>[];
-    var fIndex = 0;
-    var gIndex = 0;
-    while (fIndex < fParameters.length && gIndex < gParameters.length) {
-      var fParameter = fParameters[fIndex];
-      var gParameter = gParameters[gIndex];
-      if (fParameter.isRequiredPositional) {
-        if (gParameter.isRequiredPositional) {
-          fIndex++;
-          gIndex++;
-          parameters.add(
-            ParameterElementImpl.synthetic(
-              fParameter.name,
-              getGreatestLowerBound(fParameter.type, gParameter.type),
-              ParameterKind.REQUIRED,
-            ),
-          );
-        } else {
-          break;
-        }
-      } else if (fParameter.isOptionalPositional) {
-        if (gParameter.isOptionalPositional) {
-          fIndex++;
-          gIndex++;
-          parameters.add(
-            ParameterElementImpl.synthetic(
-              fParameter.name,
-              getGreatestLowerBound(fParameter.type, gParameter.type),
-              ParameterKind.POSITIONAL,
-            ),
-          );
-        } else {
-          break;
-        }
-      } else if (fParameter.isNamed) {
-        if (gParameter.isNamed) {
-          var compareNames = fParameter.name.compareTo(gParameter.name);
-          if (compareNames == 0) {
-            fIndex++;
-            gIndex++;
-            parameters.add(
-              ParameterElementImpl.synthetic(
-                fParameter.name,
-                getGreatestLowerBound(fParameter.type, gParameter.type),
-                fParameter.isRequiredNamed || gParameter.isRequiredNamed
-                    ? ParameterKind.NAMED_REQUIRED
-                    : ParameterKind.NAMED,
-              ),
-            );
-          } else if (compareNames < 0) {
-            if (fParameter.isRequiredNamed) {
-              // We cannot skip required named.
-              return _interfaceTypeFunctionNone;
-            } else {
-              fIndex++;
-            }
-          } else {
-            assert(compareNames > 0);
-            if (gParameter.isRequiredNamed) {
-              // We cannot skip required named.
-              return _interfaceTypeFunctionNone;
-            } else {
-              gIndex++;
-            }
-          }
-        } else {
-          break;
-        }
-      }
-    }
-
-    while (fIndex < fParameters.length) {
-      var fParameter = fParameters[fIndex++];
-      if (fParameter.isNotOptional) {
-        return _interfaceTypeFunctionNone;
-      }
-    }
-
-    while (gIndex < gParameters.length) {
-      var gParameter = gParameters[gIndex++];
-      if (gParameter.isNotOptional) {
-        return _interfaceTypeFunctionNone;
-      }
-    }
-
-    var returnType = getLeastUpperBound(f.returnType, g.returnType);
-
-    return FunctionTypeImpl(
-      typeFormals: typeFormals,
-      parameters: parameters,
-      returnType: returnType,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
-  }
-
-  /// Check that [f] is a subtype of [g].
-  bool _isFunctionSubtypeOf(FunctionType f, FunctionType g) {
-    var fTypeFormals = f.typeFormals;
-    var gTypeFormals = g.typeFormals;
-
-    // The number of type parameters must be the same.
-    if (fTypeFormals.length != gTypeFormals.length) {
-      return false;
-    }
-
-    // The bounds of type parameters must be equal.
-    var freshTypeFormalTypes =
-        FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) {
-      return isSubtypeOf2(t, s) && isSubtypeOf2(s, t);
-    });
-    if (freshTypeFormalTypes == null) {
-      return false;
-    }
-
-    f = f.instantiate(freshTypeFormalTypes);
-    g = g.instantiate(freshTypeFormalTypes);
-
-    if (!isSubtypeOf2(f.returnType, g.returnType)) {
-      return false;
-    }
-
-    var fParameters = f.parameters;
-    var gParameters = g.parameters;
-
-    var fIndex = 0;
-    var gIndex = 0;
-    while (fIndex < fParameters.length && gIndex < gParameters.length) {
-      var fParameter = fParameters[fIndex];
-      var gParameter = gParameters[gIndex];
-      if (fParameter.isRequiredPositional) {
-        if (gParameter.isRequiredPositional) {
-          if (isSubtypeOf2(gParameter.type, fParameter.type)) {
-            fIndex++;
-            gIndex++;
-          } else {
-            return false;
-          }
-        } else {
-          return false;
-        }
-      } else if (fParameter.isOptionalPositional) {
-        if (gParameter.isPositional) {
-          if (isSubtypeOf2(gParameter.type, fParameter.type)) {
-            fIndex++;
-            gIndex++;
-          } else {
-            return false;
-          }
-        } else {
-          return false;
-        }
-      } else if (fParameter.isNamed) {
-        if (gParameter.isNamed) {
-          var compareNames = fParameter.name.compareTo(gParameter.name);
-          if (compareNames == 0) {
-            var gIsRequiredOrLegacy = gParameter.isRequiredNamed ||
-                g.nullabilitySuffix == NullabilitySuffix.star;
-            if (fParameter.isRequiredNamed && !gIsRequiredOrLegacy) {
-              return false;
-            } else if (isSubtypeOf2(gParameter.type, fParameter.type)) {
-              fIndex++;
-              gIndex++;
-            } else {
-              return false;
-            }
-          } else if (compareNames < 0) {
-            if (fParameter.isRequiredNamed) {
-              return false;
-            } else {
-              fIndex++;
-            }
-          } else {
-            assert(compareNames > 0);
-            // The subtype must accept all parameters of the supertype.
-            return false;
-          }
-        } else {
-          break;
-        }
-      }
-    }
-
-    // The supertype must provide all required parameters to the subtype.
-    while (fIndex < fParameters.length) {
-      var fParameter = fParameters[fIndex++];
-      if (fParameter.isNotOptional) {
-        return false;
-      }
-    }
-
-    // The subtype must accept all parameters of the supertype.
-    assert(fIndex == fParameters.length);
-    if (gIndex < gParameters.length) {
-      return false;
-    }
-
-    return true;
-  }
-
-  bool _isInterfaceSubtypeOf(
-      InterfaceType i1, InterfaceType i2, Set<ClassElement> visitedTypes) {
-    // Note: we should never reach `_isInterfaceSubtypeOf` with `i2 == Object`,
-    // because top types are eliminated before `isSubtypeOf` calls this.
-    if (identical(i1, i2) || i2.isObject) {
-      return true;
-    }
-
-    // Object cannot subtype anything but itself (handled above).
-    if (i1.isObject) {
-      return false;
-    }
-
-    ClassElement i1Element = i1.element;
-    if (i1Element == i2.element) {
-      List<DartType> tArgs1 = i1.typeArguments;
-      List<DartType> tArgs2 = i2.typeArguments;
-      List<TypeParameterElement> tParams = i1Element.typeParameters;
-
-      assert(tArgs1.length == tArgs2.length);
-      assert(tParams.length == tArgs1.length);
-
-      for (int i = 0; i < tArgs1.length; i++) {
-        DartType t1 = tArgs1[i];
-        DartType t2 = tArgs2[i];
-
-        // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
-        // variance is added to the interface.
-        Variance variance = (tParams[i] as TypeParameterElementImpl).variance;
-        if (variance.isCovariant) {
-          if (!isSubtypeOf2(t1, t2)) {
-            return false;
-          }
-        } else if (variance.isContravariant) {
-          if (!isSubtypeOf2(t2, t1)) {
-            return false;
-          }
-        } else if (variance.isInvariant) {
-          if (!isSubtypeOf2(t1, t2) || !isSubtypeOf2(t2, t1)) {
-            return false;
-          }
-        } else {
-          throw StateError('Type parameter ${tParams[i]} has unknown '
-              'variance $variance for subtype checking.');
-        }
-      }
-      return true;
-    }
-
-    // Classes types cannot subtype `Function` or vice versa.
-    if (i1.isDartCoreFunction || i2.isDartCoreFunction) {
-      return false;
-    }
-
-    // Guard against loops in the class hierarchy.
-    //
-    // Dart 2 does not allow multiple implementations of the same generic type
-    // with different type arguments. So we can track just the class element
-    // to find cycles, rather than tracking the full interface type.
-    visitedTypes ??= HashSet<ClassElement>();
-    if (!visitedTypes.add(i1Element)) return false;
-
-    InterfaceType superclass = i1.superclass;
-    if (superclass != null &&
-        _isInterfaceSubtypeOf(superclass, i2, visitedTypes)) {
-      return true;
-    }
-
-    for (final parent in i1.interfaces) {
-      if (_isInterfaceSubtypeOf(parent, i2, visitedTypes)) {
-        return true;
-      }
-    }
-
-    for (final parent in i1.mixins) {
-      if (_isInterfaceSubtypeOf(parent, i2, visitedTypes)) {
-        return true;
-      }
-    }
-
-    if (i1Element.isMixin) {
-      for (final parent in i1.superclassConstraints) {
-        if (_isInterfaceSubtypeOf(parent, i2, visitedTypes)) {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
-  DartType _typeParameterResolveToObjectBounds(DartType type) {
-    var element = type.element;
-    type = type.resolveToBound(typeProvider.objectType);
-    return Substitution.fromMap({element: typeProvider.objectType})
-        .substituteType(type);
-  }
-
-  static FunctionTypeImpl _functionTypeWithNamedRequired(FunctionType type) {
-    return FunctionTypeImpl(
-      typeFormals: type.typeFormals,
-      parameters: type.parameters.map((e) {
-        if (e.isNamed) {
-          return ParameterElementImpl.synthetic(
-            e.name,
-            e.type,
-            ParameterKind.NAMED_REQUIRED,
-          );
-        } else {
-          return e;
-        }
-      }).toList(growable: false),
-      returnType: type.returnType,
-      nullabilitySuffix: type.nullabilitySuffix,
-    );
-  }
-
-  static bool _isFunctionTypeWithNamedRequired(DartType type) {
-    if (type is FunctionType) {
-      return type.parameters.any((e) => e.isRequiredNamed);
-    }
-    return false;
-  }
-}
-
-/// A type that is being inferred but is not currently known.
-///
-/// This type will only appear in a downward inference context for type
-/// parameters that we do not know yet. Notationally it is written `?`, for
-/// example `List<?>`. This is distinct from `List<dynamic>`. These types will
-/// never appear in the final resolved AST.
-class UnknownInferredType extends TypeImpl {
-  static final UnknownInferredType instance = UnknownInferredType._();
-
-  UnknownInferredType._() : super(UnknownInferredTypeElement.instance);
-
-  @override
-  int get hashCode => 1;
-
-  @override
-  bool get isDynamic => true;
-
-  @Deprecated('Check element, or use getDisplayString()')
-  @override
-  String get name => Keyword.DYNAMIC.lexeme;
-
-  @override
-  NullabilitySuffix get nullabilitySuffix => NullabilitySuffix.star;
-
-  @override
-  bool operator ==(Object object) => identical(object, this);
-
-  @override
-  void appendTo(ElementDisplayStringBuilder builder) {
-    builder.writeUnknownInferredType();
-  }
-
-  @override
-  DartType replaceTopAndBottom(TypeProvider typeProvider,
-      {bool isCovariant = true}) {
-    // In theory this should never happen, since we only need to do this
-    // replacement when checking super-boundedness of explicitly-specified
-    // types, or types produced by mixin inference or instantiate-to-bounds, and
-    // the unknown type can't occur in any of those cases.
-    assert(
-        false, 'Attempted to check super-boundedness of a type including "?"');
-    // But just in case it does, behave similar to `dynamic`.
-    if (isCovariant) {
-      return typeProvider.nullType;
-    } else {
-      return this;
-    }
-  }
-
-  @override
-  DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes) {
-    int length = parameterTypes.length;
-    for (int i = 0; i < length; i++) {
-      if (parameterTypes[i] == this) {
-        return argumentTypes[i];
-      }
-    }
-    return this;
-  }
-
-  @override
-  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) => this;
-
-  /// Given a [type] T, return true if it does not have an unknown type `?`.
-  static bool isKnown(DartType type) => !isUnknown(type);
-
-  /// Given a [type] T, return true if it has an unknown type `?`.
-  static bool isUnknown(DartType type) {
-    if (identical(type, UnknownInferredType.instance)) {
-      return true;
-    }
-    if (type is InterfaceTypeImpl) {
-      return type.typeArguments.any(isUnknown);
-    }
-    if (type is FunctionType) {
-      return isUnknown(type.returnType) ||
-          type.parameters.any((p) => isUnknown(p.type));
-    }
-    return false;
-  }
-}
-
-/// The synthetic element for [UnknownInferredType].
-class UnknownInferredTypeElement extends ElementImpl
-    implements TypeDefiningElement {
-  static final UnknownInferredTypeElement instance =
-      UnknownInferredTypeElement._();
-
-  UnknownInferredTypeElement._() : super(Keyword.DYNAMIC.lexeme, -1) {
-    setModifier(Modifier.SYNTHETIC, true);
-  }
-
-  @override
-  ElementKind get kind => ElementKind.DYNAMIC;
-
-  @override
-  UnknownInferredType get type => UnknownInferredType.instance;
-
-  @override
-  T accept<T>(ElementVisitor visitor) => null;
-}
-
-/// A constraint on a type parameter that we're inferring.
-class _TypeConstraint extends _TypeRange {
-  /// The type parameter that is constrained by [lowerBound] or [upperBound].
-  final TypeParameterElement typeParameter;
-
-  /// Where this constraint comes from, used for error messages.
-  ///
-  /// See [toString].
-  final _TypeConstraintOrigin origin;
-
-  _TypeConstraint(this.origin, this.typeParameter,
-      {DartType upper, DartType lower})
-      : super(upper: upper, lower: lower);
-
-  _TypeConstraint.fromExtends(
-      TypeParameterElement element, DartType extendsType,
-      {@required bool isNonNullableByDefault})
-      : this(
-            _TypeConstraintFromExtendsClause(
-              element,
-              extendsType,
-              isNonNullableByDefault: isNonNullableByDefault,
-            ),
-            element,
-            upper: extendsType);
-
-  bool get isDownwards => origin is! _TypeConstraintFromArgument;
-
-  bool isSatisifedBy(TypeSystemImpl ts, DartType type) =>
-      ts.isSubtypeOf2(lowerBound, type) && ts.isSubtypeOf2(type, upperBound);
-
-  /// Converts this constraint to a message suitable for a type inference error.
-  @override
-  String toString() => !identical(upperBound, UnknownInferredType.instance)
-      ? "'$typeParameter' must extend '$upperBound'"
-      : "'$lowerBound' must extend '$typeParameter'";
-}
-
-class _TypeConstraintFromArgument extends _TypeConstraintOrigin {
-  final DartType argumentType;
-  final DartType parameterType;
-  final String parameterName;
-  final ClassElement genericClass;
-
-  _TypeConstraintFromArgument(
-      this.argumentType, this.parameterType, this.parameterName,
-      {this.genericClass, @required bool isNonNullableByDefault})
-      : super(isNonNullableByDefault: isNonNullableByDefault);
-
-  @override
-  formatError() {
-    // TODO(jmesserly): we should highlight the span. That would be more useful.
-    // However in summary code it doesn't look like the AST node with span is
-    // available.
-    String prefix;
-    if (genericClass != null &&
-        (genericClass.name == "List" || genericClass.name == "Map") &&
-        genericClass.library.isDartCore == true) {
-      // This will become:
-      //     "List element"
-      //     "Map key"
-      //     "Map value"
-      prefix = "${genericClass.name} $parameterName";
-    } else {
-      prefix = "Parameter '$parameterName'";
-    }
-
-    return [
-      prefix,
-      "declared as     '${_typeStr(parameterType)}'",
-      "but argument is '${_typeStr(argumentType)}'."
-    ];
-  }
-}
-
-class _TypeConstraintFromExtendsClause extends _TypeConstraintOrigin {
-  final TypeParameterElement typeParam;
-  final DartType extendsType;
-
-  _TypeConstraintFromExtendsClause(this.typeParam, this.extendsType,
-      {@required bool isNonNullableByDefault})
-      : super(isNonNullableByDefault: isNonNullableByDefault);
-
-  @override
-  formatError() {
-    return [
-      "Type parameter '${typeParam.name}'",
-      "declared to extend '${_typeStr(extendsType)}'."
-    ];
-  }
-}
-
-class _TypeConstraintFromFunctionContext extends _TypeConstraintOrigin {
-  final DartType contextType;
-  final DartType functionType;
-
-  _TypeConstraintFromFunctionContext(this.functionType, this.contextType,
-      {@required bool isNonNullableByDefault})
-      : super(isNonNullableByDefault: isNonNullableByDefault);
-
-  @override
-  formatError() {
-    return [
-      "Function type",
-      "declared as '${_typeStr(functionType)}'",
-      "used where  '${_typeStr(contextType)}' is required."
-    ];
-  }
-}
-
-class _TypeConstraintFromReturnType extends _TypeConstraintOrigin {
-  final DartType contextType;
-  final DartType declaredType;
-
-  _TypeConstraintFromReturnType(this.declaredType, this.contextType,
-      {@required bool isNonNullableByDefault})
-      : super(isNonNullableByDefault: isNonNullableByDefault);
-
-  @override
-  formatError() {
-    return [
-      "Return type",
-      "declared as '${_typeStr(declaredType)}'",
-      "used where  '${_typeStr(contextType)}' is required."
-    ];
-  }
-}
-
-/// The origin of a type constraint, for the purposes of producing a human
-/// readable error message during type inference as well as determining whether
-/// the constraint was used to fix the type parameter or not.
-abstract class _TypeConstraintOrigin {
-  final bool isNonNullableByDefault;
-
-  _TypeConstraintOrigin({@required this.isNonNullableByDefault});
-
-  List<String> formatError();
-
-  String _typeStr(DartType type) {
-    return type.getDisplayString(withNullability: isNonNullableByDefault);
-  }
-}
-
-class _TypeRange {
-  /// The upper bound of the type parameter. In other words, T <: upperBound.
-  ///
-  /// In Dart this can be written as `<T extends UpperBoundType>`.
-  ///
-  /// In inference, this can happen as a result of parameters of function type.
-  /// For example, consider a signature like:
-  ///
-  ///     T reduce<T>(List<T> values, T f(T x, T y));
-  ///
-  /// and a call to it like:
-  ///
-  ///     reduce(values, (num x, num y) => ...);
-  ///
-  /// From the function expression's parameters, we conclude `T <: num`. We may
-  /// still be able to conclude a different [lower] based on `values` or
-  /// the type of the elided `=> ...` body. For example:
-  ///
-  ///      reduce(['x'], (num x, num y) => 'hi');
-  ///
-  /// Here the [lower] will be `String` and the upper bound will be `num`,
-  /// which cannot be satisfied, so this is ill typed.
-  final DartType upperBound;
-
-  /// The lower bound of the type parameter. In other words, lowerBound <: T.
-  ///
-  /// This kind of constraint cannot be expressed in Dart, but it applies when
-  /// we're doing inference. For example, consider a signature like:
-  ///
-  ///     T pickAtRandom<T>(T x, T y);
-  ///
-  /// and a call to it like:
-  ///
-  ///     pickAtRandom(1, 2.0)
-  ///
-  /// when we see the first parameter is an `int`, we know that `int <: T`.
-  /// When we see `double` this implies `double <: T`.
-  /// Combining these constraints results in a lower bound of `num`.
-  ///
-  /// In general, we choose the lower bound as our inferred type, so we can
-  /// offer the most constrained (strongest) result type.
-  final DartType lowerBound;
-
-  _TypeRange({DartType lower, DartType upper})
-      : lowerBound = lower ?? UnknownInferredType.instance,
-        upperBound = upper ?? UnknownInferredType.instance;
-
-  /// Formats the typeRange as a string suitable for unit testing.
-  ///
-  /// For example, if [typeName] is 'T' and the range has bounds int and Object
-  /// respectively, the returned string will be 'int <: T <: Object'.
-  @visibleForTesting
-  String format(String typeName, {@required bool withNullability}) {
-    String typeStr(DartType type) {
-      return type.getDisplayString(withNullability: withNullability);
-    }
-
-    var lowerString = identical(lowerBound, UnknownInferredType.instance)
-        ? ''
-        : '${typeStr(lowerBound)} <: ';
-    var upperString = identical(upperBound, UnknownInferredType.instance)
-        ? ''
-        : ' <: ${typeStr(upperBound)}';
-    return '$lowerString$typeName$upperString';
-  }
-
-  @override
-  String toString() => format('(type)', withNullability: true);
 }
 
 class _TypeVariableEliminator extends Substitution {
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index b0e1884..7ea5feb 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -59,7 +59,6 @@
 
   analysisOptions.hint = false;
   analysisOptions.lint = options.enableLints;
-  analysisOptions.generateSdkErrors = options.showSdkWarnings;
   analysisOptions.enableTiming = options.enableTiming;
   analysisOptions.lintRules = options.enabledLints?.toList(growable: false);
   return analysisOptions;
@@ -85,9 +84,6 @@
   /// The path to the package root.
   String packageRootPath;
 
-  /// Whether to show SDK warnings.
-  bool showSdkWarnings = false;
-
   /// Whether to use Dart's Strong Mode analyzer.
   bool strongMode = true;
 
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 93ca7de..49e76be 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -17,14 +17,20 @@
 import 'package:analyzer/file_system/file_system.dart' as file_system;
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/constant/compute.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/potentially_constant.dart';
+import 'package:analyzer/src/dart/constant/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisErrorInfo, AnalysisErrorInfoImpl, AnalysisOptions;
+    show
+        AnalysisErrorInfo,
+        AnalysisErrorInfoImpl,
+        AnalysisOptions,
+        AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart'
     show ConstantVerifier, ScopedVisitor;
 import 'package:analyzer/src/generated/source.dart' show LineInfo;
@@ -239,15 +245,15 @@
 
   TypeSystem get typeSystem;
 
-  /// Return `true` if it would be valid for the given instance creation
-  /// [expression] to have a keyword of `const`.
+  /// Return `true` if it would be valid for the given [expression] to have
+  /// a keyword of `const`.
   ///
   /// The [expression] is expected to be a node within one of the compilation
   /// units in [allUnits].
   ///
   /// Note that this method can cause constant evaluation to occur, which can be
   /// computationally expensive.
-  bool canBeConst(InstanceCreationExpression expression);
+  bool canBeConst(Expression expression);
 
   /// Return `true` if it would be valid for the given constructor declaration
   /// [node] to have a keyword of `const`.
@@ -307,30 +313,14 @@
   );
 
   @override
-  bool canBeConst(InstanceCreationExpression expression) {
-    //
-    // Verify that the invoked constructor is a const constructor.
-    //
-    ConstructorElement element = expression.staticElement;
-    if (element == null || !element.isConst) {
+  bool canBeConst(Expression expression) {
+    if (expression is InstanceCreationExpression) {
+      return _canBeConstInstanceCreation(expression);
+    } else if (expression is TypedLiteral) {
+      return _canBeConstTypedLiteral(expression);
+    } else {
       return false;
     }
-
-    // Ensure that dependencies (e.g. default parameter values) are computed.
-    ConstructorElementImpl implElement = element.declaration;
-    implElement.computeConstantDependencies();
-
-    //
-    // Verify that the evaluation of the constructor would not produce an
-    // exception.
-    //
-    Token oldKeyword = expression.keyword;
-    try {
-      expression.keyword = KeywordToken(Keyword.CONST, expression.offset);
-      return !_hasConstantVerifierError(expression);
-    } finally {
-      expression.keyword = oldKeyword;
-    }
   }
 
   @override
@@ -423,11 +413,57 @@
     return const LinterNameInScopeResolutionResult._none();
   }
 
+  bool _canBeConstInstanceCreation(InstanceCreationExpression node) {
+    //
+    // Verify that the invoked constructor is a const constructor.
+    //
+    ConstructorElement element = node.staticElement;
+    if (element == null || !element.isConst) {
+      return false;
+    }
+
+    // Ensure that dependencies (e.g. default parameter values) are computed.
+    ConstructorElementImpl implElement = element.declaration;
+    implElement.computeConstantDependencies();
+
+    //
+    // Verify that the evaluation of the constructor would not produce an
+    // exception.
+    //
+    Token oldKeyword = node.keyword;
+    try {
+      node.keyword = KeywordToken(Keyword.CONST, node.offset);
+      return !_hasConstantVerifierError(node);
+    } finally {
+      node.keyword = oldKeyword;
+    }
+  }
+
+  bool _canBeConstTypedLiteral(TypedLiteral node) {
+    Token oldKeyword = node.constKeyword;
+    try {
+      node.constKeyword = KeywordToken(Keyword.CONST, node.offset);
+      return !_hasConstantVerifierError(node);
+    } finally {
+      node.constKeyword = oldKeyword;
+    }
+  }
+
   /// Return `true` if [ConstantVerifier] reports an error for the [node].
   bool _hasConstantVerifierError(AstNode node) {
     var unitElement = currentUnit.unit.declaredElement;
     var libraryElement = unitElement.library;
 
+    var dependenciesFinder = ConstantExpressionsDependenciesFinder();
+    node.accept(dependenciesFinder);
+    computeConstants(
+      typeProvider,
+      typeSystem,
+      declaredVariables,
+      dependenciesFinder.dependencies.toList(),
+      (analysisOptions as AnalysisOptionsImpl).experimentStatus,
+    );
+
     var listener = ConstantAnalysisErrorListener();
     var errorReporter = ErrorReporter(
       listener,
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 2294207..0a6a1df 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -3645,6 +3645,148 @@
   String toString() => convert.json.encode(toJson());
 }
 
+class CiderUnitErrorsBuilder extends Object
+    with _CiderUnitErrorsMixin
+    implements idl.CiderUnitErrors {
+  List<AnalysisDriverUnitErrorBuilder> _errors;
+  List<int> _signature;
+
+  @override
+  List<AnalysisDriverUnitErrorBuilder> get errors =>
+      _errors ??= <AnalysisDriverUnitErrorBuilder>[];
+
+  set errors(List<AnalysisDriverUnitErrorBuilder> value) {
+    this._errors = value;
+  }
+
+  @override
+  List<int> get signature => _signature ??= <int>[];
+
+  /// The hash signature of this data.
+  set signature(List<int> value) {
+    assert(value == null || value.every((e) => e >= 0));
+    this._signature = value;
+  }
+
+  CiderUnitErrorsBuilder(
+      {List<AnalysisDriverUnitErrorBuilder> errors, List<int> signature})
+      : _errors = errors,
+        _signature = signature;
+
+  /// Flush [informative] data recursively.
+  void flushInformative() {
+    _errors?.forEach((b) => b.flushInformative());
+  }
+
+  /// Accumulate non-[informative] data into [signature].
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    if (this._signature == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._signature.length);
+      for (var x in this._signature) {
+        signature.addInt(x);
+      }
+    }
+    if (this._errors == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._errors.length);
+      for (var x in this._errors) {
+        x?.collectApiSignature(signature);
+      }
+    }
+  }
+
+  List<int> toBuffer() {
+    fb.Builder fbBuilder = fb.Builder();
+    return fbBuilder.finish(finish(fbBuilder), "CUEr");
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_errors;
+    fb.Offset offset_signature;
+    if (!(_errors == null || _errors.isEmpty)) {
+      offset_errors =
+          fbBuilder.writeList(_errors.map((b) => b.finish(fbBuilder)).toList());
+    }
+    if (!(_signature == null || _signature.isEmpty)) {
+      offset_signature = fbBuilder.writeListUint32(_signature);
+    }
+    fbBuilder.startTable();
+    if (offset_errors != null) {
+      fbBuilder.addOffset(1, offset_errors);
+    }
+    if (offset_signature != null) {
+      fbBuilder.addOffset(0, offset_signature);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+idl.CiderUnitErrors readCiderUnitErrors(List<int> buffer) {
+  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
+  return const _CiderUnitErrorsReader().read(rootRef, 0);
+}
+
+class _CiderUnitErrorsReader extends fb.TableReader<_CiderUnitErrorsImpl> {
+  const _CiderUnitErrorsReader();
+
+  @override
+  _CiderUnitErrorsImpl createObject(fb.BufferContext bc, int offset) =>
+      _CiderUnitErrorsImpl(bc, offset);
+}
+
+class _CiderUnitErrorsImpl extends Object
+    with _CiderUnitErrorsMixin
+    implements idl.CiderUnitErrors {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _CiderUnitErrorsImpl(this._bc, this._bcOffset);
+
+  List<idl.AnalysisDriverUnitError> _errors;
+  List<int> _signature;
+
+  @override
+  List<idl.AnalysisDriverUnitError> get errors {
+    _errors ??= const fb.ListReader<idl.AnalysisDriverUnitError>(
+            _AnalysisDriverUnitErrorReader())
+        .vTableGet(_bc, _bcOffset, 1, const <idl.AnalysisDriverUnitError>[]);
+    return _errors;
+  }
+
+  @override
+  List<int> get signature {
+    _signature ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 0, const <int>[]);
+    return _signature;
+  }
+}
+
+abstract class _CiderUnitErrorsMixin implements idl.CiderUnitErrors {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (errors.isNotEmpty) {
+      _result["errors"] = errors.map((_value) => _value.toJson()).toList();
+    }
+    if (signature.isNotEmpty) {
+      _result["signature"] = signature;
+    }
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "errors": errors,
+        "signature": signature,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class CiderUnlinkedUnitBuilder extends Object
     with _CiderUnlinkedUnitMixin
     implements idl.CiderUnlinkedUnit {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 073c2c3..7f390d5 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1023,6 +1023,14 @@
   signature:[uint] (id: 0);
 }
 
+/// Errors for a single unit.
+table CiderUnitErrors {
+  errors:[AnalysisDriverUnitError] (id: 1);
+
+  /// The hash signature of this data.
+  signature:[uint] (id: 0);
+}
+
 /// Information about a compilation unit, contains the content hash
 /// and unlinked summary.
 table CiderUnlinkedUnit {
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 6c505f2..2175ef2 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -465,6 +465,20 @@
   List<int> get signature;
 }
 
+/// Errors for a single unit.
+@TopLevel('CUEr')
+abstract class CiderUnitErrors extends base.SummaryClass {
+  factory CiderUnitErrors.fromBuffer(List<int> buffer) =>
+      generated.readCiderUnitErrors(buffer);
+
+  @Id(1)
+  List<AnalysisDriverUnitError> get errors;
+
+  /// The hash signature of this data.
+  @Id(0)
+  List<int> get signature;
+}
+
 /// Information about a compilation unit, contains the content hash
 /// and unlinked summary.
 @TopLevel('CUUN')
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index 3682824..16af95c 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -7,6 +7,7 @@
 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/analysis/session.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/type_system.dart';
@@ -351,6 +352,8 @@
     for (var declaration in declarations) {
       _inferDeclaration(declaration);
     }
+
+    _resetHierarchies(declarations);
   }
 
   /// This method is invoked when mixins are asked from the [element], and
@@ -388,6 +391,20 @@
     }
   }
 
+  /// When a loop is detected during mixin inference, we pretend that the list
+  /// of mixins of the class is empty. But if this happens during building a
+  /// class hierarchy, we cache such incomplete hierarchy. So, here we reset
+  /// hierarchies for all classes being linked, indiscriminately.
+  void _resetHierarchies(List<AstNode> declarations) {
+    for (var declaration in declarations) {
+      if (declaration is ClassOrMixinDeclaration) {
+        var element = declaration.declaredElement;
+        var sessionImpl = element.library.session as AnalysisSessionImpl;
+        sessionImpl.classHierarchy.remove(element);
+      }
+    }
+  }
+
   static FeatureSet _unitFeatureSet(ClassElementImpl element) {
     var unit = element.linkedNode.parent as CompilationUnit;
     return unit.featureSet;
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 1b70ef0..65daa02 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -55,6 +55,10 @@
     return _node(search, (n) => n is CascadeExpression);
   }
 
+  CatchClause catchClause(String search) {
+    return _node(search, (n) => n is CatchClause);
+  }
+
   ClassDeclaration classDeclaration(String search) {
     return _node(search, (n) => n is ClassDeclaration);
   }
@@ -304,6 +308,10 @@
     return _node(search, (n) => n is TypeAnnotation);
   }
 
+  TypedLiteral typedLiteral(String search) {
+    return _node(search, (n) => n is TypedLiteral);
+  }
+
   TypeName typeName(String search) {
     return _node(search, (n) => n is TypeName);
   }
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 4566120..c91c0d1 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -175,12 +175,11 @@
     throw 0;
   }
 
-    factory LinkedHashMap.fromIterable(Iterable iterable,
+  factory LinkedHashMap.fromIterable(Iterable iterable,
       {K Function(dynamic element)? key, V Function(dynamic element)? value}) {
     throw 0;
   }
 
-
   factory LinkedHashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
     throw 0;
   }
@@ -521,7 +520,7 @@
   external factory String.fromCharCode(int charCode);
 
   external const factory String.fromEnvironment(String name,
-    {String defaultValue = ""});
+      {String defaultValue = ""});
 
   List<int> get codeUnits;
   bool get isEmpty => false;
@@ -579,52 +578,68 @@
     '$sdkRoot/lib/ffi/ffi.dart',
     '''
 library dart.ffi;
+
 class NativeType {
   const NativeType();
 }
+
 class Void extends NativeType {}
+
 class Int8 extends NativeType {
   const Int8();
 }
+
 class Uint8 extends NativeType {
   const Uint8();
 }
+
 class Int16 extends NativeType {
   const Int16();
 }
+
 class Uint16 extends NativeType {
   const Uint16();
 }
+
 class Int32 extends NativeType {
   const Int32();
 }
+
 class Uint32 extends NativeType {
   const Uint32();
 }
+
 class Int64 extends NativeType {
   const Int64();
 }
+
 class Uint64 extends NativeType {
   const Uint64();
 }
+
 class Float extends NativeType {
   const Float();
 }
+
 class Double extends NativeType {
   const Double();
 }
+
 class Pointer<T extends NativeType> extends NativeType {
   static Pointer<NativeFunction<T>> fromFunction<T extends Function>(
       @DartRepresentationOf("T") Function f,
-      [Object exceptionalReturn]);
+      [Object exceptionalReturn]) {}
 }
+
 extension NativeFunctionPointer<NF extends Function>
     on Pointer<NativeFunction<NF>> {
   external DF asFunction<DF extends Function>();
 }
+
 class Struct extends NativeType {}
 
 abstract class DynamicLibrary {}
+
 extension DynamicLibraryExtension on DynamicLibrary {
   external F lookupFunction<T extends Function, F extends Function>(
       String symbolName);
@@ -646,22 +661,36 @@
       '$sdkRoot/lib/html/dart2js/html_dart2js.dart',
       '''
 library dart.dom.html;
+
 import 'dart:async';
 
 class Event {}
+
 class MouseEvent extends Event {}
+
 class FocusEvent extends Event {}
+
 class KeyEvent extends Event {}
 
 abstract class ElementStream<T extends Event> implements Stream<T> {}
 
 abstract class Element {
+  factory Element.html(String html,
+          {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) =>
+      new HtmlElement();
+
   /// Stream of `cut` events handled by this [Element].
   ElementStream<Event> get onCut => throw 0;
 
   String get id => throw 0;
 
   set id(String value) => throw 0;
+
+  DocumentFragment createFragment(String html,
+          {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) => null;
+
+  void setInnerHtml(String html,
+          {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {}
 }
 
 class HtmlElement extends Element {
@@ -682,6 +711,7 @@
   String get innerHtml {
     throw 'not the real implementation';
   }
+
   set innerHtml(String value) {
     // stuff
   }
@@ -706,7 +736,9 @@
 }
 
 class ButtonElement extends HtmlElement {
-  factory ButtonElement._() { throw new UnsupportedError("Not supported"); }
+  factory ButtonElement._() {
+    throw new UnsupportedError("Not supported");
+  }
   factory ButtonElement() => document.createElement("button");
 
   bool autofocus;
@@ -717,14 +749,22 @@
 }
 
 class HeadingElement extends HtmlElement {
-  factory HeadingElement._() { throw new UnsupportedError("Not supported"); }
+  factory HeadingElement._() {
+    throw new UnsupportedError("Not supported");
+  }
   factory HeadingElement.h1() => document.createElement("h1");
   factory HeadingElement.h2() => document.createElement("h2");
   factory HeadingElement.h3() => document.createElement("h3");
 }
 
+class ImageElement extends HtmlEment {
+  String src;
+}
+
 class InputElement extends HtmlElement {
-  factory InputElement._() { throw new UnsupportedError("Not supported"); }
+  factory InputElement._() {
+    throw new UnsupportedError("Not supported");
+  }
   factory InputElement() => document.createElement("input");
 
   String value;
@@ -732,7 +772,9 @@
 }
 
 class IFrameElement extends HtmlElement {
-  factory IFrameElement._() { throw new UnsupportedError("Not supported"); }
+  factory IFrameElement._() {
+    throw new UnsupportedError("Not supported");
+  }
   factory IFrameElement() => JS(
       'returns:IFrameElement;creates:IFrameElement;new:true',
       '#.createElement(#)',
@@ -742,16 +784,12 @@
   String src;
 }
 
-class ImageElement extends HtmlEment {
-  String src;
-}
-
 class OptionElement extends HtmlElement {
-  factory OptionElement({String data: '', String value : '', bool selected: false}) {
-  }
+  factory OptionElement(
+      {String data: '', String value: '', bool selected: false}) {}
 
-  factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) {
-  }
+  factory OptionElement._(
+      [String data, String value, bool defaultSelected, bool selected]) {}
 }
 
 class ScriptElement extends HtmlElement {
@@ -760,15 +798,15 @@
 }
 
 class TableSectionElement extends HtmlElement {
-
   List<TableRowElement> get rows => throw 0;
 
-  TableRowElement addRow() {
-  }
+  TableRowElement addRow() {}
 
   TableRowElement insertRow(int index) => throw 0;
 
-  factory TableSectionElement._() { throw new UnsupportedError("Not supported"); }
+  factory TableSectionElement._() {
+    throw new UnsupportedError("Not supported");
+  }
 
   @Deprecated("Internal Use Only")
   external static Type get instanceRuntimeType;
@@ -778,7 +816,9 @@
 }
 
 class TemplateElement extends HtmlElement {
-  factory TemplateElement._() { throw new UnsupportedError("Not supported"); }
+  factory TemplateElement._() {
+    throw new UnsupportedError("Not supported");
+  }
   factory TemplateElement() => document.createElement("template");
 }
 
@@ -799,6 +839,21 @@
 
 class MediaElement extends Element {}
 
+class WindowBase {}
+
+class Window extends WindowBase {
+  WindowBase open(String url, String name, [String options]) => null;
+}
+
+class NodeValidator {}
+
+class NodeTreeSanitizer {}
+
+class DocumentFragment {
+  DocumentFragment.html(String html,
+          {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {}
+}
+
 dynamic JS(a, b, c, d) {}
 ''',
     )
@@ -824,7 +879,9 @@
       '$sdkRoot/lib/_internal/internal.dart',
       '''
 library dart._internal;
+
 class Symbol {}
+
 class ExternalName {
   final String name;
   const ExternalName(this.name);
@@ -881,10 +938,11 @@
   static Future<bool> isLink(String path) async => true;
   static bool isLinkSync(String path) => true;
 
-  static Future<FileSystemEntityType> type(
-    String path, {bool followLinks: true}) => throw 0;
-  static FileSystemEntityType typeSync(
-    String path, {bool followLinks: true}) => throw 0;
+  static Future<FileSystemEntityType> type(String path,
+          {bool followLinks: true}) =>
+      throw 0;
+  static FileSystemEntityType typeSync(String path, {bool followLinks: true}) =>
+      throw 0;
 }
 
 enum ProcessStartMode {
@@ -958,7 +1016,7 @@
 
 const double E = 2.718281828459045;
 const double PI = 3.1415926535897932;
-const double LN10 =  2.302585092994046;
+const double LN10 = 2.302585092994046;
 
 T min<T extends num>(T a, T b) => throw 0;
 T max<T extends num>(T a, T b) => throw 0;
@@ -1014,17 +1072,13 @@
 
   final AnalysisOptionsImpl _analysisOptions;
 
-  /**
-   * The [AnalysisContextImpl] which is used for all of the sources.
-   */
+  /// The [AnalysisContextImpl] which is used for all of the sources.
   AnalysisContextImpl _analysisContext;
 
   @override
   final List<SdkLibrary> sdkLibraries = [];
 
-  /**
-   * The cached linked bundle of the SDK.
-   */
+  /// The cached linked bundle of the SDK.
   PackageBundle _bundle;
 
   /// Optional [additionalLibraries] should have unique URIs, and paths in
@@ -1176,9 +1230,7 @@
     return null;
   }
 
-  /**
-   * Compute the bytes of the linked bundle associated with this SDK.
-   */
+  /// Compute the bytes of the linked bundle associated with this SDK.
   List<int> _computeLinkedBundleBytes() {
     List<Source> librarySources = sdkLibraries
         .map((SdkLibrary library) => mapDartUri(library.shortName))
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
index 2699efb..894e924 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
@@ -5,6 +5,7 @@
 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/analysis/session.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
@@ -18,9 +19,9 @@
 
   factory MockSdkElements(
     engine.AnalysisContext analysisContext,
-    NullabilitySuffix nullabilitySuffix,
+    AnalysisSessionImpl analysisSession,
   ) {
-    var builder = _MockSdkElementsBuilder(analysisContext, nullabilitySuffix);
+    var builder = _MockSdkElementsBuilder(analysisContext, analysisSession);
     var coreLibrary = builder._buildCore();
     var asyncLibrary = builder._buildAsync();
     return MockSdkElements._(coreLibrary, asyncLibrary);
@@ -31,7 +32,7 @@
 
 class _MockSdkElementsBuilder {
   final engine.AnalysisContext analysisContext;
-  final NullabilitySuffix nullabilitySuffix;
+  final AnalysisSessionImpl analysisSession;
 
   ClassElementImpl _boolElement;
   ClassElementImpl _comparableElement;
@@ -67,7 +68,10 @@
   InterfaceType _stringType;
   InterfaceType _typeType;
 
-  _MockSdkElementsBuilder(this.analysisContext, this.nullabilitySuffix);
+  _MockSdkElementsBuilder(
+    this.analysisContext,
+    this.analysisSession,
+  );
 
   ClassElementImpl get boolElement {
     if (_boolElement != null) return _boolElement;
@@ -815,11 +819,11 @@
   LibraryElementImpl _buildAsync() {
     var asyncLibrary = LibraryElementImpl(
       analysisContext,
-      null,
+      analysisSession,
       'dart.async',
       0,
       0,
-      nullabilitySuffix == NullabilitySuffix.none,
+      true,
     );
 
     var asyncUnit = CompilationUnitElementImpl();
@@ -908,11 +912,11 @@
 
     var coreLibrary = LibraryElementImpl(
       analysisContext,
-      null,
+      analysisSession,
       'dart.core',
       0,
       0,
-      nullabilitySuffix == NullabilitySuffix.none,
+      true,
     );
     coreLibrary.definingCompilationUnit = coreUnit;
 
@@ -976,7 +980,7 @@
       typeFormals: typeFormals,
       parameters: parameters,
       returnType: returnType,
-      nullabilitySuffix: nullabilitySuffix,
+      nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
@@ -1009,7 +1013,7 @@
     return InterfaceTypeImpl(
       element: element,
       typeArguments: typeArguments,
-      nullabilitySuffix: nullabilitySuffix,
+      nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
@@ -1077,7 +1081,7 @@
   TypeParameterType _typeParameterType(TypeParameterElement element) {
     return TypeParameterTypeImpl(
       element: element,
-      nullabilitySuffix: nullabilitySuffix,
+      nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 0c72327..364a1d3 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.39.4
+version: 0.39.7
 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.6.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared: ^1.0.3
+  _fe_analyzer_shared: ^2.2.0
   args: ^1.0.0
   charcode: ^1.1.0
   collection: ^1.10.1
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index ad07280..c4efa4a 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -699,7 +699,7 @@
     MethodInvocation invocation =
         AstTestFactory.methodInvocation(left, methodName);
     _resolveNode(invocation);
-    expect(invocation.methodName.staticElement,
+    expect(invocation.methodName.staticElement.declaration,
         same(numType.getMethod(methodName)));
     _listener.assertNoErrors();
   }
@@ -883,14 +883,6 @@
     _listener.assertNoErrors();
   }
 
-  test_visitSimpleIdentifier_dynamic() async {
-    SimpleIdentifier node = AstTestFactory.identifier3("dynamic");
-    _resolveIdentifier(node);
-    expect(node.staticElement, same(_typeProvider.dynamicType.element));
-    expect(node.staticType, same(_typeProvider.typeType));
-    _listener.assertNoErrors();
-  }
-
   test_visitSimpleIdentifier_lexicalScope() async {
     SimpleIdentifier node = AstTestFactory.identifier3("i");
     VariableElementImpl element = ElementFactory.localVariableElement(node);
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
index 27375f7..9d932a3 100644
--- a/pkg/analyzer/test/generated/elements_types_mixin.dart
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -6,13 +6,19 @@
 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/analysis/session.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/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:meta/meta.dart';
 
 mixin ElementsTypesMixin {
+  LibraryElementImpl get testLibrary => null;
+
   InterfaceType get boolNone {
     var element = typeProvider.boolElement;
     return interfaceTypeNone(element);
@@ -157,6 +163,7 @@
     List<MethodElement> methods = const [],
   }) {
     var element = ClassElementImpl(name, 0);
+    element.enclosingElement = testLibrary;
     element.typeParameters = typeParameters;
     element.supertype = superType ?? typeProvider.objectType;
     element.interfaces = interfaces;
@@ -387,6 +394,30 @@
     );
   }
 
+  LibraryElementImpl library_({
+    @required String uriStr,
+    @required TypeSystemImpl typeSystem,
+    AnalysisContext analysisContext,
+    AnalysisSessionImpl analysisSession,
+  }) {
+    var library = LibraryElementImpl(analysisContext, analysisSession, uriStr,
+        -1, 0, typeSystem.isNonNullableByDefault);
+    library.typeSystem = typeSystem;
+    library.typeProvider = typeSystem.typeProvider;
+
+    var uri = Uri.parse(uriStr);
+    var source = _MockSource(uri);
+
+    var definingUnit = CompilationUnitElementImpl();
+    definingUnit.source = source;
+    definingUnit.librarySource = source;
+
+    definingUnit.enclosingElement = library;
+    library.definingCompilationUnit = definingUnit;
+
+    return library;
+  }
+
   InterfaceType listNone(DartType type) {
     return typeProvider.listElement.instantiate(
       typeArguments: [type],
@@ -408,6 +439,27 @@
     );
   }
 
+  InterfaceType mapNone(DartType key, DartType value) {
+    return typeProvider.mapElement.instantiate(
+      typeArguments: [key, value],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType mapQuestion(DartType key, DartType value) {
+    return typeProvider.mapElement.instantiate(
+      typeArguments: [key, value],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType mapStar(DartType key, DartType value) {
+    return typeProvider.mapElement.instantiate(
+      typeArguments: [key, value],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
   MethodElement method(
     String name,
     DartType returnType, {
@@ -429,6 +481,7 @@
     List<InterfaceType> interfaces = const [],
   }) {
     var element = MixinElementImpl(name, 0);
+    element.enclosingElement = testLibrary;
     element.typeParameters = typeParameters;
     element.superclassConstraints = constraints ?? [typeProvider.objectType];
     element.interfaces = interfaces;
@@ -537,16 +590,6 @@
     return element;
   }
 
-  TypeParameterTypeImpl typeParameterType(
-    TypeParameterElement element, {
-    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
-  }) {
-    return TypeParameterTypeImpl(
-      element: element,
-      nullabilitySuffix: nullabilitySuffix,
-    );
-  }
-
   TypeParameterTypeImpl typeParameterTypeNone(TypeParameterElement element) {
     return element.instantiate(nullabilitySuffix: NullabilitySuffix.none);
   }
@@ -560,3 +603,13 @@
     return element.instantiate(nullabilitySuffix: NullabilitySuffix.star);
   }
 }
+
+class _MockSource implements Source {
+  @override
+  final Uri uri;
+
+  _MockSource(this.uri);
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
deleted file mode 100644
index 71a877f..0000000
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ /dev/null
@@ -1,61 +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.
-
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(AnalysisOptionsImplTest);
-  });
-}
-
-@reflectiveTest
-class AnalysisOptionsImplTest {
-  test_resetToDefaults() {
-    // Note that this only tests options visible from the interface.
-    AnalysisOptionsImpl defaultOptions = AnalysisOptionsImpl();
-    AnalysisOptionsImpl modifiedOptions = AnalysisOptionsImpl();
-    modifiedOptions.dart2jsHint = true;
-    modifiedOptions.disableCacheFlushing = true;
-    modifiedOptions.enabledPluginNames = ['somePackage'];
-    modifiedOptions.enableLazyAssignmentOperators = true;
-    modifiedOptions.enableTiming = true;
-    modifiedOptions.errorProcessors = [null];
-    modifiedOptions.excludePatterns = ['a'];
-    modifiedOptions.generateImplicitErrors = false;
-    modifiedOptions.generateSdkErrors = true;
-    modifiedOptions.hint = false;
-    modifiedOptions.lint = true;
-    modifiedOptions.lintRules = [null];
-    modifiedOptions.patchPaths = {
-      'dart:core': ['/dart_core.patch.dart']
-    };
-    modifiedOptions.preserveComments = false;
-    modifiedOptions.trackCacheDependencies = false;
-
-    modifiedOptions.resetToDefaults();
-
-    expect(modifiedOptions.dart2jsHint, defaultOptions.dart2jsHint);
-    expect(modifiedOptions.disableCacheFlushing,
-        defaultOptions.disableCacheFlushing);
-    expect(modifiedOptions.enabledPluginNames, isEmpty);
-    expect(modifiedOptions.enableLazyAssignmentOperators,
-        defaultOptions.enableLazyAssignmentOperators);
-    expect(modifiedOptions.enableTiming, defaultOptions.enableTiming);
-    expect(modifiedOptions.errorProcessors, defaultOptions.errorProcessors);
-    expect(modifiedOptions.excludePatterns, defaultOptions.excludePatterns);
-    expect(modifiedOptions.generateImplicitErrors,
-        defaultOptions.generateImplicitErrors);
-    expect(modifiedOptions.generateSdkErrors, defaultOptions.generateSdkErrors);
-    expect(modifiedOptions.hint, defaultOptions.hint);
-    expect(modifiedOptions.lint, defaultOptions.lint);
-    expect(modifiedOptions.lintRules, defaultOptions.lintRules);
-    expect(modifiedOptions.patchPaths, defaultOptions.patchPaths);
-    expect(modifiedOptions.preserveComments, defaultOptions.preserveComments);
-    expect(modifiedOptions.trackCacheDependencies,
-        defaultOptions.trackCacheDependencies);
-  }
-}
diff --git a/pkg/analyzer/test/generated/error_suppression_test.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
index 003c3b0..877c713 100644
--- a/pkg/analyzer/test/generated/error_suppression_test.dart
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -16,86 +16,102 @@
 
 @reflectiveTest
 class ErrorSuppressionTest extends DriverResolutionTest with PackageMixin {
-  String get ignoredCode => 'const_initialized_with_non_constant_value';
+  String get ignoredCode => 'unused_element';
+
+  test_does_not_ignore_errors() async {
+    await assertErrorsInCode('''
+int x = ''; // ignore: invalid_assignment
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 8, 2),
+    ]);
+  }
+
+  test_error_cannot_be_ignored() async {
+    await assertErrorsInCode('''
+// ignore: unused_import, undefined_function
+f() => g();
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_FUNCTION, 52, 1),
+    ]);
+  }
 
   test_error_code_mismatch() async {
     await assertErrorsInCode('''
 // ignore: $ignoredCode
 int x = '';
-const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int _y = 0; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
 ''', [
-      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 61, 2),
-      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 75,
-          1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 34, 2),
+      error(HintCode.UNUSED_ELEMENT, 42, 2),
     ]);
   }
 
   test_ignore_first() async {
     await assertErrorsInCode('''
-// ignore: invalid_assignment
-int x = '';
+// ignore: unnecessary_cast
+int x = (0 as int);
 // ... but no ignore here ...
 const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
 ''', [
-      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 82,
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 88,
           1),
     ]);
   }
 
   test_ignore_first_trailing() async {
     await assertErrorsInCode('''
-int x = ''; // ignore: invalid_assignment
+int x = (0 as int); // ignore: unnecessary_cast
 // ... but no ignore here ...
 const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
 ''', [
-      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 82,
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 88,
           1),
     ]);
   }
 
   test_ignore_for_file() async {
     await assertErrorsInCode('''
-int x = '';  //INVALID_ASSIGNMENT
+int x = (0 as int); //UNNECESSARY_CAST
 const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
-// ignore_for_file: invalid_assignment
+// ignore_for_file: unnecessary_cast
 ''', [
-      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 44,
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 49,
           1),
     ]);
   }
 
   test_ignore_for_file_whitespace_variant() async {
     await assertNoErrorsInCode('''
-//ignore_for_file:   $ignoredCode , invalid_assignment
-int x = '';  //INVALID_ASSIGNMENT
-const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+//ignore_for_file:   $ignoredCode , unnecessary_cast
+int x = (0 as int);  //UNNECESSARY_CAST
+String _foo; //UNUSED_ELEMENT
 ''');
   }
 
   test_ignore_only_trailing() async {
     await assertNoErrorsInCode('''
-int x = ''; // ignore: invalid_assignment
+int x = (0 as int); // ignore: unnecessary_cast
 ''');
   }
 
   test_ignore_second() async {
     await assertErrorsInCode('''
-//INVALID_ASSIGNMENT
-int x = '';
+//UNNECESSARY_CAST
+int x = (0 as int);
 // ignore: $ignoredCode
-const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+String _foo; //UNUSED_ELEMENT
 ''', [
-      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 29, 2),
+      error(HintCode.UNNECESSARY_CAST, 28, 8),
     ]);
   }
 
   test_ignore_second_trailing() async {
     await assertErrorsInCode('''
-//INVALID_ASSIGNMENT
-int x = '';
-const y = x; // ignore: $ignoredCode
+//UNNECESSARY_CAST
+int x = (0 as int);
+String _foo; // ignore: $ignoredCode
 ''', [
-      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 29, 2),
+      error(HintCode.UNNECESSARY_CAST, 28, 8),
     ]);
   }
 
@@ -113,7 +129,7 @@
 
   test_ignore_upper_case() async {
     await assertNoErrorsInCode('''
-int x = ''; // ignore: INVALID_ASSIGNMENT
+int x = (0 as int); // ignore: UNNECESSARY_CAST
 ''');
   }
 
@@ -152,78 +168,111 @@
 
   test_multiple_comments() async {
     await assertErrorsInCode('''
-int x = ''; //This is the first comment...
+int x = (0 as int); //This is the first comment...
 // ignore: $ignoredCode
-const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+String _foo; //UNUSED_ELEMENT
 ''', [
-      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 8, 2),
+      error(HintCode.UNNECESSARY_CAST, 9, 8),
     ]);
   }
 
   test_multiple_ignore_for_files() async {
     await assertNoErrorsInCode('''
-int x = '';  //INVALID_ASSIGNMENT
-const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
-// ignore_for_file: invalid_assignment,$ignoredCode
+int x = (0 as int); //UNNECESSARY_CAST
+String _foo; //UNUSED_ELEMENT
+// ignore_for_file: unnecessary_cast,$ignoredCode
 ''');
   }
 
   test_multiple_ignores() async {
     await assertNoErrorsInCode('''
 int x = 3;
-// ignore: invalid_assignment, $ignoredCode
-const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// ignore: unnecessary_cast, $ignoredCode
+int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
 ''');
   }
 
   test_multiple_ignores_trailing() async {
     await assertNoErrorsInCode('''
 int x = 3;
-const String y = x; // ignore: invalid_assignment, $ignoredCode
+int _y = x as int; // ignore: unnecessary_cast, $ignoredCode
 ''');
   }
 
   test_multiple_ignores_whitespace_variant_1() async {
     await assertNoErrorsInCode('''
 int x = 3;
-//ignore:invalid_assignment,$ignoredCode
-const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+//ignore:unnecessary_cast,$ignoredCode
+int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
 ''');
   }
 
   test_multiple_ignores_whitespace_variant_2() async {
     await assertNoErrorsInCode('''
 int x = 3;
-//ignore: invalid_assignment,$ignoredCode
-const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+//ignore: unnecessary_cast,$ignoredCode
+int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
 ''');
   }
 
   test_multiple_ignores_whitespace_variant_3() async {
     await assertNoErrorsInCode('''
 int x = 3;
-// ignore: invalid_assignment,$ignoredCode
-const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// ignore: unnecessary_cast,$ignoredCode
+int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
 ''');
   }
 
   test_no_ignores() async {
     await assertErrorsInCode('''
-int x = '';  //INVALID_ASSIGNMENT
+int x = ''; //INVALID_ASSIGNMENT
 const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
 ''', [
       error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 8, 2),
-      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 44,
+      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 43,
           1),
     ]);
   }
 
   test_trailing_not_above() async {
     await assertErrorsInCode('''
-int x = ''; // ignore: invalid_assignment
-int y = '';
+int x = (0 as int); // ignore: unnecessary_cast
+int y = (0 as int);
 ''', [
-      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 50, 2),
+      error(HintCode.UNNECESSARY_CAST, 57, 8),
     ]);
   }
+
+  test_undefined_function_within_flutter_can_be_ignored() async {
+    await assertErrorsInFile(
+      '/workspace/flutterlib/flutter.dart',
+      '''
+// ignore: undefined_function
+f() => g();
+''',
+      [],
+    );
+  }
+
+  test_undefined_function_within_flutter_without_ignore() async {
+    await assertErrorsInFile(
+      '/workspace/flutterlib/flutter.dart',
+      '''
+f() => g();
+''',
+      [error(StaticTypeWarningCode.UNDEFINED_FUNCTION, 7, 1)],
+    );
+  }
+
+  test_undefined_prefixed_name_within_flutter_can_be_ignored() async {
+    await assertErrorsInFile(
+      '/workspace/flutterlib/flutter.dart',
+      '''
+import 'dart:collection' as c;
+// ignore: undefined_prefixed_name
+f() => c.g;
+''',
+      [],
+    );
+  }
 }
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index ba70d51..575463a 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -163,6 +163,17 @@
     expect(invocation.argumentList.arguments, hasLength(0));
   }
 
+  void test_parseConstructor_operator_name() {
+    var unit = parseCompilationUnit('class A { operator/() : super(); }',
+        errors: [
+          expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 10, 8)
+        ]);
+    var classDeclaration = unit.declarations[0] as ClassDeclaration;
+    var constructor = classDeclaration.members[0] as ConstructorDeclaration;
+    var invocation = constructor.initializers[0] as SuperConstructorInvocation;
+    expect(invocation.argumentList.arguments, hasLength(0));
+  }
+
   void test_parseField_const_late() {
     createParser('const late T f = 0;', featureSet: nonNullable);
     ClassMember member = parser.parseClassMember('C');
@@ -2714,6 +2725,28 @@
     parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
   }
 
+  void test_bangQuestionIndex() {
+    // http://dartbug.com/41177
+    CompilationUnit unit = parseCompilationUnit('f(dynamic a) { a!?[0]; }');
+    FunctionDeclaration funct = unit.declarations[0];
+    BlockFunctionBody body = funct.functionExpression.body;
+
+    ExpressionStatement statement = body.block.statements[0];
+    IndexExpression expression = statement.expression;
+
+    IntegerLiteral index = expression.index;
+    expect(index.value, 0);
+
+    Token question = expression.question;
+    expect(question, isNotNull);
+    expect(question.lexeme, "?");
+
+    PostfixExpression target = expression.target;
+    SimpleIdentifier identifier = target.operand;
+    expect(identifier.name, 'a');
+    expect(target.operator.lexeme, '!');
+  }
+
   void test_bangBeforeFuctionCall1() {
     // https://github.com/dart-lang/sdk/issues/39776
     var unit = parseCompilationUnit('f() { Function? f1; f1!(42); }');
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 5936dbd..fac087f 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -263,7 +263,7 @@
     ClassElementImpl derivedClass =
         ElementFactory.classElement2('Derived', ['T']);
     derivedClass.supertype =
-        futureType(typeParameterType(derivedClass.typeParameters[0]));
+        futureType(typeParameterTypeStar(derivedClass.typeParameters[0]));
     InterfaceType intType = _typeProvider.intType;
     DartType dynamicType = _typeProvider.dynamicType;
     InterfaceType derivedIntType =
@@ -307,7 +307,7 @@
     ClassElementImpl derivedClass =
         ElementFactory.classElement2('Derived', ['T']);
     derivedClass.supertype =
-        futureType(typeParameterType(derivedClass.typeParameters[0]));
+        futureType(typeParameterTypeStar(derivedClass.typeParameters[0]));
     // class A extends Derived<int> implements Derived<num> { ... }
     ClassElementImpl classA = ElementFactory.classElement(
         'A', interfaceTypeStar(derivedClass, typeArguments: [intType]));
@@ -908,16 +908,6 @@
     _listener.assertNoErrors();
   }
 
-  void test_visitSimpleIdentifier_dynamic() {
-    // "dynamic"
-    SimpleIdentifier identifier = AstTestFactory.identifier3('dynamic');
-    DynamicElementImpl element = DynamicElementImpl.instance;
-    identifier.staticElement = element;
-    identifier.staticType = _typeProvider.typeType;
-    expect(_analyze(identifier), same(_typeProvider.typeType));
-    _listener.assertNoErrors();
-  }
-
   void test_visitSimpleStringLiteral() {
     // "a"
     Expression node = _resolvedString("a");
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index f3db5e9..12c45df 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -11,7 +11,6 @@
 // ignore: deprecated_member_use_from_same_package
 import 'constant_test.dart' as constant_test;
 import 'element_resolver_test.dart' as element_resolver_test;
-import 'engine_test.dart' as engine_test;
 import 'error_suppression_test.dart' as error_suppression;
 import 'invalid_code_test.dart' as invalid_code;
 import 'issues_test.dart' as issues;
@@ -41,7 +40,6 @@
     compile_time_error_code.main();
     constant_test.main();
     element_resolver_test.main();
-    engine_test.main();
     error_suppression.main();
     invalid_code.main();
     issues.main();
diff --git a/pkg/analyzer/test/generated/test_analysis_context.dart b/pkg/analyzer/test/generated/test_analysis_context.dart
index 8d2ff9b1c..35ea5c4 100644
--- a/pkg/analyzer/test/generated/test_analysis_context.dart
+++ b/pkg/analyzer/test/generated/test_analysis_context.dart
@@ -3,9 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/analysis/session.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';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
@@ -16,6 +18,7 @@
   @override
   final SourceFactory sourceFactory = _MockSourceFactory();
 
+  _MockAnalysisSession _analysisSession = _MockAnalysisSession();
   AnalysisOptionsImpl _analysisOptions;
 
   TypeProvider _typeProviderLegacy;
@@ -28,12 +31,7 @@
     _analysisOptions = AnalysisOptionsImpl()
       ..contextFeatures = featureSet ?? FeatureSet.forTesting();
 
-    var sdkElements = MockSdkElements(
-      this,
-      analysisOptions.contextFeatures.isEnabled(Feature.non_nullable)
-          ? NullabilitySuffix.none
-          : NullabilitySuffix.star,
-    );
+    var sdkElements = MockSdkElements(this, _analysisSession);
 
     _typeProviderLegacy = TypeProviderImpl(
       coreLibrary: sdkElements.coreLibrary,
@@ -68,6 +66,8 @@
   @override
   AnalysisOptions get analysisOptions => _analysisOptions;
 
+  AnalysisSessionImpl get analysisSession => _analysisSession;
+
   @Deprecated('Use LibraryElement.typeProvider')
   @override
   TypeProvider get typeProvider => typeProviderLegacy;
@@ -96,11 +96,22 @@
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 
   void _setLibraryTypeSystem(LibraryElementImpl libraryElement) {
-    libraryElement.typeProvider = _typeProviderLegacy;
-    libraryElement.typeSystem = _typeSystemLegacy;
+    libraryElement.typeProvider = _typeProviderNonNullableByDefault;
+    libraryElement.typeSystem = _typeSystemNonNullableByDefault;
   }
 }
 
+class _MockAnalysisSession implements AnalysisSessionImpl {
+  @override
+  final ClassHierarchy classHierarchy = ClassHierarchy();
+
+  @override
+  final InheritanceManager3 inheritanceManager = InheritanceManager3();
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
 class _MockSource implements Source {
   @override
   final Uri uri;
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index caef5dfa..8561e3c 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -3,24 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart' show astFactory;
-import 'package:analyzer/dart/ast/token.dart' show Keyword;
 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/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/session.dart';
-import 'package:analyzer/src/dart/ast/token.dart' show KeywordToken;
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/least_upper_bound.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/variance.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart'
-    show NonExistingSource, Source, UriKind;
-import 'package:path/path.dart' show toUri;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -30,19 +21,51 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AssignabilityTest);
-    defineReflectiveTests(ConstraintMatchingTest);
-    defineReflectiveTests(GenericFunctionInferenceTest);
-    defineReflectiveTests(GreatestLowerBoundTest);
     defineReflectiveTests(LeastUpperBoundFunctionsTest);
     defineReflectiveTests(LeastUpperBoundTest);
     defineReflectiveTests(TryPromoteToTest);
   });
 }
 
+abstract class AbstractTypeSystemNullSafetyTest with ElementsTypesMixin {
+  TestAnalysisContext analysisContext;
+
+  @override
+  LibraryElementImpl testLibrary;
+
+  @override
+  TypeProvider typeProvider;
+
+  TypeSystemImpl typeSystem;
+
+  FeatureSet get testFeatureSet {
+    return FeatureSet.forTesting(
+      additionalFeatures: [Feature.non_nullable],
+    );
+  }
+
+  void setUp() {
+    analysisContext = TestAnalysisContext(
+      featureSet: testFeatureSet,
+    );
+    typeProvider = analysisContext.typeProviderNonNullableByDefault;
+    typeSystem = analysisContext.typeSystemNonNullableByDefault;
+
+    testLibrary = library_(
+      uriStr: 'package:test/test.dart',
+      analysisSession: analysisContext.analysisSession,
+      typeSystem: typeSystem,
+    );
+  }
+}
+
 abstract class AbstractTypeSystemTest with ElementsTypesMixin {
   TestAnalysisContext analysisContext;
 
   @override
+  LibraryElementImpl testLibrary;
+
+  @override
   TypeProvider typeProvider;
 
   TypeSystemImpl typeSystem;
@@ -57,6 +80,12 @@
     );
     typeProvider = analysisContext.typeProviderLegacy;
     typeSystem = analysisContext.typeSystemLegacy;
+
+    testLibrary = library_(
+      uriStr: 'package:test/test.dart',
+      analysisSession: analysisContext.analysisSession,
+      typeSystem: typeSystem,
+    );
   }
 
   String _typeString(TypeImpl type) {
@@ -92,7 +121,6 @@
       ],
     );
 
-    var testLibrary = _testLibrary();
     B.enclosingElement = testLibrary.definingCompilationUnit;
 
     _checkIsStrictAssignableTo(
@@ -411,39 +439,12 @@
     _checkIsNotAssignableTo(type1, type2);
     _checkIsNotAssignableTo(type2, type1);
   }
-
-  /// Return a test library, in `/test.dart` file.
-  LibraryElementImpl _testLibrary() {
-    var source = _MockSource(toUri('/test.dart'));
-
-    var definingUnit = CompilationUnitElementImpl();
-    definingUnit.source = definingUnit.librarySource = source;
-
-    var testLibrary = LibraryElementImpl(
-        analysisContext, AnalysisSessionImpl(null), '', -1, 0, false);
-    testLibrary.definingCompilationUnit = definingUnit;
-    return testLibrary;
-  }
 }
 
 /**
  * Base class for testing LUB and GLB in spec and strong mode.
  */
 abstract class BoundTestBase extends AbstractTypeSystemTest {
-  void _checkGreatestLowerBound(
-      DartType type1, DartType type2, DartType expectedResult) {
-    var glb = typeSystem.getGreatestLowerBound(type1, type2);
-    expect(glb, expectedResult);
-
-    // Check that the result is a lower bound.
-    expect(typeSystem.isSubtypeOf(glb, type1), true);
-    expect(typeSystem.isSubtypeOf(glb, type2), true);
-
-    // Check for symmetry while we're at it.
-    glb = typeSystem.getGreatestLowerBound(type2, type1);
-    expect(glb, expectedResult);
-  }
-
   void _checkLeastUpperBound(DartType T1, DartType T2, DartType expected) {
     var expectedStr = _typeString(expected);
 
@@ -469,1623 +470,6 @@
 }
 
 @reflectiveTest
-class ConstraintMatchingTest extends AbstractTypeSystemTest {
-  TypeParameterType T;
-
-  @override
-  void setUp() {
-    super.setUp();
-    T = typeParameterTypeStar(
-      typeParameter('T'),
-    );
-  }
-
-  void test_function_coreFunction() {
-    _checkOrdinarySubtypeMatch(
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: intStar),
-        ],
-        returnType: stringStar,
-      ),
-      typeProvider.functionType,
-      [T],
-      covariant: true,
-    );
-  }
-
-  void test_function_parameter_types() {
-    _checkIsSubtypeMatchOf(
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: T),
-        ],
-        returnType: intStar,
-      ),
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: stringStar),
-        ],
-        returnType: intStar,
-      ),
-      [T],
-      ['String <: T'],
-      covariant: true,
-    );
-  }
-
-  void test_function_return_types() {
-    _checkIsSubtypeMatchOf(
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: intStar),
-        ],
-        returnType: T,
-      ),
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: intStar),
-        ],
-        returnType: stringStar,
-      ),
-      [T],
-      ['T <: String'],
-      covariant: true,
-    );
-  }
-
-  void test_futureOr_futureOr() {
-    _checkIsSubtypeMatchOf(
-        futureOrStar(T), futureOrStar(stringStar), [T], ['T <: String'],
-        covariant: true);
-  }
-
-  void test_futureOr_x_fail_future_branch() {
-    // FutureOr<List<T>> <: List<String> can't be satisfied because
-    // Future<List<T>> <: List<String> can't be satisfied
-    _checkIsNotSubtypeMatchOf(
-        futureOrStar(listStar(T)), listStar(stringStar), [T],
-        covariant: true);
-  }
-
-  void test_futureOr_x_fail_nonFuture_branch() {
-    // FutureOr<List<T>> <: Future<List<String>> can't be satisfied because
-    // List<T> <: Future<List<String>> can't be satisfied
-    _checkIsNotSubtypeMatchOf(
-        futureOrStar(listStar(T)), futureStar(listStar(stringStar)), [T],
-        covariant: true);
-  }
-
-  void test_futureOr_x_success() {
-    // FutureOr<T> <: Future<T> can be satisfied by T=Null.  At this point in
-    // the type inference algorithm all we figure out is that T must be a
-    // subtype of both String and Future<String>.
-    _checkIsSubtypeMatchOf(futureOrStar(T), futureStar(stringStar), [T],
-        ['T <: String', 'T <: Future<String>'],
-        covariant: true);
-  }
-
-  void test_lhs_null() {
-    // Null <: T is trivially satisfied by the constraint Null <: T.
-    _checkIsSubtypeMatchOf(nullStar, T, [T], ['Null <: T'], covariant: false);
-    // For any other type X, Null <: X is satisfied without the need for any
-    // constraints.
-    _checkOrdinarySubtypeMatch(nullStar, listStar(T), [T], covariant: false);
-    _checkOrdinarySubtypeMatch(nullStar, stringStar, [T], covariant: false);
-    _checkOrdinarySubtypeMatch(nullStar, voidNone, [T], covariant: false);
-    _checkOrdinarySubtypeMatch(nullStar, dynamicType, [T], covariant: false);
-    _checkOrdinarySubtypeMatch(nullStar, objectStar, [T], covariant: false);
-    _checkOrdinarySubtypeMatch(nullStar, nullStar, [T], covariant: false);
-    _checkOrdinarySubtypeMatch(
-      nullStar,
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: intStar),
-        ],
-        returnType: stringStar,
-      ),
-      [T],
-      covariant: false,
-    );
-  }
-
-  void test_param_on_lhs_contravariant_direct() {
-    // When doing a contravariant match, the type parameters we're trying to
-    // find types for are on the right hand side.  Is a type parameter also
-    // appears on the left hand side, there is a condition in which the
-    // constraint can be satisfied without consulting the bound of the LHS type
-    // parameter: the condition where both parameters appear at corresponding
-    // locations in the type tree.
-    //
-    // In other words, List<S> <: List<T> is satisfied provided that
-    // S <: T.
-    var S = typeParameterTypeStar(typeParameter('S'));
-    _checkIsSubtypeMatchOf(listStar(S), listStar(T), [T], ['S <: T'],
-        covariant: false);
-  }
-
-  void test_param_on_lhs_contravariant_via_bound() {
-    // When doing a contravariant match, the type parameters we're trying to
-    // find types for are on the right hand side.  Is a type parameter also
-    // appears on the left hand side, we may have to constrain the RHS type
-    // parameter using the bounds of the LHS type parameter.
-    //
-    // In other words, S <: List<T> is satisfied provided that
-    // bound(S) <: List<T>.
-    var S = typeParameterTypeStar(typeParameter(
-      'S',
-      bound: listStar(stringStar),
-    ));
-    _checkIsSubtypeMatchOf(S, listStar(T), [T], ['String <: T'],
-        covariant: false);
-  }
-
-  void test_param_on_lhs_covariant() {
-    // When doing a covariant match, the type parameters we're trying to find
-    // types for are on the left hand side.
-    _checkIsSubtypeMatchOf(T, stringStar, [T], ['T <: String'],
-        covariant: true);
-  }
-
-  void test_param_on_rhs_contravariant() {
-    // When doing a contravariant match, the type parameters we're trying to
-    // find types for are on the right hand side.
-    _checkIsSubtypeMatchOf(stringStar, T, [T], ['String <: T'],
-        covariant: false);
-  }
-
-  void test_param_on_rhs_covariant_match() {
-    // When doing a covariant match, the type parameters we're trying to find
-    // types for are on the left hand side.  If a type parameter appears on the
-    // right hand side, there is a condition in which the constraint can be
-    // satisfied: where both parameters appear at corresponding locations in the
-    // type tree.
-    //
-    // In other words, T <: S can be satisfied trivially by the constraint
-    // T <: S.
-    var S = typeParameterTypeStar(typeParameter('S'));
-    _checkIsSubtypeMatchOf(T, S, [T], ['T <: S'], covariant: true);
-  }
-
-  void test_param_on_rhs_covariant_no_match() {
-    // When doing a covariant match, the type parameters we're trying to find
-    // types for are on the left hand side.  If a type parameter appears on the
-    // right hand side, it's probable that the constraint can't be satisfied,
-    // because there is no possible type for the LHS (other than bottom)
-    // that's guaranteed to satisfy the relation for all possible assignments of
-    // the RHS type parameter.
-    //
-    // In other words, no match can be found for List<T> <: S because regardless
-    // of T, we can't guarantee that List<T> <: S for all S.
-    var S = typeParameterTypeStar(typeParameter('S'));
-    _checkIsNotSubtypeMatchOf(listStar(T), S, [T], covariant: true);
-  }
-
-  void test_related_interface_types_failure() {
-    _checkIsNotSubtypeMatchOf(iterableStar(T), listStar(stringStar), [T],
-        covariant: true);
-  }
-
-  void test_related_interface_types_success() {
-    _checkIsSubtypeMatchOf(
-        listStar(T), iterableStar(stringStar), [T], ['T <: String'],
-        covariant: true);
-  }
-
-  void test_rhs_dynamic() {
-    // T <: dynamic is trivially satisfied by the constraint T <: dynamic.
-    _checkIsSubtypeMatchOf(T, dynamicType, [T], ['T <: dynamic'],
-        covariant: true);
-    // For any other type X, X <: dynamic is satisfied without the need for any
-    // constraints.
-    _checkOrdinarySubtypeMatch(listStar(T), dynamicType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(stringStar, dynamicType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(voidNone, dynamicType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(dynamicType, dynamicType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(objectStar, dynamicType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(nullStar, dynamicType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: intStar),
-        ],
-        returnType: stringStar,
-      ),
-      dynamicType,
-      [T],
-      covariant: true,
-    );
-  }
-
-  void test_rhs_object() {
-    // T <: Object is trivially satisfied by the constraint T <: Object.
-    _checkIsSubtypeMatchOf(T, objectStar, [T], ['T <: Object'],
-        covariant: true);
-    // For any other type X, X <: Object is satisfied without the need for any
-    // constraints.
-    _checkOrdinarySubtypeMatch(listStar(T), objectStar, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(stringStar, objectStar, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(voidNone, objectStar, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(dynamicType, objectStar, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(objectStar, objectStar, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(nullStar, objectStar, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: intStar),
-        ],
-        returnType: stringStar,
-      ),
-      objectStar,
-      [T],
-      covariant: true,
-    );
-  }
-
-  void test_rhs_void() {
-    // T <: void is trivially satisfied by the constraint T <: void.
-    _checkIsSubtypeMatchOf(T, voidNone, [T], ['T <: void'], covariant: true);
-    // For any other type X, X <: void is satisfied without the need for any
-    // constraints.
-    _checkOrdinarySubtypeMatch(listStar(T), voidNone, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(stringStar, voidNone, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(voidNone, voidNone, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(dynamicType, voidNone, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(objectStar, voidNone, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(nullStar, voidNone, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(
-      functionTypeStar(
-        parameters: [
-          requiredParameter(type: intStar),
-        ],
-        returnType: stringStar,
-      ),
-      voidNone,
-      [T],
-      covariant: true,
-    );
-  }
-
-  void test_same_interface_types() {
-    _checkIsSubtypeMatchOf(
-        listStar(T), listStar(stringStar), [T], ['T <: String'],
-        covariant: true);
-  }
-
-  void test_variance_contravariant() {
-    // class A<in T>
-    var tContravariant = typeParameter('T', variance: Variance.contravariant);
-    var tType = typeParameterType(tContravariant);
-    var A = class_(name: 'A', typeParameters: [tContravariant]);
-
-    // A<num>
-    // A<T>
-    var aNum = interfaceType(A,
-        typeArguments: [numStar], nullabilitySuffix: NullabilitySuffix.none);
-    var aT = interfaceType(A,
-        typeArguments: [tType], nullabilitySuffix: NullabilitySuffix.none);
-
-    _checkIsSubtypeMatchOf(aT, aNum, [tType], ['num <: in T'], covariant: true);
-  }
-
-  void test_variance_covariant() {
-    // class A<out T>
-    var tCovariant = typeParameter('T', variance: Variance.covariant);
-    var tType = typeParameterType(tCovariant);
-    var A = class_(name: 'A', typeParameters: [tCovariant]);
-
-    // A<num>
-    // A<T>
-    var aNum = interfaceType(A,
-        typeArguments: [numStar], nullabilitySuffix: NullabilitySuffix.none);
-    var aT = interfaceType(A,
-        typeArguments: [tType], nullabilitySuffix: NullabilitySuffix.none);
-
-    _checkIsSubtypeMatchOf(aT, aNum, [tType], ['out T <: num'],
-        covariant: true);
-  }
-
-  void test_variance_invariant() {
-    // class A<inout T>
-    var tInvariant = typeParameter('T', variance: Variance.invariant);
-    var tType = typeParameterType(tInvariant);
-    var A = class_(name: 'A', typeParameters: [tInvariant]);
-
-    // A<num>
-    // A<T>
-    var aNum = interfaceType(A,
-        typeArguments: [numStar], nullabilitySuffix: NullabilitySuffix.none);
-    var aT = interfaceType(A,
-        typeArguments: [tType], nullabilitySuffix: NullabilitySuffix.none);
-
-    _checkIsSubtypeMatchOf(
-        aT, aNum, [tType], ['inout T <: num', 'num <: inout T'],
-        covariant: true);
-  }
-
-  void test_x_futureOr_fail_both_branches() {
-    // List<T> <: FutureOr<String> can't be satisfied because neither
-    // List<T> <: Future<String> nor List<T> <: int can be satisfied
-    _checkIsNotSubtypeMatchOf(listStar(T), futureOrStar(stringStar), [T],
-        covariant: true);
-  }
-
-  void test_x_futureOr_pass_both_branches_constraints_from_both_branches() {
-    // Future<String> <: FutureOr<T> can be satisfied because both
-    // Future<String> <: Future<T> and Future<String> <: T can be satisfied.
-    // Trying to match Future<String> <: Future<T> generates the constraint
-    // String <: T, whereas trying to match Future<String> <: T generates the
-    // constraint Future<String> <: T.  We keep the constraint based on trying
-    // to match Future<String> <: Future<T>, so String <: T.
-    _checkIsSubtypeMatchOf(
-        futureStar(stringStar), futureOrStar(T), [T], ['String <: T'],
-        covariant: false);
-  }
-
-  void test_x_futureOr_pass_both_branches_constraints_from_future_branch() {
-    // Future<T> <: FutureOr<Object> can be satisfied because both
-    // Future<T> <: Future<Object> and Future<T> <: Object can be satisfied.
-    // Trying to match Future<T> <: Future<Object> generates the constraint
-    // T <: Object, whereas trying to match Future<T> <: Object generates no
-    // constraints, so we keep the constraint T <: Object.
-    _checkIsSubtypeMatchOf(
-        futureStar(T), futureOrStar(objectStar), [T], ['T <: Object'],
-        covariant: true);
-  }
-
-  void test_x_futureOr_pass_both_branches_constraints_from_nonFuture_branch() {
-    // Null <: FutureOr<T> can be satisfied because both
-    // Null <: Future<T> and Null <: T can be satisfied.
-    // Trying to match Null <: FutureOr<T> generates no constraints, whereas
-    // trying to match Null <: T generates the constraint Null <: T,
-    // so we keep the constraint Null <: T.
-    _checkIsSubtypeMatchOf(nullStar, futureOrStar(T), [T], ['Null <: T'],
-        covariant: false);
-  }
-
-  void test_x_futureOr_pass_both_branches_no_constraints() {
-    // Future<String> <: FutureOr<Object> is satisfied because both
-    // Future<String> <: Future<Object> and Future<String> <: Object.
-    // No constraints are recorded.
-    _checkIsSubtypeMatchOf(
-        futureStar(stringStar), futureOrStar(objectStar), [T], [],
-        covariant: true);
-  }
-
-  void test_x_futureOr_pass_future_branch() {
-    // Future<T> <: FutureOr<String> can be satisfied because
-    // Future<T> <: Future<String> can be satisfied
-    _checkIsSubtypeMatchOf(
-        futureStar(T), futureOrStar(stringStar), [T], ['T <: String'],
-        covariant: true);
-  }
-
-  void test_x_futureOr_pass_nonFuture_branch() {
-    // List<T> <: FutureOr<List<String>> can be satisfied because
-    // List<T> <: List<String> can be satisfied
-    _checkIsSubtypeMatchOf(
-        listStar(T), futureOrStar(listStar(stringStar)), [T], ['T <: String'],
-        covariant: true);
-  }
-
-  void _checkIsNotSubtypeMatchOf(
-      DartType t1, DartType t2, Iterable<TypeParameterType> typeFormals,
-      {bool covariant}) {
-    var inferrer = GenericInferrer(
-      typeSystem,
-      typeFormals.map((t) => t.element),
-    );
-    var success =
-        inferrer.tryMatchSubtypeOf(t1, t2, null, covariant: covariant);
-    expect(success, isFalse);
-    inferrer.constraints.forEach((typeParameter, constraintsForTypeParameter) {
-      expect(constraintsForTypeParameter, isEmpty);
-    });
-  }
-
-  void _checkIsSubtypeMatchOf(
-      DartType t1,
-      DartType t2,
-      Iterable<TypeParameterType> typeFormals,
-      Iterable<String> expectedConstraints,
-      {bool covariant}) {
-    var inferrer = GenericInferrer(
-      typeSystem,
-      typeFormals.map((t) => t.element),
-    );
-    var success =
-        inferrer.tryMatchSubtypeOf(t1, t2, null, covariant: covariant);
-    expect(success, isTrue);
-    var formattedConstraints = <String>[];
-    inferrer.constraints.forEach((typeParameter, constraintsForTypeParameter) {
-      for (var constraint in constraintsForTypeParameter) {
-        formattedConstraints.add(
-          constraint.format(
-            typeParameter.getDisplayString(
-              withNullability: typeSystem.isNonNullableByDefault,
-            ),
-            withNullability: false,
-          ),
-        );
-      }
-    });
-    expect(formattedConstraints, unorderedEquals(expectedConstraints));
-  }
-
-  void _checkOrdinarySubtypeMatch(
-      DartType t1, DartType t2, Iterable<TypeParameterType> typeFormals,
-      {bool covariant}) {
-    bool expectSuccess = typeSystem.isSubtypeOf(t1, t2);
-    if (expectSuccess) {
-      _checkIsSubtypeMatchOf(t1, t2, typeFormals, [], covariant: covariant);
-    } else {
-      _checkIsNotSubtypeMatchOf(t1, t2, typeFormals);
-    }
-  }
-}
-
-@reflectiveTest
-class GenericFunctionInferenceTest extends AbstractTypeSystemTest {
-  void test_boundedByAnotherTypeParameter() {
-    // <TFrom, TTo extends Iterable<TFrom>>(TFrom) -> TTo
-    var tFrom = typeParameter('TFrom');
-    var tTo =
-        typeParameter('TTo', bound: iterableStar(typeParameterTypeStar(tFrom)));
-    var cast = functionTypeStar(
-      typeFormals: [tFrom, tTo],
-      parameters: [
-        requiredParameter(
-          type: typeParameterTypeStar(tFrom),
-        ),
-      ],
-      returnType: typeParameterTypeStar(tTo),
-    );
-    expect(_inferCall(cast, [stringStar]),
-        [stringStar, (iterableStar(stringStar))]);
-  }
-
-  void test_boundedByOuterClass() {
-    // Regression test for https://github.com/dart-lang/sdk/issues/25740.
-
-    // class A {}
-    var A = class_(name: 'A', superType: objectStar);
-    var typeA = interfaceTypeStar(A);
-
-    // class B extends A {}
-    var B = class_(name: 'B', superType: typeA);
-    var typeB = interfaceTypeStar(B);
-
-    // class C<T extends A> {
-    var CT = typeParameter('T', bound: typeA);
-    var C = class_(
-      name: 'C',
-      superType: objectStar,
-      typeParameters: [CT],
-    );
-    //   S m<S extends T>(S);
-    var S = typeParameter('S', bound: typeParameterTypeStar(CT));
-    var m = method(
-      'm',
-      typeParameterTypeStar(S),
-      typeFormals: [S],
-      parameters: [
-        requiredParameter(
-          name: '_',
-          type: typeParameterTypeStar(S),
-        ),
-      ],
-    );
-    C.methods = [m];
-    // }
-
-    // C<Object> cOfObject;
-    var cOfObject = interfaceTypeStar(C, typeArguments: [objectStar]);
-    // C<A> cOfA;
-    var cOfA = interfaceTypeStar(C, typeArguments: [typeA]);
-    // C<B> cOfB;
-    var cOfB = interfaceTypeStar(C, typeArguments: [typeB]);
-    // B b;
-    // cOfB.m(b); // infer <B>
-    _assertType(
-        _inferCall2(cOfB.getMethod('m').type, [typeB]), 'B Function(B)');
-    // cOfA.m(b); // infer <B>
-    _assertType(
-        _inferCall2(cOfA.getMethod('m').type, [typeB]), 'B Function(B)');
-    // cOfObject.m(b); // infer <B>
-    _assertType(
-        _inferCall2(cOfObject.getMethod('m').type, [typeB]), 'B Function(B)');
-  }
-
-  void test_boundedByOuterClassSubstituted() {
-    // Regression test for https://github.com/dart-lang/sdk/issues/25740.
-
-    // class A {}
-    var A = class_(name: 'A', superType: objectStar);
-    var typeA = interfaceTypeStar(A);
-
-    // class B extends A {}
-    var B = class_(name: 'B', superType: typeA);
-    var typeB = interfaceTypeStar(B);
-
-    // class C<T extends A> {
-    var CT = typeParameter('T', bound: typeA);
-    var C = class_(
-      name: 'C',
-      superType: objectStar,
-      typeParameters: [CT],
-    );
-    //   S m<S extends Iterable<T>>(S);
-    var iterableOfT = iterableStar(typeParameterTypeStar(CT));
-    var S = typeParameter('S', bound: iterableOfT);
-    var m = method(
-      'm',
-      typeParameterTypeStar(S),
-      typeFormals: [S],
-      parameters: [
-        requiredParameter(
-          name: '_',
-          type: typeParameterTypeStar(S),
-        ),
-      ],
-    );
-    C.methods = [m];
-    // }
-
-    // C<Object> cOfObject;
-    var cOfObject = interfaceTypeStar(C, typeArguments: [objectStar]);
-    // C<A> cOfA;
-    var cOfA = interfaceTypeStar(C, typeArguments: [typeA]);
-    // C<B> cOfB;
-    var cOfB = interfaceTypeStar(C, typeArguments: [typeB]);
-    // List<B> b;
-    var listOfB = listStar(typeB);
-    // cOfB.m(b); // infer <B>
-    _assertType(_inferCall2(cOfB.getMethod('m').type, [listOfB]),
-        'List<B> Function(List<B>)');
-    // cOfA.m(b); // infer <B>
-    _assertType(_inferCall2(cOfA.getMethod('m').type, [listOfB]),
-        'List<B> Function(List<B>)');
-    // cOfObject.m(b); // infer <B>
-    _assertType(_inferCall2(cOfObject.getMethod('m').type, [listOfB]),
-        'List<B> Function(List<B>)');
-  }
-
-  void test_boundedRecursively() {
-    // class A<T extends A<T>>
-    var T = typeParameter('T');
-    var A = class_(
-      name: 'Cloneable',
-      superType: objectStar,
-      typeParameters: [T],
-    );
-    T.bound = interfaceTypeStar(
-      A,
-      typeArguments: [typeParameterTypeStar(T)],
-    );
-
-    // class B extends A<B> {}
-    var B = class_(name: 'B', superType: null);
-    B.supertype = interfaceTypeStar(A, typeArguments: [interfaceTypeStar(B)]);
-    var typeB = interfaceTypeStar(B);
-
-    // <S extends A<S>>
-    var S = typeParameter('S');
-    var typeS = typeParameterTypeStar(S);
-    S.bound = interfaceTypeStar(A, typeArguments: [typeS]);
-
-    // (S, S) -> S
-    var clone = functionTypeStar(
-      typeFormals: [S],
-      parameters: [
-        requiredParameter(type: typeS),
-        requiredParameter(type: typeS),
-      ],
-      returnType: typeS,
-    );
-    expect(_inferCall(clone, [typeB, typeB]), [typeB]);
-
-    // Something invalid...
-    expect(
-      _inferCall(clone, [stringStar, numStar], expectError: true),
-      [objectStar],
-    );
-  }
-
-  void test_genericCastFunction() {
-    // <TFrom, TTo>(TFrom) -> TTo
-    var tFrom = typeParameter('TFrom');
-    var tTo = typeParameter('TTo');
-    var cast = functionTypeStar(
-      typeFormals: [tFrom, tTo],
-      parameters: [
-        requiredParameter(
-          type: typeParameterTypeStar(tFrom),
-        ),
-      ],
-      returnType: typeParameterTypeStar(tTo),
-    );
-    expect(_inferCall(cast, [intStar]), [intStar, dynamicType]);
-  }
-
-  void test_genericCastFunctionWithUpperBound() {
-    // <TFrom, TTo extends TFrom>(TFrom) -> TTo
-    var tFrom = typeParameter('TFrom');
-    var tTo = typeParameter(
-      'TTo',
-      bound: typeParameterTypeStar(tFrom),
-    );
-    var cast = functionTypeStar(
-      typeFormals: [tFrom, tTo],
-      parameters: [
-        requiredParameter(
-          type: typeParameterTypeStar(tFrom),
-        ),
-      ],
-      returnType: typeParameterTypeStar(tTo),
-    );
-    expect(_inferCall(cast, [intStar]), [intStar, intStar]);
-  }
-
-  void test_parameter_contravariantUseUpperBound() {
-    // <T>(T x, void Function(T) y) -> T
-    // Generates constraints int <: T <: num.
-    // Since T is contravariant, choose num.
-    var T = typeParameter('T', variance: Variance.contravariant);
-    var tFunction = functionTypeStar(
-        parameters: [requiredParameter(type: typeParameterTypeStar(T))],
-        returnType: voidNone);
-    var numFunction = functionTypeStar(
-        parameters: [requiredParameter(type: numStar)], returnType: voidNone);
-    var function = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(type: typeParameterTypeStar(T)),
-        requiredParameter(type: tFunction)
-      ],
-      returnType: typeParameterTypeStar(T),
-    );
-
-    expect(_inferCall(function, [intStar, numFunction]), [numStar]);
-  }
-
-  void test_parameter_covariantUseLowerBound() {
-    // <T>(T x, void Function(T) y) -> T
-    // Generates constraints int <: T <: num.
-    // Since T is covariant, choose int.
-    var T = typeParameter('T', variance: Variance.covariant);
-    var tFunction = functionTypeStar(
-        parameters: [requiredParameter(type: typeParameterTypeStar(T))],
-        returnType: voidNone);
-    var numFunction = functionTypeStar(
-        parameters: [requiredParameter(type: numStar)], returnType: voidNone);
-    var function = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(type: typeParameterTypeStar(T)),
-        requiredParameter(type: tFunction)
-      ],
-      returnType: typeParameterTypeStar(T),
-    );
-
-    expect(_inferCall(function, [intStar, numFunction]), [intStar]);
-  }
-
-  void test_parametersToFunctionParam() {
-    // <T>(f(T t)) -> T
-    var T = typeParameter('T');
-    var cast = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(
-          type: functionTypeStar(
-            parameters: [
-              requiredParameter(
-                type: typeParameterTypeStar(T),
-              ),
-            ],
-            returnType: dynamicType,
-          ),
-        ),
-      ],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(
-      _inferCall(cast, [
-        functionTypeStar(
-          parameters: [
-            requiredParameter(type: numStar),
-          ],
-          returnType: dynamicType,
-        )
-      ]),
-      [numStar],
-    );
-  }
-
-  void test_parametersUseLeastUpperBound() {
-    // <T>(T x, T y) -> T
-    var T = typeParameter('T');
-    var cast = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(type: typeParameterTypeStar(T)),
-        requiredParameter(type: typeParameterTypeStar(T)),
-      ],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(_inferCall(cast, [intStar, doubleStar]), [numStar]);
-  }
-
-  void test_parameterTypeUsesUpperBound() {
-    // <T extends num>(T) -> dynamic
-    var T = typeParameter('T', bound: numStar);
-    var f = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(type: typeParameterTypeStar(T)),
-      ],
-      returnType: dynamicType,
-    );
-    expect(_inferCall(f, [intStar]), [intStar]);
-  }
-
-  void test_returnFunctionWithGenericParameter() {
-    // <T>(T -> T) -> (T -> void)
-    var T = typeParameter('T');
-    var f = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(
-          type: functionTypeStar(
-            parameters: [
-              requiredParameter(type: typeParameterTypeStar(T)),
-            ],
-            returnType: typeParameterTypeStar(T),
-          ),
-        ),
-      ],
-      returnType: functionTypeStar(
-        parameters: [
-          requiredParameter(type: typeParameterTypeStar(T)),
-        ],
-        returnType: voidNone,
-      ),
-    );
-    expect(
-      _inferCall(f, [
-        functionTypeStar(
-          parameters: [
-            requiredParameter(type: numStar),
-          ],
-          returnType: intStar,
-        ),
-      ]),
-      [intStar],
-    );
-  }
-
-  void test_returnFunctionWithGenericParameterAndContext() {
-    // <T>(T -> T) -> (T -> Null)
-    var T = typeParameter('T');
-    var f = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(
-          type: functionTypeStar(
-            parameters: [
-              requiredParameter(type: typeParameterTypeStar(T)),
-            ],
-            returnType: typeParameterTypeStar(T),
-          ),
-        ),
-      ],
-      returnType: functionTypeStar(
-        parameters: [
-          requiredParameter(type: typeParameterTypeStar(T)),
-        ],
-        returnType: nullStar,
-      ),
-    );
-    expect(
-      _inferCall(
-        f,
-        [],
-        returnType: functionTypeStar(
-          parameters: [
-            requiredParameter(type: numStar),
-          ],
-          returnType: intStar,
-        ),
-      ),
-      [numStar],
-    );
-  }
-
-  void test_returnFunctionWithGenericParameterAndReturn() {
-    // <T>(T -> T) -> (T -> T)
-    var T = typeParameter('T');
-    var f = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(
-          type: functionTypeStar(
-            parameters: [
-              requiredParameter(type: typeParameterTypeStar(T)),
-            ],
-            returnType: typeParameterTypeStar(T),
-          ),
-        ),
-      ],
-      returnType: functionTypeStar(
-        parameters: [
-          requiredParameter(type: typeParameterTypeStar(T)),
-        ],
-        returnType: typeParameterTypeStar(T),
-      ),
-    );
-    expect(
-      _inferCall(f, [
-        functionTypeStar(
-          parameters: [
-            requiredParameter(type: numStar),
-          ],
-          returnType: intStar,
-        )
-      ]),
-      [intStar],
-    );
-  }
-
-  void test_returnFunctionWithGenericReturn() {
-    // <T>(T -> T) -> (() -> T)
-    var T = typeParameter('T');
-    var f = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(
-          type: functionTypeStar(
-            parameters: [
-              requiredParameter(type: typeParameterTypeStar(T)),
-            ],
-            returnType: typeParameterTypeStar(T),
-          ),
-        ),
-      ],
-      returnType: functionTypeStar(
-        returnType: typeParameterTypeStar(T),
-      ),
-    );
-    expect(
-      _inferCall(f, [
-        functionTypeStar(
-          parameters: [
-            requiredParameter(type: numStar),
-          ],
-          returnType: intStar,
-        )
-      ]),
-      [intStar],
-    );
-  }
-
-  void test_returnTypeFromContext() {
-    // <T>() -> T
-    var T = typeParameter('T');
-    var f = functionTypeStar(
-      typeFormals: [T],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(_inferCall(f, [], returnType: stringStar), [stringStar]);
-  }
-
-  void test_returnTypeWithBoundFromContext() {
-    // <T extends num>() -> T
-    var T = typeParameter('T', bound: numStar);
-    var f = functionTypeStar(
-      typeFormals: [T],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(_inferCall(f, [], returnType: doubleStar), [doubleStar]);
-  }
-
-  void test_returnTypeWithBoundFromInvalidContext() {
-    // <T extends num>() -> T
-    var T = typeParameter('T', bound: numStar);
-    var f = functionTypeStar(
-      typeFormals: [T],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(_inferCall(f, [], returnType: stringStar), [nullStar]);
-  }
-
-  void test_unifyParametersToFunctionParam() {
-    // <T>(f(T t), g(T t)) -> T
-    var T = typeParameter('T');
-    var cast = functionTypeStar(
-      typeFormals: [T],
-      parameters: [
-        requiredParameter(
-          type: functionTypeStar(
-            parameters: [
-              requiredParameter(
-                type: typeParameterTypeStar(T),
-              ),
-            ],
-            returnType: dynamicType,
-          ),
-        ),
-        requiredParameter(
-          type: functionTypeStar(
-            parameters: [
-              requiredParameter(
-                type: typeParameterTypeStar(T),
-              ),
-            ],
-            returnType: dynamicType,
-          ),
-        ),
-      ],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(
-      _inferCall(cast, [
-        functionTypeStar(
-          parameters: [
-            requiredParameter(type: intStar),
-          ],
-          returnType: dynamicType,
-        ),
-        functionTypeStar(
-          parameters: [
-            requiredParameter(type: doubleStar),
-          ],
-          returnType: dynamicType,
-        )
-      ]),
-      [nullStar],
-    );
-  }
-
-  void test_unusedReturnTypeIsDynamic() {
-    // <T>() -> T
-    var T = typeParameter('T');
-    var f = functionTypeStar(
-      typeFormals: [T],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(_inferCall(f, []), [dynamicType]);
-  }
-
-  void test_unusedReturnTypeWithUpperBound() {
-    // <T extends num>() -> T
-    var T = typeParameter('T', bound: numStar);
-    var f = functionTypeStar(
-      typeFormals: [T],
-      returnType: typeParameterTypeStar(T),
-    );
-    expect(_inferCall(f, []), [numStar]);
-  }
-
-  void _assertType(DartType type, String expected) {
-    var typeStr = type.getDisplayString(withNullability: false);
-    expect(typeStr, expected);
-  }
-
-  List<DartType> _inferCall(FunctionTypeImpl ft, List<DartType> arguments,
-      {DartType returnType, bool expectError = false}) {
-    var listener = RecordingErrorListener();
-
-    var reporter = ErrorReporter(
-      listener,
-      NonExistingSource('/test.dart', toUri('/test.dart'), UriKind.FILE_URI),
-      isNonNullableByDefault: false,
-    );
-
-    var typeArguments = typeSystem.inferGenericFunctionOrType(
-      typeParameters: ft.typeFormals,
-      parameters: ft.parameters,
-      declaredReturnType: ft.returnType,
-      argumentTypes: arguments,
-      contextReturnType: returnType,
-      errorReporter: reporter,
-      errorNode: astFactory.nullLiteral(KeywordToken(Keyword.NULL, 0)),
-    );
-
-    if (expectError) {
-      expect(listener.errors.map((e) => e.errorCode).toList(),
-          [StrongModeCode.COULD_NOT_INFER],
-          reason: 'expected exactly 1 could not infer error.');
-    } else {
-      expect(listener.errors, isEmpty, reason: 'did not expect any errors.');
-    }
-    return typeArguments;
-  }
-
-  FunctionType _inferCall2(FunctionTypeImpl ft, List<DartType> arguments,
-      {DartType returnType, bool expectError = false}) {
-    var typeArguments = _inferCall(
-      ft,
-      arguments,
-      returnType: returnType,
-      expectError: expectError,
-    );
-    return ft.instantiate(typeArguments);
-  }
-}
-
-@reflectiveTest
-class GreatestLowerBoundTest extends BoundTestBase {
-  void test_bottom_function() {
-    _checkGreatestLowerBound(
-        neverStar, functionTypeStar(returnType: voidNone), neverStar);
-  }
-
-  void test_bottom_interface() {
-    var A = class_(name: 'A');
-    _checkGreatestLowerBound(neverStar, interfaceTypeStar(A), neverStar);
-  }
-
-  void test_bottom_typeParam() {
-    var T = typeParameter('T');
-    _checkGreatestLowerBound(neverStar, typeParameterTypeStar(T), neverStar);
-  }
-
-  void test_bounds_of_top_types_complete() {
-    // Test every combination of a subset of Tops programatically.
-    var futureOrDynamicType = futureOrStar(dynamicType);
-    var futureOrObjectType = futureOrStar(objectStar);
-    var futureOrVoidType = futureOrStar(voidNone);
-    final futureOrFutureOrDynamicType = futureOrStar(futureOrDynamicType);
-    final futureOrFutureOrObjectType = futureOrStar(futureOrObjectType);
-    final futureOrFutureOrVoidType = futureOrStar(futureOrVoidType);
-
-    var orderedTops = [
-      // Lower index, so lower Top
-      voidNone,
-      dynamicType,
-      objectStar,
-      futureOrVoidType,
-      futureOrDynamicType,
-      futureOrObjectType,
-      futureOrFutureOrVoidType,
-      futureOrFutureOrDynamicType,
-      futureOrFutureOrObjectType,
-      // Higher index, higher Top
-    ];
-
-    // We could sort and check the sort result is correct in O(n log n), but a
-    // good sorting algorithm would only run n tests here (that each value is
-    // correct relative to its nearest neighbors). But O(n^2) for n=6 is stupid
-    // fast, in this case, so just do the brute force check because we can.
-    for (var i = 0; i < orderedTops.length; ++i) {
-      for (var lower = 0; lower <= i; ++lower) {
-        _checkGreatestLowerBound(
-            orderedTops[i], orderedTops[lower], orderedTops[i]);
-        _checkLeastUpperBound(
-            orderedTops[i], orderedTops[lower], orderedTops[lower]);
-      }
-      for (var greater = i; greater < orderedTops.length; ++greater) {
-        _checkGreatestLowerBound(
-            orderedTops[i], orderedTops[greater], orderedTops[greater]);
-        _checkLeastUpperBound(
-            orderedTops[i], orderedTops[greater], orderedTops[i]);
-      }
-    }
-  }
-
-  void test_bounds_of_top_types_sanity() {
-    var futureOrDynamicType = futureOrStar(dynamicType);
-    final futureOrFutureOrDynamicType = futureOrStar(futureOrDynamicType);
-
-    // Sanity check specific cases of top for GLB/LUB.
-    _checkLeastUpperBound(objectStar, dynamicType, dynamicType);
-    _checkGreatestLowerBound(objectStar, dynamicType, objectStar);
-    _checkLeastUpperBound(objectStar, voidNone, voidNone);
-    _checkLeastUpperBound(futureOrDynamicType, dynamicType, dynamicType);
-    _checkGreatestLowerBound(
-        futureOrDynamicType, objectStar, futureOrDynamicType);
-    _checkGreatestLowerBound(futureOrDynamicType, futureOrFutureOrDynamicType,
-        futureOrFutureOrDynamicType);
-  }
-
-  void test_classAndSuperclass() {
-    // class A
-    // class B extends A
-    // class C extends B
-    var A = class_(name: 'A');
-    var B = class_(name: 'B', superType: interfaceTypeStar(A));
-    var C = class_(name: 'C', superType: interfaceTypeStar(B));
-    _checkGreatestLowerBound(
-      interfaceTypeStar(A),
-      interfaceTypeStar(C),
-      interfaceTypeStar(C),
-    );
-  }
-
-  void test_classAndSuperinterface() {
-    // class A
-    // class B implements A
-    // class C implements B
-    var A = class_(name: 'A');
-    var B = class_(name: 'B', interfaces: [interfaceTypeStar(A)]);
-    var C = class_(name: 'C', interfaces: [interfaceTypeStar(B)]);
-    _checkGreatestLowerBound(
-      interfaceTypeStar(A),
-      interfaceTypeStar(C),
-      interfaceTypeStar(C),
-    );
-  }
-
-  void test_dynamic_bottom() {
-    _checkGreatestLowerBound(dynamicType, neverStar, neverStar);
-  }
-
-  void test_dynamic_function() {
-    _checkGreatestLowerBound(
-        dynamicType,
-        functionTypeStar(returnType: voidNone),
-        functionTypeStar(returnType: voidNone));
-  }
-
-  void test_dynamic_interface() {
-    var A = class_(name: 'A');
-    var typeA = interfaceTypeStar(A);
-    _checkGreatestLowerBound(dynamicType, typeA, typeA);
-  }
-
-  void test_dynamic_typeParam() {
-    var T = typeParameter('T');
-    var typeT = typeParameterTypeStar(T);
-    _checkGreatestLowerBound(dynamicType, typeT, typeT);
-  }
-
-  void test_dynamic_void() {
-    // Note: _checkGreatestLowerBound tests `GLB(x, y)` as well as `GLB(y, x)`
-    _checkGreatestLowerBound(dynamicType, voidNone, dynamicType);
-  }
-
-  void test_functionsDifferentNamedTakeUnion() {
-    var type1 = functionTypeStar(
-      parameters: [
-        namedParameter(name: 'a', type: intStar),
-        namedParameter(name: 'b', type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        namedParameter(name: 'b', type: doubleStar),
-        namedParameter(name: 'c', type: stringStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        namedParameter(name: 'a', type: intStar),
-        namedParameter(name: 'b', type: numStar),
-        namedParameter(name: 'c', type: stringStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsDifferentOptionalArityTakeMax() {
-    var type1 = functionTypeStar(
-      parameters: [
-        positionalParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        positionalParameter(type: doubleStar),
-        positionalParameter(type: stringStar),
-        positionalParameter(type: objectStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        positionalParameter(type: numStar),
-        positionalParameter(type: stringStar),
-        positionalParameter(type: objectStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsDifferentRequiredArityBecomeOptional() {
-    var type1 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-        positionalParameter(type: intStar),
-        positionalParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsFromDynamic() {
-    var type1 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: dynamicType),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        requiredParameter(type: dynamicType),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsGlbReturnType() {
-    var type1 = functionTypeStar(
-      returnType: intStar,
-    );
-    var type2 = functionTypeStar(
-      returnType: numStar,
-    );
-    var expected = functionTypeStar(
-      returnType: intStar,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsLubNamedParams() {
-    var type1 = functionTypeStar(
-      parameters: [
-        namedParameter(name: 'a', type: stringStar),
-        namedParameter(name: 'b', type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        namedParameter(name: 'a', type: intStar),
-        namedParameter(name: 'b', type: numStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        namedParameter(name: 'a', type: objectStar),
-        namedParameter(name: 'b', type: numStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsLubPositionalParams() {
-    var type1 = functionTypeStar(
-      parameters: [
-        positionalParameter(type: stringStar),
-        positionalParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        positionalParameter(type: intStar),
-        positionalParameter(type: numStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        positionalParameter(type: objectStar),
-        positionalParameter(type: numStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsLubRequiredParams() {
-    var type1 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: stringStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-        requiredParameter(type: doubleStar),
-        requiredParameter(type: numStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        requiredParameter(type: objectStar),
-        requiredParameter(type: numStar),
-        requiredParameter(type: numStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsMixedOptionalAndRequiredBecomeOptional() {
-    var type1 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-        requiredParameter(type: intStar),
-        positionalParameter(type: intStar),
-        positionalParameter(type: intStar),
-        positionalParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-        positionalParameter(type: intStar),
-        positionalParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var expected = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-        positionalParameter(type: intStar),
-        positionalParameter(type: intStar),
-        positionalParameter(type: intStar),
-        positionalParameter(type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsReturnBottomIfMixOptionalAndNamed() {
-    // Dart doesn't allow a function to have both optional and named parameters,
-    // so if we would have synthethized that, pick bottom instead.
-    var type1 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: intStar),
-        namedParameter(name: 'a', type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    var type2 = functionTypeStar(
-      parameters: [
-        namedParameter(name: 'a', type: intStar),
-      ],
-      returnType: voidNone,
-    );
-    _checkGreatestLowerBound(type1, type2, neverStar);
-  }
-
-  void test_functionsSameType_withNamed() {
-    var type1 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: stringStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: numStar),
-        namedParameter(name: 'n', type: numStar),
-      ],
-      returnType: intStar,
-    );
-
-    var type2 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: stringStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: numStar),
-        namedParameter(name: 'n', type: numStar),
-      ],
-      returnType: intStar,
-    );
-
-    var expected = functionTypeStar(
-      parameters: [
-        requiredParameter(type: stringStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: numStar),
-        namedParameter(name: 'n', type: numStar),
-      ],
-      returnType: intStar,
-    );
-
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_functionsSameType_withOptional() {
-    var type1 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: stringStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: numStar),
-        positionalParameter(type: doubleStar),
-      ],
-      returnType: intStar,
-    );
-
-    var type2 = functionTypeStar(
-      parameters: [
-        requiredParameter(type: stringStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: numStar),
-        positionalParameter(type: doubleStar),
-      ],
-      returnType: intStar,
-    );
-
-    var expected = functionTypeStar(
-      parameters: [
-        requiredParameter(type: stringStar),
-        requiredParameter(type: intStar),
-        requiredParameter(type: numStar),
-        positionalParameter(type: doubleStar),
-      ],
-      returnType: intStar,
-    );
-
-    _checkGreatestLowerBound(type1, type2, expected);
-  }
-
-  void test_interface_function() {
-    var A = class_(name: 'A');
-    var typeA = interfaceTypeStar(A);
-    _checkGreatestLowerBound(
-      typeA,
-      functionTypeStar(returnType: voidNone),
-      neverStar,
-    );
-  }
-
-  void test_mixin() {
-    // class A
-    // class B
-    // class C
-    // class D extends A with B, C
-    var A = class_(name: 'A');
-    var typeA = interfaceTypeStar(A);
-
-    var B = class_(name: 'B');
-    var typeB = interfaceTypeStar(B);
-
-    var C = class_(name: 'C');
-    var typeC = interfaceTypeStar(C);
-
-    var D = class_(
-      name: 'D',
-      superType: interfaceTypeStar(A),
-      mixins: [typeB, typeC],
-    );
-    var typeD = interfaceTypeStar(D);
-
-    _checkGreatestLowerBound(typeA, typeD, typeD);
-    _checkGreatestLowerBound(typeB, typeD, typeD);
-    _checkGreatestLowerBound(typeC, typeD, typeD);
-  }
-
-  void test_self() {
-    var T = typeParameter('T');
-    var A = class_(name: 'A');
-
-    List<DartType> types = [
-      dynamicType,
-      voidNone,
-      neverStar,
-      typeParameterTypeStar(T),
-      interfaceTypeStar(A),
-      functionTypeStar(returnType: voidNone),
-    ];
-
-    for (DartType type in types) {
-      _checkGreatestLowerBound(type, type, type);
-    }
-  }
-
-  void test_typeParam_function_noBound() {
-    var T = typeParameter('T');
-    _checkGreatestLowerBound(
-      typeParameterTypeStar(T),
-      functionTypeStar(returnType: voidNone),
-      neverStar,
-    );
-  }
-
-  void test_typeParam_interface_bounded() {
-    var A = class_(name: 'A');
-    var typeA = interfaceTypeStar(A);
-
-    var B = class_(name: 'B', superType: typeA);
-    var typeB = interfaceTypeStar(B);
-
-    var C = class_(name: 'C', superType: typeB);
-    var typeC = interfaceTypeStar(C);
-
-    var T = typeParameter('T', bound: typeB);
-    _checkGreatestLowerBound(typeParameterTypeStar(T), typeC, neverStar);
-  }
-
-  void test_typeParam_interface_noBound() {
-    // GLB(T, A) = ⊥
-    var T = typeParameter('T');
-    var A = class_(name: 'A');
-    _checkGreatestLowerBound(
-      typeParameterTypeStar(T),
-      interfaceTypeStar(A),
-      neverStar,
-    );
-  }
-
-  void test_typeParameters_different() {
-    // GLB(List<int>, List<double>) = ⊥
-    var listOfIntType = listStar(intStar);
-    var listOfDoubleType = listStar(doubleStar);
-    // TODO(rnystrom): Can we do something better here?
-    _checkGreatestLowerBound(listOfIntType, listOfDoubleType, neverStar);
-  }
-
-  void test_typeParameters_same() {
-    // GLB(List<int>, List<int>) = List<int>
-    var listOfIntType = listStar(intStar);
-    _checkGreatestLowerBound(listOfIntType, listOfIntType, listOfIntType);
-  }
-
-  void test_unrelatedClasses() {
-    // class A
-    // class B
-    // class C
-    var A = class_(name: 'A');
-    var B = class_(name: 'B');
-    _checkGreatestLowerBound(
-        interfaceTypeStar(A), interfaceTypeStar(B), neverStar);
-  }
-
-  void test_void() {
-    var A = class_(name: 'A');
-    var T = typeParameter('T');
-    List<DartType> types = [
-      neverStar,
-      functionTypeStar(returnType: voidNone),
-      interfaceTypeStar(A),
-      typeParameterTypeStar(T),
-    ];
-    for (DartType type in types) {
-      _checkGreatestLowerBound(
-        functionTypeStar(returnType: voidNone),
-        functionTypeStar(returnType: type),
-        functionTypeStar(returnType: type),
-      );
-    }
-  }
-}
-
-@reflectiveTest
 class LeastUpperBoundFunctionsTest extends BoundTestBase {
   void test_differentRequiredArity() {
     var type1 = functionTypeStar(
@@ -3343,16 +1727,3 @@
     check(T2, T, intNone);
   }
 }
-
-class _MockSource implements Source {
-  @override
-  final Uri uri;
-
-  _MockSource(this.uri);
-
-  @override
-  String get encoding => '$uri';
-
-  @override
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analyzer/test/id_tests/assigned_variables_test.dart b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
index 9ac842c..f674c7c 100644
--- a/pkg/analyzer/test/id_tests/assigned_variables_test.dart
+++ b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
@@ -118,7 +118,7 @@
   const _AssignedVariablesDataInterpreter();
 
   @override
-  String getText(_Data actualData) {
+  String getText(_Data actualData, [String indentation]) {
     var parts = <String>[];
     if (actualData.declared.isNotEmpty) {
       parts.add('declared=${_setToString(actualData.declared)}');
diff --git a/pkg/analyzer/test/id_tests/constant_test.dart b/pkg/analyzer/test/id_tests/constant_test.dart
index e249afe2..7d6e44f 100644
--- a/pkg/analyzer/test/id_tests/constant_test.dart
+++ b/pkg/analyzer/test/id_tests/constant_test.dart
@@ -11,7 +11,9 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
 
 import '../util/id_testing_helper.dart';
@@ -36,6 +38,18 @@
   DataInterpreter<String> get dataValidator => const StringDataInterpreter();
 
   @override
+  bool get supportsErrors => true;
+
+  @override
+  String computeErrorData(TestConfig config, TestingData testingData, Id id,
+      List<AnalysisError> errors) {
+    var errorCodes = errors.map((e) => e.errorCode).where((errorCode) =>
+        errorCode !=
+        CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE);
+    return errorCodes.isNotEmpty ? errorCodes.join(',') : null;
+  }
+
+  @override
   void computeUnitData(TestingData testingData, CompilationUnit unit,
       Map<Id, ActualData<String>> actualMap) {
     ConstantsDataExtractor(unit.declaredElement.source.uri, actualMap)
diff --git a/pkg/analyzer/test/id_tests/definite_assignment_test.dart b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
index 732c27a..0581c64 100644
--- a/pkg/analyzer/test/id_tests/definite_assignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
@@ -73,7 +73,7 @@
     if (node is SimpleIdentifier && node.inGetterContext()) {
       var element = node.staticElement;
       if (element is LocalVariableElement || element is ParameterElement) {
-        if (_flowResult.unassignedNodes.contains(node)) {
+        if (_flowResult.potentiallyUnassignedNodes.contains(node)) {
           return 'unassigned';
         }
       }
@@ -86,7 +86,7 @@
   const _DefiniteAssignmentDataInterpreter();
 
   @override
-  String getText(String actualData) => actualData;
+  String getText(String actualData, [String indentation]) => actualData;
 
   @override
   String isAsExpected(String actualData, String expectedData) {
diff --git a/pkg/analyzer/test/id_tests/definite_unassignment_test.dart b/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
index 1e2b9c5..359b481 100644
--- a/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
@@ -86,7 +86,7 @@
   const _DefiniteUnassignmentDataInterpreter();
 
   @override
-  String getText(String actualData) => actualData;
+  String getText(String actualData, [String indentation]) => actualData;
 
   @override
   String isAsExpected(String actualData, String expectedData) {
diff --git a/pkg/analyzer/test/id_tests/nullability_test.dart b/pkg/analyzer/test/id_tests/nullability_test.dart
index 4d9128a..1490e2e 100644
--- a/pkg/analyzer/test/id_tests/nullability_test.dart
+++ b/pkg/analyzer/test/id_tests/nullability_test.dart
@@ -96,7 +96,7 @@
   const _NullabilityDataInterpreter();
 
   @override
-  String getText(String actualData) => actualData;
+  String getText(String actualData, [String indentation]) => actualData;
 
   @override
   String isAsExpected(String actualData, String expectedData) {
diff --git a/pkg/analyzer/test/id_tests/reachability_test.dart b/pkg/analyzer/test/id_tests/reachability_test.dart
index 093d824..833f131 100644
--- a/pkg/analyzer/test/id_tests/reachability_test.dart
+++ b/pkg/analyzer/test/id_tests/reachability_test.dart
@@ -116,7 +116,7 @@
   const _ReachabilityDataInterpreter();
 
   @override
-  String getText(Set<_ReachabilityAssertion> actualData) =>
+  String getText(Set<_ReachabilityAssertion> actualData, [String indentation]) =>
       _sortedRepresentation(_toStrings(actualData));
 
   @override
diff --git a/pkg/analyzer/test/id_tests/type_promotion_test.dart b/pkg/analyzer/test/id_tests/type_promotion_test.dart
index 4e7705a..067dc95 100644
--- a/pkg/analyzer/test/id_tests/type_promotion_test.dart
+++ b/pkg/analyzer/test/id_tests/type_promotion_test.dart
@@ -70,7 +70,7 @@
   const _TypePromotionDataInterpreter();
 
   @override
-  String getText(DartType actualData) {
+  String getText(DartType actualData, [String indentation]) {
     if (actualData is TypeParameterTypeImpl) {
       var element = actualData.element;
       var promotedBound = actualData.promotedBound;
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 28a121a..7ebbad5 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -234,8 +234,6 @@
     // being returned.
     AnalysisOptionsImpl defaultOptions = AnalysisOptionsImpl();
     defaultOptions.dart2jsHint = !defaultOptions.dart2jsHint;
-    defaultOptions.enableLazyAssignmentOperators =
-        !defaultOptions.enableLazyAssignmentOperators;
     builderOptions.defaultOptions = defaultOptions;
     AnalysisOptions options = builder.createDefaultOptions();
     _expectEqualOptions(options, defaultOptions);
@@ -614,10 +612,8 @@
 
   void test_getAnalysisOptions_default_noOverrides() {
     AnalysisOptionsImpl defaultOptions = AnalysisOptionsImpl();
-    defaultOptions.enableLazyAssignmentOperators = true;
     builderOptions.defaultOptions = defaultOptions;
     AnalysisOptionsImpl expected = AnalysisOptionsImpl();
-    expected.enableLazyAssignmentOperators = true;
     String path = convertPath('/some/directory/path');
     String filePath = join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
     newFile(filePath, content: '''
@@ -830,28 +826,19 @@
   void _expectEqualOptions(
       AnalysisOptionsImpl actual, AnalysisOptionsImpl expected) {
     // TODO(brianwilkerson) Consider moving this to AnalysisOptionsImpl.==.
-    expect(actual.analyzeFunctionBodiesPredicate,
-        same(expected.analyzeFunctionBodiesPredicate));
     expect(actual.dart2jsHint, expected.dart2jsHint);
-    expect(actual.enableLazyAssignmentOperators,
-        expected.enableLazyAssignmentOperators);
     expect(actual.enableTiming, expected.enableTiming);
-    expect(actual.generateImplicitErrors, expected.generateImplicitErrors);
-    expect(actual.generateSdkErrors, expected.generateSdkErrors);
     expect(actual.hint, expected.hint);
     expect(actual.lint, expected.lint);
     expect(
       actual.lintRules.map((l) => l.name),
       unorderedEquals(expected.lintRules.map((l) => l.name)),
     );
-    expect(actual.preserveComments, expected.preserveComments);
     expect(actual.strongMode, expected.strongMode);
     expect(actual.implicitCasts, expected.implicitCasts);
     expect(actual.implicitDynamic, expected.implicitDynamic);
     expect(actual.strictInference, expected.strictInference);
     expect(actual.strictRawTypes, expected.strictRawTypes);
-    expect(actual.trackCacheDependencies, expected.trackCacheDependencies);
-    expect(actual.disableCacheFlushing, expected.disableCacheFlushing);
   }
 
   Uri _relativeUri(String path, {String from}) {
diff --git a/pkg/analyzer/test/src/context/packages_test.dart b/pkg/analyzer/test/src/context/packages_test.dart
index 2868970..0313bbc 100644
--- a/pkg/analyzer/test/src/context/packages_test.dart
+++ b/pkg/analyzer/test/src/context/packages_test.dart
@@ -102,6 +102,42 @@
     );
   }
 
+  test_packageForPath() {
+    var packages = Packages(
+      {
+        'aaa': Package(
+          name: 'aaa',
+          rootFolder: getFolder('/home/aaa'),
+          libFolder: getFolder('/home/aaa/lib'),
+          languageVersion: Version.parse('2.7.0'),
+        ),
+        'bbb': Package(
+          name: 'bbb',
+          rootFolder: getFolder('/home/aaa/bbb'),
+          libFolder: getFolder('/home/aaa/bbb/lib'),
+          languageVersion: Version.parse('2.7.0'),
+        ),
+        'ccc': Package(
+          name: 'ccc',
+          rootFolder: getFolder('/home/ccc'),
+          libFolder: getFolder('/home/ccc/lib'),
+          languageVersion: Version.parse('2.7.0'),
+        ),
+      },
+    );
+
+    void check(String posixPath, String expectedPackageName) {
+      var path = convertPath(posixPath);
+      var package = packages.packageForPath(path);
+      expect(package?.name, expectedPackageName);
+    }
+
+    check('/home/aaa/lib/a.dart', 'aaa');
+    check('/home/aaa/bbb/lib/b.dart', 'bbb');
+    check('/home/ccc/lib/c.dart', 'ccc');
+    check('/home/ddd/lib/c.dart', null);
+  }
+
   test_parseDotPackagesFile() {
     var file = newFile('/test/.packages', content: '''
 # Generated by pub
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 4a26ff6..7f8d145 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -1344,7 +1344,7 @@
 
     ClassDeclaration bNode = result.unit.declarations[1];
     TypeParameterType uType =
-        typeParameterType(bNode.declaredElement.typeParameters[0]);
+        typeParameterTypeStar(bNode.declaredElement.typeParameters[0]);
     InterfaceType auType = aElement.instantiate(
       typeArguments: [uType],
       nullabilitySuffix: NullabilitySuffix.star,
@@ -1720,7 +1720,8 @@
     FieldDeclaration fDeclaration = cNode.members[0];
     VariableDeclaration fNode = fDeclaration.fields.variables[0];
     FieldElement fElement = fNode.declaredElement;
-    expect(fElement.type, typeProvider.listType2(typeParameterType(tElement)));
+    expect(
+        fElement.type, typeProvider.listType2(typeParameterTypeStar(tElement)));
   }
 
   test_field_generic() async {
@@ -4010,7 +4011,7 @@
 
     TypeName fReturnTypeNode = fNode.returnType;
     expect(fReturnTypeNode.name.staticElement, same(tElement));
-    expect(fReturnTypeNode.type, typeParameterType(tElement));
+    expect(fReturnTypeNode.type, typeParameterTypeStar(tElement));
 
     expect(fExpression.declaredElement, same(fElement));
 
@@ -4025,13 +4026,13 @@
           name: 'a',
           offset: 28,
           kind: ParameterKind.REQUIRED,
-          type: typeParameterType(tElement));
+          type: typeParameterTypeStar(tElement));
 
       _assertSimpleParameter(nodes[1], parameters[1],
           name: 'b',
           offset: 33,
           kind: ParameterKind.REQUIRED,
-          type: typeParameterType(uElement));
+          type: typeParameterTypeStar(uElement));
 
       var aRef = findNode.simple('a;');
       assertElement(aRef, parameters[0]);
@@ -7266,7 +7267,7 @@
 
       VariableDeclaration bNode = bDeclaration.fields.variables[0];
       expect(bNode.declaredElement, same(bElement));
-      expect(bElement.type, typeParameterType(tElement));
+      expect(bElement.type, typeParameterTypeStar(tElement));
       expect(bNode.name.staticElement, same(bElement));
       expect(bNode.name.staticType, isNull);
     }
@@ -7504,7 +7505,7 @@
         name: 'b',
         offset: 27,
         kind: ParameterKind.REQUIRED,
-        type: typeParameterType(aliasElement.typeParameters[0]));
+        type: typeParameterTypeStar(aliasElement.typeParameters[0]));
   }
 
   test_top_typeParameter() async {
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 901f3b1..9de6844 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
@@ -6,6 +6,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/context/source.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -35,6 +36,52 @@
     _createSourceFactory();
   }
 
+  test_nested() {
+    var packages = Packages(
+      {
+        'aaa': Package(
+          name: 'aaa',
+          rootFolder: getFolder('/packages/aaa'),
+          libFolder: getFolder('/packages/aaa/lib'),
+          languageVersion: Version.parse('2.5.0'),
+        ),
+        'bbb': Package(
+          name: 'bbb',
+          rootFolder: getFolder('/packages/aaa/bbb'),
+          libFolder: getFolder('/packages/aaa/bbb/lib'),
+          languageVersion: Version.parse('2.6.0'),
+        ),
+        'ccc': Package(
+          name: 'ccc',
+          rootFolder: getFolder('/packages/ccc'),
+          libFolder: getFolder('/packages/ccc/lib'),
+          languageVersion: Version.parse('2.7.0'),
+        ),
+      },
+    );
+
+    provider = FeatureSetProvider.build(
+      resourceProvider: resourceProvider,
+      packages: packages,
+      packageDefaultFeatureSet: FeatureSet.fromEnableFlags([]),
+      nonPackageDefaultFeatureSet: FeatureSet.fromEnableFlags([]),
+    );
+
+    void check(String posixPath, Version expected) {
+      var path = convertPath(posixPath);
+      var uri = Uri.parse('package:aaa/a.dart');
+      expect(
+        provider.getLanguageVersion(path, uri),
+        expected,
+      );
+    }
+
+    check('/packages/aaa/a.dart', Version.parse('2.5.0'));
+    check('/packages/aaa/bbb/b.dart', Version.parse('2.6.0'));
+    check('/packages/ccc/c.dart', Version.parse('2.7.0'));
+    check('/packages/ddd/d.dart', ExperimentStatus.currentVersion);
+  }
+
   test_packages() {
     var packages = Packages(
       {
@@ -104,7 +151,7 @@
           name: 'ccc',
           rootFolder: newFolder('/packages/ccc'),
           libFolder: newFolder('/packages/ccc/lib'),
-          languageVersion: Version(2, 8, 0),
+          languageVersion: Version(2, 9, 0),
         ),
       },
     );
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 0c8d536..056f1c4 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -15,6 +15,7 @@
 
 import '../../../generated/test_support.dart';
 import '../resolution/driver_resolution.dart';
+import 'potentially_constant_test.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -22,6 +23,7 @@
     defineReflectiveTests(ConstantVisitorWithConstantUpdate2018Test);
     defineReflectiveTests(
         ConstantVisitorWithFlowControlAndSpreadCollectionsTest);
+    defineReflectiveTests(ConstantVisitorWithNullSafetyTest);
   });
 }
 
@@ -1152,3 +1154,22 @@
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
   }
 }
+
+@reflectiveTest
+class ConstantVisitorWithNullSafetyTest extends ConstantVisitorTestSupport
+    with WithNullSafetyMixin {
+  test_visitAsExpression_potentialConstType() async {
+    await assertNoErrorsInCode('''
+const num three = 3;
+
+class C<T extends num> {
+  final T w;
+  const C() : w = three as T;
+}
+
+void main() {
+  const C<int>().w;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/constant/has_type_parameter_reference_test.dart b/pkg/analyzer/test/src/dart/constant/has_type_parameter_reference_test.dart
new file mode 100644
index 0000000..bc0be60
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/has_type_parameter_reference_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/constant/has_type_parameter_reference.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/type_system_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(HasTypeParameterReferenceTest);
+  });
+}
+
+@reflectiveTest
+class HasTypeParameterReferenceTest extends AbstractTypeSystemNullSafetyTest {
+  test_dynamic() {
+    _checkFalse(dynamicNone);
+  }
+
+  test_functionType() {
+    _checkFalse(functionTypeNone(returnType: voidNone));
+
+    var T = typeParameter('T');
+    var T_none = typeParameterTypeNone(T);
+
+    _checkTrue(
+      functionTypeNone(returnType: T_none),
+    );
+
+    _checkTrue(
+      functionTypeNone(
+        returnType: voidNone,
+        parameters: [requiredParameter(type: T_none)],
+      ),
+    );
+
+    _checkTrue(
+      functionTypeNone(
+        returnType: voidNone,
+        typeFormals: [typeParameter('S', bound: T_none)],
+      ),
+    );
+  }
+
+  test_interfaceType() {
+    _checkFalse(intNone);
+    _checkFalse(intQuestion);
+    _checkFalse(intStar);
+
+    var T = typeParameter('T');
+    var T_none = typeParameterTypeNone(T);
+    _checkTrue(listNone(T_none));
+    _checkTrue(mapNone(T_none, intNone));
+    _checkTrue(mapNone(intNone, T_none));
+  }
+
+  test_typeParameter() {
+    var T = typeParameter('T');
+    _checkTrue(typeParameterTypeNone(T));
+    _checkTrue(typeParameterTypeQuestion(T));
+    _checkTrue(typeParameterTypeStar(T));
+  }
+
+  test_void() {
+    _checkFalse(voidNone);
+  }
+
+  void _checkFalse(DartType type) {
+    expect(hasTypeParameterReference(type), isFalse);
+  }
+
+  void _checkTrue(DartType type) {
+    expect(hasTypeParameterReference(type), isTrue);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
index b2431e5..44d4dd4 100644
--- a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
@@ -2,8 +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 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/constant/potentially_constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -12,7 +15,9 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(IsConstantTypeExpressionTest);
+    defineReflectiveTests(IsPotentiallyConstantTypeExpressionTest);
     defineReflectiveTests(PotentiallyConstantTest);
+    defineReflectiveTests(PotentiallyConstantWithNullSafetyTest);
   });
 }
 
@@ -132,6 +137,35 @@
 }
 
 @reflectiveTest
+class IsPotentiallyConstantTypeExpressionTest
+    extends IsConstantTypeExpressionTest {
+  @override
+  test_typeParameter() async {
+    await _assertConst(r'''
+class A<T> {
+  m() {
+    T x;
+  }
+}
+''');
+  }
+
+  @override
+  Future<void> _assertConst(String code) async {
+    await resolveTestCode(code);
+    var type = findNode.variableDeclarationList('x;').type;
+    expect(isPotentiallyConstantTypeExpression(type), isTrue);
+  }
+
+  @override
+  Future<void> _assertNotConst(String code) async {
+    await resolveTestCode(code);
+    var type = findNode.variableDeclarationList('x;').type;
+    expect(isPotentiallyConstantTypeExpression(type), isFalse);
+  }
+}
+
+@reflectiveTest
 class PotentiallyConstantTest extends DriverResolutionTest {
   test_adjacentStrings() async {
     await _assertConst(r'''
@@ -153,7 +187,7 @@
 ''', () => _xInitializer(), () => [findNode.simple('a as')]);
   }
 
-  test_asExpression_notConstType() async {
+  test_asExpression_typeParameter() async {
     await _assertNotConst(r'''
 const a = 0;
 class A<T> {
@@ -249,7 +283,7 @@
 ''', () => _xInitializer(), () => [findNode.simple('a is')]);
   }
 
-  test_isExpression_notConstType() async {
+  test_isExpression_typeParameter() async {
     await _assertNotConst(r'''
 const a = 0;
 class A<T> {
@@ -845,7 +879,10 @@
   _assertConst(String code, AstNode Function() getNode) async {
     await resolveTestCode(code);
     var node = getNode();
-    var notConstList = getNotPotentiallyConstants(node);
+    var notConstList = getNotPotentiallyConstants(
+      node,
+      isNonNullableByDefault: typeSystem.isNonNullableByDefault,
+    );
     expect(notConstList, isEmpty);
   }
 
@@ -853,7 +890,10 @@
       List<AstNode> Function() getNotConstList) async {
     await resolveTestCode(code);
     var node = getNode();
-    var notConstList = getNotPotentiallyConstants(node);
+    var notConstList = getNotPotentiallyConstants(
+      node,
+      isNonNullableByDefault: typeSystem.isNonNullableByDefault,
+    );
 
     var expectedNotConst = getNotConstList();
     expect(notConstList, unorderedEquals(expectedNotConst));
@@ -863,3 +903,42 @@
     return findNode.variableDeclaration('x = ').initializer;
   }
 }
+
+@reflectiveTest
+class PotentiallyConstantWithNullSafetyTest extends PotentiallyConstantTest
+    with WithNullSafetyMixin {
+  @override
+  test_asExpression_typeParameter() async {
+    await _assertConst(r'''
+const a = 0;
+class A<T> {
+  m() {
+    var x = a as T;
+  }
+}
+''', () => _xInitializer());
+  }
+
+  @override
+  test_isExpression_typeParameter() async {
+    await _assertConst(r'''
+const a = 0;
+class A<T> {
+  m() {
+    var x = a is T;
+  }
+}
+''', () => _xInitializer());
+  }
+}
+
+mixin WithNullSafetyMixin on DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.fromEnableFlags(
+      [EnableString.non_nullable],
+    );
+
+  @override
+  bool get typeToStringWithNullability => true;
+}
diff --git a/pkg/analyzer/test/src/dart/constant/test_all.dart b/pkg/analyzer/test/src/dart/constant/test_all.dart
index 95c1b2e..977b74c 100644
--- a/pkg/analyzer/test/src/dart/constant/test_all.dart
+++ b/pkg/analyzer/test/src/dart/constant/test_all.dart
@@ -5,6 +5,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'evaluation_test.dart' as evaluation;
+import 'has_type_parameter_reference_test.dart' as has_type_parameter_reference;
 import 'potentially_constant_test.dart' as potentially_constant;
 import 'utilities_test.dart' as utilities;
 import 'value_test.dart' as value;
@@ -12,6 +13,7 @@
 main() {
   defineReflectiveSuite(() {
     evaluation.main();
+    has_type_parameter_reference.main();
     potentially_constant.main();
     utilities.main();
     value.main();
diff --git a/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart b/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
new file mode 100644
index 0000000..08ec4f4
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/nullability_suffix.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/class_hierarchy.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:meta/meta.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/elements_types_mixin.dart';
+import '../../../generated/type_system_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ClassHierarchyLegacyTest);
+    defineReflectiveTests(ClassHierarchyNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class ClassHierarchyLegacyTest extends AbstractTypeSystemTest
+    with _AbstractClassHierarchyMixin {
+  @override
+  void setUp() {
+    super.setUp();
+    _createSharedElements();
+  }
+
+  test_invalid() {
+    _checkA(
+      typeArguments: [intNone, doubleNone],
+      interfaces: ['A<int*>'],
+      errors: ['A<int*> vs. A<double*>'],
+    );
+  }
+
+  test_valid() {
+    _checkA(
+      typeArguments: [intNone, intQuestion],
+      interfaces: ['A<int*>'],
+    );
+  }
+}
+
+@reflectiveTest
+class ClassHierarchyNullSafetyTest extends AbstractTypeSystemNullSafetyTest
+    with _AbstractClassHierarchyMixin {
+  @override
+  void setUp() {
+    super.setUp();
+    _createSharedElements();
+  }
+
+  test_invalid() {
+    _checkA(
+      typeArguments: [intNone, doubleNone],
+      interfaces: ['A<int>'],
+      errors: ['A<int> vs. A<double>'],
+    );
+  }
+
+  test_valid_equal() {
+    _checkA(
+      typeArguments: [intNone, intNone],
+      interfaces: ['A<int>'],
+    );
+  }
+
+  test_valid_equal_neverNone() {
+    _checkA(
+      typeArguments: [neverNone, neverNone],
+      interfaces: ['A<Never>'],
+    );
+  }
+
+  test_valid_merge() {
+    _checkA(
+      typeArguments: [objectQuestion, dynamicNone],
+      interfaces: ['A<Object?>'],
+    );
+  }
+}
+
+mixin _AbstractClassHierarchyMixin on ElementsTypesMixin {
+  ClassElementImpl A;
+
+  void _assertErrors(List<ClassHierarchyError> errors, List<String> expected) {
+    expect(
+      errors.map((e) {
+        if (e is IncompatibleInterfacesClassHierarchyError) {
+          var firstStr = _interfaceString(e.first);
+          var secondStr = _interfaceString(e.second);
+          return '$firstStr vs. $secondStr';
+        } else {
+          throw UnimplementedError('${e.runtimeType}');
+        }
+      }).toList(),
+      unorderedEquals(expected),
+    );
+  }
+
+  void _assertInterfaces(
+    List<InterfaceType> interfaces,
+    List<String> expected,
+  ) {
+    var interfacesStr = interfaces.map(_interfaceString).toList();
+    expect(interfacesStr, unorderedEquals(['Object', ...expected]));
+  }
+
+  void _checkA({
+    @required List<DartType> typeArguments,
+    @required List<String> interfaces,
+    List<String> errors = const [],
+  }) {
+    var specifiedInterfaces = typeArguments
+        .map((e) => interfaceTypeNone(A, typeArguments: [e]))
+        .toList();
+    var X = class_(name: 'X', interfaces: specifiedInterfaces);
+
+    var classHierarchy = ClassHierarchy();
+
+    var actualInterfaces = classHierarchy.implementedInterfaces(X);
+    _assertInterfaces(actualInterfaces, interfaces);
+
+    var actualErrors = classHierarchy.errors(X);
+    _assertErrors(actualErrors, errors);
+  }
+
+  void _createSharedElements() {
+    var T = typeParameter('T');
+    A = class_(name: 'A', typeParameters: [T]);
+  }
+
+  String _interfaceString(InterfaceType interface) {
+    return (interface as InterfaceTypeImpl)
+        .withNullability(NullabilitySuffix.none)
+        .getDisplayString(withNullability: true);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 2e0b1b2..7887d88 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -39,14 +40,25 @@
 
 class AbstractTypeTest with ElementsTypesMixin {
   TestAnalysisContext _analysisContext;
-  TypeProvider _typeProvider;
 
   @override
-  TypeProvider get typeProvider => _typeProvider;
+  LibraryElementImpl testLibrary;
+
+  @override
+  TypeProvider typeProvider;
+
+  TypeSystemImpl typeSystem;
 
   void setUp() {
     _analysisContext = TestAnalysisContext();
-    _typeProvider = _analysisContext.typeProviderLegacy;
+    typeProvider = _analysisContext.typeProviderLegacy;
+    typeSystem = _analysisContext.typeSystemLegacy;
+
+    testLibrary = library_(
+      uriStr: 'package:test/test.dart',
+      analysisSession: _analysisContext.analysisSession,
+      typeSystem: typeSystem,
+    );
   }
 }
 
@@ -1184,7 +1196,7 @@
   void test_substitute2_equal() {
     ClassElementImpl definingClass = ElementFactory.classElement2("C", ["E"]);
     TypeParameterType parameterType =
-        typeParameterType(definingClass.typeParameters[0]);
+        typeParameterTypeStar(definingClass.typeParameters[0]);
     MethodElementImpl functionElement = MethodElementImpl('m', -1);
     String namedParameterName = "c";
     functionElement.parameters = <ParameterElement>[
@@ -1309,7 +1321,7 @@
       typeParameters: [BE],
       interfaces: [
         A.instantiate(
-          typeArguments: [typeParameterType(BE)],
+          typeArguments: [typeParameterTypeStar(BE)],
           nullabilitySuffix: NullabilitySuffix.star,
         ),
       ],
@@ -1399,7 +1411,7 @@
     var AE = typeParameter('E');
     var A = class_(name: 'A', typeParameters: [AE]);
 
-    DartType typeAE = typeParameterType(AE);
+    DartType typeAE = typeParameterTypeStar(AE);
     String getterName = "g";
     PropertyAccessorElementImpl getterG =
         ElementFactory.getterElement(getterName, false, typeAE);
@@ -1461,7 +1473,7 @@
       typeParameters: [F],
       interfaces: [
         A.instantiate(
-          typeArguments: [typeParameterType(F)],
+          typeArguments: [typeParameterTypeStar(F)],
           nullabilitySuffix: NullabilitySuffix.star,
         )
       ],
@@ -1520,7 +1532,7 @@
     //
     var E = typeParameter('E');
     var A = class_(name: 'A', typeParameters: [E]);
-    DartType typeE = typeParameterType(E);
+    DartType typeE = typeParameterTypeStar(E);
     String methodName = "m";
     MethodElementImpl methodM =
         ElementFactory.methodElement(methodName, typeE, [typeE]);
@@ -1599,7 +1611,7 @@
       typeParameters: [F],
       mixins: [
         interfaceTypeStar(A, typeArguments: [
-          typeParameterType(F),
+          typeParameterTypeStar(F),
         ]),
       ],
     );
@@ -1635,7 +1647,7 @@
     //
     var E = typeParameter('E');
     var A = class_(name: 'A', typeParameters: [E]);
-    DartType typeE = typeParameterType(E);
+    DartType typeE = typeParameterTypeStar(E);
     String setterName = "s";
     PropertyAccessorElementImpl setterS =
         ElementFactory.setterElement(setterName, false, typeE);
@@ -1683,7 +1695,7 @@
     var A = class_(name: 'A', typeParameters: [E]);
 
     var F = typeParameter('F');
-    var typeF = typeParameterType(F);
+    var typeF = typeParameterTypeStar(F);
 
     var B = class_(
       name: 'B',
@@ -1894,7 +1906,7 @@
     //
     var E = typeParameter('E');
     var A = class_(name: 'A', typeParameters: [E]);
-    DartType typeE = typeParameterType(E);
+    DartType typeE = typeParameterTypeStar(E);
     String methodName = "m";
     MethodElementImpl methodM =
         ElementFactory.methodElement(methodName, typeE, [typeE]);
@@ -1905,7 +1917,7 @@
       name: 'B',
       typeParameters: [F],
       superType: interfaceTypeStar(A, typeArguments: [
-        typeParameterType(F),
+        typeParameterTypeStar(F),
       ]),
     );
     LibraryElementImpl library =
diff --git a/pkg/analyzer/test/src/dart/element/factor_type_test.dart b/pkg/analyzer/test/src/dart/element/factor_type_test.dart
index 111da27..94a865c 100644
--- a/pkg/analyzer/test/src/dart/element/factor_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/factor_type_test.dart
@@ -2,12 +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.
 
+import 'package:_fe_analyzer_shared/src/flow_analysis/factory_type_test_helper.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 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/generated/resolver.dart' show TypeSystemImpl;
-import 'package:test/test.dart';
+import 'package:test/test.dart' as test;
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../../generated/elements_types_mixin.dart';
@@ -20,7 +21,7 @@
 }
 
 @reflectiveTest
-class FactorTypeTest with ElementsTypesMixin {
+class FactorTypeTest with FactorTypeTestMixin<DartType>, ElementsTypesMixin {
   @override
   TypeProvider typeProvider;
 
@@ -40,89 +41,19 @@
     typeSystem = analysisContext.typeSystemNonNullableByDefault;
   }
 
-  void test_futureOr() {
-    _check(futureOrNone(intNone), intNone, 'Future<int>');
-    _check(futureOrNone(intNone), futureNone(intNone), 'int');
-
-    _check(futureOrNone(intQuestion), intNone, 'FutureOr<int?>');
-    _check(futureOrNone(intQuestion), futureNone(intNone), 'FutureOr<int?>');
-    _check(futureOrNone(intQuestion), intQuestion, 'Future<int?>');
-    _check(futureOrNone(intQuestion), futureNone(intQuestion), 'int?');
-    _check(futureOrNone(intQuestion), intStar, 'Future<int?>');
-    _check(futureOrNone(intQuestion), futureNone(intStar), 'int?');
-
-    _check(futureOrNone(intNone), numNone, 'Future<int>');
-    _check(futureOrNone(intNone), futureNone(numNone), 'int');
+  @override
+  DartType factor(DartType T, DartType S) {
+    return typeSystem.factor(T, S);
   }
 
-  void test_object() {
-    _check(objectNone, objectNone, 'Never');
-    _check(objectNone, objectQuestion, 'Never');
-    _check(objectNone, objectStar, 'Never');
-
-    _check(objectNone, intNone, 'Object');
-    _check(objectNone, intQuestion, 'Object');
-    _check(objectNone, intStar, 'Object');
-
-    _check(objectQuestion, objectNone, 'Never?');
-    _check(objectQuestion, objectQuestion, 'Never');
-    _check(objectQuestion, objectStar, 'Never');
-
-    _check(objectQuestion, intNone, 'Object?');
-    _check(objectQuestion, intQuestion, 'Object');
-    _check(objectQuestion, intStar, 'Object');
+  @override
+  void expect(
+      DartType T, DartType S, String actualResult, String expectedResult) {
+    test.expect(actualResult, expectedResult);
   }
 
-  test_subtype() {
-    _check(intNone, intNone, 'Never');
-    _check(intNone, intQuestion, 'Never');
-    _check(intNone, intStar, 'Never');
-
-    _check(intQuestion, intNone, 'Never?');
-    _check(intQuestion, intQuestion, 'Never');
-    _check(intQuestion, intStar, 'Never');
-
-    _check(intStar, intNone, 'Never');
-    _check(intStar, intQuestion, 'Never');
-    _check(intStar, intStar, 'Never');
-
-    _check(intNone, numNone, 'Never');
-    _check(intNone, numQuestion, 'Never');
-    _check(intNone, numStar, 'Never');
-
-    _check(intQuestion, numNone, 'Never?');
-    _check(intQuestion, numQuestion, 'Never');
-    _check(intQuestion, numStar, 'Never');
-
-    _check(intStar, numNone, 'Never');
-    _check(intStar, numQuestion, 'Never');
-    _check(intStar, numStar, 'Never');
-
-    _check(intNone, nullNone, 'int');
-    _check(intQuestion, nullNone, 'int');
-    _check(intStar, nullNone, 'int');
-
-    _check(intNone, stringNone, 'int');
-    _check(intQuestion, stringNone, 'int?');
-    _check(intStar, stringNone, 'int*');
-
-    _check(intNone, stringQuestion, 'int');
-    _check(intQuestion, stringQuestion, 'int');
-    _check(intStar, stringQuestion, 'int');
-
-    _check(intNone, stringStar, 'int');
-    _check(intQuestion, stringStar, 'int');
-    _check(intStar, stringStar, 'int');
-  }
-
-  void _check(DartType T, DartType S, String expectedStr) {
-    var result = typeSystem.factor(T, S);
-    var resultStr = _typeString(result);
-
-    expect(resultStr, expectedStr);
-  }
-
-  String _typeString(TypeImpl type) {
+  @override
+  String typeString(covariant TypeImpl type) {
     return type.getDisplayString(withNullability: true);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/element/flatten_type_test.dart b/pkg/analyzer/test/src/dart/element/flatten_type_test.dart
index a27da75..685c771 100644
--- a/pkg/analyzer/test/src/dart/element/flatten_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/flatten_type_test.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index 12a11bf..c17d008 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -300,11 +300,11 @@
   test_synthetic_instantiate() {
     // T Function<T>(T x)
     var t = typeParameter('T');
-    var x = requiredParameter(name: 'x', type: typeParameterType(t));
+    var x = requiredParameter(name: 'x', type: typeParameterTypeNone(t));
     FunctionType f = FunctionTypeImpl(
       typeFormals: [t],
       parameters: [x],
-      returnType: typeParameterType(t),
+      returnType: typeParameterTypeNone(t),
       nullabilitySuffix: NullabilitySuffix.star,
     );
     FunctionType instantiated = f.instantiate([objectType]);
@@ -346,7 +346,7 @@
     FunctionType f = FunctionTypeImpl(
       typeFormals: [t],
       parameters: [x],
-      returnType: typeParameterType(t),
+      returnType: typeParameterTypeNone(t),
       nullabilitySuffix: NullabilitySuffix.star,
     );
     FunctionType instantiated = f.instantiate([objectType]);
@@ -432,24 +432,24 @@
   test_synthetic_substitute() {
     // Map<T, U> Function<U extends T>(T x, U y)
     var t = typeParameter('T');
-    var u = typeParameter('U', bound: typeParameterType(t));
-    var x = requiredParameter(name: 'x', type: typeParameterType(t));
-    var y = requiredParameter(name: 'y', type: typeParameterType(u));
+    var u = typeParameter('U', bound: typeParameterTypeNone(t));
+    var x = requiredParameter(name: 'x', type: typeParameterTypeNone(t));
+    var y = requiredParameter(name: 'y', type: typeParameterTypeNone(u));
     FunctionType f = FunctionTypeImpl.synthetic(
-        mapOf(typeParameterType(t), typeParameterType(u)), [u], [x, y],
+        mapOf(typeParameterTypeNone(t), typeParameterTypeNone(u)), [u], [x, y],
         nullabilitySuffix: NullabilitySuffix.star);
     FunctionType substituted =
-        f.substitute2([objectType], [typeParameterType(t)]);
+        f.substitute2([objectType], [typeParameterTypeNone(t)]);
     var uSubstituted = substituted.typeFormals[0];
     basicChecks(substituted,
         element: isNull,
         displayName: 'Map<Object, U> Function<U extends Object>(Object, U)',
-        returnType: mapOf(objectType, typeParameterType(uSubstituted)),
+        returnType: mapOf(objectType, typeParameterTypeNone(uSubstituted)),
         typeFormals: [uSubstituted],
         normalParameterNames: ['x', 'y'],
         normalParameterTypes: [
           same(objectType),
-          typeParameterType(uSubstituted)
+          typeParameterTypeNone(uSubstituted)
         ],
         parameters: hasLength(2));
   }
@@ -460,7 +460,7 @@
     var t = typeParameter('T');
     FunctionType f = FunctionTypeImpl.synthetic(dynamicType, [], [],
         nullabilitySuffix: NullabilitySuffix.star);
-    expect(() => f.substitute2([], [typeParameterType(t)]),
+    expect(() => f.substitute2([], [typeParameterTypeStar(t)]),
         throwsA(TypeMatcher<ArgumentError>()));
   }
 
@@ -469,11 +469,11 @@
     // dynamic Function<U>(U x)
     var t = typeParameter('T');
     var u = typeParameter('U');
-    var x = requiredParameter(name: 'x', type: typeParameterType(u));
+    var x = requiredParameter(name: 'x', type: typeParameterTypeStar(u));
     FunctionType f = FunctionTypeImpl.synthetic(dynamicType, [u], [x],
         nullabilitySuffix: NullabilitySuffix.star);
     FunctionType substituted =
-        f.substitute2([objectType], [typeParameterType(t)]);
+        f.substitute2([objectType], [typeParameterTypeStar(t)]);
     expect(substituted, same(f));
   }
 
@@ -482,13 +482,13 @@
     FunctionType f = FunctionTypeImpl(
       typeFormals: [t],
       parameters: const [],
-      returnType: typeParameterType(t),
+      returnType: typeParameterTypeStar(t),
       nullabilitySuffix: NullabilitySuffix.star,
     );
     basicChecks(f,
         element: isNull,
         displayName: 'T Function<T>()',
-        returnType: typeParameterType(t),
+        returnType: typeParameterTypeStar(t),
         typeFormals: [same(t)]);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
new file mode 100644
index 0000000..4354565
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
@@ -0,0 +1,1214 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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/standard_ast_factory.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/ast/token.dart';
+import 'package:analyzer/src/dart/element/generic_inferrer.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:meta/meta.dart';
+import 'package:path/path.dart' show toUri;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/type_system_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstraintMatchingTest);
+    defineReflectiveTests(GenericFunctionInferenceTest);
+  });
+}
+
+@reflectiveTest
+class ConstraintMatchingTest extends AbstractTypeSystemNullSafetyTest {
+  TypeParameterElement T;
+  TypeParameterType T_none;
+  TypeParameterType T_question;
+
+  @override
+  void setUp() {
+    super.setUp();
+    T = typeParameter('T');
+    T_none = typeParameterTypeNone(T);
+    T_question = typeParameterTypeQuestion(T);
+  }
+
+  void test_function_coreFunction() {
+    _checkOrdinarySubtypeMatch(
+      functionTypeNone(
+        returnType: voidNone,
+      ),
+      typeProvider.functionType,
+      [T],
+      covariant: true,
+    );
+  }
+
+  void test_function_parameters_requiredPositional() {
+    _checkIsSubtypeMatchOf(
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: T_none),
+        ],
+        returnType: intNone,
+      ),
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: stringNone),
+        ],
+        returnType: intNone,
+      ),
+      [T],
+      ['String <: T'],
+      covariant: true,
+    );
+  }
+
+  void test_function_returnType() {
+    _checkIsSubtypeMatchOf(
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: intNone),
+        ],
+        returnType: T_none,
+      ),
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: intNone),
+        ],
+        returnType: stringNone,
+      ),
+      [T],
+      ['T <: String'],
+      covariant: true,
+    );
+  }
+
+  /// Left FutureOr: if `T0` is `FutureOr<S0>` then:
+  /// * `T0 <: T1` iff `Future<S0> <: T1` and `S0 <: T1`
+  void test_futureOr_left() {
+    _checkIsSubtypeMatchOf(
+      futureOrNone(T_none),
+      futureOrNone(stringNone),
+      [T],
+      ['T <: String'],
+      covariant: true,
+    );
+
+    _checkIsSubtypeMatchOf(
+      futureOrNone(T_none),
+      futureNone(stringNone),
+      [T],
+      ['T <: String', 'T <: Future<String>'],
+      covariant: true,
+    );
+
+    // Future<List<T>> <: List<String> can't be satisfied
+    _checkIsNotSubtypeMatchOf(
+      futureOrNone(listNone(T_none)),
+      listNone(stringNone),
+      [T],
+      covariant: true,
+    );
+
+    // List<T> <: Future<List<String>> can't be satisfied
+    _checkIsNotSubtypeMatchOf(
+      futureOrNone(listNone(T_none)),
+      futureNone(listNone(stringNone)),
+      [T],
+      covariant: true,
+    );
+  }
+
+  void test_futureOr_right_both_noConstraints() {
+    // `Future<String> <: Future<Object>` can be satisfied:
+    //    * no constraints
+    //
+    // `Future<String> <: Object` can be satisfied:
+    //    * no constraints
+    _checkIsSubtypeMatchOf(
+      futureNone(stringNone),
+      futureOrNone(objectNone),
+      [T],
+      [],
+      covariant: true,
+    );
+  }
+
+  void test_futureOr_right_both_prefer_future() {
+    // `Future<String> <: Future<T>` can be satisfied:
+    //    * `String <: T`
+    //
+    // `Future<String> <: T` can be satisfied:
+    //    * `Future<String> <: T`
+    //
+    // We prefer `String <: T`.
+    _checkIsSubtypeMatchOf(
+      futureNone(stringNone),
+      futureOrNone(T_none),
+      [T],
+      ['String <: T'],
+      covariant: false,
+    );
+
+    // `Future<T> <: Future<Object>` can be satisfied:
+    //   * `T <: Object`
+    //
+    // `Future<T> <: Object` can be satisfied:
+    //   * no constraints
+    //
+    // We prefer `T <: Object`.
+    _checkIsSubtypeMatchOf(
+      futureNone(T_none),
+      futureOrNone(objectNone),
+      [T],
+      ['T <: Object'],
+      covariant: true,
+    );
+  }
+
+  /// Right FutureOr: if `T1` is `FutureOr<S1>` then:
+  /// `T0 <: T1` iff any of the following hold:
+  /// * either `T0 <: Future<S1>`
+  /// * or `T0 <: S1`
+  void test_futureOr_right_none() {
+    // `List<T> <: Future<String>` cannot be satisfied.
+    // `List<T> <: int` cannot be satisfied.
+    _checkIsNotSubtypeMatchOf(
+      listNone(T_none),
+      futureOrNone(stringNone),
+      [T],
+      covariant: true,
+    );
+  }
+
+  void test_futureOr_right_single_future() {
+    // `Future<T> <: Future<String>` can be satisfied:
+    //    * `T <: String`
+    //
+    // `Future<T> <: String` cannot be satisfied.
+    _checkIsSubtypeMatchOf(
+      futureNone(T_none),
+      futureOrNone(stringNone),
+      [T],
+      ['T <: String'],
+      covariant: true,
+    );
+  }
+
+  void test_futureOr_right_single_nonFuture() {
+    // `List<T> <: Future<List<String>>` cannot be satisfied.
+    //
+    // `List<T> <: List<String>` can be satisfied:
+    //    * `T <: String`
+    _checkIsSubtypeMatchOf(
+      listNone(T_none),
+      futureOrNone(listNone(stringNone)),
+      [T],
+      ['T <: String'],
+      covariant: true,
+    );
+  }
+
+  void test_futureOr_right_single_nonFuture_null() {
+    // `Null <: Future<T>` can be satisfied:
+    //    * no constraints
+    //
+    // `Null <: T` can be satisfied:
+    //    * `Null <: T`
+    //
+    // We prefer `Null <: T`.
+    _checkIsSubtypeMatchOf(
+      nullNone,
+      futureOrNone(T_none),
+      [T],
+      ['Null <: T'],
+      covariant: false,
+    );
+  }
+
+  void test_interfaceType_interface_left() {
+    _checkIsNotSubtypeMatchOf(
+      iterableNone(T_none),
+      listNone(stringNone),
+      [T],
+      covariant: true,
+    );
+  }
+
+  void test_interfaceType_interface_right() {
+    _checkIsSubtypeMatchOf(
+      listNone(T_none),
+      iterableNone(stringNone),
+      [T],
+      ['T <: String'],
+      covariant: true,
+    );
+  }
+
+  void test_interfaceType_sameClass() {
+    _checkIsSubtypeMatchOf(
+      listNone(T_none),
+      listNone(stringNone),
+      [T],
+      ['T <: String'],
+      covariant: true,
+    );
+  }
+
+  void test_interfaceType_topMerge() {
+    var testClassIndex = 0;
+
+    void check1(
+      DartType extendsTypeArgument,
+      DartType implementsTypeArgument,
+      String expectedConstraint,
+    ) {
+      var library = library_(
+        uriStr: 'package:test/test.dart',
+        analysisSession: analysisContext.analysisSession,
+        typeSystem: typeSystem,
+      );
+
+      // class A<T> {}
+      var A = class_(name: 'A', typeParameters: [
+        typeParameter('T'),
+      ]);
+      A.enclosingElement = library.definingCompilationUnit;
+
+      // class B<T> extends A<T> {}
+      var B_T = typeParameter('T');
+      var B_T_none = typeParameterTypeNone(B_T);
+      var B = class_(
+        name: 'B',
+        typeParameters: [B_T],
+        superType: interfaceTypeNone(A, typeArguments: [B_T_none]),
+      );
+      B.enclosingElement = library.definingCompilationUnit;
+
+      // class Cx extends A<> implements B<> {}
+      var C = class_(
+        name: 'C${testClassIndex++}',
+        superType: interfaceTypeNone(
+          A,
+          typeArguments: [extendsTypeArgument],
+        ),
+        interfaces: [
+          interfaceTypeNone(
+            B,
+            typeArguments: [implementsTypeArgument],
+          )
+        ],
+      );
+      C.enclosingElement = library.definingCompilationUnit;
+
+      _checkIsSubtypeMatchOf(
+        interfaceTypeNone(C),
+        interfaceTypeNone(A, typeArguments: [T_none]),
+        [T],
+        [expectedConstraint],
+        covariant: false,
+      );
+    }
+
+    void check(
+      DartType typeArgument1,
+      DartType typeArgument2,
+      String expectedConstraint,
+    ) {
+      check1(typeArgument1, typeArgument2, expectedConstraint);
+      check1(typeArgument2, typeArgument1, expectedConstraint);
+    }
+
+    check(objectQuestion, dynamicNone, 'Object? <: T');
+    check(objectStar, dynamicNone, 'Object? <: T');
+    check(voidNone, objectQuestion, 'Object? <: T');
+    check(voidNone, objectStar, 'Object? <: T');
+  }
+
+  void test_left_null() {
+    // Null <: T is trivially satisfied by the constraint Null <: T.
+    _checkIsSubtypeMatchOf(nullNone, T_none, [T], ['Null <: T'],
+        covariant: false);
+
+    // For any other type X, Null <: X is satisfied without the need for any
+    // constraints.
+    _checkOrdinarySubtypeMatch(nullNone, listQuestion(T_none), [T],
+        covariant: false);
+    _checkOrdinarySubtypeMatch(nullNone, stringQuestion, [T], covariant: false);
+    _checkOrdinarySubtypeMatch(nullNone, voidNone, [T], covariant: false);
+    _checkOrdinarySubtypeMatch(nullNone, dynamicNone, [T], covariant: false);
+    _checkOrdinarySubtypeMatch(nullNone, objectQuestion, [T], covariant: false);
+    _checkOrdinarySubtypeMatch(nullNone, nullNone, [T], covariant: false);
+    _checkOrdinarySubtypeMatch(
+      nullNone,
+      functionTypeQuestion(returnType: voidNone),
+      [T],
+      covariant: false,
+    );
+  }
+
+  void test_right_dynamic() {
+    // T <: dynamic is trivially satisfied by the constraint T <: dynamic.
+    _checkIsSubtypeMatchOf(T_none, dynamicNone, [T], ['T <: dynamic'],
+        covariant: true);
+
+    // For any other type X, X <: dynamic is satisfied without the need for any
+    // constraints.
+    _checkOrdinarySubtypeMatch(listNone(T_none), dynamicNone, [T],
+        covariant: true);
+    _checkOrdinarySubtypeMatch(stringNone, dynamicNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(voidNone, dynamicNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(dynamicNone, dynamicNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(objectNone, dynamicNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(nullNone, dynamicNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: intNone),
+        ],
+        returnType: stringNone,
+      ),
+      dynamicNone,
+      [T],
+      covariant: true,
+    );
+  }
+
+  void test_right_object() {
+    // T <: Object is trivially satisfied by the constraint T <: Object.
+    _checkIsSubtypeMatchOf(T_none, objectNone, [T], ['T <: Object'],
+        covariant: true);
+
+    // For any other type X, X <: Object is satisfied without the need for any
+    // constraints.
+    _checkOrdinarySubtypeMatch(listNone(T_none), objectNone, [T],
+        covariant: true);
+    _checkOrdinarySubtypeMatch(stringNone, objectNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(voidNone, objectNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(dynamicNone, objectNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(objectNone, objectNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(nullNone, objectNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: intNone),
+        ],
+        returnType: stringNone,
+      ),
+      objectNone,
+      [T],
+      covariant: true,
+    );
+  }
+
+  void test_right_void() {
+    // T <: void is trivially satisfied by the constraint T <: void.
+    _checkIsSubtypeMatchOf(T_none, voidNone, [T], ['T <: void'],
+        covariant: true);
+
+    // For any other type X, X <: void is satisfied without the need for any
+    // constraints.
+    _checkOrdinarySubtypeMatch(listNone(T_none), voidNone, [T],
+        covariant: true);
+    _checkOrdinarySubtypeMatch(stringNone, voidNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(voidNone, voidNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(dynamicNone, voidNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(objectNone, voidNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(nullNone, voidNone, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: intNone),
+        ],
+        returnType: stringNone,
+      ),
+      voidNone,
+      [T],
+      covariant: true,
+    );
+  }
+
+  void test_typeParameter_left_covariant() {
+    // When doing a covariant match, the type parameters we're trying to find
+    // types for are on the left hand side.
+    _checkIsSubtypeMatchOf(T_none, stringNone, [T], ['T <: String'],
+        covariant: true);
+  }
+
+  void test_typeParameter_left_covariant_match() {
+    // When doing a covariant match, the type parameters we're trying to find
+    // types for are on the left hand side.  If a type parameter appears on the
+    // right hand side, there is a condition in which the constraint can be
+    // satisfied: where both parameters appear at corresponding locations in the
+    // type tree.
+    //
+    // In other words, T <: S can be satisfied trivially by the constraint
+    // T <: S.
+    var S = typeParameter('S');
+    var S_none = typeParameterTypeNone(S);
+    _checkIsSubtypeMatchOf(T_none, S_none, [T], ['T <: S'], covariant: true);
+  }
+
+  void test_typeParameter_left_covariant_no_match() {
+    // When doing a covariant match, the type parameters we're trying to find
+    // types for are on the left hand side.  If a type parameter appears on the
+    // right hand side, it's probable that the constraint can't be satisfied,
+    // because there is no possible type for the LHS (other than bottom)
+    // that's guaranteed to satisfy the relation for all possible assignments of
+    // the RHS type parameter.
+    //
+    // In other words, no match can be found for List<T> <: S because regardless
+    // of T, we can't guarantee that List<T> <: S for all S.
+    var S = typeParameter('S');
+    var S_none = typeParameterTypeNone(S);
+    _checkIsNotSubtypeMatchOf(listNone(T_none), S_none, [T], covariant: true);
+  }
+
+  void test_typeParameter_nullable() {
+    _checkIsSubtypeMatchOf(T_question, stringQuestion, [T], ['T <: String'],
+        covariant: true);
+
+    _checkIsSubtypeMatchOf(stringQuestion, T_question, [T], ['String <: T'],
+        covariant: false);
+  }
+
+  void test_typeParameter_right_contravariant() {
+    // When doing a contravariant match, the type parameters we're trying to
+    // find types for are on the right hand side.
+    _checkIsSubtypeMatchOf(stringNone, T_none, [T], ['String <: T'],
+        covariant: false);
+  }
+
+  void test_typeParameter_right_contravariant_direct() {
+    // When doing a contravariant match, the type parameters we're trying to
+    // find types for are on the right hand side.  If a type parameter also
+    // appears on the left hand side, there is a condition in which the
+    // constraint can be satisfied without consulting the bound of the LHS type
+    // parameter: the condition where both parameters appear at corresponding
+    // locations in the type tree.
+    //
+    // In other words, List<S> <: List<T> is satisfied provided that
+    // S <: T.
+    var S = typeParameter('S');
+    var S_none = typeParameterTypeNone(S);
+    _checkIsSubtypeMatchOf(listNone(S_none), listNone(T_none), [T], ['S <: T'],
+        covariant: false);
+  }
+
+  void test_typeParameter_right_contravariant_via_bound() {
+    // When doing a contravariant match, the type parameters we're trying to
+    // find types for are on the right hand side.  If a type parameter also
+    // appears on the left hand side, we may have to constrain the RHS type
+    // parameter using the bounds of the LHS type parameter.
+    //
+    // In other words, S <: List<T> is satisfied provided that
+    // bound(S) <: List<T>.
+    var S = typeParameter('S', bound: listNone(stringNone));
+    var S_none = typeParameterTypeNone(S);
+    _checkIsSubtypeMatchOf(S_none, listNone(T_none), [T], ['String <: T'],
+        covariant: false);
+  }
+
+  void test_variance_contravariant() {
+    // class A<in T>
+    var T = typeParameter('T', variance: Variance.contravariant);
+    var T_none = typeParameterTypeNone(T);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    _checkIsSubtypeMatchOf(
+      interfaceTypeNone(A, typeArguments: [T_none]),
+      interfaceTypeNone(A, typeArguments: [numNone]),
+      [T],
+      ['num <: in T'],
+      covariant: true,
+    );
+  }
+
+  void test_variance_covariant() {
+    // class A<out T>
+    var T = typeParameter('T', variance: Variance.covariant);
+    var T_none = typeParameterTypeNone(T);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    _checkIsSubtypeMatchOf(
+      interfaceTypeNone(A, typeArguments: [T_none]),
+      interfaceTypeNone(A, typeArguments: [numNone]),
+      [T],
+      ['out T <: num'],
+      covariant: true,
+    );
+  }
+
+  void test_variance_invariant() {
+    // class A<inout T>
+    var T = typeParameter('T', variance: Variance.invariant);
+    var T_none = typeParameterTypeNone(T);
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    _checkIsSubtypeMatchOf(
+      interfaceTypeNone(A, typeArguments: [T_none]),
+      interfaceTypeNone(A, typeArguments: [numNone]),
+      [T],
+      ['inout T <: num', 'num <: inout T'],
+      covariant: true,
+    );
+  }
+
+  void _checkIsNotSubtypeMatchOf(
+    DartType subtype,
+    DartType supertype,
+    List<TypeParameterElement> typeFormals, {
+    @required bool covariant,
+  }) {
+    var inferrer = GenericInferrer(typeSystem, typeFormals);
+
+    var success = inferrer.tryMatchSubtypeOf(subtype, supertype, null,
+        covariant: covariant);
+    expect(success, isFalse);
+
+    inferrer.constraints.forEach((typeParameter, constraints) {
+      expect(constraints, isEmpty);
+    });
+  }
+
+  void _checkIsSubtypeMatchOf(
+    DartType subtype,
+    DartType supertype,
+    List<TypeParameterElement> typeFormals,
+    Iterable<String> expectedConstraints, {
+    @required bool covariant,
+  }) {
+    var inferrer = GenericInferrer(typeSystem, typeFormals);
+
+    var success = inferrer.tryMatchSubtypeOf(subtype, supertype, null,
+        covariant: covariant);
+    expect(success, isTrue);
+
+    var formattedConstraints = <String>[];
+    inferrer.constraints.forEach((typeParameter, constraints) {
+      for (var constraint in constraints) {
+        formattedConstraints.add(
+          constraint.format(
+            typeParameter.getDisplayString(withNullability: true),
+            withNullability: true,
+          ),
+        );
+      }
+    });
+    expect(formattedConstraints, unorderedEquals(expectedConstraints));
+  }
+
+  void _checkOrdinarySubtypeMatch(
+    DartType subtype,
+    DartType supertype,
+    List<TypeParameterElement> typeFormals, {
+    @required bool covariant,
+  }) {
+    var expectSuccess = typeSystem.isSubtypeOf(subtype, supertype);
+    if (expectSuccess) {
+      _checkIsSubtypeMatchOf(subtype, supertype, typeFormals, [],
+          covariant: covariant);
+    } else {
+      _checkIsNotSubtypeMatchOf(subtype, supertype, typeFormals,
+          covariant: covariant);
+    }
+  }
+}
+
+@reflectiveTest
+class GenericFunctionInferenceTest extends AbstractTypeSystemNullSafetyTest {
+  void test_boundedByAnotherTypeParameter() {
+    // <TFrom, TTo extends Iterable<TFrom>>(TFrom) -> TTo
+    var tFrom = typeParameter('TFrom');
+    var tTo =
+        typeParameter('TTo', bound: iterableNone(typeParameterTypeNone(tFrom)));
+    var cast = functionTypeNone(
+      typeFormals: [tFrom, tTo],
+      parameters: [
+        requiredParameter(
+          type: typeParameterTypeNone(tFrom),
+        ),
+      ],
+      returnType: typeParameterTypeNone(tTo),
+    );
+    expect(_inferCall(cast, [stringNone]),
+        [stringNone, (iterableNone(stringNone))]);
+  }
+
+  void test_boundedByOuterClass() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/25740.
+
+    // class A {}
+    var A = class_(name: 'A', superType: objectNone);
+    var typeA = interfaceTypeNone(A);
+
+    // class B extends A {}
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceTypeNone(B);
+
+    // class C<T extends A> {
+    var CT = typeParameter('T', bound: typeA);
+    var C = class_(
+      name: 'C',
+      superType: objectNone,
+      typeParameters: [CT],
+    );
+    //   S m<S extends T>(S);
+    var S = typeParameter('S', bound: typeParameterTypeNone(CT));
+    var m = method(
+      'm',
+      typeParameterTypeNone(S),
+      typeFormals: [S],
+      parameters: [
+        requiredParameter(
+          name: '_',
+          type: typeParameterTypeNone(S),
+        ),
+      ],
+    );
+    C.methods = [m];
+    // }
+
+    // C<Object> cOfObject;
+    var cOfObject = interfaceTypeNone(C, typeArguments: [objectNone]);
+    // C<A> cOfA;
+    var cOfA = interfaceTypeNone(C, typeArguments: [typeA]);
+    // C<B> cOfB;
+    var cOfB = interfaceTypeNone(C, typeArguments: [typeB]);
+    // B b;
+    // cOfB.m(b); // infer <B>
+    _assertType(
+        _inferCall2(cOfB.getMethod('m').type, [typeB]), 'B Function(B)');
+    // cOfA.m(b); // infer <B>
+    _assertType(
+        _inferCall2(cOfA.getMethod('m').type, [typeB]), 'B Function(B)');
+    // cOfObject.m(b); // infer <B>
+    _assertType(
+        _inferCall2(cOfObject.getMethod('m').type, [typeB]), 'B Function(B)');
+  }
+
+  void test_boundedByOuterClassSubstituted() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/25740.
+
+    // class A {}
+    var A = class_(name: 'A', superType: objectNone);
+    var typeA = interfaceTypeNone(A);
+
+    // class B extends A {}
+    var B = class_(name: 'B', superType: typeA);
+    var typeB = interfaceTypeNone(B);
+
+    // class C<T extends A> {
+    var CT = typeParameter('T', bound: typeA);
+    var C = class_(
+      name: 'C',
+      superType: objectNone,
+      typeParameters: [CT],
+    );
+    //   S m<S extends Iterable<T>>(S);
+    var iterableOfT = iterableNone(typeParameterTypeNone(CT));
+    var S = typeParameter('S', bound: iterableOfT);
+    var m = method(
+      'm',
+      typeParameterTypeNone(S),
+      typeFormals: [S],
+      parameters: [
+        requiredParameter(
+          name: '_',
+          type: typeParameterTypeNone(S),
+        ),
+      ],
+    );
+    C.methods = [m];
+    // }
+
+    // C<Object> cOfObject;
+    var cOfObject = interfaceTypeNone(C, typeArguments: [objectNone]);
+    // C<A> cOfA;
+    var cOfA = interfaceTypeNone(C, typeArguments: [typeA]);
+    // C<B> cOfB;
+    var cOfB = interfaceTypeNone(C, typeArguments: [typeB]);
+    // List<B> b;
+    var listOfB = listNone(typeB);
+    // cOfB.m(b); // infer <B>
+    _assertType(_inferCall2(cOfB.getMethod('m').type, [listOfB]),
+        'List<B> Function(List<B>)');
+    // cOfA.m(b); // infer <B>
+    _assertType(_inferCall2(cOfA.getMethod('m').type, [listOfB]),
+        'List<B> Function(List<B>)');
+    // cOfObject.m(b); // infer <B>
+    _assertType(_inferCall2(cOfObject.getMethod('m').type, [listOfB]),
+        'List<B> Function(List<B>)');
+  }
+
+  void test_boundedRecursively() {
+    // class A<T extends A<T>>
+    var T = typeParameter('T');
+    var A = class_(
+      name: 'Cloneable',
+      superType: objectNone,
+      typeParameters: [T],
+    );
+    T.bound = interfaceTypeNone(
+      A,
+      typeArguments: [typeParameterTypeNone(T)],
+    );
+
+    // class B extends A<B> {}
+    var B = class_(name: 'B', superType: null);
+    B.supertype = interfaceTypeNone(A, typeArguments: [interfaceTypeNone(B)]);
+    var typeB = interfaceTypeNone(B);
+
+    // <S extends A<S>>
+    var S = typeParameter('S');
+    var typeS = typeParameterTypeNone(S);
+    S.bound = interfaceTypeNone(A, typeArguments: [typeS]);
+
+    // (S, S) -> S
+    var clone = functionTypeNone(
+      typeFormals: [S],
+      parameters: [
+        requiredParameter(type: typeS),
+        requiredParameter(type: typeS),
+      ],
+      returnType: typeS,
+    );
+    expect(_inferCall(clone, [typeB, typeB]), [typeB]);
+
+    // Something invalid...
+    expect(
+      _inferCall(clone, [stringNone, numNone], expectError: true),
+      [objectNone],
+    );
+  }
+
+  void test_genericCastFunction() {
+    // <TFrom, TTo>(TFrom) -> TTo
+    var tFrom = typeParameter('TFrom');
+    var tTo = typeParameter('TTo');
+    var cast = functionTypeNone(
+      typeFormals: [tFrom, tTo],
+      parameters: [
+        requiredParameter(
+          type: typeParameterTypeNone(tFrom),
+        ),
+      ],
+      returnType: typeParameterTypeNone(tTo),
+    );
+    expect(_inferCall(cast, [intNone]), [intNone, dynamicNone]);
+  }
+
+  void test_genericCastFunctionWithUpperBound() {
+    // <TFrom, TTo extends TFrom>(TFrom) -> TTo
+    var tFrom = typeParameter('TFrom');
+    var tTo = typeParameter(
+      'TTo',
+      bound: typeParameterTypeNone(tFrom),
+    );
+    var cast = functionTypeNone(
+      typeFormals: [tFrom, tTo],
+      parameters: [
+        requiredParameter(
+          type: typeParameterTypeNone(tFrom),
+        ),
+      ],
+      returnType: typeParameterTypeNone(tTo),
+    );
+    expect(_inferCall(cast, [intNone]), [intNone, intNone]);
+  }
+
+  void test_parameter_contravariantUseUpperBound() {
+    // <T>(T x, void Function(T) y) -> T
+    // Generates constraints int <: T <: num.
+    // Since T is contravariant, choose num.
+    var T = typeParameter('T', variance: Variance.contravariant);
+    var tFunction = functionTypeNone(
+        parameters: [requiredParameter(type: typeParameterTypeNone(T))],
+        returnType: voidNone);
+    var numFunction = functionTypeNone(
+        parameters: [requiredParameter(type: numNone)], returnType: voidNone);
+    var function = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(type: typeParameterTypeNone(T)),
+        requiredParameter(type: tFunction)
+      ],
+      returnType: typeParameterTypeNone(T),
+    );
+
+    expect(_inferCall(function, [intNone, numFunction]), [numNone]);
+  }
+
+  void test_parameter_covariantUseLowerBound() {
+    // <T>(T x, void Function(T) y) -> T
+    // Generates constraints int <: T <: num.
+    // Since T is covariant, choose int.
+    var T = typeParameter('T', variance: Variance.covariant);
+    var tFunction = functionTypeNone(
+        parameters: [requiredParameter(type: typeParameterTypeNone(T))],
+        returnType: voidNone);
+    var numFunction = functionTypeNone(
+        parameters: [requiredParameter(type: numNone)], returnType: voidNone);
+    var function = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(type: typeParameterTypeNone(T)),
+        requiredParameter(type: tFunction)
+      ],
+      returnType: typeParameterTypeNone(T),
+    );
+
+    expect(_inferCall(function, [intNone, numFunction]), [intNone]);
+  }
+
+  void test_parametersToFunctionParam() {
+    // <T>(f(T t)) -> T
+    var T = typeParameter('T');
+    var cast = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(
+          type: functionTypeNone(
+            parameters: [
+              requiredParameter(
+                type: typeParameterTypeNone(T),
+              ),
+            ],
+            returnType: dynamicNone,
+          ),
+        ),
+      ],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(
+      _inferCall(cast, [
+        functionTypeNone(
+          parameters: [
+            requiredParameter(type: numNone),
+          ],
+          returnType: dynamicNone,
+        )
+      ]),
+      [numNone],
+    );
+  }
+
+  void test_parametersUseLeastUpperBound() {
+    // <T>(T x, T y) -> T
+    var T = typeParameter('T');
+    var cast = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(type: typeParameterTypeNone(T)),
+        requiredParameter(type: typeParameterTypeNone(T)),
+      ],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(_inferCall(cast, [intNone, doubleNone]), [numNone]);
+  }
+
+  void test_parameterTypeUsesUpperBound() {
+    // <T extends num>(T) -> dynamic
+    var T = typeParameter('T', bound: numNone);
+    var f = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(type: typeParameterTypeNone(T)),
+      ],
+      returnType: dynamicNone,
+    );
+    expect(_inferCall(f, [intNone]), [intNone]);
+  }
+
+  void test_returnFunctionWithGenericParameter() {
+    // <T>(T -> T) -> (T -> void)
+    var T = typeParameter('T');
+    var f = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(
+          type: functionTypeNone(
+            parameters: [
+              requiredParameter(type: typeParameterTypeNone(T)),
+            ],
+            returnType: typeParameterTypeNone(T),
+          ),
+        ),
+      ],
+      returnType: functionTypeNone(
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(T)),
+        ],
+        returnType: voidNone,
+      ),
+    );
+    expect(
+      _inferCall(f, [
+        functionTypeNone(
+          parameters: [
+            requiredParameter(type: numNone),
+          ],
+          returnType: intNone,
+        ),
+      ]),
+      [intNone],
+    );
+  }
+
+  void test_returnFunctionWithGenericParameterAndContext() {
+    // <T>(T -> T) -> (T -> Null)
+    var T = typeParameter('T');
+    var f = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(
+          type: functionTypeNone(
+            parameters: [
+              requiredParameter(type: typeParameterTypeNone(T)),
+            ],
+            returnType: typeParameterTypeNone(T),
+          ),
+        ),
+      ],
+      returnType: functionTypeNone(
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(T)),
+        ],
+        returnType: nullNone,
+      ),
+    );
+    expect(
+      _inferCall(
+        f,
+        [],
+        returnType: functionTypeNone(
+          parameters: [
+            requiredParameter(type: numNone),
+          ],
+          returnType: intNone,
+        ),
+      ),
+      [numNone],
+    );
+  }
+
+  void test_returnFunctionWithGenericParameterAndReturn() {
+    // <T>(T -> T) -> (T -> T)
+    var T = typeParameter('T');
+    var f = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(
+          type: functionTypeNone(
+            parameters: [
+              requiredParameter(type: typeParameterTypeNone(T)),
+            ],
+            returnType: typeParameterTypeNone(T),
+          ),
+        ),
+      ],
+      returnType: functionTypeNone(
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(T)),
+        ],
+        returnType: typeParameterTypeNone(T),
+      ),
+    );
+    expect(
+      _inferCall(f, [
+        functionTypeNone(
+          parameters: [
+            requiredParameter(type: numNone),
+          ],
+          returnType: intNone,
+        )
+      ]),
+      [intNone],
+    );
+  }
+
+  void test_returnFunctionWithGenericReturn() {
+    // <T>(T -> T) -> (() -> T)
+    var T = typeParameter('T');
+    var f = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(
+          type: functionTypeNone(
+            parameters: [
+              requiredParameter(type: typeParameterTypeNone(T)),
+            ],
+            returnType: typeParameterTypeNone(T),
+          ),
+        ),
+      ],
+      returnType: functionTypeNone(
+        returnType: typeParameterTypeNone(T),
+      ),
+    );
+    expect(
+      _inferCall(f, [
+        functionTypeNone(
+          parameters: [
+            requiredParameter(type: numNone),
+          ],
+          returnType: intNone,
+        )
+      ]),
+      [intNone],
+    );
+  }
+
+  void test_returnTypeFromContext() {
+    // <T>() -> T
+    var T = typeParameter('T');
+    var f = functionTypeNone(
+      typeFormals: [T],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(_inferCall(f, [], returnType: stringNone), [stringNone]);
+  }
+
+  void test_returnTypeWithBoundFromContext() {
+    // <T extends num>() -> T
+    var T = typeParameter('T', bound: numNone);
+    var f = functionTypeNone(
+      typeFormals: [T],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(_inferCall(f, [], returnType: doubleNone), [doubleNone]);
+  }
+
+  void test_returnTypeWithBoundFromInvalidContext() {
+    // <T extends num>() -> T
+    var T = typeParameter('T', bound: numNone);
+    var f = functionTypeNone(
+      typeFormals: [T],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(_inferCall(f, [], returnType: stringNone), [neverNone]);
+  }
+
+  void test_unifyParametersToFunctionParam() {
+    // <T>(f(T t), g(T t)) -> T
+    var T = typeParameter('T');
+    var cast = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(
+          type: functionTypeNone(
+            parameters: [
+              requiredParameter(
+                type: typeParameterTypeNone(T),
+              ),
+            ],
+            returnType: dynamicNone,
+          ),
+        ),
+        requiredParameter(
+          type: functionTypeNone(
+            parameters: [
+              requiredParameter(
+                type: typeParameterTypeNone(T),
+              ),
+            ],
+            returnType: dynamicNone,
+          ),
+        ),
+      ],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(
+      _inferCall(cast, [
+        functionTypeNone(
+          parameters: [
+            requiredParameter(type: intNone),
+          ],
+          returnType: dynamicNone,
+        ),
+        functionTypeNone(
+          parameters: [
+            requiredParameter(type: doubleNone),
+          ],
+          returnType: dynamicNone,
+        )
+      ]),
+      [neverNone],
+    );
+  }
+
+  void test_unusedReturnTypeIsDynamic() {
+    // <T>() -> T
+    var T = typeParameter('T');
+    var f = functionTypeNone(
+      typeFormals: [T],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(_inferCall(f, []), [dynamicNone]);
+  }
+
+  void test_unusedReturnTypeWithUpperBound() {
+    // <T extends num>() -> T
+    var T = typeParameter('T', bound: numNone);
+    var f = functionTypeNone(
+      typeFormals: [T],
+      returnType: typeParameterTypeNone(T),
+    );
+    expect(_inferCall(f, []), [numNone]);
+  }
+
+  void _assertType(DartType type, String expected) {
+    var typeStr = type.getDisplayString(withNullability: false);
+    expect(typeStr, expected);
+  }
+
+  List<DartType> _inferCall(FunctionTypeImpl ft, List<DartType> arguments,
+      {DartType returnType, bool expectError = false}) {
+    var listener = RecordingErrorListener();
+
+    var reporter = ErrorReporter(
+      listener,
+      NonExistingSource('/test.dart', toUri('/test.dart'), UriKind.FILE_URI),
+      isNonNullableByDefault: false,
+    );
+
+    var typeArguments = typeSystem.inferGenericFunctionOrType(
+      typeParameters: ft.typeFormals,
+      parameters: ft.parameters,
+      declaredReturnType: ft.returnType,
+      argumentTypes: arguments,
+      contextReturnType: returnType,
+      errorReporter: reporter,
+      errorNode: astFactory.nullLiteral(KeywordToken(Keyword.NULL, 0)),
+    );
+
+    if (expectError) {
+      expect(listener.errors.map((e) => e.errorCode).toList(),
+          [StrongModeCode.COULD_NOT_INFER],
+          reason: 'expected exactly 1 could not infer error.');
+    } else {
+      expect(listener.errors, isEmpty, reason: 'did not expect any errors.');
+    }
+    return typeArguments;
+  }
+
+  FunctionType _inferCall2(FunctionTypeImpl ft, List<DartType> arguments,
+      {DartType returnType, bool expectError = false}) {
+    var typeArguments = _inferCall(
+      ft,
+      arguments,
+      returnType: returnType,
+      expectError: expectError,
+    );
+    return ft.instantiate(typeArguments);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index dc308ff..0da7a31 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -1075,10 +1075,35 @@
 ''');
 
     _assertInheritedMap('C', r'''
-B.foo: void Function({required int a})
+A.foo: void Function({int a})
 ''');
   }
 
+  test_getMember_mixin_notMerge_replace() async {
+    await resolveTestCode('''
+class A<T> {
+  T foo() => throw 0;
+}
+
+mixin M<T> {
+  T foo() => throw 1;
+}
+
+class X extends A<dynamic> with M<Object?> {}
+class Y extends A<Object?> with M<dynamic> {}
+''');
+    _assertGetMember2(
+      className: 'X',
+      name: 'foo',
+      expected: 'M.foo: Object? Function()',
+    );
+    _assertGetMember2(
+      className: 'Y',
+      name: 'foo',
+      expected: 'M.foo: dynamic Function()',
+    );
+  }
+
   test_getMember_optIn_inheritsOptIn() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
@@ -1303,6 +1328,26 @@
     _assertExecutable(member, expected);
   }
 
+  void _assertGetMember2({
+    @required String className,
+    @required String name,
+    String expected,
+  }) {
+    _assertGetMember(
+      className: className,
+      name: name,
+      expected: expected,
+      concrete: false,
+    );
+
+    _assertGetMember(
+      className: className,
+      name: name,
+      expected: expected,
+      concrete: true,
+    );
+  }
+
   void _assertInheritedConcreteMap(String className, String expected) {
     var type = _classInterfaceType(className);
     var map = manager.getInheritedConcreteMap(type);
diff --git a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
index 9cb8284..3e95b6c 100644
--- a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
@@ -5,9 +5,9 @@
 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/least_upper_bound.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/generated/type_system.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -166,7 +166,7 @@
       interfaces: [
         InstantiatedClass(
           classB,
-          [typeParameterType(CT)],
+          [typeParameterTypeStar(CT)],
         ).withNullabilitySuffixNone,
       ],
     );
@@ -228,7 +228,7 @@
       typeParameters: typeParametersC,
       supertype: InstantiatedClass(
         classB,
-        [typeParameterType(typeParametersC[0])],
+        [typeParameterTypeStar(typeParametersC[0])],
       ).withNullabilitySuffixNone,
     );
 
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 66d8fb5..e7c1853 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -6,16 +6,13 @@
 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/type.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
 import 'package:analyzer/src/dart/resolver/variance.dart';
-import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/elements_types_mixin.dart';
-import '../../../generated/test_analysis_context.dart';
+import '../../../generated/type_system_test.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -5965,28 +5962,9 @@
   }
 }
 
-@reflectiveTest
-class _SubtypingTestBase with ElementsTypesMixin {
-  @override
-  TypeProvider typeProvider;
-
-  TypeSystemImpl typeSystem;
-
-  FeatureSet get testFeatureSet {
-    return FeatureSet.forTesting();
-  }
-
-  void setUp() {
-    var analysisContext = TestAnalysisContext(
-      featureSet: testFeatureSet,
-    );
-    typeProvider = analysisContext.typeProviderNonNullableByDefault;
-    typeSystem = analysisContext.typeSystemNonNullableByDefault;
-  }
-}
+class _SubtypingTestBase extends AbstractTypeSystemNullSafetyTest {}
 
 class _TypeParameterCollector extends DartTypeVisitor<void> {
-//  final Set<TypeParameterElement> typeParameters = {};
   final Set<String> typeParameters = {};
 
   /// We don't need to print bounds for these type parameters, because
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index 43eab7c..ef6a0df 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -4,10 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'class_hierarchy_test.dart' as class_hierarchy;
 import 'element_test.dart' as element;
 import 'factor_type_test.dart' as factor_type;
 import 'flatten_type_test.dart' as flatten_type;
 import 'function_type_test.dart' as function_type;
+import 'generic_inferrer_test.dart' as generic_inferrer;
 import 'inheritance_manager3_test.dart' as inheritance_manager3;
 import 'least_upper_bound_helper_test.dart' as least_upper_bound_helper;
 import 'normalize_type_test.dart' as normalize_type;
@@ -24,10 +26,12 @@
 /// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
+    class_hierarchy.main();
     element.main();
     factor_type.main();
     flatten_type.main();
     function_type.main();
+    generic_inferrer.main();
     inheritance_manager3.main();
     least_upper_bound_helper.main();
     normalize_type.main();
diff --git a/pkg/analyzer/test/src/dart/element/top_merge_test.dart b/pkg/analyzer/test/src/dart/element/top_merge_test.dart
index 6f77a5f..be03653 100644
--- a/pkg/analyzer/test/src/dart/element/top_merge_test.dart
+++ b/pkg/analyzer/test/src/dart/element/top_merge_test.dart
@@ -46,7 +46,7 @@
     _check(
       functionTypeNone(returnType: voidNone),
       functionTypeNone(returnType: objectQuestion),
-      functionTypeNone(returnType: voidNone),
+      functionTypeNone(returnType: objectQuestion),
     );
 
     _check(
@@ -213,7 +213,7 @@
     _check(
       listNone(voidNone),
       listNone(objectQuestion),
-      listNone(voidNone),
+      listNone(objectQuestion),
     );
 
     _check(
@@ -263,16 +263,19 @@
     // NNBD_TOP_MERGE(Object?, Object?) = Object?
     _check(objectQuestion, objectQuestion, objectQuestion);
 
+    // NNBD_TOP_MERGE(Object?, void) = Object?
+    // NNBD_TOP_MERGE(void, Object?) = Object?
+    _check(objectQuestion, voidNone, objectQuestion);
+
     // NNBD_TOP_MERGE(Object?, dynamic) = Object?
     // NNBD_TOP_MERGE(dynamic, Object?) = Object?
     _check(objectQuestion, dynamicNone, objectQuestion);
-    _check(dynamicNone, objectQuestion, objectQuestion);
   }
 
   test_objectStar() {
-    // NNBD_TOP_MERGE(Object*, void) = void
-    // NNBD_TOP_MERGE(void, Object*) = void
-    _check(objectStar, voidNone, voidNone);
+    // NNBD_TOP_MERGE(Object*, void) = Object?
+    // NNBD_TOP_MERGE(void, Object*) = Object?
+    _check(objectStar, voidNone, objectQuestion);
 
     // NNBD_TOP_MERGE(Object*, dynamic) = Object?
     // NNBD_TOP_MERGE(dynamic, Object*) = Object?
@@ -303,15 +306,9 @@
     // NNBD_TOP_MERGE(void, void) = void
     _check(voidNone, voidNone, voidNone);
 
-    // NNBD_TOP_MERGE(void, Object?) = void
-    // NNBD_TOP_MERGE(Object?, void) = void
-    _check(voidNone, objectQuestion, voidNone);
-    _check(objectQuestion, voidNone, voidNone);
-
-    // NNBD_TOP_MERGE(void, dynamic) = void
-    // NNBD_TOP_MERGE(dynamic, void) = void
-    _check(voidNone, dynamicNone, voidNone);
-    _check(dynamicNone, voidNone, voidNone);
+    // NNBD_TOP_MERGE(void, dynamic) = Object?
+    // NNBD_TOP_MERGE(dynamic, void) = Object?
+    _check(voidNone, dynamicNone, objectQuestion);
   }
 
   void _check(DartType T, DartType S, DartType expected) {
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index 3de9097..75efd3f 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -7,8 +7,8 @@
 import 'package:analyzer/dart/element/type.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_schema.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/generated/type_system.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -54,7 +54,7 @@
     var substitution = Substitution.fromInterfaceType(BofInt);
 
     // A<U>
-    var type = interfaceTypeStar(A, typeArguments: [typeParameterType(U)]);
+    var type = interfaceTypeStar(A, typeArguments: [typeParameterTypeStar(U)]);
     assertType(type, 'A<U>');
 
     var result = substitution.substituteType(type);
@@ -73,8 +73,8 @@
     var type = interfaceTypeStar(
       A,
       typeArguments: [
-        typeParameterType(T),
-        typeParameterType(U),
+        typeParameterTypeStar(T),
+        typeParameterTypeStar(U),
       ],
     );
 
@@ -93,9 +93,9 @@
     var T = typeParameter('T');
     var type = functionTypeStar(
       parameters: [
-        requiredParameter(type: typeParameterType(T)),
+        requiredParameter(type: typeParameterTypeStar(T)),
       ],
-      returnType: typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
 
     var result = Substitution.fromUpperAndLowerBounds(
@@ -136,10 +136,10 @@
     var U = typeParameter('U');
     var type = functionTypeStar(
       parameters: [
-        requiredParameter(type: typeParameterType(U)),
+        requiredParameter(type: typeParameterTypeStar(U)),
         requiredParameter(type: boolType),
       ],
-      returnType: typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
 
     assertType(type, 'T Function(U, bool)');
@@ -158,13 +158,13 @@
   test_function_typeFormals() async {
     // typedef F<T> = T Function<U extends T>(U);
     var T = typeParameter('T');
-    var U = typeParameter('U', bound: typeParameterType(T));
+    var U = typeParameter('U', bound: typeParameterTypeStar(T));
     var type = functionTypeStar(
       typeFormals: [U],
       parameters: [
-        requiredParameter(type: typeParameterType(U)),
+        requiredParameter(type: typeParameterTypeStar(U)),
       ],
-      returnType: typeParameterType(T),
+      returnType: typeParameterTypeStar(T),
     );
 
     assertType(type, 'T Function<U extends T>(U)');
@@ -188,9 +188,9 @@
     var U = typeParameter('U');
     var V = typeParameter('V');
     T.bound = interfaceTypeStar(classTriplet, typeArguments: [
-      typeParameterType(T),
-      typeParameterType(U),
-      typeParameterType(V),
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(U),
+      typeParameterTypeStar(V),
     ]);
     var type = functionTypeStar(
       typeFormals: [T, U],
@@ -221,7 +221,7 @@
 
     var U = typeParameter('U');
     var type = interfaceTypeStar(A, typeArguments: [
-      typeParameterType(U),
+      typeParameterTypeStar(U),
     ]);
 
     assertType(type, 'A<U>');
@@ -237,7 +237,7 @@
       interfaceTypeStar(
         typeProvider.listElement,
         typeArguments: [
-          typeParameterType(U),
+          typeParameterTypeStar(U),
         ],
       )
     ]);
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 8e159b5..c41a840 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
@@ -6,16 +6,15 @@
 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/type.dart';
+import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/elements_types_mixin.dart';
-import '../../../generated/test_analysis_context.dart';
+import '../../../generated/type_system_test.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -924,6 +923,56 @@
     );
   }
 
+  test_futureOr() {
+    InterfaceType futureOrFunction(DartType T, String str) {
+      var result = futureOrNone(
+        functionTypeNone(returnType: voidNone, parameters: [
+          requiredParameter(type: T),
+        ]),
+      );
+      expect(result.getDisplayString(withNullability: true), str);
+      return result;
+    }
+
+    // DOWN(FutureOr<T1>, FutureOr<T2>) = FutureOr<S>, S = DOWN(T1, T2)
+    _checkGreatestLowerBound(
+      futureOrNone(intNone),
+      futureOrNone(numNone),
+      futureOrNone(intNone),
+    );
+    _checkGreatestLowerBound(
+      futureOrFunction(intNone, 'FutureOr<void Function(int)>'),
+      futureOrFunction(doubleNone, 'FutureOr<void Function(double)>'),
+      futureOrFunction(numNone, 'FutureOr<void Function(num)>'),
+    );
+
+    // DOWN(FutureOr<T1>, Future<T2>) = Future<S>, S = DOWN(T1, T2)
+    // DOWN(Future<T1>, FutureOr<T2>) = Future<S>, S = DOWN(T1, T2)
+    _checkGreatestLowerBound(
+      futureOrNone(numNone),
+      futureNone(intNone),
+      futureNone(intNone),
+    );
+    _checkGreatestLowerBound(
+      futureOrNone(intNone),
+      futureNone(numNone),
+      futureNone(intNone),
+    );
+
+    // DOWN(FutureOr<T1>, T2) = S, S = DOWN(T1, T2)
+    // DOWN(T1, FutureOr<T2>) = S, S = DOWN(T1, T2)
+    _checkGreatestLowerBound(
+      futureOrNone(numNone),
+      intNone,
+      intNone,
+    );
+    _checkGreatestLowerBound(
+      futureOrNone(intNone),
+      numNone,
+      intNone,
+    );
+  }
+
   test_identical() {
     void check(DartType type) {
       _checkGreatestLowerBound(type, type, type);
@@ -943,8 +992,67 @@
       _checkGreatestLowerBound(T1, T2, expected);
     }
 
+    check(intNone, intNone, intNone);
     check(numNone, intNone, intNone);
     check(doubleNone, intNone, neverNone);
+
+    check(listNone(intNone), listNone(intNone), listNone(intNone));
+    check(listNone(numNone), listNone(intNone), listNone(intNone));
+    check(listNone(doubleNone), listNone(intNone), neverNone);
+  }
+
+  void test_interfaceType2_interfaces() {
+    // class A
+    // class B implements A
+    // class C implements B
+    var A = class_(name: 'A');
+    var B = class_(name: 'B', interfaces: [interfaceTypeNone(A)]);
+    var C = class_(name: 'C', interfaces: [interfaceTypeNone(B)]);
+    _checkGreatestLowerBound(
+      interfaceTypeNone(A),
+      interfaceTypeNone(C),
+      interfaceTypeNone(C),
+    );
+  }
+
+  void test_interfaceType2_mixins() {
+    // class A
+    // class B
+    // class C
+    // class D extends A with B, C
+    var A = class_(name: 'A');
+    var typeA = interfaceTypeNone(A);
+
+    var B = class_(name: 'B');
+    var typeB = interfaceTypeNone(B);
+
+    var C = class_(name: 'C');
+    var typeC = interfaceTypeNone(C);
+
+    var D = class_(
+      name: 'D',
+      superType: interfaceTypeNone(A),
+      mixins: [typeB, typeC],
+    );
+    var typeD = interfaceTypeNone(D);
+
+    _checkGreatestLowerBound(typeA, typeD, typeD);
+    _checkGreatestLowerBound(typeB, typeD, typeD);
+    _checkGreatestLowerBound(typeC, typeD, typeD);
+  }
+
+  void test_interfaceType2_superType() {
+    // class A
+    // class B extends A
+    // class C extends B
+    var A = class_(name: 'A');
+    var B = class_(name: 'B', superType: interfaceTypeNone(A));
+    var C = class_(name: 'C', superType: interfaceTypeNone(B));
+    _checkGreatestLowerBound(
+      interfaceTypeNone(A),
+      interfaceTypeNone(C),
+      interfaceTypeNone(C),
+    );
   }
 
   test_none_question() {
@@ -1147,6 +1255,23 @@
     check(intQuestion, doubleQuestion, neverQuestion);
   }
 
+  test_self() {
+    var T = typeParameter('T');
+
+    List<DartType> types = [
+      dynamicType,
+      voidNone,
+      neverNone,
+      typeParameterTypeStar(T),
+      intNone,
+      functionTypeNone(returnType: voidNone),
+    ];
+
+    for (var type in types) {
+      _checkGreatestLowerBound(type, type, type);
+    }
+  }
+
   test_star_question() {
     void check(DartType T1, DartType T2, DartType expected) {
       _assertNullabilityQuestion(T1);
@@ -1195,6 +1320,8 @@
     check(voidNone, intStar);
     check(voidNone, listNone(intNone));
     check(voidNone, futureOrNone(intNone));
+    check(voidNone, neverNone);
+    check(voidNone, functionTypeNone(returnType: voidNone));
 
     check(dynamicNone, objectNone);
     check(dynamicNone, intNone);
@@ -1202,6 +1329,8 @@
     check(dynamicNone, intStar);
     check(dynamicNone, listNone(intNone));
     check(dynamicNone, futureOrNone(intNone));
+    check(dynamicNone, neverNone);
+    check(dynamicNone, functionTypeNone(returnType: voidNone));
 
     check(objectQuestion, objectNone);
     check(objectQuestion, intNone);
@@ -1209,6 +1338,8 @@
     check(objectQuestion, intStar);
     check(objectQuestion, listNone(intNone));
     check(objectQuestion, futureOrNone(intNone));
+    check(objectQuestion, neverNone);
+    check(objectQuestion, functionTypeNone(returnType: voidNone));
 
     check(objectStar, objectNone);
     check(objectStar, intNone);
@@ -1216,6 +1347,8 @@
     check(objectStar, intStar);
     check(objectStar, listNone(intNone));
     check(objectStar, futureOrNone(intNone));
+    check(objectStar, neverNone);
+    check(objectStar, functionTypeNone(returnType: voidNone));
 
     check(futureOrNone(voidNone), intNone);
     check(futureOrQuestion(voidNone), intNone);
@@ -1278,6 +1411,22 @@
     check(futureOrNone(dynamicNone), futureOrNone(objectStar));
   }
 
+  test_typeParameter() {
+    void check({DartType bound, DartType T2}) {
+      var T1 = typeParameterTypeNone(
+        typeParameter('T', bound: bound),
+      );
+      _checkGreatestLowerBound(T1, T2, neverNone);
+    }
+
+    check(
+      bound: null,
+      T2: functionTypeNone(returnType: voidNone),
+    );
+    check(bound: null, T2: intNone);
+    check(bound: numNone, T2: intNone);
+  }
+
   void _checkGreatestLowerBound(DartType T1, DartType T2, DartType expected,
       {bool checkSubtype = true}) {
     var expectedStr = _typeString(expected);
@@ -2064,24 +2213,7 @@
 }
 
 @reflectiveTest
-class _BoundsTestBase with ElementsTypesMixin {
-  @override
-  TypeProvider typeProvider;
-
-  TypeSystemImpl typeSystem;
-
-  FeatureSet get testFeatureSet {
-    return FeatureSet.forTesting();
-  }
-
-  void setUp() {
-    var analysisContext = TestAnalysisContext(
-      featureSet: testFeatureSet,
-    );
-    typeProvider = analysisContext.typeProviderNonNullableByDefault;
-    typeSystem = analysisContext.typeSystemNonNullableByDefault;
-  }
-
+class _BoundsTestBase extends AbstractTypeSystemNullSafetyTest {
   void _assertNotBottom(DartType type) {
     if (typeSystem.isBottom(type)) {
       fail('isBottom must be false: ' + _typeString(type));
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index 22f938e..605677e 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -5,78 +5,92 @@
 import 'dart:convert';
 
 import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/micro/resolve_file.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
 import 'package:crypto/crypto.dart';
+import 'package:linter/src/rules.dart';
 
 import '../resolution/resolution.dart';
 
 /// [FileResolver] based implementation of [ResolutionTest].
 class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
+  static final String _testFile = '/workspace/dart/test/lib/test.dart';
+
   final ByteStore byteStore = MemoryByteStore();
 
   final StringBuffer logBuffer = StringBuffer();
   PerformanceLog logger;
+  MockSdk sdk;
 
-  DartSdk sdk;
-  Map<String, List<Folder>> packageMap;
   FileResolver fileResolver;
 
-  List<MockSdkLibrary> get additionalMockSdkLibraries => [];
+  @override
+  void addTestFile(String content) {
+    newFile(_testFile, content: content);
+  }
 
-  /// Override this to change the analysis options for a given set of tests.
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl();
+  /// Create a new [FileResolver] into [fileResolver].
+  ///
+  /// We do this the first time, and to test reusing results from [byteStore].
+  void createFileResolver() {
+    var workspace = BazelWorkspace.find(
+      resourceProvider,
+      convertPath(_testFile),
+    );
+
+    fileResolver = FileResolver(
+      logger,
+      resourceProvider,
+      byteStore,
+      workspace.createSourceFactory(sdk, null),
+      (String path) => _getDigest(path),
+      null,
+      workspace: workspace,
+    );
+    fileResolver.testView = FileResolverTestView();
+  }
+
+  ErrorsResult getTestErrors() {
+    var path = convertPath(_testFile);
+    return fileResolver.getErrors(path);
+  }
 
   @override
   Future<ResolvedUnitResult> resolveFile(String path) async {
     return fileResolver.resolve(path);
   }
 
-  String _getDigest(String path) {
-    var content;
-    try {
-      content = resourceProvider.getFile(path).readAsStringSync();
-    } catch (_) {
-      return '';
-    }
-    var contentBytes = utf8.encode(content);
-    return md5.convert(contentBytes).toString();
+  @override
+  Future<void> resolveTestFile() async {
+    var path = convertPath(_testFile);
+    result = await resolveFile(path);
+    findNode = FindNode(result.content, result.unit);
+    findElement = FindElement(result.unit);
   }
 
   void setUp() {
-    sdk = MockSdk(
-      resourceProvider: resourceProvider,
-      additionalLibraries: additionalMockSdkLibraries,
-    );
+    registerLintRules();
+
     logger = PerformanceLog(logBuffer);
+    sdk = MockSdk(resourceProvider: resourceProvider);
 
-    // TODO(brianwilkerson) Create an empty package map by default and only add
-    //  packages in the tests that need them.
-    packageMap = <String, List<Folder>>{
-      'test': [getFolder('/test/lib')],
-      'aaa': [getFolder('/aaa/lib')],
-      'bbb': [getFolder('/bbb/lib')],
-      'meta': [getFolder('/.pub-cache/meta/lib')],
-    };
+    newFile('/workspace/WORKSPACE', content: '');
+    createFileResolver();
+  }
 
-    fileResolver = FileResolver(
-        logger,
-        resourceProvider,
-        byteStore,
-        SourceFactory([
-          DartUriResolver(sdk),
-          PackageMapUriResolver(resourceProvider, packageMap),
-          ResourceUriResolver(resourceProvider)
-        ]),
-        (String path) => _getDigest(path),
-        null);
+  String _getDigest(String path) {
+    try {
+      var content = resourceProvider.getFile(path).readAsStringSync();
+      var contentBytes = utf8.encode(content);
+      return md5.convert(contentBytes).toString();
+    } catch (_) {
+      return '';
+    }
   }
 }
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 d4155ce..3236c52 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,1301 +2,243 @@
 // for details. 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/src/error/codes.dart';
+import 'package:analyzer/src/lint/registry.dart';
+import 'package:matcher/matcher.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'file_resolution.dart';
-import '../../../generated/resolver_test_case.dart';
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(SimpleFileResolverTest);
+    defineReflectiveTests(FileResolverTest);
   });
 }
 
 @reflectiveTest
-class SimpleFileResolverTest extends FileResolutionTest {
-  test_argumentResolution_required_matching() async {
-    await resolveTestCode(r'''
-class A {
-  void f() {
-    g(1, 2, 3);
-  }
-  void g(a, b, c) {}
-}''');
-    await _validateArgumentResolution([0, 1, 2]);
+class FileResolverTest extends FileResolutionTest {
+  test_analysisOptions_default_fromPackageUri() async {
+    newFile('/workspace/dart/analysis_options/lib/default.yaml', content: r'''
+analyzer:
+  strong-mode:
+    implicit-casts: false
+''');
+
+    await assertErrorsInCode(r'''
+num a = 0;
+int b = a;
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 19, 1),
+    ]);
   }
 
-  test_argumentResolution_required_tooFew() async {
-    await resolveTestCode(r'''
-class A {
-  void f() {
-    g(1, 2);
-  }
-  void g(a, b, c) {}
-}''');
-    await _validateArgumentResolution([0, 1]);
+  test_analysisOptions_file_inPackage() async {
+    newFile('/workspace/dart/test/analysis_options.yaml', content: r'''
+analyzer:
+  strong-mode:
+    implicit-casts: false
+''');
+
+    await assertErrorsInCode(r'''
+num a = 0;
+int b = a;
+''', [
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 19, 1),
+    ]);
   }
 
-  test_argumentResolution_required_tooMany() async {
-    await resolveTestCode(r'''
-class A {
-  void f() {
-    g(1, 2, 3);
-  }
-  void g(a, b) {}
-}''');
-    await _validateArgumentResolution([0, 1, -1]);
-  }
+  test_analysisOptions_lints() async {
+    newFile('/workspace/dart/analysis_options/lib/default.yaml', content: r'''
+linter:
+  rules:
+    - omit_local_variable_types
+''');
 
-  test_argumentResolution_requiredAndNamed_extra() async {
-    await resolveTestCode('''
-class A {
-  void f() {
-    g(1, 2, c: 3, d: 4);
-  }
-  void g(a, b, {c}) {}
-}''');
-    await _validateArgumentResolution([0, 1, 2, -1]);
-  }
+    var rule = Registry.ruleRegistry.getRule('omit_local_variable_types');
 
-  test_argumentResolution_requiredAndNamed_matching() async {
-    await resolveTestCode(r'''
-class A {
-  void f() {
-    g(1, 2, c: 3);
-  }
-  void g(a, b, {c}) {}
-}''');
-    await _validateArgumentResolution([0, 1, 2]);
-  }
-
-  test_argumentResolution_requiredAndNamed_missing() async {
-    await resolveTestCode('''
-class A {
-  void f() {
-    g(1, 2, d: 3);
-  }
-  void g(a, b, {c, d}) {}
-}''');
-    await _validateArgumentResolution([0, 1, 3]);
-  }
-
-  test_argumentResolution_requiredAndPositional_fewer() async {
-    await resolveTestCode('''
-class A {
-  void f() {
-    g(1, 2, 3);
-  }
-  void g(a, b, [c, d]) {}
-}''');
-    await _validateArgumentResolution([0, 1, 2]);
-  }
-
-  test_argumentResolution_requiredAndPositional_matching() async {
-    await resolveTestCode(r'''
-class A {
-  void f() {
-    g(1, 2, 3, 4);
-  }
-  void g(a, b, [c, d]) {}
-}''');
-    await _validateArgumentResolution([0, 1, 2, 3]);
-  }
-
-  test_argumentResolution_requiredAndPositional_more() async {
-    await resolveTestCode(r'''
-class A {
-  void f() {
-    g(1, 2, 3, 4);
-  }
-  void g(a, b, [c]) {}
-}''');
-    await _validateArgumentResolution([0, 1, 2, -1]);
-  }
-
-  test_argumentResolution_setter_propagated() async {
-    await resolveTestCode(r'''
+    await assertErrorsInCode(r'''
 main() {
-  var a = new A();
-  a.sss = 0;
+  int a = 0;
+  a;
 }
-class A {
-  set sss(x) {}
-}''');
-    var rhs = findNode.assignment(' = 0;').rightHandSide;
-    expect(
-      rhs.staticParameterElement,
-      findElement.parameter('x'),
-    );
+''', [
+      error(rule.lintCode, 11, 9),
+    ]);
   }
 
-  test_argumentResolution_setter_propagated_propertyAccess() async {
-    await resolveTestCode(r'''
-main() {
-  var a = new A();
-  a.b.sss = 0;
-}
-class A {
-  B b = new B();
-}
-class B {
-  set sss(x) {}
-}''');
-    var rhs = findNode.assignment(' = 0;').rightHandSide;
-    expect(
-      rhs.staticParameterElement,
-      findElement.parameter('x'),
-    );
-  }
-
-  test_argumentResolution_setter_static() async {
-    await resolveTestCode(r'''
-main() {
-  A a = new A();
-  a.sss = 0;
-}
-class A {
-  set sss(x) {}
-}''');
-    var rhs = findNode.assignment(' = 0;').rightHandSide;
-    expect(
-      rhs.staticParameterElement,
-      findElement.parameter('x'),
-    );
-  }
-
-  test_argumentResolution_setter_static_propertyAccess() async {
-    await resolveTestCode(r'''
-main() {
-  A a = new A();
-  a.b.sss = 0;
-}
-class A {
-  B b = new B();
-}
-class B {
-  set sss(x) {}
-}''');
-    var rhs = findNode.assignment(' = 0;').rightHandSide;
-    expect(
-      rhs.staticParameterElement,
-      findElement.parameter('x'),
-    );
-  }
-
-  test_breakTarget_labeled() async {
-    // Verify that the target of the label is correctly found and is recorded
-    // as the unlabeled portion of the statement.
-    await resolveTestCode(r'''
-void f() {
-  loop1: while (true) {
-    loop2: for (int i = 0; i < 10; i++) {
-      break loop1;
-      break loop2;
-    }
-  }
-}
-''');
-    var break1 = findNode.breakStatement('break loop1;');
-    var whileStatement = findNode.whileStatement('while (');
-    expect(break1.target, same(whileStatement));
-
-    var break2 = findNode.breakStatement('break loop2;');
-    var forStatement = findNode.forStatement('for (');
-    expect(break2.target, same(forStatement));
-  }
-
-  test_breakTarget_unlabeledBreakFromDo() async {
-    await resolveTestCode('''
-void f() {
-  do {
-    break;
-  } while (true);
-}
-''');
-    var doStatement = findNode.doStatement('do {');
-    var breakStatement = findNode.breakStatement('break;');
-    expect(breakStatement.target, same(doStatement));
-  }
-
-  test_breakTarget_unlabeledBreakFromFor() async {
-    await resolveTestCode(r'''
-void f() {
-  for (int i = 0; i < 10; i++) {
-    break;
-  }
-}
-''');
-    var forStatement = findNode.forStatement('for (');
-    var breakStatement = findNode.breakStatement('break;');
-    expect(breakStatement.target, same(forStatement));
-  }
-
-  test_breakTarget_unlabeledBreakFromForEach() async {
-    await resolveTestCode('''
-void f() {
-  for (x in []) {
-    break;
-  }
-}
-''');
-    var forStatement = findNode.forStatement('for (');
-    var breakStatement = findNode.breakStatement('break;');
-    expect(breakStatement.target, same(forStatement));
-  }
-
-  test_breakTarget_unlabeledBreakFromSwitch() async {
-    await resolveTestCode(r'''
-void f() {
-  while (true) {
-    switch (0) {
-      case 0:
-        break;
-    }
-  }
-}
-''');
-    var switchStatement = findNode.switchStatement('switch (');
-    var breakStatement = findNode.breakStatement('break;');
-    expect(breakStatement.target, same(switchStatement));
-  }
-
-  test_breakTarget_unlabeledBreakFromWhile() async {
-    await resolveTestCode(r'''
-void f() {
-  while (true) {
-    break;
-  }
-}
-''');
-    var whileStatement = findNode.whileStatement('while (');
-    var breakStatement = findNode.breakStatement('break;');
-    expect(breakStatement.target, same(whileStatement));
-  }
-
-  test_breakTarget_unlabeledBreakToOuterFunction() async {
-    // Verify that unlabeled break statements can't resolve to loops in an
-    // outer function.
-    await resolveTestCode(r'''
-void f() {
-  while (true) {
-    void g() {
-      break;
-    }
-  }
-}
-''');
-    var breakStatement = findNode.breakStatement('break;');
-    expect(breakStatement.target, isNull);
-  }
-
-  test_class_definesCall() async {
+  test_analysisOptions_no() async {
     await assertNoErrorsInCode(r'''
-class A {
-  int call(int x) { return x; }
-}
-int f(A a) {
-  return a(0);
-}''');
+num a = 0;
+int b = a;
+''');
   }
 
-  test_class_extends_implements() async {
+  test_basic() async {
     await assertNoErrorsInCode(r'''
-class A extends B implements C {}
-class B {}
-class C {}''');
-  }
-
-  test_continueTarget_labeled() async {
-    // Verify that the target of the label is correctly found and is recorded
-    // as the unlabeled portion of the statement.
-    await resolveTestCode('''
-void f() {
-  loop1: while (true) {
-    loop2: for (int i = 0; i < 10; i++) {
-      continue loop1;
-      continue loop2;
-    }
-  }
-}
+int a = 0;
+var b = 1 + 2;
 ''');
-    var continue1 = findNode.continueStatement('continue loop1');
-    var whileStatement = findNode.whileStatement('while (');
-    expect(continue1.target, same(whileStatement));
+    assertType(findElement.topVar('a').type, 'int');
+    assertElement(findNode.simple('int a'), intElement);
 
-    var continue2 = findNode.continueStatement('continue loop2');
-    var forStatement = findNode.forStatement('for (');
-    expect(continue2.target, same(forStatement));
+    assertType(findElement.topVar('b').type, 'int');
   }
 
-  test_continueTarget_unlabeledContinueFromDo() async {
-    await resolveTestCode('''
-void f() {
-  do {
-    continue;
-  } while (true);
-}
-''');
-    var doStatement = findNode.doStatement('do {');
-    var continueStatement = findNode.continueStatement('continue;');
-    expect(continueStatement.target, same(doStatement));
-  }
-
-  test_continueTarget_unlabeledContinueFromFor() async {
-    await resolveTestCode('''
-void f() {
-  for (int i = 0; i < 10; i++) {
-    continue;
-  }
-}
-''');
-    var forStatement = findNode.forStatement('for (');
-    var continueStatement = findNode.continueStatement('continue;');
-    expect(continueStatement.target, same(forStatement));
-  }
-
-  test_continueTarget_unlabeledContinueFromForEach() async {
-    await resolveTestCode(r'''
-void f() {
-  for (x in []) {
-    continue;
-  }
-}
-''');
-    var forStatement = findNode.forStatement('for (');
-    var continueStatement = findNode.continueStatement('continue;');
-    expect(continueStatement.target, same(forStatement));
-  }
-
-  test_continueTarget_unlabeledContinueFromWhile() async {
-    await resolveTestCode(r'''
-void f() {
-  while (true) {
-    continue;
-  }
-}
-''');
-    var whileStatement = findNode.whileStatement('while (');
-    var continueStatement = findNode.continueStatement('continue;');
-    expect(continueStatement.target, same(whileStatement));
-  }
-
-  test_continueTarget_unlabeledContinueSkipsSwitch() async {
-    await resolveTestCode(r'''
-void f() {
-  while (true) {
-    switch (0) {
-      case 0:
-        continue;
-    }
-  }
-}
-''');
-    var whileStatement = findNode.whileStatement('while (');
-    var continueStatement = findNode.continueStatement('continue;');
-    expect(continueStatement.target, same(whileStatement));
-  }
-
-  test_continueTarget_unlabeledContinueToOuterFunction() async {
-    // Verify that unlabeled continue statements can't resolve to loops in an
-    // outer function.
-    await resolveTestCode(r'''
-void f() {
-  while (true) {
-    void g() {
-      continue;
-    }
-  }
-}
-''');
-    var continueStatement = findNode.continueStatement('continue;');
-    expect(continueStatement.target, isNull);
-  }
-
-  test_empty() async {
-    await assertNoErrorsInCode('');
-  }
-
-  test_entryPoint_exported() async {
-    newFile('/test/lib/a.dart', content: r'''
-main() {}
+  test_getErrors() {
+    addTestFile(r'''
+var a = b;
+var foo = 0;
 ''');
 
-    await assertNoErrorsInCode(r'''
-export 'a.dart';
-''');
-
-    var library = result.libraryElement;
-    var main = library.entryPoint;
-
-    expect(main, isNotNull);
-    expect(main.library, isNot(same(library)));
+    var result = getTestErrors();
+    expect(result.path, convertPath('/workspace/dart/test/lib/test.dart'));
+    expect(result.uri.toString(), 'package:dart.test/test.dart');
+    assertErrorsInList(result.errors, [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 8, 1),
+    ]);
+    expect(result.lineInfo.lineStarts, [0, 11, 24]);
   }
 
-  test_entryPoint_local() async {
-    await assertNoErrorsInCode(r'''
-main() {}
-''');
+  test_getErrors_reuse() {
+    addTestFile('var a = b;');
 
-    var library = result.libraryElement;
-    var main = library.entryPoint;
+    var path = convertPath('/workspace/dart/test/lib/test.dart');
 
-    expect(main, isNotNull);
-    expect(main.library, same(library));
+    // No resolved files yet.
+    expect(fileResolver.testView.resolvedFiles, isEmpty);
+
+    // No cached, will resolve once.
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, [path]);
+
+    // Has cached, will be not resolved again.
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, [path]);
+
+    // New resolver.
+    // Still has cached, will be not resolved.
+    createFileResolver();
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, []);
+
+    // Change the file, new resolver.
+    // With changed file the previously cached result cannot be used.
+    addTestFile('var a = c;');
+    createFileResolver();
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, [path]);
+
+    // New resolver.
+    // Still has cached, will be not resolved.
+    createFileResolver();
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, []);
   }
 
-  test_entryPoint_none() async {
-    await assertNoErrorsInCode('');
-
-    var library = result.libraryElement;
-    expect(library.entryPoint, isNull);
-  }
-
-  test_enum_externalLibrary() async {
-    newFile('/test/lib/a.dart', content: r'''
-enum EEE {A, B, C}
+  test_getErrors_reuse_changeDependency() {
+    newFile('/workspace/dart/test/lib/a.dart', content: r'''
+var a = 0;
 ''');
-    await assertNoErrorsInCode(r'''
+
+    addTestFile(r'''
 import 'a.dart';
-
-void f(EEE e) {}
+var b = a.foo;
 ''');
-    verifyTestResolved();
+
+    var path = convertPath('/workspace/dart/test/lib/test.dart');
+
+    // No resolved files yet.
+    expect(fileResolver.testView.resolvedFiles, isEmpty);
+
+    // No cached, will resolve once.
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, [path]);
+
+    // Has cached, will be not resolved again.
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, [path]);
+
+    // Change the dependency, new resolver.
+    // The signature of the result is different.
+    // The previously cached result cannot be used.
+    newFile('/workspace/dart/test/lib/a.dart', content: r'''
+var a = 4.2;
+''');
+    createFileResolver();
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, [path]);
+
+    // New resolver.
+    // Still has cached, will be not resolved.
+    createFileResolver();
+    expect(getTestErrors().errors, hasLength(1));
+    expect(fileResolver.testView.resolvedFiles, []);
   }
 
-  test_extractedMethodAsConstant() async {
-    await assertNoErrorsInCode(r'''
-abstract class Comparable<T> {
-  int compareTo(T other);
-  static int compare(Comparable a, Comparable b) => a.compareTo(b);
-}
-class A {
-  void sort([compare = Comparable.compare]) {}
-}''');
-    verifyTestResolved();
-  }
-
-  test_fieldFormalParameter() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int x;
-  int y;
-  A(this.x) : y = x {}
-}''');
-    verifyTestResolved();
-
-    var xParameter = findNode.fieldFormalParameter('this.x');
-
-    var xParameterElement =
-        xParameter.declaredElement as FieldFormalParameterElement;
-    expect(xParameterElement.field, findElement.field('x'));
-
-    assertElement(
-      findNode.simple('x {}'),
-      xParameterElement,
-    );
-  }
-
-  test_forEachLoops_nonConflicting() async {
+  test_hint() async {
     await assertErrorsInCode(r'''
-f() {
-  List list = [1,2,3];
-  for (int x in list) {}
-  for (int x in list) {}
-}
+import 'dart:math';
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 65, 1),
+      error(HintCode.UNUSED_IMPORT, 7, 11),
     ]);
-    verifyTestResolved();
   }
 
-  test_forLoops_nonConflicting() async {
-    await assertNoErrorsInCode(r'''
-f() {
-  for (int i = 0; i < 3; i++) {
-  }
-  for (int i = 0; i < 3; i++) {
-  }
-}''');
-    verifyTestResolved();
+  test_reuse_compatibleOptions() async {
+    var aPath = '/workspace/dart/aaa/lib/a.dart';
+    var aResult = await assertErrorsInFile(aPath, r'''
+num a = 0;
+int b = a;
+''', []);
+
+    var bPath = '/workspace/dart/bbb/lib/a.dart';
+    var bResult = await assertErrorsInFile(bPath, r'''
+num a = 0;
+int b = a;
+''', []);
+
+    // Both files use the same (default) analysis options.
+    // So, when we resolve 'bbb', we can reuse the context after 'aaa'.
+    expect(
+      aResult.libraryElement.context,
+      same(bResult.libraryElement.context),
+    );
   }
 
-  test_functionTypeAlias() async {
-    await assertNoErrorsInCode(r'''
-typedef bool P(e);
-class A {
-  P p;
-  m(e) {
-    if (p(e)) {}
-  }
-}''');
-    verifyTestResolved();
-  }
-
-  test_getter_and_setter_fromMixins_bare_identifier() async {
-    await assertNoErrorsInCode('''
-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 f() {
-    x += 1;
-  }
-}
+  test_reuse_incompatibleOptions_implicitCasts() async {
+    newFile('/workspace/dart/aaa/analysis_options.yaml', content: r'''
+analyzer:
+  strong-mode:
+    implicit-casts: false
 ''');
-    verifyTestResolved();
 
-    // Verify that both the getter and setter for "x" in C.f() 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_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;
-}
+    newFile('/workspace/dart/bbb/analysis_options.yaml', content: r'''
+analyzer:
+  strong-mode:
+    implicit-casts: true
 ''');
-    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 {}
-class M1 {
-  get x => null;
-}
-class M2 {
-  get x => null;
-}
-class C extends B with M1, M2 {
-  f() {
-    return x;
-  }
-}
-''');
-    verifyTestResolved();
-
-    // Verify that the getter for "x" in C.f() refers to the getter defined in
-    // M2.
-    expect(
-      findNode.simple('x;').staticElement,
-      findElement.getter('x', of: 'M2'),
-    );
-  }
-
-  test_getter_fromMixins_property_access() async {
-    await assertErrorsInCode('''
-class B {}
-class M1 {
-  get x => null;
-}
-class M2 {
-  get x => null;
-}
-class C extends B with M1, M2 {}
-void main() {
-  var y = new C().x;
-}
+    // Implicit casts are disabled in 'aaa'.
+    var aPath = '/workspace/dart/aaa/lib/a.dart';
+    var aResult = await assertErrorsInFile(aPath, r'''
+num a = 0;
+int b = a;
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 124, 1),
+      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 19, 1),
     ]);
-    verifyTestResolved();
 
-    // Verify that the getter for "x" in "new C().x" refers to the getter
-    // defined in M2.
+    // Implicit casts are enabled in 'bbb'.
+    var bPath = '/workspace/dart/bbb/lib/a.dart';
+    var bResult = await assertErrorsInFile(bPath, r'''
+num a = 0;
+int b = a;
+''', []);
+
+    // Packages 'aaa' and 'bbb' have different options affecting type system.
+    // So, we cannot share the same context.
     expect(
-      findNode.simple('x;').staticElement,
-      findElement.getter('x', of: 'M2'),
+      aResult.libraryElement.context,
+      isNot(same(bResult.libraryElement.context)),
     );
   }
-
-  test_hasReferenceToSuper() async {
-    await assertNoErrorsInCode(r'''
-class A {}
-class B {toString() => super.toString();}''');
-    verifyTestResolved();
-
-    var a = findElement.class_('A');
-    expect(a.hasReferenceToSuper, isFalse);
-
-    var b = findElement.class_('B');
-    expect(b.hasReferenceToSuper, isTrue);
-  }
-
-  test_import_hide() async {
-    newFile('/test/lib/lib1.dart', content: r'''
-set foo(value) {}
-class A {}''');
-
-    newFile('/test/lib/lib2.dart', content: r'''
-set foo(value) {}''');
-
-    await assertNoErrorsInCode(r'''
-import 'lib1.dart' hide foo;
-import 'lib2.dart';
-
-main() {
-  foo = 0;
-}
-A a;''');
-    verifyTestResolved();
-  }
-
-  test_import_prefix() async {
-    newFile('/test/lib/a.dart', content: r'''
-f(int x) {
-  return x * x;
-}''');
-
-    await assertNoErrorsInCode(r'''
-import 'a.dart' as _a;
-main() {
-  _a.f(0);
-}''');
-    verifyTestResolved();
-  }
-
-  test_import_prefix_doesNotExist() async {
-    //
-    // The primary purpose of this test is to ensure that we are only getting a
-    // single error generated when the only problem is that an imported file
-    // does not exist.
-    //
-    await assertErrorsInCode('''
-import 'missing.dart' as p;
-int a = p.q + p.r.s;
-String b = p.t(a) + p.u(v: 0);
-p.T c = new p.T();
-class D<E> extends p.T {
-  D(int i) : super(i);
-  p.U f = new p.V();
-}
-class F implements p.T {
-  p.T m(p.U u) => null;
-}
-class G extends Object with p.V {}
-class H extends D<p.W> {
-  H(int i) : super(i);
-}
-''', [
-      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 14),
-    ]);
-    verifyTestResolved();
-  }
-
-  test_import_show_doesNotExist() async {
-    //
-    // The primary purpose of this test is to ensure that we are only getting a
-    // single error generated when the only problem is that an imported file
-    // does not exist.
-    //
-    await assertErrorsInCode('''
-import 'missing.dart' show q, r, t, u, T, U, V, W;
-int a = q + r.s;
-String b = t(a) + u(v: 0);
-T c = new T();
-class D<E> extends T {
-  D(int i) : super(i);
-  U f = new V();
-}
-class F implements T {
-  T m(U u) => null;
-}
-class G extends Object with V {}
-class H extends D<W> {
-  H(int i) : super(i);
-}
-''', [
-      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 14),
-    ]);
-  }
-
-  @failingTest
-  test_import_spaceInUri() async {
-    // TODO(scheglov) Fix this. The problem is in `package` URI resolver.
-    newFile('/test/lib/sub folder/a.dart', content: r'''
-foo() {}''');
-
-    await assertNoErrorsInCode(r'''
-import 'sub folder/a.dart';
-
-main() {
-  foo();
-}''');
-    verifyTestResolved();
-  }
-
-  test_indexExpression_typeParameters() async {
-    await assertNoErrorsInCode(r'''
-f() {
-  List<int> a;
-  a[0];
-  List<List<int>> b;
-  b[0][0];
-  List<List<List<int>>> c;
-  c[0][0][0];
-}''');
-    verifyTestResolved();
-  }
-
-  test_indexExpression_typeParameters_invalidAssignmentWarning() async {
-    await assertErrorsInCode(r'''
-f() {
-  List<List<int>> b;
-  b[0][0] = 'hi';
-}''', [
-      error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 39, 4),
-    ]);
-    verifyTestResolved();
-  }
-
-  test_indirectOperatorThroughCall() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  B call() { return new B(); }
-}
-
-class B {
-  int operator [](int i) { return i; }
-}
-
-A f = new A();
-
-g(int x) {}
-
-main() {
-  g(f()[0]);
-}''');
-    verifyTestResolved();
-  }
-
-  test_invoke_dynamicThroughGetter() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  List get X => [() => 0];
-  m(A a) {
-    X.last;
-  }
-}''');
-    verifyTestResolved();
-  }
-
-  test_isValidMixin_badSuperclass() async {
-    await assertErrorsInCode(r'''
-class A extends B {}
-class B {}
-class C = Object with A;''', [
-      error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 54, 1),
-    ]);
-    verifyTestResolved();
-
-    var a = findElement.class_('A');
-    expect(a.isValidMixin, isFalse);
-  }
-
-  test_isValidMixin_constructor() async {
-    await assertErrorsInCode(r'''
-class A {
-  A() {}
-}
-class C = Object with A;''', [
-      error(CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR, 43, 1),
-    ]);
-    verifyTestResolved();
-
-    var a = findElement.class_('A');
-    expect(a.isValidMixin, isFalse);
-  }
-
-  test_isValidMixin_factoryConstructor() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  factory A() => throw 0;
-}
-class C = Object with A;''');
-    verifyTestResolved();
-
-    var a = findElement.class_('A');
-    expect(a.isValidMixin, isTrue);
-  }
-
-  test_isValidMixin_super() async {
-    await assertErrorsInCode(r'''
-class A {
-  toString() {
-    return super.toString();
-  }
-}
-class C = Object with A;''', [
-      error(CompileTimeErrorCode.MIXIN_REFERENCES_SUPER, 82, 1),
-    ]);
-    verifyTestResolved();
-
-    var a = findElement.class_('A');
-    expect(a.isValidMixin, isFalse);
-  }
-
-  test_isValidMixin_valid() async {
-    await assertNoErrorsInCode('''
-class A {}
-class C = Object with A;''');
-    verifyTestResolved();
-
-    var a = findElement.class_('A');
-    expect(a.isValidMixin, isTrue);
-  }
-
-  test_labels_switch() async {
-    await assertNoErrorsInCode(r'''
-void doSwitch(int target) {
-  switch (target) {
-    l0: case 0:
-      continue l1;
-    l1: case 1:
-      continue l0;
-    default:
-      continue l1;
-  }
-}''');
-    verifyTestResolved();
-  }
-
-  test_localVariable_types_invoked() async {
-    await resolveTestCode(r'''
-const A = null;
-main() {
-  var myVar = (int p) => 'foo';
-  myVar(42);
-}''');
-    var node = findNode.simple('myVar(42)');
-    assertType(node, 'String Function(int)');
-  }
-
-  test_metadata_class() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-@A class C<A> {}''');
-    verifyTestResolved();
-
-    var annotations = findElement.class_('C').metadata;
-    expect(annotations, hasLength(1));
-
-    var cDeclaration = findNode.classDeclaration('C<A>');
-    assertElement(
-      cDeclaration.metadata[0].name,
-      findElement.topGet('A'),
-    );
-  }
-
-  test_metadata_field() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-class C {
-  @A int f;
-}''');
-    verifyTestResolved();
-
-    var metadata = findElement.field('f').metadata;
-    expect(metadata, hasLength(1));
-  }
-
-  test_metadata_fieldFormalParameter() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-class C {
-  int f;
-  C(@A this.f);
-}''');
-    verifyTestResolved();
-
-    var metadata = findElement.fieldFormalParameter('f').metadata;
-    expect(metadata, hasLength(1));
-  }
-
-  test_metadata_function() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-@A f() {}''');
-    verifyTestResolved();
-
-    var annotations = findElement.topFunction('f').metadata;
-    expect(annotations, hasLength(1));
-  }
-
-  test_metadata_functionTypedParameter() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-f(@A int p(int x)) {}''');
-    verifyTestResolved();
-
-    var metadata = findElement.parameter('p').metadata;
-    expect(metadata, hasLength(1));
-  }
-
-  test_metadata_libraryDirective() async {
-    await assertNoErrorsInCode(r'''
-@A library lib;
-const A = null;''');
-    verifyTestResolved();
-
-    var metadata = result.libraryElement.metadata;
-    expect(metadata, hasLength(1));
-  }
-
-  test_metadata_method() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-class C {
-  @A void m() {}
-}''');
-    verifyTestResolved();
-
-    var metadata = findElement.method('m').metadata;
-    expect(metadata, hasLength(1));
-  }
-
-  test_metadata_namedParameter() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-f({@A int p : 0}) {}''');
-    verifyTestResolved();
-
-    var metadata = findElement.parameter('p').metadata;
-    expect(metadata, hasLength(1));
-  }
-
-  test_metadata_positionalParameter() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-f([@A int p = 0]) {}''');
-    verifyTestResolved();
-
-    var metadata = findElement.parameter('p').metadata;
-    expect(metadata, hasLength(1));
-  }
-
-  test_metadata_simpleParameter() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-f(@A p1, @A int p2) {}''');
-    verifyTestResolved();
-
-    expect(findElement.parameter('p1').metadata, hasLength(1));
-    expect(findElement.parameter('p2').metadata, hasLength(1));
-  }
-
-  test_metadata_typedef() async {
-    await assertNoErrorsInCode(r'''
-const A = null;
-@A typedef F<A>();''');
-    verifyTestResolved();
-
-    expect(
-      findElement.functionTypeAlias('F').metadata,
-      hasLength(1),
-    );
-
-    var actualElement = findNode.annotation('@A').name.staticElement;
-    expect(actualElement, findElement.topGet('A'));
-  }
-
-  test_method_fromMixin() async {
-    await assertNoErrorsInCode(r'''
-class B {
-  bar() => 1;
-}
-class A {
-  foo() => 2;
-}
-
-class C extends B with A {
-  bar() => super.bar();
-  foo() => super.foo();
-}''');
-    verifyTestResolved();
-  }
-
-  test_method_fromMixins() async {
-    await assertNoErrorsInCode('''
-class B {}
-class M1 {
-  void f() {}
-}
-class M2 {
-  void f() {}
-}
-class C extends B with M1, M2 {}
-void main() {
-  new C().f();
-}
-''');
-    verifyTestResolved();
-
-    expect(
-      findNode.simple('f();').staticElement,
-      findElement.method('f', of: 'M2'),
-    );
-  }
-
-  test_method_fromMixins_bare_identifier() async {
-    await assertNoErrorsInCode('''
-class B {}
-class M1 {
-  void f() {}
-}
-class M2 {
-  void f() {}
-}
-class C extends B with M1, M2 {
-  void g() {
-    f();
-  }
-}
-''');
-    verifyTestResolved();
-
-    expect(
-      findNode.simple('f();').staticElement,
-      findElement.method('f', of: 'M2'),
-    );
-  }
-
-  test_method_fromMixins_invoked_from_outside_class() async {
-    await assertNoErrorsInCode('''
-class B {}
-class M1 {
-  void f() {}
-}
-class M2 {
-  void f() {}
-}
-class C extends B with M1, M2 {}
-void main() {
-  new C().f();
-}
-''');
-    verifyTestResolved();
-
-    expect(
-      findNode.simple('f();').staticElement,
-      findElement.method('f', of: 'M2'),
-    );
-  }
-
-  test_method_fromSuperclassMixin() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  void m1() {}
-}
-class B extends Object with A {
-}
-class C extends B {
-}
-f(C c) {
-  c.m1();
-}''');
-    verifyTestResolved();
-  }
-
-  test_methodCascades() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  void m1() {}
-  void m2() {}
-  void m() {
-    A a = new A();
-    a..m1()
-     ..m2();
-  }
-}''');
-    verifyTestResolved();
-  }
-
-  test_methodCascades_withSetter() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  String name;
-  void m1() {}
-  void m2() {}
-  void m() {
-    A a = new A();
-    a..m1()
-     ..name = 'name'
-     ..m2();
-  }
-}''');
-    verifyTestResolved();
-  }
-
-  test_resolveAgainstNull() async {
-    await assertNoErrorsInCode(r'''
-f(var p) {
-  return null == p;
-}''');
-    verifyTestResolved();
-  }
-
-  test_setter_fromMixins_bare_identifier() async {
-    await resolveTestCode('''
-class B {}assertNoErrorsInCode
-class M1 {
-  set x(value) {}
-}
-class M2 {
-  set x(value) {}
-}
-class C extends B with M1, M2 {
-  void f() {
-    x = 1;
-  }
-}
-''');
-    verifyTestResolved();
-
-    expect(
-      findNode.simple('x = ').staticElement,
-      findElement.setter('x', of: 'M2'),
-    );
-  }
-
-  test_setter_fromMixins_property_access() async {
-    await assertNoErrorsInCode('''
-class B {}
-class M1 {
-  set x(value) {}
-}
-class M2 {
-  set x(value) {}
-}
-class C extends B with M1, M2 {}
-void main() {
-  new C().x = 1;
-}
-''');
-    verifyTestResolved();
-
-    expect(
-      findNode.simple('x = ').staticElement,
-      findElement.setter('x', of: 'M2'),
-    );
-  }
-
-  test_setter_inherited() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int get x => 0;
-  set x(int p) {}
-}
-class B extends A {
-  int get x => super.x == null ? 0 : super.x;
-  int f() => x = 1;
-}''');
-    verifyTestResolved();
-  }
-
-  test_setter_static() async {
-    await assertNoErrorsInCode(r'''
-set s(x) {
-}
-
-main() {
-  s = 123;
-}''');
-    verifyTestResolved();
-  }
-
-  /**
-   * Verify that all of the identifiers in the [result] have been resolved.
-   */
-  void verifyTestResolved() {
-    var verifier = ResolutionVerifier();
-    result.unit.accept(verifier);
-    verifier.assertResolved();
-  }
-
-  /**
-   * Resolve the test file and verify that the arguments in a specific method
-   * invocation were correctly resolved.
-   *
-   * The file is expected to define a method named `g`, and has exactly one
-   * [MethodInvocation] in a statement ending with `);`. It is the arguments to
-   * that method invocation that are tested. The method invocation can contain
-   * errors.
-   *
-   * The arguments were resolved correctly if the number of expressions in the list matches the
-   * length of the array of indices and if, for each index in the array of indices, the parameter to
-   * which the argument expression was resolved is the parameter in the invoked method's list of
-   * parameters at that index. Arguments that should not be resolved to a parameter because of an
-   * error can be denoted by including a negative index in the array of indices.
-   *
-   * @param indices the array of indices used to associate arguments with parameters
-   * @throws Exception if the source could not be resolved or if the structure of the source is not
-   *           valid
-   */
-  Future<void> _validateArgumentResolution(List<int> indices) async {
-    var g = findElement.method('g');
-    var parameters = g.parameters;
-
-    var invocation = findNode.methodInvocation(');');
-
-    var arguments = invocation.argumentList.arguments;
-
-    var argumentCount = arguments.length;
-    expect(argumentCount, indices.length);
-
-    for (var i = 0; i < argumentCount; i++) {
-      var argument = arguments[i];
-      var actualParameter = argument.staticParameterElement;
-
-      var index = indices[i];
-      if (index < 0) {
-        expect(actualParameter, isNull);
-      } else {
-        var expectedParameter = parameters[index];
-        expect(actualParameter, same(expectedParameter));
-      }
-    }
-  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart
index a74c799..4ff5920 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -456,16 +456,6 @@
     ]);
   }
 
-  test_error_memberWithClassName_getter() async {
-    await assertErrorsInCode(r'''
-class C {
-  int get C => null;
-}
-''', [
-      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 20, 1),
-    ]);
-  }
-
   test_error_memberWithClassName_field() async {
     await assertErrorsInCode(r'''
 class C {
@@ -476,6 +466,16 @@
     ]);
   }
 
+  test_error_memberWithClassName_getter() async {
+    await assertErrorsInCode(r'''
+class C {
+  int get C => null;
+}
+''', [
+      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 20, 1),
+    ]);
+  }
+
   test_error_memberWithClassName_getter_static() async {
     await assertErrorsInCode(r'''
 class C {
@@ -587,6 +587,46 @@
     ]);
   }
 
+  test_inconsistentInheritanceGetterAndMethod_mixinApp() async {
+    await assertErrorsInCode('''
+class S {
+  bool get m => false;
+}
+
+class M {
+  int m() => 1;
+}
+
+class C = S with M;
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD, 71,
+          1),
+    ]);
+  }
+
+  test_inconsistentInheritanceGetterAndMethod_mixinApp2() async {
+    await assertErrorsInCode('''
+class S {
+  bool get m => false;
+}
+
+class M1 {
+  int m() => 1;
+}
+
+class M2 {
+  bool get m => false;
+}
+
+class C = S with M1, M2;
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
+          109, 1),
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD,
+          109, 1),
+    ]);
+  }
+
   test_issue32815() async {
     await assertErrorsInCode(r'''
 class A<T> extends B<T> {}
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index f764905..cfc3b74 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -4,8 +4,11 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/test_utilities/find_element.dart';
+import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -223,7 +226,8 @@
   test_optIn_fromOptOut_class_constructor() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
-  const A.named(int a);
+  final int a;
+  const A.named(this.a);
 }
 ''');
 
@@ -231,7 +235,7 @@
 // @dart = 2.7
 import 'a.dart';
 
-@A.named(0)
+@A.named(42)
 void f() {}
 ''');
 
@@ -245,12 +249,52 @@
       declaration: import_a.constructor('named', of: 'A'),
       isLegacy: true,
     );
+
+    _assertConstantValue(
+      findElement.function('f').metadata[0].computeConstantValue(),
+      type: 'A*',
+      fieldMap: {'a': 42},
+    );
+  }
+
+  test_optIn_fromOptOut_class_constructor_withDefault() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  final int a;
+  const A.named({this.a = 42});
+}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart = 2.7
+import 'a.dart';
+
+@A.named()
+void f() {}
+''');
+
+    assertElement2(
+      findNode.simple('A.named('),
+      declaration: import_a.class_('A'),
+    );
+
+    assertElement2(
+      findNode.annotation('@A'),
+      declaration: import_a.constructor('named', of: 'A'),
+      isLegacy: true,
+    );
+
+    _assertConstantValue(
+      findElement.function('f').metadata[0].computeConstantValue(),
+      type: 'A*',
+      fieldMap: {'a': 42},
+    );
   }
 
   test_optIn_fromOptOut_class_getter() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
-  const foo = 0;
+  const foo = 42;
 }
 ''');
 
@@ -272,11 +316,13 @@
       declaration: import_a.getter('foo'),
       isLegacy: true,
     );
+
+    _assertIntValue(findElement.function('f').metadata[0], 42);
   }
 
   test_optIn_fromOptOut_getter() async {
     newFile('/test/lib/a.dart', content: r'''
-const foo = 0;
+const foo = 42;
 ''');
 
     await assertNoErrorsInCode(r'''
@@ -292,6 +338,8 @@
       declaration: import_a.topGet('foo'),
       isLegacy: true,
     );
+
+    _assertIntValue(findElement.function('f').metadata[0], 42);
   }
 
   test_optIn_fromOptOut_prefix_class() async {
@@ -394,4 +442,36 @@
       isLegacy: true,
     );
   }
+
+  void _assertConstantValue(
+    DartObject object, {
+    @required String type,
+    Map<String, Object> fieldMap,
+    int intValue,
+  }) {
+    assertType(object.type, type);
+    if (fieldMap != null) {
+      for (var entry in fieldMap.entries) {
+        var actual = object.getField(entry.key);
+        var expected = entry.value;
+        if (expected is int) {
+          expect(actual.toIntValue(), expected);
+        } else {
+          fail('Unsupported expected type: ${expected.runtimeType} $expected');
+        }
+      }
+    } else if (intValue != null) {
+      expect(object.toIntValue(), intValue);
+    } else {
+      fail('No expectations.');
+    }
+  }
+
+  void _assertIntValue(ElementAnnotation annotation, int intValue) {
+    _assertConstantValue(
+      annotation.computeConstantValue(),
+      type: 'int*',
+      intValue: intValue,
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
index a47b170..8998675 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
@@ -18,6 +18,22 @@
 
 @reflectiveTest
 class PrefixedIdentifierResolutionTest extends DriverResolutionTest {
+  test_dynamic_explicitCore_withPrefix() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:core' as mycore;
+
+main() {
+  mycore.dynamic;
+}
+''');
+
+    assertPrefixedIdentifier(
+      findNode.prefixed('mycore.dynamic'),
+      element: dynamicElement,
+      type: 'Type',
+    );
+  }
+
   test_implicitCall_tearOff() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index d851422..b052e2e 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -243,7 +243,7 @@
     assertErrorsInResolvedUnit(result, expectedErrors);
   }
 
-  Future<void> assertErrorsInFile(
+  Future<ResolvedUnitResult> assertErrorsInFile(
     String path,
     String content,
     List<ExpectedError> expectedErrors,
@@ -253,15 +253,24 @@
 
     var result = await resolveFile(path);
     assertErrorsInResolvedUnit(result, expectedErrors);
+
+    return result;
+  }
+
+  void assertErrorsInList(
+    List<AnalysisError> errors,
+    List<ExpectedError> expectedErrors,
+  ) {
+    GatheringErrorListener errorListener = GatheringErrorListener();
+    errorListener.addAll(errors);
+    errorListener.assertErrors(expectedErrors);
   }
 
   void assertErrorsInResolvedUnit(
     ResolvedUnitResult result,
     List<ExpectedError> expectedErrors,
   ) {
-    GatheringErrorListener errorListener = GatheringErrorListener();
-    errorListener.addAll(result.errors);
-    errorListener.assertErrors(expectedErrors);
+    assertErrorsInList(result.errors, expectedErrors);
   }
 
   void assertFunctionExpressionInvocation(
diff --git a/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
index fab2d68..97ceec7 100644
--- a/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
@@ -18,6 +18,54 @@
 
 @reflectiveTest
 class SimpleIdentifierResolutionTest extends DriverResolutionTest {
+  test_dynamic_explicitCore() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:core';
+
+main() {
+  dynamic;
+}
+''');
+
+    assertSimpleIdentifier(
+      findNode.simple('dynamic;'),
+      element: dynamicElement,
+      type: 'Type',
+    );
+  }
+
+  test_dynamic_explicitCore_withPrefix_referenceWithout() async {
+    await assertErrorsInCode(r'''
+import 'dart:core' as mycore;
+
+main() {
+  dynamic;
+}
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 42, 7),
+    ]);
+
+    assertSimpleIdentifier(
+      findNode.simple('dynamic;'),
+      element: null,
+      type: 'dynamic',
+    );
+  }
+
+  test_dynamic_implicitCore() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  dynamic;
+}
+''');
+
+    assertSimpleIdentifier(
+      findNode.simple('dynamic;'),
+      element: dynamicElement,
+      type: 'Type',
+    );
+  }
+
   test_implicitCall_tearOff() async {
     await assertNoErrorsInCode('''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index d1251c4..2918265 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -50,6 +50,7 @@
 import 'property_access_test.dart' as property_access;
 import 'simple_identifier_test.dart' as simple_identifier;
 import 'top_type_inference_test.dart' as top_type_inference;
+import 'try_statement_test.dart' as try_statement;
 import 'type_inference/test_all.dart' as type_inference;
 import 'type_name_test.dart' as type_name;
 import 'yield_statement_test.dart' as yield_statement;
@@ -99,6 +100,7 @@
     property_access.main();
     simple_identifier.main();
     top_type_inference.main();
+    try_statement.main();
     type_name.main();
     type_inference.main();
     yield_statement.main();
diff --git a/pkg/analyzer/test/src/dart/resolution/try_statement_test.dart b/pkg/analyzer/test/src/dart/resolution/try_statement_test.dart
new file mode 100644
index 0000000..6f5c306
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/try_statement_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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TryStatementTest);
+  });
+}
+
+@reflectiveTest
+class TryStatementTest extends DriverResolutionTest {
+  test_catch_withoutType() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  try {} catch (e, st) {
+    st;
+  }
+}
+''');
+
+    var e = findElement.localVar('e');
+    expect(e.isFinal, isTrue);
+    assertTypeDynamic(e.type);
+
+    var st = findElement.localVar('st');
+    expect(st.isFinal, isTrue);
+    assertType(st.type, 'StackTrace');
+
+    var node = findNode.catchClause('catch');
+    expect(node.exceptionParameter.staticElement, e);
+    expect(node.stackTraceParameter.staticElement, st);
+  }
+
+  test_catch_withType() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  try {} on int catch (e, st) {
+    st;
+  }
+}
+''');
+
+    var e = findElement.localVar('e');
+    expect(e.isFinal, isTrue);
+    assertType(e.type, 'int');
+
+    var st = findElement.localVar('st');
+    expect(st.isFinal, isTrue);
+    assertType(st.type, 'StackTrace');
+
+    var node = findNode.catchClause('catch');
+    expect(node.exceptionParameter.staticElement, e);
+    expect(node.stackTraceParameter.staticElement, st);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
index 0ca414d..15bea04 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
@@ -54,18 +54,51 @@
     );
   }
 
-  test_returnType_blockBody_notNullable() async {
+  test_returnType_async_blockBody() async {
+    await resolveTestCode('''
+var v = () async {
+  return 0;
+};
+''');
+    _assertReturnType('() async {', 'Future<int>');
+  }
+
+  test_returnType_async_expressionBody() async {
+    await resolveTestCode('''
+var v = () async => 0;
+''');
+    _assertReturnType('() async =>', 'Future<int>');
+  }
+
+  test_returnType_asyncStar_blockBody() async {
+    await resolveTestCode('''
+var v = () async* {
+  yield 0;
+};
+''');
+    _assertReturnType('() async* {', 'Stream<int>');
+  }
+
+  test_returnType_sync_blockBody() async {
+    await resolveTestCode('''
+var v = () {
+  return 0;
+};
+''');
+    _assertReturnType('() {', 'int');
+  }
+
+  test_returnType_sync_blockBody_notNullable() async {
     await resolveTestCode('''
 var v = (bool b) {
   if (b) return 0;
   return 1.2;
 };
 ''');
-    var element = findNode.functionExpression('(bool').declaredElement;
-    assertType(element.returnType, 'num');
+    _assertReturnType('(bool b) {', 'num');
   }
 
-  test_returnType_blockBody_notNullable_switch_onEnum() async {
+  test_returnType_sync_blockBody_notNullable_switch_onEnum() async {
     var expectedErrors = expectedErrorsByNullability(
       nullable: [],
       legacy: [
@@ -86,11 +119,10 @@
   };
 }
 ''', expectedErrors);
-    var element = findNode.functionExpression('(E e)').declaredElement;
-    assertType(element.returnType, 'int');
+    _assertReturnType('(E e) {', 'int');
   }
 
-  test_returnType_blockBody_notNullable_switch_onEnum_imported() async {
+  test_returnType_sync_blockBody_notNullable_switch_onEnum_imported() async {
     newFile('/test/lib/a.dart', content: r'''
 enum E { a, b }
 ''');
@@ -115,42 +147,38 @@
   };
 }
 ''', expectedErrors);
-    var element = findNode.functionExpression('(p.E e)').declaredElement;
-    assertType(element.returnType, 'int');
+    _assertReturnType('(p.E e) {', 'int');
   }
 
-  test_returnType_blockBody_null_hasReturn() async {
+  test_returnType_sync_blockBody_null_hasReturn() async {
     await resolveTestCode('''
 var v = (bool b) {
   if (b) return;
 };
 ''');
-    var element = findNode.functionExpression('(bool').declaredElement;
-    assertType(element.returnType, 'Null');
+    _assertReturnType('(bool b) {', 'Null');
   }
 
-  test_returnType_blockBody_null_noReturn() async {
+  test_returnType_sync_blockBody_null_noReturn() async {
     await resolveTestCode('''
 var v = () {};
 ''');
-    var element = findNode.functionExpression('() {}').declaredElement;
-    assertType(element.returnType, 'Null');
+    _assertReturnType('() {}', 'Null');
   }
 
-  test_returnType_blockBody_nullable() async {
+  test_returnType_sync_blockBody_nullable() async {
     await resolveTestCode('''
 var v = (bool b) {
   if (b) return 0;
 };
 ''');
-    var element = findNode.functionExpression('(bool').declaredElement;
-    assertType(
-      element.returnType,
+    _assertReturnType(
+      '(bool b) {',
       typeStringByNullability(nullable: 'int?', legacy: 'int'),
     );
   }
 
-  test_returnType_blockBody_nullable_switch() async {
+  test_returnType_sync_blockBody_nullable_switch() async {
     var expectedErrors = expectedErrorsByNullability(
       nullable: [],
       legacy: [
@@ -167,38 +195,48 @@
   };
 }
 ''', expectedErrors);
-    var element = findNode.functionExpression('(int a)').declaredElement;
-    assertType(
-      element.returnType,
+    _assertReturnType(
+      '(int a) {',
       typeStringByNullability(nullable: 'int?', legacy: 'int'),
     );
   }
 
-  test_returnType_expressionBody_Never() async {
+  test_returnType_sync_expressionBody_Never() async {
     await resolveTestCode('''
 var v = () => throw 42;
 ''');
-    var element = findNode.functionExpression('() =>').declaredElement;
-    assertType(
-      element.returnType,
+    _assertReturnType(
+      '() =>',
       typeStringByNullability(nullable: 'Never', legacy: 'Null'),
     );
   }
 
-  test_returnType_expressionBody_notNullable() async {
+  test_returnType_sync_expressionBody_notNullable() async {
     await resolveTestCode('''
 var v = () => 42;
 ''');
-    var element = findNode.functionExpression('() =>').declaredElement;
-    assertType(element.returnType, 'int');
+    _assertReturnType('() =>', 'int');
   }
 
-  test_returnType_expressionBody_Null() async {
+  test_returnType_sync_expressionBody_Null() async {
     await resolveTestCode('''
 var v = () => null;
 ''');
-    var element = findNode.functionExpression('() =>').declaredElement;
-    assertType(element.returnType, 'Null');
+    _assertReturnType('() =>', 'Null');
+  }
+
+  test_returnType_syncStar_blockBody() async {
+    await resolveTestCode('''
+var v = () sync* {
+  yield 0;
+};
+''');
+    _assertReturnType('() sync* {', 'Iterable<int>');
+  }
+
+  void _assertReturnType(String search, String expected) {
+    var element = findNode.functionExpression(search).declaredElement;
+    assertType(element.returnType, expected);
   }
 }
 
@@ -224,7 +262,6 @@
   foo(() => null);
 }
 ''');
-    var element = findNode.functionExpression('() =>').declaredElement;
-    assertType(element.returnType, 'Null*');
+    _assertReturnType('() =>', 'Null*');
   }
 }
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 08ba80b..d287dbd 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
@@ -242,6 +242,17 @@
     assertType(findNode.listLiteral('[...'), 'List<Object>');
   }
 
+  test_noContext_noTypeArgs_spread_mixin() async {
+    await resolveTestCode(r'''
+mixin L on List<int> {}
+main() {
+  L l1;
+  var l2 = [...l1];
+}
+''');
+    assertType(findNode.listLiteral('[...'), 'List<int>');
+  }
+
   test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
     await resolveTestCode('''
 List<int> c;
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 023d13e..6f441c5 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
@@ -254,6 +254,17 @@
     assertType(setOrMapLiteral('{...'), 'Map<Object, Object>');
   }
 
+  test_noContext_noTypeArgs_spread_mixin() async {
+    await resolveTestCode(r'''
+mixin M on Map<String, int> {}
+main() {
+  M m1;
+  var m2 = {...m1};
+}
+''');
+    assertType(setOrMapLiteral('{...'), 'Map<String, int>');
+  }
+
   test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
     await resolveTestCode('''
 Map<String, int> c;
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
index dc673a4..0711c83 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
@@ -216,6 +216,17 @@
     assertType(setLiteral('{...'), 'Set<Object>');
   }
 
+  test_noContext_noTypeArgs_spread_mixin() async {
+    await resolveTestCode(r'''
+mixin S on Set<int> {}
+main() {
+  S s1;
+  var s2 = {...s1};
+}
+''');
+    assertType(setLiteral('{...'), 'Set<int>');
+  }
+
   test_noContext_noTypeArgs_spread_nestedInIf_oneAmbiguous() async {
     await resolveTestCode('''
 List<int> c;
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 6c54c0b..ed3d0fb 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
@@ -78,6 +78,63 @@
     );
   }
 
+  test_dynamic_explicitCore() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:core';
+
+dynamic a;
+''');
+
+    assertTypeName(
+      findNode.typeName('dynamic a;'),
+      dynamicElement,
+      'dynamic',
+    );
+  }
+
+  test_dynamic_explicitCore_withPrefix() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:core' as mycore;
+
+mycore.dynamic a;
+''');
+
+    assertTypeName(
+      findNode.typeName('mycore.dynamic a;'),
+      dynamicElement,
+      'dynamic',
+      expectedPrefix: findElement.import('dart:core').prefix,
+    );
+  }
+
+  test_dynamic_explicitCore_withPrefix_referenceWithout() async {
+    await assertErrorsInCode(r'''
+import 'dart:core' as mycore;
+
+dynamic a;
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_CLASS, 31, 7),
+    ]);
+
+    assertTypeName(
+      findNode.typeName('dynamic a;'),
+      null,
+      'dynamic',
+    );
+  }
+
+  test_dynamic_implicitCore() async {
+    await assertNoErrorsInCode(r'''
+dynamic a;
+''');
+
+    assertTypeName(
+      findNode.typeName('dynamic a;'),
+      dynamicElement,
+      'dynamic',
+    );
+  }
+
   test_functionTypeAlias() async {
     await assertNoErrorsInCode(r'''
 typedef F = int Function();
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart
index f392af5..c12c914 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart
@@ -86,6 +86,15 @@
     ..contextFeatures = FeatureSet.forTesting(
         sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
 
+  test_class_extends_implements_never() async {
+    await assertNoErrorsInCode('''
+class I<T> {}
+class A implements I<Never> {}
+class B implements I<Never> {}
+class C extends A implements B {}
+''');
+  }
+
   test_class_extends_implements_nullability() async {
     await assertErrorsInCode('''
 class I<T> {}
@@ -125,6 +134,30 @@
 ''');
   }
 
+  test_class_mixed_viaLegacy() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A<T> {}
+
+class Bi implements A<int> {}
+
+class Biq implements A<int?> {}
+''');
+
+    // Both `Bi` and `Biq` implement `A<int*>` in legacy, so identical.
+    newFile('/test/lib/b.dart', content: r'''
+// @dart = 2.7
+import 'a.dart';
+
+class C extends Bi implements Biq {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'b.dart';
+
+abstract class D implements C {}
+''');
+  }
+
   test_class_topMerge() async {
     await assertNoErrorsInCode('''
 import 'dart:async';
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
index d7ac1a6..bde5cd0 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
@@ -434,12 +434,22 @@
   test_index() async {
     await assertErrorsInCode(r'''
 enum E {
-  a, index
+  a, index, b
 }
 ''', [
       error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 14, 5),
     ]);
   }
+
+  test_toString() async {
+    await assertErrorsInCode(r'''
+enum E {
+  a, toString, b
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 14, 8),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/enum_constant_same_name_as_enclosing.dart b/pkg/analyzer/test/src/diagnostics/enum_constant_same_name_as_enclosing.dart
new file mode 100644
index 0000000..e0b57f8
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/enum_constant_same_name_as_enclosing.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.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(EnumConstantSameNameAsEnclosingTest);
+  });
+}
+
+@reflectiveTest
+class EnumConstantSameNameAsEnclosingTest extends DriverResolutionTest {
+  test_name() async {
+    await assertErrorsInCode(r'''
+enum E {
+  E
+}
+''', [
+      error(CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING, 11, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/export_legacy_symbol_test.dart b/pkg/analyzer/test/src/diagnostics/export_legacy_symbol_test.dart
index a95fada..364015d 100644
--- a/pkg/analyzer/test/src/diagnostics/export_legacy_symbol_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/export_legacy_symbol_test.dart
@@ -25,6 +25,18 @@
   @override
   bool get typeToStringWithNullability => true;
 
+  test_exportDartAsync() async {
+    await assertNoErrorsInCode(r'''
+export 'dart:async';
+''');
+  }
+
+  test_exportDartCore() async {
+    await assertNoErrorsInCode(r'''
+export 'dart:core';
+''');
+  }
+
   test_exportOptedIn() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {}
diff --git a/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart b/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart
index bc9db02..5a1293a 100644
--- a/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart
@@ -24,7 +24,6 @@
     ]);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38188')
   test_function_nonFuture_withReturn() async {
     await assertErrorsInCode('''
 int f() async {
diff --git a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
index 8bc17df..0236a09 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
@@ -23,7 +23,62 @@
     ..contextFeatures = FeatureSet.forTesting(
         sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
 
-  test_constructor_nonNullable_named_optional_noDefault() async {
+  test_constructor_externalFactory_nonNullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+class C {
+  external factory C({int a});
+}
+''');
+  }
+
+  test_constructor_externalFactory_nonNullable_positional_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+class C {
+  external factory C([int a]);
+}
+''');
+  }
+
+  test_constructor_externalFactory_nullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+class C {
+  external factory C({int? a});
+}
+''');
+  }
+
+  test_constructor_factory_nonNullable_named_optional_noDefault() async {
+    await assertErrorsInCode('''
+class C {
+  factory C({int a}) => C._();
+  C._();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 27, 1),
+    ]);
+  }
+
+  test_constructor_factory_nonNullable_positional_optional_noDefault() async {
+    await assertErrorsInCode('''
+class C {
+  factory C([int a]) => C._();
+  C._();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 27, 1),
+    ]);
+  }
+
+  test_constructor_factory_nullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+class C {
+  factory C({int? a}) => C._();
+  C._();
+}
+''');
+  }
+
+  test_constructor_generative_nonNullable_named_optional_noDefault() async {
     await assertErrorsInCode('''
 class C {
   C({int a});
@@ -33,7 +88,7 @@
     ]);
   }
 
-  test_constructor_nonNullable_positional_optional_noDefault() async {
+  test_constructor_generative_nonNullable_positional_optional_noDefault() async {
     await assertErrorsInCode('''
 class C {
   C([int a]);
@@ -43,7 +98,7 @@
     ]);
   }
 
-  test_constructor_nullable_named_optional_noDefault() async {
+  test_constructor_generative_nullable_named_optional_noDefault() async {
     await assertNoErrorsInCode('''
 class C {
   C({int? a});
@@ -51,7 +106,7 @@
 ''');
   }
 
-  test_constructor_nullable_named_optional_noDefault_fieldFormal() async {
+  test_constructor_generative_nullable_named_optional_noDefault_fieldFormal() async {
     await assertNoErrorsInCode('''
 class C {
   int? f;
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart
index 195f47c..10b129c 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_catch_clause_test.dart
@@ -1,13 +1,11 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
 // for details. 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/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../dart/constant/potentially_constant_test.dart';
 import '../dart/resolution/driver_resolution.dart';
 
 main() {
@@ -17,13 +15,8 @@
 }
 
 @reflectiveTest
-class NullableTypeInCatchClauseTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..contextFeatures = FeatureSet.fromEnableFlags(
-      [EnableString.non_nullable],
-    );
-
+class NullableTypeInCatchClauseTest extends DriverResolutionTest
+    with WithNullSafetyMixin {
   test_noOnClause() async {
     await assertNoErrorsInCode('''
 f() {
@@ -34,43 +27,60 @@
 ''');
   }
 
-  test_on_class_nonNullable() async {
+  test_on_dynamic() async {
     await assertErrorsInCode('''
 class A {}
 f() {
   try {
-  } on A catch (e) {
+  } on dynamic {
   }
 }
 ''', [
-      error(HintCode.UNUSED_CATCH_CLAUSE, 41, 1),
+      error(HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE, 32, 7),
     ]);
   }
 
-  test_on_class_nullable() async {
-    await assertErrorsInCode('''
-class A {}
+  test_on_functionType_nonNullable() async {
+    await assertNoErrorsInCode('''
 f() {
   try {
-  } on A? {
+  } on void Function() {
+  }
+}
+''');
+  }
+
+  test_on_functionType_nullable() async {
+    await assertErrorsInCode('''
+f() {
+  try {
+  } on void Function()? {
   }
 }
 ''', [
-      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_CATCH_CLAUSE, 32, 2),
+      error(HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE, 21, 16),
     ]);
   }
 
-  test_on_typeParameter() async {
+  test_on_interfaceType_nonNullable() async {
+    await assertNoErrorsInCode('''
+f() {
+  try {
+  } on int {
+  }
+}
+''');
+  }
+
+  test_on_interfaceType_nullable() async {
     await assertErrorsInCode('''
-class A<B> {
-  m() {
-    try {
-    } on B {
-    }
+f() {
+  try {
+  } on int? {
   }
 }
 ''', [
-      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_CATCH_CLAUSE, 40, 1),
+      error(HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE, 21, 4),
     ]);
   }
 
@@ -86,6 +96,20 @@
 ''');
   }
 
+  test_on_typeParameter_nullable() async {
+    await assertErrorsInCode('''
+class A<B> {
+  m() {
+    try {
+    } on B {
+    }
+  }
+}
+''', [
+      error(HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE, 40, 1),
+    ]);
+  }
+
   test_optOut() async {
     await assertNoErrorsInCode('''
 // @dart = 2.7
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
index 2946765..7f9667b 100644
--- a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
@@ -39,18 +39,12 @@
   }
 
   test_async_future_int_mismatches_int() async {
-    // TODO(brianwilkerson) Stop producing RETURN_OF_INVALID_TYPE_FROM_FUNCTION.
     await assertErrorsInCode('''
 int f() async {
   return 5;
 }
 ''', [
       error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 0, 3),
-      error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 25, 1,
-          contextMessages: [
-            message('/sdk/lib/core/core.dart', 2150, 3),
-            message('/sdk/lib/core/core.dart', 2150, 3)
-          ]),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 67486e1..37b0a05 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -82,6 +82,8 @@
 import 'duplicate_named_argument_test.dart' as duplicate_named_argument;
 import 'duplicate_part_test.dart' as duplicate_part;
 import 'duplicate_shown_name_test.dart' as duplicate_shown_name;
+import 'enum_constant_same_name_as_enclosing.dart'
+    as enum_constant_same_name_as_enclosing;
 import 'equal_elements_in_const_set_test.dart' as equal_elements_in_const_set;
 import 'equal_elements_in_set_test.dart' as equal_elements_in_set;
 import 'equal_keys_in_const_map_test.dart' as equal_keys_in_const_map;
@@ -431,6 +433,7 @@
     as switch_case_completes_normally;
 import 'switch_expression_not_assignable_test.dart'
     as switch_expression_not_assignable;
+import 'throw_of_invalid_type_test.dart' as throw_of_invalid_type;
 import 'todo_test.dart' as todo_test;
 import 'top_level_instance_getter_test.dart' as top_level_instance_getter;
 import 'top_level_instance_method_test.dart' as top_level_instance_method;
@@ -560,6 +563,7 @@
     duplicate_named_argument.main();
     duplicate_part.main();
     duplicate_shown_name.main();
+    enum_constant_same_name_as_enclosing.main();
     equal_elements_in_const_set.main();
     equal_elements_in_set.main();
     equal_keys_in_const_map.main();
@@ -791,6 +795,7 @@
     super_initializer_in_object.main();
     switch_case_completes_normally.main();
     switch_expression_not_assignable.main();
+    throw_of_invalid_type.main();
     todo_test.main();
     top_level_instance_getter.main();
     top_level_instance_method.main();
diff --git a/pkg/analyzer/test/src/diagnostics/throw_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/throw_of_invalid_type_test.dart
new file mode 100644
index 0000000..448719d
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/throw_of_invalid_type_test.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.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ThrowOfInvalidTypeTest);
+  });
+}
+
+@reflectiveTest
+class ThrowOfInvalidTypeTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.fromEnableFlags(
+      [EnableString.non_nullable],
+    );
+
+  test_dynamic() async {
+    await assertNoErrorsInCode('''
+f(dynamic a) {
+  throw a;
+}
+''');
+  }
+
+  test_legacy() async {
+    newFile('/test/lib/a.dart', content: r'''
+// @dart = 2.7
+int a = 0;
+''');
+    await assertNoErrorsInCode('''
+import 'a.dart';
+
+f() {
+  throw a;
+}
+''');
+  }
+
+  test_nonNullable() async {
+    await assertNoErrorsInCode('''
+f(int a) {
+  throw a;
+}
+''');
+  }
+
+  test_nullable() async {
+    await assertErrorsInCode('''
+f(int? a) {
+  throw a;
+}
+''', [
+      error(CompileTimeErrorCode.THROW_OF_INVALID_TYPE, 20, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
index cb92c0d..045edd4 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
@@ -95,6 +95,13 @@
 ''');
   }
 
+  test_isUsed_privateEnum_values() async {
+    await assertNoErrorsInCode(r'''
+enum _Foo {a}
+f() => _Foo.values;
+''');
+  }
+
   test_isUsed_publicEnum_privateValue() async {
     await assertNoErrorsInCode(r'''
 enum Foo {_a, _b}
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 94e0f48..2f12e46 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -16,7 +16,8 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(CanBeConstConstructorTest);
-    defineReflectiveTests(CanBeConstTest);
+    defineReflectiveTests(CanBeConstInstanceCreationTest);
+    defineReflectiveTests(CanBeConstTypedLiteralTest);
     defineReflectiveTests(EvaluateExpressionTest);
     defineReflectiveTests(PubDependencyTest);
   });
@@ -149,7 +150,7 @@
 }
 
 @reflectiveTest
-class CanBeConstTest extends AbstractLinterContextTest {
+class CanBeConstInstanceCreationTest extends AbstractLinterContextTest {
   void assertCanBeConst(String snippet, bool expectedResult) {
     var node = findNode.instanceCreation(snippet);
     expect(context.canBeConst(node), expectedResult);
@@ -208,6 +209,23 @@
     assertCanBeConst("A<U>", false);
   }
 
+  void test_true_computeDependencies() async {
+    newFile('/test/lib/a.dart', content: r'''
+const a = 0;
+''');
+
+    await resolve('''
+import 'a.dart';
+
+class A {
+  const A(int a);
+}
+
+A f() => A(a);
+''');
+    assertCanBeConst('A(a)', true);
+  }
+
   void test_true_constConstructorArg() async {
     await resolve('''
 class A {
@@ -249,6 +267,102 @@
 }
 
 @reflectiveTest
+class CanBeConstTypedLiteralTest extends AbstractLinterContextTest {
+  void assertCanBeConst(String snippet, bool expectedResult) {
+    var node = findNode.typedLiteral(snippet);
+    expect(context.canBeConst(node), expectedResult);
+  }
+
+  void test_listLiteral_false_methodInvocation() async {
+    await resolve('''
+f() => [g()];
+int g() => 0;
+''');
+    assertCanBeConst('[', false);
+  }
+
+  void test_listLiteral_false_typeParameter() async {
+    await resolve('''
+class A<T> {
+  const A();
+}
+
+f<U>() => [A<U>()];
+''');
+    assertCanBeConst('[', false);
+  }
+
+  void test_listLiteral_true_computeDependencies() async {
+    newFile('/test/lib/a.dart', content: r'''
+const a = 0;
+''');
+
+    await resolve('''
+import 'a.dart';
+
+f() => [a];
+''');
+    assertCanBeConst('[', true);
+  }
+
+  void test_listLiteral_true_constConstructor() async {
+    await resolve('''
+class A {
+  const A();
+}
+
+f() => [A()];
+''');
+    assertCanBeConst('[', true);
+  }
+
+  void test_listLiteral_true_integerLiteral() async {
+    await resolve('''
+f() => [1, 2, 3];
+''');
+    assertCanBeConst('[', true);
+  }
+
+  void test_mapLiteral_false_methodInvocation_key() async {
+    await resolve('''
+f() => {g(): 0};
+int g() => 0;
+''');
+    assertCanBeConst('{', false);
+  }
+
+  void test_mapLiteral_false_methodInvocation_value() async {
+    await resolve('''
+f() => {0: g()};
+int g() => 0;
+''');
+    assertCanBeConst('{', false);
+  }
+
+  void test_mapLiteral_true_integerLiteral() async {
+    await resolve('''
+f() => {1: 2, 3: 4};
+''');
+    assertCanBeConst('{', true);
+  }
+
+  void test_setLiteral_false_methodInvocation() async {
+    await resolve('''
+f() => {g()};
+int g() => 0;
+''');
+    assertCanBeConst('{', false);
+  }
+
+  void test_setLiteral_true_integerLiteral() async {
+    await resolve('''
+f() => {1, 2, 3};
+''');
+    assertCanBeConst('{', true);
+  }
+}
+
+@reflectiveTest
 class EvaluateExpressionTest extends AbstractLinterContextTest {
   test_hasError_listLiteral_forElement() async {
     await resolve('''
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 340a034..5e594b8 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/element/class_hierarchy.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -216,7 +216,10 @@
   }
 }
 
-class _AnalysisSessionForLinking implements AnalysisSession {
+class _AnalysisSessionForLinking implements AnalysisSessionImpl {
+  @override
+  final ClassHierarchy classHierarchy = ClassHierarchy();
+
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 2850837..0162d95 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2747,20 +2747,13 @@
     int x;
 }
 
-class /*error:INCONSISTENT_INHERITANCE*/T1 extends Base
-    with /*error:INVALID_OVERRIDE*/M1 {}
-class /*error:INCONSISTENT_INHERITANCE*/T2 extends Base
-    with /*error:INVALID_OVERRIDE*/M1, M2 {}
-class /*error:INCONSISTENT_INHERITANCE*/T3 extends Base
-    with M2, /*error:INVALID_OVERRIDE*/M1 {}
+class T1 extends Base with /*error:INVALID_OVERRIDE*/M1 {}
+class T2 extends Base with /*error:INVALID_OVERRIDE*/M1, M2 {}
+class T3 extends Base with M2, /*error:INVALID_OVERRIDE*/M1 {}
 
-
-class /*error:INCONSISTENT_INHERITANCE*/U1 = Base
-    with /*error:INVALID_OVERRIDE*/M1;
-class /*error:INCONSISTENT_INHERITANCE*/U2 = Base
-    with /*error:INVALID_OVERRIDE*/M1, M2;
-class /*error:INCONSISTENT_INHERITANCE*/U3 = Base
-    with M2, /*error:INVALID_OVERRIDE*/M1;
+class U1 = Base with /*error:INVALID_OVERRIDE*/M1;
+class U2 = Base with /*error:INVALID_OVERRIDE*/M1, M2;
+class U3 = Base with M2, /*error:INVALID_OVERRIDE*/M1;
 ''');
   }
 
@@ -2782,13 +2775,9 @@
     int x;
 }
 
-class /*error:INCONSISTENT_INHERITANCE*/T1 extends Base
-    with M1,
-    /*error:INVALID_OVERRIDE*/M2 {}
+class T1 extends Base with M1, /*error:INVALID_OVERRIDE*/M2 {}
 
-class /*error:INCONSISTENT_INHERITANCE*/U1 = Base
-    with M1,
-    /*error:INVALID_OVERRIDE*/M2;
+class U1 = Base with M1, /*error:INVALID_OVERRIDE*/M2;
 ''');
   }
 
@@ -3410,11 +3399,9 @@
     m(B a) {}
 }
 
-class /*error:INCONSISTENT_INHERITANCE*/T1 extends Base
-    with /*error:INVALID_OVERRIDE*/M {}
+class T1 extends Base with /*error:INVALID_OVERRIDE*/M {}
 
-class /*error:INCONSISTENT_INHERITANCE*/U1 = Base
-    with /*error:INVALID_OVERRIDE*/M;
+class U1 = Base with /*error:INVALID_OVERRIDE*/M;
 ''');
   }
 
@@ -3434,11 +3421,9 @@
     m(B a) {}
 }
 
-class /*error:INCONSISTENT_INHERITANCE*/T1 extends Base
-    with /*error:INVALID_OVERRIDE*/M {}
+class T1 extends Base with /*error:INVALID_OVERRIDE*/M {}
 
-class /*error:INCONSISTENT_INHERITANCE*/U1 = Base
-    with /*error:INVALID_OVERRIDE*/M;
+class U1 = Base with /*error:INVALID_OVERRIDE*/M;
 ''');
   }
 
diff --git a/pkg/analyzer_cli/lib/src/context_cache.dart b/pkg/analyzer_cli/lib/src/context_cache.dart
index b3af37d..82e7f1e 100644
--- a/pkg/analyzer_cli/lib/src/context_cache.dart
+++ b/pkg/analyzer_cli/lib/src/context_cache.dart
@@ -106,12 +106,8 @@
             verbosePrint: clOptions.verbose ? verbosePrint : null)
         as AnalysisOptionsImpl;
 
-    contextOptions.trackCacheDependencies = false;
-    contextOptions.disableCacheFlushing = clOptions.disableCacheFlushing;
     _buildContextFeatureSet(contextOptions);
     contextOptions.hint = !clOptions.disableHints;
-    contextOptions.generateImplicitErrors = clOptions.showPackageWarnings;
-    contextOptions.generateSdkErrors = clOptions.showSdkWarnings;
     contextOptions.useFastaParser = clOptions.useFastaParser;
     return contextOptions;
   }
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart
index 592f09a..219b110 100644
--- a/pkg/analyzer_cli/test/mocks.dart
+++ b/pkg/analyzer_cli/test/mocks.dart
@@ -92,6 +92,9 @@
   bool get hasPublishedDocs => false;
 
   @override
+  bool get isIgnorable => true;
+
+  @override
   bool get isUnresolvedIdentifier => false;
 
   @override
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 4e80d11..6b93571 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -96,7 +97,7 @@
   /// possible). However, there is one exception: when the cursor is inside of
   /// a multi-character token which is not a keyword or identifier (e.g. a
   /// comment, or a token like "+=", the entity will be always be the token.
-  final Object entity;
+  final SyntacticEntity entity;
 
   /// The [entity] is a comment token, which is either not a documentation
   /// comment or the position is not in a [CommentReference].
@@ -231,7 +232,7 @@
   /// Create a [CompletionTarget] holding the given [containingNode] and
   /// [entity].
   CompletionTarget._(this.unit, this.offset, AstNode containingNode,
-      Object entity, this.isCommentText)
+      SyntacticEntity entity, this.isCommentText)
       : containingNode = containingNode,
         entity = entity,
         argIndex = _computeArgIndex(containingNode, entity),
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 4ce976b..e06795d 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.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/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -80,6 +81,9 @@
   /// The suggested completion kind.
   CompletionSuggestionKind suggestKind = CompletionSuggestionKind.INVOCATION;
 
+  /// An representation of the location at which completion was requested.
+  String completionLocation;
+
   /// The type that is required by the context in which the completion was
   /// activated, or `null` if there is no such type, or it cannot be determined.
   DartType _requiredType;
@@ -226,9 +230,9 @@
 }
 
 class _OpTypeAstVisitor extends GeneralizingAstVisitor<void> {
-  /// The entity (AstNode or Token) which will be replaced or displaced by the
+  /// The entity (AstNode or Token) that will be replaced or displaced by the
   /// added text.
-  final Object entity;
+  final SyntacticEntity entity;
 
   /// The offset within the source at which the completion is requested.
   final int offset;
@@ -241,9 +245,16 @@
   @override
   void visitAnnotation(Annotation node) {
     if (identical(entity, node.name)) {
+      optype.completionLocation = 'Annotation_name';
       optype.includeTypeNameSuggestions = true;
       optype.includeReturnValueSuggestions = true;
     } else if (identical(entity, node.constructorName)) {
+      // There is no location for the constructor name because only named
+      // constructors are valid.
+      // TODO(brianwilkerson) The following looks wrong. I think we want to set
+      //  includeConstructorSuggestions = true, but not type names or return
+      //  values. On the other hand, I can't construct a test case that reaches
+      //  this point, so perhaps we should just remove this branch.
       optype.includeTypeNameSuggestions = true;
       optype.includeReturnValueSuggestions = true;
       optype.isPrefixed = true;
@@ -282,6 +293,18 @@
           optype.includeNamedArgumentSuggestions = true;
         }
       }
+    } else if (parent is SuperConstructorInvocation) {
+      parameters = parent.staticElement?.parameters;
+    } else if (parent is RedirectingConstructorInvocation) {
+      parameters = parent.staticElement?.parameters;
+    } else if (parent is Annotation) {
+      var constructor = parent.element;
+      if (constructor is ConstructorElement) {
+        parameters = constructor.parameters;
+      } else if (constructor == null) {
+        // If unresolved, then include named arguments
+        optype.includeNamedArgumentSuggestions = true;
+      }
     }
     // Based upon the insertion location and declared parameters
     // determine whether only named arguments should be suggested
@@ -303,11 +326,15 @@
       if (0 <= index && index < parameters.length) {
         var param = parameters[index];
         if (param?.isNamed == true) {
+          var context = _argumentListContext(node);
+          optype.completionLocation = 'ArgumentList_${context}_named';
           optype.includeNamedArgumentSuggestions = true;
           return;
         }
       }
     }
+    var context = _argumentListContext(node);
+    optype.completionLocation = 'ArgumentList_${context}_unnamed';
     optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
   }
@@ -315,6 +342,7 @@
   @override
   void visitAsExpression(AsExpression node) {
     if (identical(entity, node.type)) {
+      optype.completionLocation = 'AsExpression_type';
       optype.includeTypeNameSuggestions = true;
       optype.typeNameSuggestionsFilter = (DartType dartType, int relevance) {
         var staticType = node.expression.staticType;
@@ -333,22 +361,33 @@
   @override
   void visitAssertInitializer(AssertInitializer node) {
     if (identical(entity, node.condition)) {
+      optype.completionLocation = 'AssertInitializer_condition';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
+    } else if (identical(entity, node.message)) {
+      optype.completionLocation = 'AssertInitializer_message';
+      // TODO(brianwilkerson) Consider including return value suggestions and
+      //  type name suggestions here.
     }
   }
 
   @override
   void visitAssertStatement(AssertStatement node) {
     if (identical(entity, node.condition)) {
+      optype.completionLocation = 'AssertStatement_condition';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
+    } else if (identical(entity, node.message)) {
+      optype.completionLocation = 'AssertStatement_message';
+      // TODO(brianwilkerson) Consider including return value suggestions and
+      //  type name suggestions here.
     }
   }
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
     if (identical(entity, node.rightHandSide)) {
+      optype.completionLocation = 'AssignmentExpression_rightHandSide';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -357,6 +396,7 @@
   @override
   void visitAwaitExpression(AwaitExpression node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'AwaitExpression_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -365,6 +405,8 @@
   @override
   void visitBinaryExpression(BinaryExpression node) {
     if (identical(entity, node.rightOperand)) {
+      optype.completionLocation =
+          'BinaryExpression_${node.operator}_rightOperand';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -372,6 +414,7 @@
 
   @override
   void visitBlock(Block node) {
+    optype.completionLocation = 'Block_statement';
     var prevStmt = OpType.getPreviousStatement(node, entity);
     if (prevStmt is TryStatement) {
       if (prevStmt.catchClauses.isEmpty && prevStmt.finallyBlock == null) {
@@ -393,6 +436,7 @@
   @override
   void visitCascadeExpression(CascadeExpression node) {
     if (node.cascadeSections.contains(entity)) {
+      optype.completionLocation = 'CascadeExpression_cascadeSection';
       optype.includeReturnValueSuggestions = true;
       optype.includeVoidReturnSuggestions = true;
       optype.isPrefixed = true;
@@ -402,6 +446,7 @@
   @override
   void visitCatchClause(CatchClause node) {
     if (identical(entity, node.exceptionType)) {
+      optype.completionLocation = 'CatchClause_exceptionType';
       optype.includeTypeNameSuggestions = true;
     }
   }
@@ -410,6 +455,7 @@
   void visitClassDeclaration(ClassDeclaration node) {
     // Make suggestions in the body of the class declaration
     if (node.members.contains(entity) || identical(entity, node.rightBracket)) {
+      optype.completionLocation = 'ClassDeclaration_member';
       optype.includeTypeNameSuggestions = true;
     }
   }
@@ -418,7 +464,16 @@
   void visitClassMember(ClassMember node) {}
 
   @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    if (identical(entity, node.superclass)) {
+      optype.completionLocation = 'ClassTypeAlias_superclass';
+      optype.includeTypeNameSuggestions = true;
+    }
+  }
+
+  @override
   void visitCommentReference(CommentReference node) {
+    optype.completionLocation = 'CommentReference_identifier';
     optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
     optype.includeVoidReturnSuggestions = true;
@@ -428,19 +483,54 @@
   @override
   void visitCompilationUnit(CompilationUnit node) {
     if (entity is! CommentToken) {
+      int declarationStart() {
+        var declarations = node.declarations;
+        if (declarations.isNotEmpty) {
+          return declarations[0].offset;
+        }
+        var directives = node.directives;
+        if (directives.isNotEmpty) {
+          return directives.last.end;
+        }
+        return node.end;
+      }
+
+      if (entity != null) {
+        if (entity.offset <= declarationStart()) {
+          optype.completionLocation = 'CompilationUnit_declaration';
+        } else {
+          optype.completionLocation = 'CompilationUnit_declaration';
+        }
+      }
       optype.includeTypeNameSuggestions = true;
     }
   }
 
   @override
   void visitConditionalExpression(ConditionalExpression node) {
+    if (identical(entity, node.thenExpression)) {
+      optype.completionLocation = 'ConditionalExpression_thenExpression';
+    } else if (identical(entity, node.elseExpression)) {
+      optype.completionLocation = 'ConditionalExpression_elseExpression';
+    }
     optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
   }
 
   @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    if (identical(entity, node.returnType)) {
+      optype.completionLocation = 'ConstructorDeclaration_returnType';
+      optype.includeTypeNameSuggestions = true;
+    } else if (node.initializers.contains(entity)) {
+      optype.completionLocation = 'ConstructorDeclaration_initializer';
+    }
+  }
+
+  @override
   void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'ConstructorFieldInitializer_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -473,6 +563,7 @@
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
     if (identical(entity, node.defaultValue)) {
+      optype.completionLocation = 'DefaultFormalParameter_defaultValue';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -480,7 +571,10 @@
 
   @override
   void visitDoStatement(DoStatement node) {
-    if (identical(entity, node.condition)) {
+    if (identical(entity, node.body)) {
+      optype.completionLocation = 'DoStatement_body';
+    } else if (identical(entity, node.condition)) {
+      optype.completionLocation = 'DoStatement_condition';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -503,6 +597,7 @@
   @override
   void visitExpressionFunctionBody(ExpressionFunctionBody node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'ExpressionFunctionBody_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -510,6 +605,7 @@
 
   @override
   void visitExpressionStatement(ExpressionStatement node) {
+    optype.completionLocation = 'ExpressionStatement_expression';
     // Given f[], the parser drops the [] from the expression statement
     // but the [] token is the CompletionTarget entity
     if (entity is Token) {
@@ -528,6 +624,7 @@
   @override
   void visitExtendsClause(ExtendsClause node) {
     if (identical(entity, node.superclass)) {
+      optype.completionLocation = 'ExtendsClause_superclass';
       optype.includeTypeNameSuggestions = true;
       optype.typeNameSuggestionsFilter = _nonMixinClasses;
     }
@@ -535,8 +632,12 @@
 
   @override
   void visitExtensionDeclaration(ExtensionDeclaration node) {
-    // Make suggestions in the body of the extension declaration
-    if (node.members.contains(entity) || identical(entity, node.rightBracket)) {
+    if (identical(entity, node.extendedType)) {
+      optype.completionLocation = 'ExtensionDeclaration_extendedType';
+    } else if (node.members.contains(entity) ||
+        identical(entity, node.rightBracket)) {
+      // Make suggestions in the body of the extension declaration
+      optype.completionLocation = 'ExtensionDeclaration_member';
       optype.includeTypeNameSuggestions = true;
     }
   }
@@ -546,6 +647,9 @@
     if (offset <= node.semicolon.offset) {
       optype.includeVarNameSuggestions = true;
     }
+    if (offset <= node.fields.offset) {
+      optype.includeTypeNameSuggestions = true;
+    }
   }
 
   @override
@@ -560,24 +664,38 @@
 
   @override
   void visitForEachParts(ForEachParts node) {
-    if (node is ForEachPartsWithIdentifier &&
-        identical(entity, node.identifier)) {
-      optype.includeTypeNameSuggestions = true;
-    }
-    if (node is ForEachPartsWithDeclaration &&
-        identical(entity, node.loopVariable)) {
-      optype.includeTypeNameSuggestions = true;
-    }
     if (identical(entity, node.inKeyword) && offset <= node.inKeyword.offset) {
       if (!(node is ForEachPartsWithIdentifier && node.identifier != null ||
           node is ForEachPartsWithDeclaration && node.loopVariable != null)) {
         optype.includeTypeNameSuggestions = true;
       }
     }
-    if (identical(entity, node.iterable)) {
+  }
+
+  @override
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+    if (identical(entity, node.loopVariable)) {
+      optype.completionLocation = 'ForEachPartsWithDeclaration_loopVariable';
+      optype.includeTypeNameSuggestions = true;
+    } else if (identical(entity, node.iterable)) {
+      optype.completionLocation = 'ForEachPartsWithDeclaration_iterable';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
+    visitForEachParts(node);
+  }
+
+  @override
+  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+    if (identical(entity, node.identifier)) {
+      optype.completionLocation = 'ForEachPartsWithIdentifier_identifier';
+      optype.includeTypeNameSuggestions = true;
+    } else if (identical(entity, node.iterable)) {
+      optype.completionLocation = 'ForEachPartsWithIdentifier_iterable';
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+    }
+    visitForEachParts(node);
   }
 
   @override
@@ -588,9 +706,8 @@
     // but for any practical use we need only types.
     if (entity == node.forLoopParts) {
       optype.includeTypeNameSuggestions = true;
-    }
-
-    if (entity == node.body) {
+    } else if (entity == node.body) {
+      optype.completionLocation = 'ForElement_body';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -598,7 +715,8 @@
 
   @override
   void visitFormalParameterList(FormalParameterList node) {
-    dynamic entity = this.entity;
+    optype.completionLocation = 'FormalParameterList_parameter';
+    var entity = this.entity;
     if (entity is Token) {
       var previous = node.findPrevious(entity);
       if (previous != null) {
@@ -646,13 +764,14 @@
       //                    ^
       optype.includeVarNameSuggestions = true;
     } else {
-      // for (; ^) {}
       if (entity == node.condition) {
+        // for (; ^) {}
+        optype.completionLocation = 'ForParts_condition';
         optype.includeTypeNameSuggestions = true;
         optype.includeReturnValueSuggestions = true;
-      }
-      // for (; ; ^) {}
-      if (node.updaters.contains(entity)) {
+      } else if (node.updaters.contains(entity)) {
+        // for (; ; ^) {}
+        optype.completionLocation = 'ForParts_updater';
         optype.includeTypeNameSuggestions = true;
         optype.includeReturnValueSuggestions = true;
         optype.includeVoidReturnSuggestions = true;
@@ -668,6 +787,8 @@
     // but for any practical use we need only types.
     if (entity == node.forLoopParts) {
       optype.includeTypeNameSuggestions = true;
+    } else if (entity == node.body) {
+      optype.completionLocation = 'ForElement_body';
     }
   }
 
@@ -694,12 +815,32 @@
   }
 
   @override
+  void visitGenericTypeAlias(GenericTypeAlias node) {
+    if (entity == node.functionType) {
+      optype.completionLocation = 'GenericTypeAlias_functionType';
+    }
+  }
+
+  @override
+  void visitHideCombinator(HideCombinator node) {
+    if (node.hiddenNames.contains(entity)) {
+      optype.completionLocation = 'HideCombinator_hiddenName';
+    }
+  }
+
+  @override
   void visitIfElement(IfElement node) {
     if (identical(entity, node.condition)) {
+      optype.completionLocation = 'IfElement_condition';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
-    } else if (identical(entity, node.thenElement) ||
-        identical(entity, node.elseElement)) {
+    } else if (identical(entity, node.thenElement)) {
+      optype.completionLocation = 'IfElement_thenElement';
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+      optype.includeVoidReturnSuggestions = true;
+    } else if (identical(entity, node.elseElement)) {
+      optype.completionLocation = 'IfElement_elseElement';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
       optype.includeVoidReturnSuggestions = true;
@@ -712,10 +853,16 @@
       // Actual: if (var v i^)
       // Parsed: if (v) i^;
     } else if (identical(entity, node.condition)) {
+      optype.completionLocation = 'IfStatement_condition';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
-    } else if (identical(entity, node.thenStatement) ||
-        identical(entity, node.elseStatement)) {
+    } else if (identical(entity, node.thenStatement)) {
+      optype.completionLocation = 'IfStatement_thenElement';
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+      optype.includeVoidReturnSuggestions = true;
+    } else if (identical(entity, node.elseStatement)) {
+      optype.completionLocation = 'IfStatement_elseElement';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
       optype.includeVoidReturnSuggestions = true;
@@ -724,11 +871,13 @@
 
   @override
   void visitImplementsClause(ImplementsClause node) {
+    optype.completionLocation = 'ImplementsClause_interface';
     optype.includeTypeNameSuggestions = true;
   }
 
   @override
   void visitIndexExpression(IndexExpression node) {
+    optype.completionLocation = 'IndexExpression_index';
     optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
   }
@@ -743,6 +892,7 @@
   @override
   void visitInterpolationExpression(InterpolationExpression node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'InterpolationExpression_expression';
       optype.includeReturnValueSuggestions = true;
       // Only include type names in a ${ } expression
       optype.includeTypeNameSuggestions =
@@ -753,6 +903,7 @@
   @override
   void visitIsExpression(IsExpression node) {
     if (identical(entity, node.type)) {
+      optype.completionLocation = 'IsExpression_type';
       optype.includeTypeNameSuggestions = true;
       optype.typeNameSuggestionsFilter = (DartType dartType, int relevance) {
         var staticType = node.expression.staticType;
@@ -769,12 +920,26 @@
   }
 
   @override
+  void visitLabeledStatement(LabeledStatement node) {
+    optype.completionLocation = 'LabeledStatement_statement';
+  }
+
+  @override
   void visitLibraryIdentifier(LibraryIdentifier node) {
     // No suggestions.
   }
 
   @override
+  void visitListLiteral(ListLiteral node) {
+    if (node.elements.contains(entity)) {
+      optype.completionLocation = 'ListLiteral_element';
+    }
+    visitTypedLiteral(node);
+  }
+
+  @override
   void visitMapLiteralEntry(MapLiteralEntry node) {
+    optype.completionLocation = 'MapLiteralEntry_value';
     optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
   }
@@ -811,6 +976,7 @@
   void visitMixinDeclaration(MixinDeclaration node) {
     // Make suggestions in the body of the mixin declaration
     if (node.members.contains(entity) || identical(entity, node.rightBracket)) {
+      optype.completionLocation = 'MixinDeclaration_member';
       optype.includeTypeNameSuggestions = true;
     }
   }
@@ -818,6 +984,8 @@
   @override
   void visitNamedExpression(NamedExpression node) {
     if (identical(entity, node.expression)) {
+      var context = _argumentListContext(node.parent);
+      optype.completionLocation = 'ArgumentList_${context}_named';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
 
@@ -857,12 +1025,14 @@
 
   @override
   void visitOnClause(OnClause node) {
+    optype.completionLocation = 'OnClause_superclassConstraint';
     optype.includeTypeNameSuggestions = true;
   }
 
   @override
   void visitParenthesizedExpression(ParenthesizedExpression node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'ParenthesizedExpression_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -891,6 +1061,8 @@
       optype.isPrefixed = true;
       if (node.parent is TypeName && node.parent.parent is ConstructorName) {
         optype.includeConstructorSuggestions = true;
+      } else if (node.parent is Annotation) {
+        optype.includeConstructorSuggestions = true;
       } else {
         optype.includeReturnValueSuggestions = true;
         optype.includeTypeNameSuggestions = true;
@@ -903,6 +1075,7 @@
   @override
   void visitPrefixExpression(PrefixExpression node) {
     if (identical(entity, node.operand)) {
+      optype.completionLocation = 'PrefixExpression_${node.operator}_operand';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -919,11 +1092,13 @@
     if (identical(entity, node.operator) && offset > node.operator.offset) {
       // The cursor is between the two dots of a ".." token, so we need to
       // generate the completions we would generate after a "." token.
+      optype.completionLocation = 'PropertyAccess_propertyName';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = !isThis;
       optype.includeVoidReturnSuggestions = true;
       optype.isPrefixed = true;
     } else if (identical(entity, node.propertyName)) {
+      optype.completionLocation = 'PropertyAccess_propertyName';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions =
           !isThis && (node.parent is! CascadeExpression);
@@ -935,12 +1110,28 @@
   @override
   void visitReturnStatement(ReturnStatement node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'ReturnStatement_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
   }
 
   @override
+  void visitSetOrMapLiteral(SetOrMapLiteral node) {
+    if (node.elements.contains(entity)) {
+      optype.completionLocation = 'SetOrMapLiteral_element';
+    }
+    visitTypedLiteral(node);
+  }
+
+  @override
+  void visitShowCombinator(ShowCombinator node) {
+    if (node.shownNames.contains(entity)) {
+      optype.completionLocation = 'ShowCombinator_shownName';
+    }
+  }
+
+  @override
   void visitSimpleFormalParameter(SimpleFormalParameter node) {
     var type = node.type;
     var name = node.identifier;
@@ -1006,6 +1197,7 @@
   @override
   void visitSpreadElement(SpreadElement node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'SpreadElement_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -1019,9 +1211,11 @@
   @override
   void visitSwitchCase(SwitchCase node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'SwitchCase_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     } else if (node.statements.contains(entity)) {
+      optype.completionLocation = 'SwitchCase_statement';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
       optype.includeVoidReturnSuggestions = true;
@@ -1031,11 +1225,13 @@
   @override
   void visitSwitchStatement(SwitchStatement node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'SwitchStatement_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
     if (identical(entity, node.rightBracket)) {
       if (node.members.isNotEmpty) {
+        optype.completionLocation = 'SwitchMember_statement';
         optype.includeReturnValueSuggestions = true;
         optype.includeTypeNameSuggestions = true;
         optype.includeVoidReturnSuggestions = true;
@@ -1044,6 +1240,7 @@
     if (entity is SwitchMember && entity != node.members.first) {
       var member = entity as SwitchMember;
       if (offset <= member.offset) {
+        optype.completionLocation = 'SwitchMember_statement';
         optype.includeReturnValueSuggestions = true;
         optype.includeTypeNameSuggestions = true;
         optype.includeVoidReturnSuggestions = true;
@@ -1053,6 +1250,7 @@
 
   @override
   void visitThrowExpression(ThrowExpression node) {
+    optype.completionLocation = 'ThrowExpression_expression';
     optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
   }
@@ -1065,6 +1263,9 @@
         optype.includeVarNameSuggestions = true;
       }
     }
+    if (offset <= node.variables.offset) {
+      optype.includeTypeNameSuggestions = true;
+    }
   }
 
   @override
@@ -1072,6 +1273,7 @@
     var arguments = node.arguments;
     for (var type in arguments) {
       if (identical(entity, type)) {
+        optype.completionLocation = 'TypeArgumentList_argument';
         optype.includeTypeNameSuggestions = true;
         break;
       }
@@ -1096,6 +1298,9 @@
 
   @override
   void visitTypeParameter(TypeParameter node) {
+    if (entity == node.bound) {
+      optype.completionLocation = 'TypeParameter_bound';
+    }
     optype.includeTypeNameSuggestions = true;
   }
 
@@ -1103,6 +1308,7 @@
   void visitVariableDeclaration(VariableDeclaration node) {
     // Make suggestions for the RHS of a variable declaration
     if (identical(entity, node.initializer)) {
+      optype.completionLocation = 'VariableDeclaration_initializer';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
@@ -1125,24 +1331,63 @@
   @override
   void visitWhileStatement(WhileStatement node) {
     if (identical(entity, node.condition)) {
+      optype.completionLocation = 'WhileStatement_condition';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
+    } else if (identical(entity, node.body)) {
+      optype.completionLocation = 'WhileStatement_body';
     }
   }
 
   @override
   void visitWithClause(WithClause node) {
+    if (node.mixinTypes.contains(entity)) {
+      optype.completionLocation = 'WithClause_mixinType';
+    }
     optype.includeTypeNameSuggestions = true;
   }
 
   @override
   void visitYieldStatement(YieldStatement node) {
     if (identical(entity, node.expression)) {
+      optype.completionLocation = 'YieldStatement_expression';
       optype.includeReturnValueSuggestions = true;
       optype.includeTypeNameSuggestions = true;
     }
   }
 
+  /// Return the context in which the [node] occurs. The [node] is expected to
+  /// be the parent of the argument expression.
+  String _argumentListContext(AstNode node) {
+    if (node is ArgumentList) {
+      var parent = node.parent;
+      if (parent is InstanceCreationExpression) {
+        // TODO(brianwilkerson) Enable this case.
+//        if (flutter.isWidgetType(parent.staticType)) {
+//          return 'widgetConstructor';
+//        }
+        return 'constructor';
+      } else if (parent is MethodInvocation) {
+        return 'method';
+      } else if (parent is FunctionExpressionInvocation) {
+        return 'function';
+      } else if (parent is SuperConstructorInvocation ||
+          parent is RedirectingConstructorInvocation) {
+        return 'constructorRedirect';
+      } else if (parent is Annotation) {
+        return 'annotation';
+      }
+    } else if (node is IndexExpression) {
+      return 'index';
+    } else if (node is AssignmentExpression ||
+        node is BinaryExpression ||
+        node is PrefixExpression ||
+        node is PostfixExpression) {
+      return 'operator';
+    }
+    throw ArgumentError('Unknown parent of ${node.runtimeType}');
+  }
+
   bool _isEntityPrevTokenSynthetic() {
     var entity = this.entity;
     if (entity is AstNode) {
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index 6223a2c..7292c68 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -16,83 +15,353 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(OpTypeTest);
-    defineReflectiveTests(OpTypeDart1OnlyTest);
-    defineReflectiveTests(OpTypeTestWithExtensionMethods);
   });
 }
 
+/// Common test methods to Dart1/Dart2 versions of OpType tests.
+abstract class AbstractOpTypeTest extends AbstractContextTest {
+  String testPath;
+  int completionOffset;
+
+  void addTestSource(String content) {
+    completionOffset = content.indexOf('^');
+    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
+    var nextOffset = content.indexOf('^', completionOffset + 1);
+    expect(nextOffset, equals(-1), reason: 'too many ^');
+    content = content.substring(0, completionOffset) +
+        content.substring(completionOffset + 1);
+    super.addSource(testPath, content);
+  }
+
+  Future<void> assertOpType(
+      {bool caseLabel = false,
+      String completionLocation,
+      bool constructors = false,
+      bool namedArgs = false,
+      bool prefixed = false,
+      bool returnValue = false,
+      bool statementLabel = false,
+      bool staticMethodBody = false,
+      bool typeNames = false,
+      bool varNames = false,
+      bool voidReturn = false,
+      CompletionSuggestionKind kind =
+          CompletionSuggestionKind.INVOCATION}) async {
+    //
+    // Compute the OpType.
+    //
+    var resolvedUnit = await driver.getResult(testPath);
+    var completionTarget =
+        CompletionTarget.forOffset(resolvedUnit.unit, completionOffset);
+    var opType = OpType.forCompletion(completionTarget, completionOffset);
+    //
+    // Validate the OpType.
+    //
+    var isValid = opType.includeCaseLabelSuggestions == caseLabel &&
+        opType.completionLocation == completionLocation &&
+        opType.includeConstructorSuggestions == constructors &&
+        opType.suggestKind == kind &&
+        opType.includeNamedArgumentSuggestions == namedArgs &&
+        opType.isPrefixed == prefixed &&
+        opType.includeReturnValueSuggestions == returnValue &&
+        opType.includeStatementLabelSuggestions == statementLabel &&
+        opType.inStaticMethodBody == staticMethodBody &&
+        opType.includeTypeNameSuggestions == typeNames &&
+        opType.includeVarNameSuggestions == varNames &&
+        opType.includeVoidReturnSuggestions == voidReturn;
+    //
+    // Fail with a useful message if the OpType doesn't match the expectations.
+    //
+    if (!isValid) {
+      var args = <String>[];
+      void addArg(bool shouldAdd, String argument) {
+        if (shouldAdd) {
+          args.add(argument);
+        }
+      }
+
+      addArg(opType.includeCaseLabelSuggestions, 'caseLabel: true');
+      addArg(opType.completionLocation != null,
+          "completionLocation: '${opType.completionLocation}'");
+      addArg(opType.includeConstructorSuggestions, 'constructors: true');
+      addArg(opType.suggestKind != CompletionSuggestionKind.INVOCATION,
+          'kind: ${opType.suggestKind}');
+      addArg(opType.includeNamedArgumentSuggestions, 'namedArgs: true');
+      addArg(opType.isPrefixed, 'prefixed: true');
+      addArg(opType.includeReturnValueSuggestions, 'returnValue: true');
+      addArg(opType.includeStatementLabelSuggestions, 'statementLabel: true');
+      addArg(opType.inStaticMethodBody, 'staticMethodBody: true');
+      addArg(opType.includeTypeNameSuggestions, 'typeNames: true');
+      addArg(opType.includeVarNameSuggestions, 'varNames: true');
+      addArg(opType.includeVoidReturnSuggestions, 'voidReturn: true');
+
+      fail('''
+Actual OpType does not match expected. Actual matches
+  await assertOpType(${args.join(', ')});''');
+    }
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    testPath = convertPath('/completionTest.dart');
+  }
+}
+
 @reflectiveTest
-class OpTypeDart1OnlyTest extends OpTypeTestCommon {
+class OpTypeTest extends AbstractOpTypeTest {
+  Future<void> test_annotation_constructorName_arguments() async {
+    // SimpleIdentifier  Annotation  MethodDeclaration  ClassDeclaration
+    addTestSource('''
+class C { @A.n^() void m() {} }
+class A {
+  const A.named();
+}
+''');
+    await assertOpType(constructors: true, prefixed: true);
+  }
+
+  Future<void> test_annotation_constructorName_noArguments() async {
+    // SimpleIdentifier  Annotation  MethodDeclaration  ClassDeclaration
+    addTestSource('''
+class C { @A.^ void m() {} }
+class A {
+  const A.m();
+}
+''');
+    await assertOpType(constructors: true, prefixed: true);
+  }
+
+  Future<void> test_annotation_name() async {
+    // SimpleIdentifier  Annotation  MethodDeclaration  ClassDeclaration
+    addTestSource('''
+class C { @A^ void m() {} }
+class A {
+  const A();
+}
+''');
+    await assertOpType(
+        completionLocation: 'Annotation_name',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
   @failingTest
-  Future<void> test_Annotation() async {
+  Future<void> test_annotation_notBeforeDeclaration() async {
     // SimpleIdentifier  Annotation  MethodDeclaration  ClassDeclaration
     addTestSource('class C { @A^ }');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        constructors: true,
+        completionLocation: 'Annotation_name',
+        returnValue: true,
+        typeNames: true);
     // TODO(danrubel): This test fails because the @A is dropped from the AST.
     // Ideally we generate a synthetic field and associate the annotation
     // with that field, but doing so breaks test_constructorAndMethodNameCollision.
     // See https://dart-review.googlesource.com/c/sdk/+/65760/3/pkg/analyzer/lib/src/fasta/ast_builder.dart#2395
   }
 
-  Future<void> test_ArgumentList() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('void main() {expect(^)}');
-    // If "expect()" were resolved, then either namedArgs would be true
-    // or returnValue and typeNames would be true.
+  Future<void> test_argumentList_constructor_named_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A.b(^); }'
+      'class A{ A.b({one, two}) {} }',
+    );
     await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_constructor_named_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A.b(o^); }'
+      'class A { A.b({one, two}) {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_constructor_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A(^); }'
+      'class A{ A({one, two}) {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_constructor_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A(o^); }'
+      'class A { A({one, two}) {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_factory_named_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A.b(^); }'
+      'class A{ factory A.b({one, two}) {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_factory_named_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A.b(o^); }'
+      'class A { factory A.b({one, two}) {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_factory_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A(^); }'
+      'class A{ factory A({one, two}) {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_factory_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A(o^); }'
+      'class A { factory A({one, two}) {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ArgumentList_constructor_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_method_resolved_1_0() async {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('main() { foo(^);} foo({one, two}) {}');
+    await assertOpType(
+        completionLocation: 'ArgumentList_method_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_method_resolved_1_1() async {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('main() { foo(o^);} foo({one, two}) {}');
+    await assertOpType(
+        completionLocation: 'ArgumentList_method_named', namedArgs: true);
+  }
+
+  Future<void> test_argumentList_namedParam() async {
+    // SimpleIdentifier  NamedExpression  ArgumentList  MethodInvocation
+    // ExpressionStatement
+    addTestSource('void main() {expect(foo: ^)}');
+    await assertOpType(
+        completionLocation: 'ArgumentList_method_named',
         constructors: true,
-        namedArgs: true,
         returnValue: true,
         typeNames: true);
   }
 
-  Future<void> test_ArgumentList_namedParam() async {
-    // SimpleIdentifier  NamedExpression  ArgumentList  MethodInvocation
-    // ExpressionStatement
-    addTestSource('void main() {expect(foo: ^)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_ArgumentList_prefixedIdentifier() async {
+  Future<void> test_argumentList_prefixedIdentifier() async {
     // SimpleIdentifier  PrefixedIdentifier  ArgumentList
     addTestSource('void main() {expect(aa.^)}');
     await assertOpType(
         constructors: true, returnValue: true, typeNames: true, prefixed: true);
   }
 
-  Future<void> test_ArgumentList_resolved() async {
+  Future<void> test_argumentList_resolved() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addTestSource('void main() {int.parse(^)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_AsIdentifier() async {
-    addTestSource('class A {var asdf; foo() {as^}');
     await assertOpType(
+        completionLocation: 'ArgumentList_method_unnamed',
         constructors: true,
         returnValue: true,
-        typeNames: true,
-        voidReturn: true);
+        typeNames: true);
   }
 
-  Future<void> test_Assert() async {
-    addTestSource('main() {assert(^)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+  Future<void> test_argumentList_resolved_2_0() async {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('void main() {int.parse("16", ^)}');
+    await assertOpType(
+        completionLocation: 'ArgumentList_method_named', namedArgs: true);
   }
 
-  Future<void> test_AssertInitializer() async {
+  Future<void> test_argumentList_unresolved() async {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('void main() {expect(^)}');
+    // If "expect()" were resolved, then either namedArgs would be true
+    // or returnValue and typeNames would be true.
+    await assertOpType(
+        completionLocation: 'ArgumentList_method_unnamed',
+        constructors: true,
+        namedArgs: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_asExpression_rightHandSide() async {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('class A {var b; X _c; foo() {var a; (a as ^).foo();}');
+    await assertOpType(
+        completionLocation: 'AsExpression_type', typeNames: true);
+  }
+
+  Future<void> test_assertInitializer_firstArgument() async {
     addTestSource('class C { C() : assert(^); }');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'AssertInitializer_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_AssignmentExpression_RHS() async {
+  Future<void> test_assertInitializer_secondArgument() async {
+    addTestSource('class C { C() : assert(true, ^); }');
+    // TODO(brianwilkerson) This should have a location of
+    //  'AssertInitializer_message'
+    await assertOpType();
+  }
+
+  Future<void> test_assertStatement_firstArgument() async {
+    addTestSource('main() {assert(^)}');
+    await assertOpType(
+        completionLocation: 'AssertStatement_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_assertStatement_secondArgument() async {
+    addTestSource('main() {assert(true, ^)}');
+    // TODO(brianwilkerson) This should have a location of
+    //  'AssertStatement_message'
+    await assertOpType();
+  }
+
+  Future<void> test_assignmentExpression_name() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // VariableDeclarationStatement  Block
+    addTestSource('class A {} main() {int a; int ^b = 1;}');
+    await assertOpType(varNames: true);
+  }
+
+  Future<void> test_assignmentExpression_RHS() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('class A {} main() {int a; int b = ^}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'VariableDeclaration_initializer',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_AssignmentExpression_type() async {
+  Future<void> test_assignmentExpression_type() async {
     // SimpleIdentifier  TypeName  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('''
@@ -105,13 +374,14 @@
     // Consider suggesting only types
     // if only spaces separates the 1st and 2nd identifiers.
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_AssignmentExpression_type_newline() async {
+  Future<void> test_assignmentExpression_type_newline() async {
     // SimpleIdentifier  TypeName  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('''
@@ -123,13 +393,14 @@
     // if newline follows first identifier
     // because user is probably starting a new statement
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_AssignmentExpression_type_partial() async {
+  Future<void> test_assignmentExpression_type_partial() async {
     // SimpleIdentifier  TypeName  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('''
@@ -142,13 +413,14 @@
     // Consider suggesting only types
     // if only spaces separates the 1st and 2nd identifiers.
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_AssignmentExpression_type_partial_newline() async {
+  Future<void> test_assignmentExpression_type_partial_newline() async {
     // SimpleIdentifier  TypeName  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('''
@@ -160,69 +432,196 @@
     // if newline follows first identifier
     // because user is probably starting a new statement
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_AwaitExpression() async {
+  Future<void> test_awaitExpression_assignment() async {
+    addTestSource('main() async {A a; int x = await ^}');
+    await assertOpType(
+        completionLocation: 'AwaitExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_awaitExpression_assignment2() async {
+    addTestSource('main() async {A a; int x = await ^ await foo;}');
+    await assertOpType(
+        completionLocation: 'AwaitExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_awaitExpression_assignment3() async {
+    addTestSource('main() async {A a; int x = await v^ int y = await foo;}');
+    await assertOpType(
+        completionLocation: 'AwaitExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_awaitExpression_statement() async {
     // SimpleIdentifier  AwaitExpression  ExpressionStatement
     addTestSource('main() async {A a; await ^}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'AwaitExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_AwaitExpression2() async {
+  Future<void> test_awaitExpression_statement2() async {
     addTestSource('main() async {A a; await c^ await}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'AwaitExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_AwaitExpression3() async {
+  Future<void> test_awaitExpression_statement3() async {
     addTestSource('main() async {A a; await ^ await foo;}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'AwaitExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_AwaitExpression4() async {
+  Future<void> test_awaitExpression_statement4() async {
     addTestSource('main() async {A a; await ^ await bar();}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'AwaitExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_AwaitExpression_assignment() async {
-    addTestSource('main() async {A a; int x = await ^}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_AwaitExpression_assignment2() async {
-    addTestSource('main() async {A a; int x = await ^ await foo;}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_AwaitExpression_assignment3() async {
-    addTestSource('main() async {A a; int x = await v^ int y = await foo;}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_BinaryExpression_LHS() async {
+  Future<void> test_binaryExpression_LHS() async {
     // SimpleIdentifier  BinaryExpression  VariableDeclaration
     // VariableDeclarationList  VariableDeclarationStatement
     addTestSource('main() {int a = 1, b = ^ + 2;}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'VariableDeclaration_initializer',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_BinaryExpression_RHS() async {
+  Future<void> test_binaryExpression_RHS() async {
     // SimpleIdentifier  BinaryExpression  VariableDeclaration
     // VariableDeclarationList  VariableDeclarationStatement
     addTestSource('main() {int a = 1, b = 2 + ^;}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'BinaryExpression_+_rightOperand',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_BinaryExpression_RHS2() async {
+  Future<void> test_binaryExpression_RHS2() async {
     // SimpleIdentifier  BinaryExpression
     addTestSource('main() {if (c < ^)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'BinaryExpression_<_rightOperand',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_Block() async {
+  Future<void> test_block_empty() async {
+    // Block  BlockFunctionBody  MethodDeclaration  ClassDeclaration
+    addTestSource('class A extends E implements I with M {a() {^}}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_block_final() async {
+    addTestSource('main() {final ^}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_block_final2() async {
+    addTestSource('main() {final S^ v;}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_block_final3() async {
+    addTestSource('main() {final ^ v;}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_block_final_final() async {
+    addTestSource('main() {final ^ final S x;}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_block_final_final2() async {
+    addTestSource('main() {final S^ final S x;}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_block_identifier_partial() async {
+    addTestSource('class X {a() {var f; {var x;} D^ var r;} void b() { }}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_block_inConstructor() async {
+    addTestSource('class A {A() {^}}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_block_inFunction() async {
+    addTestSource('foo() {^}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_block_inMethod() async {
+    addTestSource('class A {foo() {^}}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_block_keyword() async {
+    addTestSource('class C { static C get instance => null; } main() {C.in^}');
+    await assertOpType(
+        constructors: true,
+        prefixed: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_block_startOfStatement() async {
     // Block  BlockFunctionBody  MethodDeclaration
     addTestSource('''
       class X {
@@ -234,141 +633,62 @@
         }
       }''');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_Block_catch_2a() async {
-    // '}'  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} catch () {} ^}');
+  Future<void> test_block_static() async {
+    addTestSource('class A {static foo() {^}}');
     await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        staticMethodBody: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_break_afterLabel() async {
+    addTestSource('main() { foo: while (true) { break foo ^ ; } }');
+    await assertOpType(/* No valid completions */);
+  }
+
+  Future<void> test_break_beforeLabel() async {
+    addTestSource('main() { foo: while (true) { break ^ foo; } }');
+    await assertOpType(statementLabel: true);
+  }
+
+  Future<void> test_break_noLabel() async {
+    addTestSource('main() { foo: while (true) { break ^; } }');
+    await assertOpType(statementLabel: true);
+  }
+
+  Future<void> test_builtInIdentifier_as() async {
+    addTestSource('class A {var asdf; foo() {as^}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_Block_catch_2b() async {
-    // [ExpressionStatement 'c']  Block  BlockFunctionBody
-    addTestSource('main() {try {} catch () {} c^}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
+  Future<void> test_builtInIdentifier_as2() async {
+    addTestSource('class A {var asdf; foo() {A as^}');
+    await assertOpType();
   }
 
-  Future<void> test_Block_catch_2c() async {
-    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} catch () {} ^;}');
+  Future<void> test_cascadeExpression_selector1() async {
+    // PropertyAccess  CascadeExpression  ExpressionStatement  Block
+    addTestSource('''
+      // looks like a cascade to the parser
+      // but the user is trying to get completions for a non-cascade
+      main() {A a; a.^.z}''');
     await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_catch_2d() async {
-    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
-    addTestSource('main() {try {} catch () {} ^ Foo foo;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_catch_3a() async {
-    // '}'  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} finally {} ^}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_catch_3b() async {
-    // [ExpressionStatement 'c']  Block  BlockFunctionBody
-    addTestSource('main() {try {} finally {} c^}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_catch_3c() async {
-    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} finally {} ^;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_catch_3d() async {
-    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
-    addTestSource('main() {try {} finally {} ^ Foo foo;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_empty() async {
-    // Block  BlockFunctionBody  MethodDeclaration  ClassDeclaration
-    addTestSource('class A extends E implements I with M {a() {^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_identifier_partial() async {
-    addTestSource('class X {a() {var f; {var x;} D^ var r;} void b() { }}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_in_constructor() async {
-    addTestSource('class A {A() {^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_in_function() async {
-    addTestSource('foo() {^}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_in_method() async {
-    addTestSource('class A {foo() {^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_Block_keyword() async {
-    addTestSource('class C { static C get instance => null; } main() {C.in^}');
-    await assertOpType(
+        completionLocation: 'PropertyAccess_propertyName',
         constructors: true,
         prefixed: true,
         returnValue: true,
@@ -376,122 +696,201 @@
         voidReturn: true);
   }
 
-  Future<void> test_Block_static() async {
-    addTestSource('class A {static foo() {^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        staticMethodBody: true,
-        voidReturn: true);
-  }
-
-  Future<void> test_CascadeExpression_selector1() async {
-    // PropertyAccess  CascadeExpression  ExpressionStatement  Block
-    addTestSource('''
-      // looks like a cascade to the parser
-      // but the user is trying to get completions for a non-cascade
-      main() {A a; a.^.z}''');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
-  Future<void> test_CascadeExpression_selector2() async {
+  Future<void> test_cascadeExpression_selector2() async {
     // SimpleIdentifier  PropertyAccess  CascadeExpression  ExpressionStatement
     addTestSource('main() {A a; a..^z}');
     await assertOpType(
+        completionLocation: 'PropertyAccess_propertyName',
         constructors: true,
+        prefixed: true,
         returnValue: true,
-        voidReturn: true,
-        prefixed: true);
+        voidReturn: true);
   }
 
-  Future<void> test_CascadeExpression_selector2_withTrailingReturn() async {
+  Future<void> test_cascadeExpression_selector2_withTrailingReturn() async {
     // PropertyAccess  CascadeExpression  ExpressionStatement  Block
     addTestSource('main() {A a; a..^ return}');
     await assertOpType(
+        completionLocation: 'PropertyAccess_propertyName',
         constructors: true,
+        prefixed: true,
         returnValue: true,
-        voidReturn: true,
-        prefixed: true);
+        voidReturn: true);
   }
 
-  Future<void> test_CascadeExpression_target() async {
+  Future<void> test_cascadeExpression_target() async {
     // SimpleIdentifier  CascadeExpression  ExpressionStatement
     addTestSource('main() {A a; a^..b}');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_CatchClause_typed() async {
-    // Block  CatchClause  TryStatement
-    addTestSource('class A {a() {try{var x;} on E catch (e) {^}}}');
+  Future<void> test_classDeclaration_body() async {
+    // ClassDeclaration  CompilationUnit
+    addTestSource('@deprecated class A {^}');
     await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
   }
 
-  Future<void> test_CatchClause_untyped() async {
-    // Block  CatchClause  TryStatement
-    addTestSource('class A {a() {try{var x;} catch (e, s) {^}}}');
+  Future<void> test_classDeclaration_body2() async {
+    // SimpleIdentifier  MethodDeclaration  ClassDeclaration
+    addTestSource('@deprecated class A {^mth() {}}');
     await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
   }
 
-  Future<void> test_CommentReference() async {
+  Future<void> test_commentReference() async {
     // SimpleIdentifier  CommentReference  Comment  MethodDeclaration
     addTestSource('class A {/** [^] */ mth() {}');
     await assertOpType(
+        completionLocation: 'CommentReference_identifier',
         constructors: true,
+        kind: CompletionSuggestionKind.IDENTIFIER,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        kind: CompletionSuggestionKind.IDENTIFIER);
+        voidReturn: true);
   }
 
-  Future<void> test_ConditionalExpression_elseExpression() async {
-    // SimpleIdentifier  ConditionalExpression  ReturnStatement
-    addTestSource('class C {foo(){var f; {var x;} return a ? T1 : T^}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_ConditionalExpression_elseExpression_empty() async {
+  Future<void> test_conditionalExpression_elseExpression_empty() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? T1 : ^}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ConditionalExpression_elseExpression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ConditionalExpression_partial_thenExpression() async {
+  Future<void> test_conditionalExpression_elseExpression_nonEmpty() async {
+    // SimpleIdentifier  ConditionalExpression  ReturnStatement
+    addTestSource('class C {foo(){var f; {var x;} return a ? T1 : T^}}');
+    await assertOpType(
+        completionLocation: 'ConditionalExpression_elseExpression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_conditionalExpression_partial_thenExpression() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? T^}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ConditionalExpression_thenExpression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ConditionalExpression_partial_thenExpression_empty() async {
+  Future<void> test_conditionalExpression_partial_thenExpression_empty() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? ^}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ConditionalExpression_thenExpression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ConditionalExpression_thenExpression() async {
+  Future<void> test_conditionalExpression_thenExpression_nonEmpty() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? T^ : c}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ConditionalExpression_thenExpression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ConstructorFieldInitializer_name() async {
+  Future<void> test_constructorDeclaration_const_named() async {
+    // ConstructorDeclaration
+    // The additional syntax with assert is to ensure that the target node is
+    // a ConstructorDeclaration, instead of a MethodDeclaration.
+    addTestSource('''
+      class ABC {
+        int i;
+        const A^.b(this.i) : assert(i != 0);
+      }''');
+    await assertOpType(
+        completionLocation: 'ConstructorDeclaration_returnType',
+        typeNames: true);
+  }
+
+  Future<void> test_constructorDeclaration_const_named2() async {
+    // ConstructorDeclaration
+    // The additional syntax with assert is to ensure that the target node is
+    // a ConstructorDeclaration, instead of a MethodDeclaration.
+    // A negative test that type names aren't expected to be the name of a named
+    // constructor.
+    addTestSource('''
+      class ABC {
+        int i;
+        const A.^b(this.i) : assert(i != 0);
+      }''');
+    await assertOpType(typeNames: false);
+  }
+
+  Future<void> test_constructorDeclaration_const_unnamed() async {
+    // ConstructorDeclaration
+    // The additional syntax with assert is to ensure that the target node is
+    // a ConstructorDeclaration, instead of a MethodDeclaration.
+    addTestSource('''
+      class ABC {
+        int i;
+        const A^(this.i) : assert(i != 0);
+      }''');
+    await assertOpType(
+        completionLocation: 'ConstructorDeclaration_returnType',
+        typeNames: true);
+  }
+
+  Future<void> test_constructorDeclaration_factory_named() async {
+    // ConstructorDeclaration
+    addTestSource(
+      'class A { factory A^.b() {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ConstructorDeclaration_returnType',
+        typeNames: true);
+  }
+
+  Future<void> test_constructorDeclaration_factory_named2() async {
+    // ConstructorDeclaration
+    // A negative test that type names aren't expected to be the name of a named
+    // constructor.
+    addTestSource(
+      'class A { factory A.^b() {} }',
+    );
+    await assertOpType(typeNames: false);
+  }
+
+  Future<void> test_constructorDeclaration_factory_unnamed() async {
+    // ConstructorDeclaration
+    addTestSource(
+      'class A { factory A^() {} }',
+    );
+    await assertOpType(
+        completionLocation: 'ConstructorDeclaration_returnType',
+        typeNames: true);
+  }
+
+  Future<void> test_constructorDeclaration_generative_unnamed() async {
+    // ClassDeclaration
+    // This ConstructorDeclaration case is handled by the ClassDeclaration
+    // visitor.
+    addTestSource('''
+      class ABC {
+        int i;
+        A^(this.i) : assert(i != 0);
+      }''');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_constructorFieldInitializer_name() async {
     addTestSource(r'''
 class C {
   final int foo;
@@ -499,10 +898,11 @@
   C() : ^
 }
 ''');
-    await assertOpType();
+    await assertOpType(
+        completionLocation: 'ConstructorDeclaration_initializer');
   }
 
-  Future<void> test_ConstructorFieldInitializer_value() async {
+  Future<void> test_constructorFieldInitializer_value() async {
     addTestSource(r'''
 class C {
   final int foo;
@@ -511,92 +911,286 @@
 }
 ''');
     await assertOpType(
-      constructors: true,
-      returnValue: true,
-      typeNames: true,
-    );
+        completionLocation: 'ConstructorFieldInitializer_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_DefaultFormalParameter_named_expression() async {
+  Future<void> test_constructorName_name() async {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
+    // InstanceCreationExpression
+    addTestSource('main() {new X.^}');
+    await assertOpType(constructors: true, prefixed: true);
+  }
+
+  Future<void> test_constructorName_name_resolved() async {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
+    // InstanceCreationExpression
+    addTestSource('main() {new Str^ing.fromCharCodes([]);}');
+    await assertOpType(constructors: true);
+  }
+
+  Future<void> test_constructorName_nameAndPrefix_resolved() async {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
+    // InstanceCreationExpression
+    addTestSource('''
+import 'dart:core' as core;
+main() {new core.String.from^CharCodes([]);}
+''');
+    await assertOpType(constructors: true, prefixed: true);
+  }
+
+  Future<void> test_constructorName_resolved() async {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
+    // InstanceCreationExpression
+    addTestSource('main() {new String.fr^omCharCodes([]);}');
+    await assertOpType(constructors: true, prefixed: true);
+  }
+
+  Future<void> test_constructorName_unresolved() async {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
+    // InstanceCreationExpression
+    addTestSource('main() {new String.fr^omCharCodes([]);}');
+    await assertOpType(constructors: true, prefixed: true);
+  }
+
+  Future<void> test_continue_afterLabel() async {
+    addTestSource('main() { foo: while (true) { continue foo ^ ; } }');
+    await assertOpType(/* No valid completions */);
+  }
+
+  Future<void> test_continue_beforeLabel() async {
+    addTestSource('main() { foo: while (true) { continue ^ foo; } }');
+    await assertOpType(statementLabel: true, caseLabel: true);
+  }
+
+  Future<void> test_continue_noLabel() async {
+    addTestSource('main() { foo: while (true) { continue ^; } }');
+    await assertOpType(statementLabel: true, caseLabel: true);
+  }
+
+  Future<void> test_defaultFormalParameter_named_expression() async {
     // DefaultFormalParameter FormalParameterList MethodDeclaration
     addTestSource('class A {a(blat: ^) { }}');
     await assertOpType(
-      constructors: true,
-      returnValue: true,
-      typeNames: true,
-    );
+        completionLocation: 'DefaultFormalParameter_defaultValue',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_DoStatement() async {
+  Future<void> test_doStatement_inCondition() async {
     // SimpleIdentifier  DoStatement  Block
     addTestSource('main() {do{} while(^x);}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'DoStatement_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ExpressionFunctionBody() async {
+  Future<void> test_doubleLiteral() async {
+    addTestSource('main() { print(1.2^); }');
+    await assertOpType();
+  }
+
+  Future<void> test_expressionFunctionBody_beginning() async {
     // SimpleIdentifier  ExpressionFunctionBody  FunctionExpression
     addTestSource('m(){[1].forEach((x)=>^x);}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ExpressionFunctionBody_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ExpressionStatement() async {
+  Future<void> test_expressionStatement_beginning() async {
     // ExpressionStatement  Block  BlockFunctionBody
     addTestSource('n(){f(3);^}');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_ForEachStatement() async {
-    // SimpleIdentifier  ForEachStatement  Block
-    addTestSource('main() {for(z in ^zs) {}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+  Future<void> test_expressionStatement_name() async {
+    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class C {a() {C ^}}');
+    await assertOpType(
+        completionLocation: 'ExpressionStatement_expression', varNames: true);
   }
 
-  Future<void> test_ForEachStatement_body_typed() async {
+  Future<void> test_expressionStatement_name_semicolon() async {
+    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class C {a() {C ^;}}');
+    await assertOpType(
+        completionLocation: 'ExpressionStatement_expression', varNames: true);
+  }
+
+  Future<void> test_expressionStatement_prefixed_name() async {
+    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class C {a() {x.Y ^}}');
+    await assertOpType(
+        completionLocation: 'ExpressionStatement_expression', varNames: true);
+  }
+
+  Future<void> test_expressionStatement_prefixed_name_semicolon() async {
+    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
+    addTestSource('class C {a() {x.Y ^;}}');
+    await assertOpType(
+        completionLocation: 'ExpressionStatement_expression', varNames: true);
+  }
+
+  Future<void> test_extendsClause_beginning() async {
+    // ExtendsClause  ClassDeclaration
+    addTestSource('class x extends ^\n{}');
+    await assertOpType(
+        completionLocation: 'ExtendsClause_superclass', typeNames: true);
+  }
+
+  Future<void> test_extensionDeclaration_body_atBeginning() async {
+    // SimpleIdentifier  MethodDeclaration  ExtensionDeclaration
+    addTestSource('extension E on int {^mth() {}}');
+    await assertOpType(
+        completionLocation: 'ExtensionDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_extensionDeclaration_body_atEnd() async {
+    // ExtensionDeclaration  CompilationUnit
+    addTestSource('extension E on int {^}');
+    await assertOpType(
+        completionLocation: 'ExtensionDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_fieldDeclaration_name_typed() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addTestSource('class C {A ^}');
+    await assertOpType(varNames: true);
+  }
+
+  Future<void> test_fieldDeclaration_name_var() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addTestSource('class C {var ^}');
+    await assertOpType();
+  }
+
+  Future<void> test_fieldDeclaration_type() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addTestSource('class C {^ foo; }');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_fieldDeclaration_type_noSemicolon() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // FieldDeclaration
+    addTestSource('class C {^ foo }');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_forEachStatement_body_typed() async {
     // Block  ForEachStatement
     addTestSource('main(args) {for (int foo in bar) {^}}');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_ForEachStatement_body_untyped() async {
+  Future<void> test_forEachStatement_body_untyped() async {
     // Block  ForEachStatement
     addTestSource('main(args) {for (foo in bar) {^}}');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_ForEachStatement_iterable() async {
+  Future<void> test_forEachStatement_iterable() async {
     // SimpleIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (int foo in ^) {}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ForEachPartsWithDeclaration_iterable',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ForElement_body() async {
+  Future<void> test_forEachStatement_iterator() async {
+    // SimpleIdentifier  ForEachStatement  Block
+    addTestSource('main() {for(z in ^zs) {}}');
+    await assertOpType(
+        completionLocation: 'ForEachPartsWithIdentifier_iterable',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_forEachStatement_loopVariable() async {
+    // SimpleIdentifier  ForEachStatement  Block
+    addTestSource('main(args) {for (^ in args) {}}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_forEachStatement_loopVariable_name() async {
+    // DeclaredIdentifier  ForEachStatement  Block
+    addTestSource('main(args) {for (String ^ in args) {}}');
+    await assertOpType();
+  }
+
+  Future<void> test_forEachStatement_loopVariable_name2() async {
+    // DeclaredIdentifier  ForEachStatement  Block
+    addTestSource('main(args) {for (String f^ in args) {}}');
+    await assertOpType();
+  }
+
+  Future<void> test_forEachStatement_loopVariable_type() async {
+    // SimpleIdentifier  ForEachStatement  Block
+    addTestSource('main(args) {for (^ foo in args) {}}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_forEachStatement_loopVariable_type2() async {
+    // DeclaredIdentifier  ForEachStatement  Block
+    addTestSource('main(args) {for (S^ foo in args) {}}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_forElement_body() async {
     addTestSource('main(args) {[for (var foo in [0]) ^];}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ForElement_body',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ForElement_forEachParts_iterable() async {
+  Future<void> test_forElement_forEachParts_iterable() async {
     addTestSource('main(args) {[for (var foo in ^) foo];}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ForEachPartsWithDeclaration_iterable',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ForElement_forEachParts_type() async {
+  Future<void> test_forElement_forEachParts_type() async {
     addTestSource('main(args) {[for (i^ foo in [0]) foo];}');
     await assertOpType(typeNames: true);
   }
 
-  Future<void> test_FormalParameter_partialType() async {
+  Future<void> test_formalParameter_partialType() async {
     // FormalParameterList MethodDeclaration
     addTestSource('class A {a(b.^ f) { }}');
     await assertOpType(
@@ -607,7 +1201,7 @@
     );
   }
 
-  Future<void> test_FormalParameter_partialType2() async {
+  Future<void> test_formalParameter_partialType2() async {
     // FormalParameterList MethodDeclaration
     addTestSource('class A {a(b.z^ f) { }}');
     await assertOpType(
@@ -618,7 +1212,7 @@
     );
   }
 
-  Future<void> test_FormalParameter_partialType3() async {
+  Future<void> test_formalParameter_partialType3() async {
     // FormalParameterList MethodDeclaration
     addTestSource('class A {a(b.^) { }}');
     await assertOpType(
@@ -629,185 +1223,752 @@
     );
   }
 
-  Future<void> test_ForStatement_condition() async {
-    // SimpleIdentifier  ForStatement
-    addTestSource('main() {for (int index = 0; i^)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+  Future<void> test_formalParameterList_empty() async {
+    // FormalParameterList MethodDeclaration
+    addTestSource('class A {a(^) { }}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
   }
 
-  Future<void> test_ForStatement_updaters() async {
+  Future<void> test_forStatement_condition() async {
+    // SimpleIdentifier  ForStatement
+    addTestSource('main() {for (int index = 0; i^)}');
+    await assertOpType(
+        completionLocation: 'ForParts_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_forStatement_initializer() async {
+    // SimpleIdentifier  ForStatement
+    addTestSource('main() {List a; for (^)}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_forStatement_initializer_inKeyword() async {
+    addTestSource('main() { for (var v i^) }');
+    await assertOpType();
+  }
+
+//
+  Future<void> test_forStatement_initializer_type() async {
+    // SimpleIdentifier  ForStatement
+    addTestSource('main() {List a; for (i^ v = 0;)}');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void>
+      test_forStatement_initializer_variableNameEmpty_afterType() async {
+    addTestSource('main() { for (String ^) }');
+    await assertOpType(varNames: true);
+  }
+
+  Future<void> test_forStatement_updaters() async {
     // SimpleIdentifier  ForStatement
     addTestSource('main() {for (int index = 0; index < 10; i^)}');
-    // TODO (danrubel) may want to exclude methods/functions with void return
+    // TODO (danrubel) might want to exclude methods/functions with void return
     await assertOpType(
+        completionLocation: 'ForParts_updater',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_ForStatement_updaters_prefix_expression() async {
+  Future<void> test_forStatement_updaters_prefix_expression() async {
     // SimpleIdentifier  PrefixExpression  ForStatement
     addTestSource('main() {for (int index = 0; index < 10; ++i^)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'PrefixExpression_++_operand',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_IfElement_condition() async {
+  Future<void> test_functionDeclaration_inLineComment() async {
+    // Comment  CompilationUnit
+    addTestSource('''
+      // normal comment ^
+      zoo(z) { } String name;''');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inLineComment2() async {
+    // Comment  CompilationUnit
+    addTestSource('''
+      // normal ^comment
+      zoo(z) { } String name;''');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inLineComment3() async {
+    // Comment  CompilationUnit
+    addTestSource('''
+      // normal comment ^
+      // normal comment 2
+      zoo(z) { } String name;''');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inLineComment4() async {
+    // Comment  CompilationUnit
+    addTestSource('''
+      // normal comment
+      // normal comment 2^
+      zoo(z) { } String name;''');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inLineDocComment() async {
+    // Comment  FunctionDeclaration  CompilationUnit
+    addTestSource('''
+      /// some dartdoc ^
+      zoo(z) { } String name;''');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inLineDocComment2() async {
+    // Comment  FunctionDeclaration  CompilationUnit
+    addTestSource('''
+      /// some ^dartdoc
+      zoo(z) { } String name;''');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inStarComment() async {
+    // Comment  CompilationUnit
+    addTestSource('/* ^ */ zoo(z) {} String name;');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inStarComment2() async {
+    // Comment  CompilationUnit
+    addTestSource('/*  *^/ zoo(z) {} String name;');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inStarDocComment() async {
+    // Comment  FunctionDeclaration  CompilationUnit
+    addTestSource('/** ^ */ zoo(z) { } String name; ');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_inStarDocComment2() async {
+    // Comment  FunctionDeclaration  CompilationUnit
+    addTestSource('/**  *^/ zoo(z) { } String name;');
+    await assertOpType();
+  }
+
+  Future<void> test_functionDeclaration_name1() async {
+    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
+    addTestSource('const ^Fara();');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_name2() async {
+    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
+    addTestSource('const F^ara();');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_returnType() async {
+    // CompilationUnit
+    addTestSource('^ zoo(z) { } String name;');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_returnType_afterLineComment() async {
+    // FunctionDeclaration  CompilationUnit
+    addTestSource('''
+      // normal comment
+      ^ zoo(z) {} String name;''');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_returnType_afterLineComment2() async {
+    // FunctionDeclaration  CompilationUnit
+    // TOD(danrubel) left align all test source
+    addTestSource('''
+// normal comment
+^ zoo(z) {} String name;''');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_returnType_afterLineDocComment() async {
+    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
+    addTestSource('''
+      /// some dartdoc
+      ^ zoo(z) { } String name;''');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void>
+      test_functionDeclaration_returnType_afterLineDocComment2() async {
+    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
+    addTestSource('''
+/// some dartdoc
+^ zoo(z) { } String name;''');
+    // TODO(brianwilkerson) This should have a location of
+    //  'CompilationUnit_declaration' (or 'CompilationUnit_directive')
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_returnType_afterStarComment() async {
+    // CompilationUnit
+    addTestSource('/* */ ^ zoo(z) { } String name;');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_returnType_afterStarComment2() async {
+    // CompilationUnit
+    addTestSource('/* */^ zoo(z) { } String name;');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_functionDeclaration_returnType_afterStarDocComment() async {
+    // FunctionDeclaration  CompilationUnit
+    addTestSource('/** */ ^ zoo(z) { } String name;');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void>
+      test_functionDeclaration_returnType_afterStarDocComment2() async {
+    // FunctionDeclaration  CompilationUnit
+    addTestSource('/** */^ zoo(z) { } String name;');
+    // TODO(brianwilkerson) This should have a location of
+    //  'CompilationUnit_declaration' (or 'CompilationUnit_directive')
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_functionExpression_beforeBody() async {
+    // BlockFunctionBody  FunctionExpression  FunctionDeclaration
+    addTestSource('main()^ { int b = 2; b++; b. }');
+    await assertOpType();
+  }
+
+  Future<void> test_functionExpressionInvocation_beforeArgumentList() async {
+    // ArgumentList  FunctionExpressionInvocation  ExpressionStatement
+    addTestSource('main() { ((x) => x + 7)^(2) }');
+    await assertOpType();
+  }
+
+  Future<void> test_functionTypeAlias_name() async {
+    // SimpleIdentifier  FunctionTypeAlias  CompilationUnit
+    addTestSource('typedef n^ ;');
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_hideCombinator() async {
+    // SimpleIdentifier  HideCombinator  ImportDirective
+    addTestSource('''
+import '/testAB.dart' hide ^;
+class X {}
+''');
+    await assertOpType(completionLocation: 'HideCombinator_hiddenName');
+  }
+
+  Future<void> test_ifElement_condition() async {
     addTestSource('''
 main() {
   [if (^)];
 }
 ''');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'IfElement_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_IfElement_else() async {
+  Future<void> test_ifElement_else() async {
     addTestSource('''
 main() {
   [if (true) 0 else ^];
 }
 ''');
     await assertOpType(
+        completionLocation: 'IfElement_elseElement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_IfElement_then() async {
+  Future<void> test_ifElement_then() async {
     addTestSource('''
 main() {
   [if (true) ^];
 }
 ''');
     await assertOpType(
+        completionLocation: 'IfElement_thenElement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_IfStatement() async {
+  Future<void> test_ifStatement_afterCondition() async {
     // EmptyStatement  IfStatement  Block  BlockFunctionBody
     addTestSource('main(){var a; if (true) ^}');
     await assertOpType(
+        completionLocation: 'IfStatement_thenElement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_IfStatement_condition() async {
+  Future<void> test_ifStatement_condition() async {
     // SimpleIdentifier  IfStatement  Block  BlockFunctionBody
     addTestSource('main(){var a; if (^)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'IfStatement_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_IfStatement_empty() async {
+  Future<void> test_ifStatement_empty() async {
     // SimpleIdentifier  PrefixIdentifier  IfStatement
     addTestSource('class A {foo() {A a; if (^) something}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'IfStatement_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_IfStatement_invocation() async {
+  Future<void> test_ifStatement_invocation() async {
     // SimpleIdentifier  PrefixIdentifier  IfStatement
     addTestSource('main() {var a; if (a.^) something}');
     await assertOpType(
         constructors: true, returnValue: true, typeNames: true, prefixed: true);
   }
 
-  Future<void> test_IndexExpression() async {
+  Future<void> test_implementsClause_beginning() async {
+    // ImplementsClause  ClassDeclaration
+    addTestSource('class x implements ^\n{}');
+    await assertOpType(
+        completionLocation: 'ImplementsClause_interface', typeNames: true);
+  }
+
+  Future<void> test_importDirective_dart() async {
+    // SimpleStringLiteral  ImportDirective
+    addTestSource('''
+      import "dart^";
+      main() {}''');
+    await assertOpType();
+  }
+
+  Future<void> test_indexExpression_emptyIndex() async {
     addTestSource('class C {foo(){var f; {var x;} f[^]}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'IndexExpression_index',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_IndexExpression2() async {
+  Future<void> test_indexExpression_nonEmptyIndex() async {
     addTestSource('class C {foo(){var f; {var x;} f[T^]}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'IndexExpression_index',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_InstanceCreationExpression_keyword() async {
+  Future<void> test_instanceCreationExpression_afterNew() async {
+    // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
+    addTestSource('class C {foo(){var f; {var x;} new ^}}');
+    await assertOpType(constructors: true);
+  }
+
+  Future<void> test_instanceCreationExpression_keyword() async {
     // InstanceCreationExpression  ExpressionStatement  Block
     addTestSource('class C {foo(){var f; {var x;} new^ }}');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_InstanceCreationExpression_keyword2() async {
+  Future<void> test_instanceCreationExpression_keyword2() async {
     // InstanceCreationExpression  ExpressionStatement  Block
     addTestSource('class C {foo(){var f; {var x;} new^ C();}}');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_InterpolationExpression() async {
+  Future<void> test_instanceCreationExpression_trailingStmt() async {
+    // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
+    addTestSource('class C {foo(){var f; {var x;} new ^ int x = 7;}}');
+    await assertOpType(constructors: true);
+  }
+
+  Future<void> test_integerLiteral_inArgumentList() async {
+    addTestSource('main() { print(1^); }');
+    await assertOpType();
+  }
+
+  Future<void> test_integerLiteral_inListLiteral() async {
+    addTestSource('main() { var items = [1^]; }');
+    await assertOpType();
+  }
+
+  Future<void> test_interpolationExpression_afterDollar() async {
     // SimpleIdentifier  InterpolationExpression  StringInterpolation
     addTestSource('main() {String name; print("hello \$^");}');
-    await assertOpType(constructors: true, returnValue: true);
+    await assertOpType(
+        completionLocation: 'InterpolationExpression_expression',
+        constructors: true,
+        returnValue: true);
   }
 
-  Future<void> test_InterpolationExpression_block() async {
+  Future<void> test_interpolationExpression_block() async {
     // SimpleIdentifier  InterpolationExpression  StringInterpolation
     addTestSource('main() {String name; print("hello \${n^}");}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'InterpolationExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_InterpolationExpression_prefix_selector() async {
+  Future<void> test_interpolationExpression_prefix_selector() async {
     // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
     addTestSource('main() {String name; print("hello \${name.^}");}');
     await assertOpType(
         constructors: true, returnValue: true, typeNames: true, prefixed: true);
   }
 
-  Future<void> test_InterpolationExpression_prefix_target() async {
+  Future<void> test_interpolationExpression_prefix_target() async {
     // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
     addTestSource('main() {String name; print("hello \${nam^e.length}");}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'InterpolationExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_IsExpression_target() async {
+  Future<void> test_isExpression_target() async {
     // IfStatement  Block  BlockFunctionBody
     addTestSource('main(){var a; if (^ is A)}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'IfStatement_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_Literal_list() async {
+  Future<void> test_isExpression_type_empty() async {
+    // SimpleIdentifier  TypeName  IsExpression  IfStatement
+    addTestSource('main() {var x; if (x is ^) { }}');
+    await assertOpType(
+        completionLocation: 'IsExpression_type', typeNames: true);
+  }
+
+  Future<void> test_isExpression_type_partial() async {
+    // SimpleIdentifier  TypeName  IsExpression  IfStatement
+    addTestSource('main(){var a; if (a is Obj^)}');
+    await assertOpType(
+        completionLocation: 'IsExpression_type', typeNames: true);
+  }
+
+  Future<void> test_literal_list() async {
     // ']'  ListLiteral  ArgumentList  MethodInvocation
     addTestSource('main() {var Some; print([^]);}');
+    // TODO(brianwilkerson) This should have a location of
+    //  'ListLiteral_element'
     await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
-  Future<void> test_Literal_list2() async {
+  Future<void> test_literal_list2() async {
     // SimpleIdentifier ListLiteral  ArgumentList  MethodInvocation
     addTestSource('main() {var Some; print([S^]);}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ListLiteral_element',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_MapLiteralEntry() async {
+  Future<void> test_literal_string() async {
+    // SimpleStringLiteral  ExpressionStatement  Block
+    addTestSource('class A {a() {"hel^lo"}}');
+    await assertOpType();
+  }
+
+  Future<void> test_mapLiteralEntry_emptyKey() async {
     // MapLiteralEntry  MapLiteral  VariableDeclaration
     addTestSource('foo = {^');
+    // TODO(brianwilkerson) This should have a location of
+    //  'SetOrMapLiteral_element'
     await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
-  Future<void> test_MapLiteralEntry1() async {
+  Future<void> test_mapLiteralEntry_partialKey() async {
     // MapLiteralEntry  MapLiteral  VariableDeclaration
     addTestSource('foo = {T^');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'SetOrMapLiteral_element',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_MapLiteralEntry2() async {
+  Future<void> test_mapLiteralEntry_value() async {
     // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
     addTestSource('foo = {7:T^};');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'MapLiteralEntry_value',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_MethodInvocation_no_semicolon() async {
+  Future<void> test_methodDeclaration_inClass1() async {
+    // SimpleIdentifier  MethodDeclaration  ClassDeclaration
+    addTestSource('class Bar {const ^Fara();}');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inClass2() async {
+    // SimpleIdentifier  MethodDeclaration  ClassDeclaration
+    addTestSource('class Bar {const F^ara();}');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inClass_inLineComment() async {
+    // Comment  ClassDeclaration  CompilationUnit
+    addTestSource('''
+class C2 {
+  // normal comment ^
+  zoo(z) { } String name;
+}
+''');
+    // TODO(brianwilkerson) This should have a location of
+    //  'ClassDeclaration_member'
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inLineComment2() async {
+    // Comment  ClassDeclaration  CompilationUnit
+    addTestSource('''
+      class C2 {
+        // normal ^comment
+        zoo(z) { } String name; }''');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inLineComment3() async {
+    // Comment  ClassDeclaration  CompilationUnit
+    addTestSource('''
+      class C2 {
+        // normal comment ^
+        // normal comment 2
+        zoo(z) { } String name; }''');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inLineDocComment() async {
+    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('''
+      class C2 {
+        /// some dartdoc ^
+        zoo(z) { } String name; }''');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inLineDocComment2() async {
+    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('''
+      class C2 {
+        /// some ^dartdoc
+        zoo(z) { } String name; }''');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inStarComment() async {
+    // Comment  ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/* ^ */ zoo(z) {} String name;}');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inStarComment2() async {
+    // Comment  ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/*  *^/ zoo(z) {} String name;}');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inStarDocComment() async {
+    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/** ^ */ zoo(z) { } String name; }');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_inStarDocComment2() async {
+    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/**  *^/ zoo(z) { } String name; }');
+    await assertOpType();
+  }
+
+  Future<void> test_methodDeclaration_inClass_returnType() async {
+    // ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {^ zoo(z) { } String name; }');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterLineComment() async {
+    // MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('''
+class C2 {
+  // normal comment
+  ^ zoo(z) {} String name;
+}
+''');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterLineComment2() async {
+    // MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('''
+class C2 {
+  // normal comment
+  ^ zoo(z) {} String name;
+}
+''');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterLineDocComment() async {
+    // SimpleIdentifier  MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('''
+class C2 {
+  /// some dartdoc
+  ^ zoo(z) { } String name;
+}
+''');
+    // TODO(brianwilkerson) This should have a location of
+    //  'ClassDeclaration_member'
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterLineDocComment2() async {
+    // SimpleIdentifier  MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('''
+class C2 {
+  /// some dartdoc
+^ zoo(z) { } String name;
+
+''');
+    // TODO(brianwilkerson) This should have a location of
+    //  'ClassDeclaration_member'
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterStarComment() async {
+    // ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/* */ ^ zoo(z) { } String name; }');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterStarComment2() async {
+    // ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/* */^ zoo(z) { } String name; }');
+    await assertOpType(
+        completionLocation: 'ClassDeclaration_member', typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterStarDocComment() async {
+    // MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/** */ ^ zoo(z) { } String name; }');
+    // TODO(brianwilkerson) This should have a location of
+    //  'ClassDeclaration_member'
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void>
+      test_methodDeclaration_inClass_returnType_afterStarDocComment2() async {
+    // MethodDeclaration  ClassDeclaration  CompilationUnit
+    addTestSource('class C2 {/** */^ zoo(z) { } String name; }');
+    // TODO(brianwilkerson) This should have a location of
+    //  'ClassDeclaration_member'
+    await assertOpType(typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inExtension2_inName() async {
+    // SimpleIdentifier  ExtensionDeclaration  MixinDeclaration
+    addTestSource('extension E on int {const F^ara();}');
+    await assertOpType(
+        completionLocation: 'ExtensionDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inExtension_beforeName() async {
+    // SimpleIdentifier  ExtensionDeclaration  MixinDeclaration
+    addTestSource('extension E on int {const ^Fara();}');
+    await assertOpType(
+        completionLocation: 'ExtensionDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inExtension_returnType() async {
+    // ExtensionDeclaration  CompilationUnit
+    addTestSource('extension E on int {^ zoo(z) { } String name; }');
+    await assertOpType(
+        completionLocation: 'ExtensionDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inMixin1() async {
+    // SimpleIdentifier  MethodDeclaration  MixinDeclaration
+    addTestSource('mixin M {const ^Fara();}');
+    await assertOpType(
+        completionLocation: 'MixinDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inMixin2() async {
+    // SimpleIdentifier  MethodDeclaration  MixinDeclaration
+    addTestSource('mixin M {const F^ara();}');
+    await assertOpType(
+        completionLocation: 'MixinDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodDeclaration_inMixin_returnType() async {
+    // MixinDeclaration  CompilationUnit
+    addTestSource('mixin M {^ zoo(z) { } String name; }');
+    await assertOpType(
+        completionLocation: 'MixinDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_methodInvocation_no_semicolon() async {
     // MethodInvocation  ExpressionStatement  Block
     addTestSource('''
       class A implements I {
@@ -822,13 +1983,45 @@
         prefixed: true);
   }
 
-  Future<void> test_PostfixExpression() async {
+  Future<void> test_mixinDeclaration_body() async {
+    // MixinDeclaration  CompilationUnit
+    addTestSource('mixin M {^}');
+    await assertOpType(
+        completionLocation: 'MixinDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_mixinDeclaration_body2() async {
+    // SimpleIdentifier  MethodDeclaration  MixinDeclaration
+    addTestSource('mixin M {^mth() {}}');
+    await assertOpType(
+        completionLocation: 'MixinDeclaration_member', typeNames: true);
+  }
+
+  Future<void> test_namedExpression_beforeName() async {
+    addTestSource('''
+main() { f(3, ^); }
+void f(int a, {int b}) {}
+''');
+    await assertOpType(
+        completionLocation: 'ArgumentList_method_named', namedArgs: true);
+  }
+
+  Future<void> test_onClause_beginning() async {
+    // OnClause  MixinDeclaration
+    addTestSource('mixin M on ^\n{}');
+    await assertOpType(
+        completionLocation: 'OnClause_superclassConstraint', typeNames: true);
+  }
+
+  Future<void> test_postfixExpression_inOperator() async {
     // SimpleIdentifier  PostfixExpression  ForStatement
     addTestSource('int x = 0; main() {ax+^+;}');
+    // TODO(brianwilkerson) This should probably have a location of
+    //  'BinaryExpression_+_rightOperand'
     await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
-  Future<void> test_PrefixedIdentifier_class_const() async {
+  Future<void> test_prefixedIdentifier_class_const() async {
     // SimpleIdentifier PrefixedIdentifier ExpressionStatement Block
     addTestSource('main() {A.^}');
     await assertOpType(
@@ -839,7 +2032,7 @@
         prefixed: true);
   }
 
-  Future<void> test_PrefixedIdentifier_class_imported() async {
+  Future<void> test_prefixedIdentifier_class_imported() async {
     // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
     addTestSource('main() {A a; a.^}');
     await assertOpType(
@@ -850,17 +2043,18 @@
         prefixed: true);
   }
 
-  Future<void> test_PrefixedIdentifier_prefix() async {
+  Future<void> test_prefixedIdentifier_prefix() async {
     // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
     addTestSource('class X {foo(){A^.bar}}');
     await assertOpType(
+        completionLocation: 'Block_statement',
         constructors: true,
-        typeNames: true,
         returnValue: true,
+        typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_PropertyAccess_expression() async {
+  Future<void> test_propertyAccess_expression() async {
     // SimpleIdentifier  MethodInvocation  PropertyAccess  ExpressionStatement
     addTestSource('class A {a() {"hello".to^String().length}}');
     await assertOpType(
@@ -871,103 +2065,301 @@
         prefixed: true);
   }
 
-  Future<void> test_PropertyAccess_selector() async {
+  Future<void> test_propertyAccess_noTarget() async {
+    // SimpleIdentifier  PropertyAccess  ExpressionStatement
+    addTestSource('main() {.^}');
+    await assertOpType();
+  }
+
+  Future<void> test_propertyAccess_noTarget2() async {
+    // SimpleIdentifier  PropertyAccess  CascadeExpressions
+    addTestSource('main() {.^.}');
+    await assertOpType();
+  }
+
+  Future<void> test_propertyAccess_noTarget3() async {
+    // SimpleIdentifier  PropertyAccess  CascadeExpressions
+    addTestSource('main() {..^}');
+    // TODO(brianwilkerson) This should have a location of
+    //  'PropertyAccess_propertyName' (as should several others before this).
+    await assertOpType();
+  }
+
+  Future<void> test_propertyAccess_selector() async {
     // SimpleIdentifier  PropertyAccess  ExpressionStatement  Block
     addTestSource('class A {a() {"hello".length.^}}');
     await assertOpType(
+        completionLocation: 'PropertyAccess_propertyName',
         constructors: true,
+        prefixed: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        prefixed: true);
+        voidReturn: true);
   }
 
-  Future<void> test_ReturnStatement() async {
+  Future<void> test_returnStatement_empty() async {
     // ReturnStatement  Block
     addTestSource('f() { var vvv = 42; return ^ }');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'ReturnStatement_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_SpreadElement() async {
+  Future<void> test_showCombinator() async {
+    // SimpleIdentifier  HideCombinator  ImportDirective
+    addTestSource('''
+      import "/testAB.dart" show ^;
+      import "/testCD.dart";
+      class X {}''');
+    await assertOpType(completionLocation: 'ShowCombinator_shownName');
+  }
+
+  Future<void> test_simpleFormalParameter_closure() async {
+    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
+    addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_functionType_name() async {
+    addTestSource('void Function(int ^) v;');
+    // TODO(brianwilkerson) This should not have a location.
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', varNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_functionType_name_named() async {
+    addTestSource('void Function({int ^}) v;');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_functionType_name_optional() async {
+    addTestSource('void Function([int ^]) v;');
+    // TODO(brianwilkerson) This should not have a location.
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', varNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_functionType_type_withName() async {
+    addTestSource('void Function(Str^ name) v;');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_functionType_type_withName2() async {
+    addTestSource('void Function(^ name) v;');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_name_typed() async {
+    addTestSource('f(String ^, int b) {}');
+    // TODO(brianwilkerson) This should not have a location.
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', varNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_name_typed_hasName() async {
+    addTestSource('f(String n^, int b) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_name_typed_last() async {
+    addTestSource('f(String ^) {}');
+    // TODO(brianwilkerson) This should not have a location.
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', varNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_name_typed_last_hasName() async {
+    addTestSource('f(String n^) {}');
+    await assertOpType(typeNames: false, varNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_type_named() async {
+    addTestSource('f(^ name) {}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_type_optionalNamed() async {
+    // SimpleIdentifier  DefaultFormalParameter  FormalParameterList
+    addTestSource('m({Str^}) {}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_type_optionalPositional() async {
+    // SimpleIdentifier  DefaultFormalParameter  FormalParameterList
+    addTestSource('m([Str^]) {}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_type_withName() async {
+    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
+    addTestSource('m(Str^ name) {}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_type_withoutName1() async {
+    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
+    addTestSource('m(Str^) {}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_type_withoutName2() async {
+    // FormalParameterList
+    addTestSource('m(^) {}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_type_withoutName3() async {
+    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
+    addTestSource('m(int first, Str^) {}');
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
+  }
+
+  Future<void> test_simpleFormalParameter_untyped() async {
+    addTestSource('main(final ^) {}');
+    // TODO(brianwilkerson) This should have a location of
+    //  'FormalParameterList_parameter'
+    await assertOpType(typeNames: true, varNames: false);
+  }
+
+  Future<void> test_spreadElement_emptyExpression() async {
     addTestSource(r'''
 main() {
   [...^];
 }
 ''');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'SpreadElement_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_SwitchCase_between() async {
+  Future<void> test_switchCase_before() async {
+    // SwitchCase  SwitchStatement  Block
+    addTestSource('main() {switch(k) {^case 1:}}');
+    await assertOpType();
+  }
+
+  Future<void> test_switchCase_between() async {
     // SwitchCase  SwitchStatement  Block
     addTestSource('main() {switch(k) {case 1: ^ case 2: return}}');
     await assertOpType(
+        completionLocation: 'SwitchMember_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_SwitchCase_expression1() async {
+  Future<void> test_switchCase_expression1() async {
     // SimpleIdentifier  SwitchCase  SwitchStatement
     addTestSource('''m() {switch (x) {case ^D: return;}}''');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'SwitchCase_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_SwitchCase_expression2() async {
+  Future<void> test_switchCase_expression2() async {
     // SimpleIdentifier  SwitchCase  SwitchStatement
     addTestSource('''m() {switch (x) {case ^}}''');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'SwitchCase_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_SwitchDefault_between() async {
+  Future<void> test_switchDefault_before() async {
+    // SwitchDefault  SwitchStatement  Block
+    addTestSource('main() {switch(k) { ^ default: return;}}');
+    await assertOpType();
+  }
+
+  Future<void> test_switchDefault_between() async {
     // SwitchDefault  SwitchStatement  Block
     addTestSource('main() {switch(k) {case 1: ^ default: return;}}');
     await assertOpType(
+        completionLocation: 'SwitchMember_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_SwitchStatement_body_end() async {
+  Future<void> test_switchStatement_body_empty() async {
+    // Token('}')  SwitchStatement  Block
+    addTestSource('main() {switch(k) {^}}');
+    await assertOpType();
+  }
+
+  Future<void> test_switchStatement_body_end() async {
     // Token('}')  SwitchStatement  Block
     addTestSource('main() {switch(k) {case 1:^}}');
     await assertOpType(
+        completionLocation: 'SwitchMember_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_SwitchStatement_body_end2() async {
+  Future<void> test_switchStatement_body_end2() async {
     addTestSource('main() {switch(k) {case 1:as^}}');
+    // TODO(brianwilkerson) This should have a location of
+    //  'SwitchMember_statement'
     await assertOpType(
+        completionLocation: 'SwitchCase_statement',
         constructors: true,
         returnValue: true,
         typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_SwitchStatement_expression1() async {
+  Future<void> test_switchStatement_expression1() async {
     // SimpleIdentifier  SwitchStatement  Block
     addTestSource('main() {switch(^k) {case 1:{}}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'SwitchStatement_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_SwitchStatement_expression2() async {
+  Future<void> test_switchStatement_expression2() async {
     // SimpleIdentifier  SwitchStatement  Block
     addTestSource('main() {switch(k^) {case 1:{}}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'SwitchStatement_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-//
-  Future<void> test_SwitchStatement_expression_empty() async {
+  Future<void> test_switchStatement_expression_empty() async {
     // SimpleIdentifier  SwitchStatement  Block
     addTestSource('main() {switch(^) {case 1:{}}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
+    await assertOpType(
+        completionLocation: 'SwitchStatement_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_ThisExpression_block() async {
+  Future<void> test_thisExpression_block() async {
     // MethodInvocation  ExpressionStatement  Block
     addTestSource('''
       class A implements I {
@@ -982,1041 +2374,21 @@
         prefixed: true);
   }
 
-  Future<void> test_ThisExpression_constructor() async {
+  Future<void> test_thisExpression_constructor() async {
     // SimpleIdentifier  PropertyAccess  ExpressionStatement
     addTestSource('''
       class A implements I {
         A() {this.^}
       }''');
     await assertOpType(
+        completionLocation: 'PropertyAccess_propertyName',
         constructors: true,
+        prefixed: true,
         returnValue: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
-  Future<void> test_ThrowExpression() async {
-    // SimpleIdentifier  ThrowExpression  ExpressionStatement
-    addTestSource('main() {throw ^;}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_VariableDeclarationStatement_afterSemicolon() async {
-    // VariableDeclarationStatement  Block  BlockFunctionBody
-    addTestSource('class A {var a; x() {var b;^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
         voidReturn: true);
   }
 
-  Future<void> test_VariableDeclarationStatement_RHS() async {
-    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
-    // VariableDeclarationStatement
-    addTestSource('class C {bar(){var f; {var x;} var e = ^}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_VariableDeclarationStatement_RHS_missing_semicolon() async {
-    // VariableDeclaration  VariableDeclarationList
-    // VariableDeclarationStatement
-    addTestSource('class C {bar(){var f; {var x;} var e = ^ var g}}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  Future<void> test_WhileStatement() async {
-    // SimpleIdentifier  WhileStatement  Block
-    addTestSource('mth() { while (b^) {} }}');
-    await assertOpType(constructors: true, returnValue: true, typeNames: true);
-  }
-
-  @failingTest
-  Future<void> test_WithClause() async {
-    // WithClause  ClassDeclaration
-    addTestSource('class x extends Object with ^\n{}');
-    await assertOpType(constructors: true, typeNames: true);
-  }
-}
-
-@reflectiveTest
-class OpTypeTest extends OpTypeTestCommon {
-  Future<void> test_ArgumentList_constructor_named_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A.b(^); }'
-      'class A{ A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_constructor_named_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A.b(o^); }'
-      'class A { A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_constructor_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A(^); }'
-      'class A{ A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_constructor_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A(o^); }'
-      'class A { A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_factory_named_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A.b(^); }'
-      'class A{ factory A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_factory_named_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A.b(o^); }'
-      'class A { factory A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_factory_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A(^); }'
-      'class A{ factory A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_factory_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A(o^); }'
-      'class A { factory A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_method_resolved_1_0() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('main() { foo(^);} foo({one, two}) {}');
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_method_resolved_1_1() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('main() { foo(o^);} foo({one, two}) {}');
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_ArgumentList_resolved_2_0() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('void main() {int.parse("16", ^)}');
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_AsExpression() async {
-    // SimpleIdentifier  TypeName  AsExpression
-    addTestSource('class A {var b; X _c; foo() {var a; (a as ^).foo();}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_AsIdentifier2() async {
-    addTestSource('class A {var asdf; foo() {A as^}');
-    await assertOpType();
-  }
-
-  Future<void> test_AssignmentExpression_name() async {
-    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
-    // VariableDeclarationStatement  Block
-    addTestSource('class A {} main() {int a; int ^b = 1;}');
-    await assertOpType(varNames: true);
-  }
-
-  Future<void> test_Block_catch_1a() async {
-    // '}'  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} ^}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
-  Future<void> test_Block_catch_1b() async {
-    // [ExpressionStatement 'c']  Block  BlockFunctionBody
-    addTestSource('main() {try {} c^}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
-  Future<void> test_Block_catch_1c() async {
-    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} ^;}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
-  Future<void> test_Block_catch_1d() async {
-    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
-    addTestSource('main() {try {} ^ Foo foo;}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
-  Future<void> test_Block_final() async {
-    addTestSource('main() {final ^}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_Block_final2() async {
-    addTestSource('main() {final S^ v;}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_Block_final3() async {
-    addTestSource('main() {final ^ v;}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_Block_final_final() async {
-    addTestSource('main() {final ^ final S x;}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_Block_final_final2() async {
-    addTestSource('main() {final S^ final S x;}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_Break_after_label() async {
-    addTestSource('main() { foo: while (true) { break foo ^ ; } }');
-    await assertOpType(/* No valid completions */);
-  }
-
-  Future<void> test_Break_before_label() async {
-    addTestSource('main() { foo: while (true) { break ^ foo; } }');
-    await assertOpType(statementLabel: true);
-  }
-
-  Future<void> test_Break_no_label() async {
-    addTestSource('main() { foo: while (true) { break ^; } }');
-    await assertOpType(statementLabel: true);
-  }
-
-  Future<void> test_catch_4a1() async {
-    addTestSource('main() {try {} ^ on SomeException {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_catch_4a2() async {
-    addTestSource('main() {try {} c^ on SomeException {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_catch_4b1() async {
-    addTestSource('main() {try {} ^ catch (e) {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_catch_4b2() async {
-    addTestSource('main() {try {} c^ catch (e) {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_catch_4c1() async {
-    addTestSource('main() {try {} ^ finally {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_catch_4c2() async {
-    addTestSource('main() {try {} c^ finally {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_catch_5a() async {
-    addTestSource('main() {try {} on ^ finally {}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_catch_5b() async {
-    addTestSource('main() {try {} on E^ finally {}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_CatchClause_onType() async {
-    // TypeName  CatchClause  TryStatement
-    addTestSource('class A {a() {try{var x;} on ^ {}}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_CatchClause_onType_noBrackets() async {
-    // TypeName  CatchClause  TryStatement
-    addTestSource('class A {a() {try{var x;} on ^}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ClassDeclaration_body() async {
-    // ClassDeclaration  CompilationUnit
-    addTestSource('@deprecated class A {^}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ClassDeclaration_body2() async {
-    // SimpleIdentifier  MethodDeclaration  ClassDeclaration
-    addTestSource('@deprecated class A {^mth() {}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_Combinator_hide() async {
-    // SimpleIdentifier  HideCombinator  ImportDirective
-    addTestSource('''
-      import "/testAB.dart" hide ^;
-      class X {}''');
-    await assertOpType();
-  }
-
-  Future<void> test_Combinator_show() async {
-    // SimpleIdentifier  HideCombinator  ImportDirective
-    addTestSource('''
-      import "/testAB.dart" show ^;
-      import "/testCD.dart";
-      class X {}''');
-    await assertOpType();
-  }
-
-  Future<void> test_ConstructorName() async {
-    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
-    // InstanceCreationExpression
-    addTestSource('main() {new X.^}');
-    await assertOpType(constructors: true, prefixed: true);
-  }
-
-  Future<void> test_ConstructorName_name_resolved() async {
-    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
-    // InstanceCreationExpression
-    addTestSource('main() {new Str^ing.fromCharCodes([]);}');
-    await assertOpType(constructors: true);
-  }
-
-  Future<void> test_ConstructorName_nameAndPrefix_resolved() async {
-    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
-    // InstanceCreationExpression
-    addTestSource('''
-import 'dart:core' as core;
-main() {new core.String.from^CharCodes([]);}
-''');
-    await assertOpType(constructors: true, prefixed: true);
-  }
-
-  Future<void> test_ConstructorName_resolved() async {
-    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
-    // InstanceCreationExpression
-    addTestSource('main() {new String.fr^omCharCodes([]);}');
-    await assertOpType(constructors: true, prefixed: true);
-  }
-
-  Future<void> test_ConstructorName_unresolved() async {
-    // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
-    // InstanceCreationExpression
-    addTestSource('main() {new String.fr^omCharCodes([]);}');
-    await assertOpType(constructors: true, prefixed: true);
-  }
-
-  Future<void> test_Continue_after_label() async {
-    addTestSource('main() { foo: while (true) { continue foo ^ ; } }');
-    await assertOpType(/* No valid completions */);
-  }
-
-  Future<void> test_Continue_before_label() async {
-    addTestSource('main() { foo: while (true) { continue ^ foo; } }');
-    await assertOpType(statementLabel: true, caseLabel: true);
-  }
-
-  Future<void> test_Continue_no_label() async {
-    addTestSource('main() { foo: while (true) { continue ^; } }');
-    await assertOpType(statementLabel: true, caseLabel: true);
-  }
-
-  Future<void> test_DoubleLiteral() async {
-    addTestSource('main() { print(1.2^); }');
-    await assertOpType();
-  }
-
-  Future<void> test_ExpressionStatement_name() async {
-    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
-    addTestSource('class C {a() {C ^}}');
-    await assertOpType(varNames: true);
-  }
-
-  Future<void> test_ExpressionStatement_name_semicolon() async {
-    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
-    addTestSource('class C {a() {C ^;}}');
-    await assertOpType(varNames: true);
-  }
-
-  Future<void> test_ExpressionStatement_prefixed_name() async {
-    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
-    addTestSource('class C {a() {x.Y ^}}');
-    await assertOpType(varNames: true);
-  }
-
-  Future<void> test_ExpressionStatement_prefixed_name_semicolon() async {
-    // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
-    addTestSource('class C {a() {x.Y ^;}}');
-    await assertOpType(varNames: true);
-  }
-
-  Future<void> test_ExtendsClause() async {
-    // ExtendsClause  ClassDeclaration
-    addTestSource('class x extends ^\n{}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FieldDeclaration_name_typed() async {
-    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
-    // FieldDeclaration
-    addTestSource('class C {A ^}');
-    await assertOpType(varNames: true);
-  }
-
-  Future<void> test_FieldDeclaration_name_var() async {
-    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
-    // FieldDeclaration
-    addTestSource('class C {var ^}');
-    await assertOpType();
-  }
-
-  Future<void> test_ForEachStatement_loopVariable() async {
-    // SimpleIdentifier  ForEachStatement  Block
-    addTestSource('main(args) {for (^ in args) {}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ForEachStatement_loopVariable_name() async {
-    // DeclaredIdentifier  ForEachStatement  Block
-    addTestSource('main(args) {for (String ^ in args) {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_ForEachStatement_loopVariable_name2() async {
-    // DeclaredIdentifier  ForEachStatement  Block
-    addTestSource('main(args) {for (String f^ in args) {}}');
-    await assertOpType();
-  }
-
-  Future<void> test_ForEachStatement_loopVariable_type() async {
-    // SimpleIdentifier  ForEachStatement  Block
-    addTestSource('main(args) {for (^ foo in args) {}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ForEachStatement_loopVariable_type2() async {
-    // DeclaredIdentifier  ForEachStatement  Block
-    addTestSource('main(args) {for (S^ foo in args) {}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FormalParameterList() async {
-    // FormalParameterList MethodDeclaration
-    addTestSource('class A {a(^) { }}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ForStatement_initializer() async {
-    // SimpleIdentifier  ForStatement
-    addTestSource('main() {List a; for (^)}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ForStatement_initializer_inKeyword() async {
-    addTestSource('main() { for (var v i^) }');
-    await assertOpType();
-  }
-
-  Future<void> test_ForStatement_initializer_type() async {
-    // SimpleIdentifier  ForStatement
-    addTestSource('main() {List a; for (i^ v = 0;)}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_ForStatement_initializer_variableNameEmpty_afterType() async {
-    addTestSource('main() { for (String ^) }');
-    await assertOpType(varNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration1() async {
-    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
-    addTestSource('const ^Fara();');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration2() async {
-    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
-    addTestSource('const F^ara();');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration_inLineComment() async {
-    // Comment  CompilationUnit
-    addTestSource('''
-      // normal comment ^
-      zoo(z) { } String name;''');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inLineComment2() async {
-    // Comment  CompilationUnit
-    addTestSource('''
-      // normal ^comment
-      zoo(z) { } String name;''');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inLineComment3() async {
-    // Comment  CompilationUnit
-    addTestSource('''
-      // normal comment ^
-      // normal comment 2
-      zoo(z) { } String name;''');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inLineComment4() async {
-    // Comment  CompilationUnit
-    addTestSource('''
-      // normal comment
-      // normal comment 2^
-      zoo(z) { } String name;''');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inLineDocComment() async {
-    // Comment  FunctionDeclaration  CompilationUnit
-    addTestSource('''
-      /// some dartdoc ^
-      zoo(z) { } String name;''');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inLineDocComment2() async {
-    // Comment  FunctionDeclaration  CompilationUnit
-    addTestSource('''
-      /// some ^dartdoc
-      zoo(z) { } String name;''');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inStarComment() async {
-    // Comment  CompilationUnit
-    addTestSource('/* ^ */ zoo(z) {} String name;');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inStarComment2() async {
-    // Comment  CompilationUnit
-    addTestSource('/*  *^/ zoo(z) {} String name;');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inStarDocComment() async {
-    // Comment  FunctionDeclaration  CompilationUnit
-    addTestSource('/** ^ */ zoo(z) { } String name; ');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_inStarDocComment2() async {
-    // Comment  FunctionDeclaration  CompilationUnit
-    addTestSource('/**  *^/ zoo(z) { } String name;');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionDeclaration_returnType() async {
-    // CompilationUnit
-    addTestSource('^ zoo(z) { } String name;');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration_returnType_afterLineComment() async {
-    // FunctionDeclaration  CompilationUnit
-    addTestSource('''
-      // normal comment
-      ^ zoo(z) {} String name;''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration_returnType_afterLineComment2() async {
-    // FunctionDeclaration  CompilationUnit
-    // TOD(danrubel) left align all test source
-    addTestSource('''
-// normal comment
-^ zoo(z) {} String name;''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration_returnType_afterLineDocComment() async {
-    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
-    addTestSource('''
-      /// some dartdoc
-      ^ zoo(z) { } String name;''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_FunctionDeclaration_returnType_afterLineDocComment2() async {
-    // SimpleIdentifier  FunctionDeclaration  CompilationUnit
-    addTestSource('''
-/// some dartdoc
-^ zoo(z) { } String name;''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration_returnType_afterStarComment() async {
-    // CompilationUnit
-    addTestSource('/* */ ^ zoo(z) { } String name;');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration_returnType_afterStarComment2() async {
-    // CompilationUnit
-    addTestSource('/* */^ zoo(z) { } String name;');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionDeclaration_returnType_afterStarDocComment() async {
-    // FunctionDeclaration  CompilationUnit
-    addTestSource('/** */ ^ zoo(z) { } String name;');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_FunctionDeclaration_returnType_afterStarDocComment2() async {
-    // FunctionDeclaration  CompilationUnit
-    addTestSource('/** */^ zoo(z) { } String name;');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_FunctionExpression() async {
-    // BlockFunctionBody  FunctionExpression  FunctionDeclaration
-    addTestSource('main()^ { int b = 2; b++; b. }');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionExpressionInvocation() async {
-    // ArgumentList  FunctionExpressionInvocation  ExpressionStatement
-    addTestSource('main() { ((x) => x + 7)^(2) }');
-    await assertOpType();
-  }
-
-  Future<void> test_FunctionTypeAlias() async {
-    // SimpleIdentifier  FunctionTypeAlias  CompilationUnit
-    addTestSource('typedef n^ ;');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ImplementsClause() async {
-    // ImplementsClause  ClassDeclaration
-    addTestSource('class x implements ^\n{}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_ImportDirective_dart() async {
-    // SimpleStringLiteral  ImportDirective
-    addTestSource('''
-      import "dart^";
-      main() {}''');
-    await assertOpType();
-  }
-
-  Future<void> test_InstanceCreationExpression() async {
-    // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
-    addTestSource('class C {foo(){var f; {var x;} new ^}}');
-    await assertOpType(constructors: true);
-  }
-
-  Future<void> test_InstanceCreationExpression_trailingStmt() async {
-    // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
-    addTestSource('class C {foo(){var f; {var x;} new ^ int x = 7;}}');
-    await assertOpType(constructors: true);
-  }
-
-  Future<void> test_IntegerLiteral_inArgumentList() async {
-    addTestSource('main() { print(1^); }');
-    await assertOpType();
-  }
-
-  Future<void> test_IntegerLiteral_inListLiteral() async {
-    addTestSource('main() { var items = [1^]; }');
-    await assertOpType();
-  }
-
-  Future<void> test_IsExpression() async {
-    // SimpleIdentifier  TypeName  IsExpression  IfStatement
-    addTestSource('main() {var x; if (x is ^) { }}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_IsExpression_type_partial() async {
-    // SimpleIdentifier  TypeName  IsExpression  IfStatement
-    addTestSource('main(){var a; if (a is Obj^)}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_Literal_string() async {
-    // SimpleStringLiteral  ExpressionStatement  Block
-    addTestSource('class A {a() {"hel^lo"}}');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass1() async {
-    // SimpleIdentifier  MethodDeclaration  ClassDeclaration
-    addTestSource('class Bar {const ^Fara();}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_MethodDeclaration_inClass2() async {
-    // SimpleIdentifier  MethodDeclaration  ClassDeclaration
-    addTestSource('class Bar {const F^ara();}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inLineComment() async {
-    // Comment  ClassDeclaration  CompilationUnit
-    addTestSource('''
-      class C2 {
-        // normal comment ^
-        zoo(z) { } String name; }''');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inLineComment2() async {
-    // Comment  ClassDeclaration  CompilationUnit
-    addTestSource('''
-      class C2 {
-        // normal ^comment
-        zoo(z) { } String name; }''');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inLineComment3() async {
-    // Comment  ClassDeclaration  CompilationUnit
-    addTestSource('''
-      class C2 {
-        // normal comment ^
-        // normal comment 2
-        zoo(z) { } String name; }''');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inLineDocComment() async {
-    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('''
-      class C2 {
-        /// some dartdoc ^
-        zoo(z) { } String name; }''');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inLineDocComment2() async {
-    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('''
-      class C2 {
-        /// some ^dartdoc
-        zoo(z) { } String name; }''');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inStarComment() async {
-    // Comment  ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/* ^ */ zoo(z) {} String name;}');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inStarComment2() async {
-    // Comment  ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/*  *^/ zoo(z) {} String name;}');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inStarDocComment() async {
-    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/** ^ */ zoo(z) { } String name; }');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_inStarDocComment2() async {
-    // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/**  *^/ zoo(z) { } String name; }');
-    await assertOpType();
-  }
-
-  Future<void> test_MethodDeclaration_inClass_returnType() async {
-    // ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {^ zoo(z) { } String name; }');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterLineComment() async {
-    // MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('''
-      class C2 {
-        // normal comment
-        ^ zoo(z) {} String name;}''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterLineComment2() async {
-    // MethodDeclaration  ClassDeclaration  CompilationUnit
-    // TOD(danrubel) left align all test source
-    addTestSource('''
-class C2 {
-  // normal comment
-^ zoo(z) {} String name;}''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterLineDocComment() async {
-    // SimpleIdentifier  MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('''
-      class C2 {
-        /// some dartdoc
-        ^ zoo(z) { } String name; }''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterLineDocComment2() async {
-    // SimpleIdentifier  MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('''
-class C2 {
-  /// some dartdoc
-^ zoo(z) { } String name; }''');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterStarComment() async {
-    // ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/* */ ^ zoo(z) { } String name; }');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterStarComment2() async {
-    // ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/* */^ zoo(z) { } String name; }');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterStarDocComment() async {
-    // MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/** */ ^ zoo(z) { } String name; }');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void>
-      test_MethodDeclaration_inClass_returnType_afterStarDocComment2() async {
-    // MethodDeclaration  ClassDeclaration  CompilationUnit
-    addTestSource('class C2 {/** */^ zoo(z) { } String name; }');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_methodDeclaration_inMixin1() async {
-    // SimpleIdentifier  MethodDeclaration  MixinDeclaration
-    addTestSource('mixin M {const ^Fara();}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_methodDeclaration_inMixin2() async {
-    // SimpleIdentifier  MethodDeclaration  MixinDeclaration
-    addTestSource('mixin M {const F^ara();}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_methodDeclaration_inMixin_returnType() async {
-    // MixinDeclaration  CompilationUnit
-    addTestSource('mixin M {^ zoo(z) { } String name; }');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_mixinDeclaration_body() async {
-    // MixinDeclaration  CompilationUnit
-    addTestSource('mixin M {^}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_mixinDeclaration_body2() async {
-    // SimpleIdentifier  MethodDeclaration  MixinDeclaration
-    addTestSource('mixin M {^mth() {}}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_NamedExpression() async {
-    addTestSource('''
-main() { f(3, ^); }
-void f(int a, {int b}) {}
-''');
-    await assertOpType(namedArgs: true);
-  }
-
-  Future<void> test_OnClause() async {
-    // OnClause  MixinDeclaration
-    addTestSource('mixin M on ^\n{}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_PropertyAccess_noTarget() async {
-    // SimpleIdentifier  PropertyAccess  ExpressionStatement
-    addTestSource('main() {.^}');
-    await assertOpType();
-  }
-
-  Future<void> test_PropertyAccess_noTarget2() async {
-    // SimpleIdentifier  PropertyAccess  CascadeExpressions
-    addTestSource('main() {.^.}');
-    await assertOpType();
-  }
-
-  Future<void> test_PropertyAccess_noTarget3() async {
-    // SimpleIdentifier  PropertyAccess  CascadeExpressions
-    addTestSource('main() {..^}');
-    await assertOpType();
-  }
-
-  Future<void> test_SimpleFormalParameter_closure() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_functionType_name() async {
-    addTestSource('void Function(int ^) v;');
-    await assertOpType(typeNames: false, varNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_functionType_name_named() async {
-    addTestSource('void Function({int ^}) v;');
-    await assertOpType(typeNames: false, varNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_functionType_name_optional() async {
-    addTestSource('void Function([int ^]) v;');
-    await assertOpType(typeNames: false, varNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_functionType_type_withName() async {
-    addTestSource('void Function(Str^ name) v;');
-    await assertOpType(typeNames: true, varNames: false);
-  }
-
-  Future<void> test_SimpleFormalParameter_functionType_type_withName2() async {
-    addTestSource('void Function(^ name) v;');
-    await assertOpType(typeNames: true, varNames: false);
-  }
-
-  Future<void> test_SimpleFormalParameter_name_typed() async {
-    addTestSource('f(String ^, int b) {}');
-    await assertOpType(typeNames: false, varNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_name_typed_hasName() async {
-    addTestSource('f(String n^, int b) {}');
-    await assertOpType(typeNames: false, varNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_name_typed_last() async {
-    addTestSource('f(String ^) {}');
-    await assertOpType(typeNames: false, varNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_name_typed_last_hasName() async {
-    addTestSource('f(String n^) {}');
-    await assertOpType(typeNames: false, varNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_type_named() async {
-    addTestSource('f(^ name) {}');
-    await assertOpType(typeNames: true, varNames: false);
-  }
-
-  Future<void> test_SimpleFormalParameter_type_optionalNamed() async {
-    // SimpleIdentifier  DefaultFormalParameter  FormalParameterList
-    addTestSource('m({Str^}) {}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_type_optionalPositional() async {
-    // SimpleIdentifier  DefaultFormalParameter  FormalParameterList
-    addTestSource('m([Str^]) {}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_type_withName() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('m(Str^ name) {}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_type_withoutName1() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('m(Str^) {}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_type_withoutName2() async {
-    // FormalParameterList
-    addTestSource('m(^) {}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_type_withoutName3() async {
-    // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
-    addTestSource('m(int first, Str^) {}');
-    await assertOpType(typeNames: true);
-  }
-
-  Future<void> test_SimpleFormalParameter_untyped() async {
-    addTestSource('main(final ^) {}');
-    await assertOpType(typeNames: true, varNames: false);
-  }
-
-  Future<void> test_SwitchCase_before() async {
-    // SwitchCase  SwitchStatement  Block
-    addTestSource('main() {switch(k) {^case 1:}}');
-    await assertOpType();
-  }
-
-  Future<void> test_SwitchDefault_before() async {
-    // SwitchDefault  SwitchStatement  Block
-    addTestSource('main() {switch(k) { ^ default: return;}}');
-    await assertOpType();
-  }
-
-  Future<void> test_SwitchStatement_body_empty() async {
-    // Token('}')  SwitchStatement  Block
-    addTestSource('main() {switch(k) {^}}');
-    await assertOpType();
-  }
-
-  Future<void> test_ThisExpression_constructor_param() async {
+  Future<void> test_thisExpression_constructor_param() async {
     // SimpleIdentifier  FieldFormalParameter  FormalParameterList
     addTestSource('''
       class A implements I {
@@ -2025,7 +2397,7 @@
     await assertOpType(prefixed: true);
   }
 
-  Future<void> test_ThisExpression_constructor_param2() async {
+  Future<void> test_thisExpression_constructor_param2() async {
     // SimpleIdentifier  FieldFormalParameter  FormalParameterList
     addTestSource('''
       class A implements I {
@@ -2034,7 +2406,7 @@
     await assertOpType(prefixed: true);
   }
 
-  Future<void> test_ThisExpression_constructor_param3() async {
+  Future<void> test_thisExpression_constructor_param3() async {
     // SimpleIdentifier  FieldFormalParameter  FormalParameterList
     addTestSource('''
       class A implements I {
@@ -2043,192 +2415,365 @@
     await assertOpType(prefixed: true);
   }
 
-  Future<void> test_ThisExpression_constructor_param4() async {
+  Future<void> test_thisExpression_constructor_param4() async {
     // FieldFormalParameter  FormalParameterList  ConstructorDeclaration
     addTestSource('''
       class A implements I {
         A(Str^ this.foo) {}
       }''');
-    await assertOpType(typeNames: true);
+    await assertOpType(
+        completionLocation: 'FormalParameterList_parameter', typeNames: true);
   }
 
-  Future<void> test_TopLevelVariableDeclaration_typed_name() async {
+  Future<void> test_throwExpression_empty() async {
+    // SimpleIdentifier  ThrowExpression  ExpressionStatement
+    addTestSource('main() {throw ^;}');
+    await assertOpType(
+        completionLocation: 'ThrowExpression_expression',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_topLevelVariableDeclaration_type() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    addTestSource('^ foo;');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_topLevelVariableDeclaration_type_no_semicolon() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // TopLevelVariableDeclaration
+    addTestSource('^ foo');
+    await assertOpType(
+        completionLocation: 'CompilationUnit_declaration', typeNames: true);
+  }
+
+  Future<void> test_topLevelVariableDeclaration_typed_name() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // TopLevelVariableDeclaration
     // _OpTypeAstVisitor.visitVariableDeclarationList is executed with this
     // source, but _OpTypeAstVisitor.visitTopLevelVariableDeclaration is called
-    // for test_TopLevelVariableDeclaration_typed_name_semicolon
+    // for test_topLevelVariableDeclaration_typed_name_semicolon
     addTestSource('class A {} B ^');
     await assertOpType(varNames: true);
   }
 
-  Future<void> test_TopLevelVariableDeclaration_typed_name_semicolon() async {
+  Future<void> test_topLevelVariableDeclaration_typed_name_semicolon() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // TopLevelVariableDeclaration
-    // See comment in test_TopLevelVariableDeclaration_typed_name
+    // See comment in test_topLevelVariableDeclaration_typed_name
     addTestSource('class A {} B ^;');
     await assertOpType(varNames: true);
   }
 
-  Future<void> test_TopLevelVariableDeclaration_untyped_name() async {
+  Future<void> test_topLevelVariableDeclaration_untyped_name() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // TopLevelVariableDeclaration
     addTestSource('class A {} var ^');
     await assertOpType();
   }
 
-  Future<void> test_TypeArgumentList() async {
+  Future<void> test_tryStatement_catch_1a() async {
+    // '}'  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} ^}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType(completionLocation: 'Block_statement');
+  }
+
+  Future<void> test_tryStatement_catch_1b() async {
+    // [ExpressionStatement 'c']  Block  BlockFunctionBody
+    addTestSource('main() {try {} c^}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType(completionLocation: 'Block_statement');
+  }
+
+  Future<void> test_tryStatement_catch_1c() async {
+    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} ^;}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType(completionLocation: 'Block_statement');
+  }
+
+  Future<void> test_tryStatement_catch_1d() async {
+    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
+    addTestSource('main() {try {} ^ Foo foo;}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType(completionLocation: 'Block_statement');
+  }
+
+  Future<void> test_tryStatement_catch_2a() async {
+    // '}'  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} catch () {} ^}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_2b() async {
+    // [ExpressionStatement 'c']  Block  BlockFunctionBody
+    addTestSource('main() {try {} catch () {} c^}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_2c() async {
+    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} catch () {} ^;}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_2d() async {
+    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
+    addTestSource('main() {try {} catch () {} ^ Foo foo;}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_3a() async {
+    // '}'  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} finally {} ^}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_3b() async {
+    // [ExpressionStatement 'c']  Block  BlockFunctionBody
+    addTestSource('main() {try {} finally {} c^}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_3c() async {
+    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} finally {} ^;}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_3d() async {
+    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
+    addTestSource('main() {try {} finally {} ^ Foo foo;}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catch_4a1() async {
+    addTestSource('main() {try {} ^ on SomeException {}}');
+    await assertOpType();
+  }
+
+  Future<void> test_tryStatement_catch_4a2() async {
+    addTestSource('main() {try {} c^ on SomeException {}}');
+    // TODO(brianwilkerson) This should not have a location.
+    await assertOpType(completionLocation: 'Block_statement');
+  }
+
+  Future<void> test_tryStatement_catch_4b1() async {
+    addTestSource('main() {try {} ^ catch (e) {}}');
+    await assertOpType();
+  }
+
+  Future<void> test_tryStatement_catch_4b2() async {
+    addTestSource('main() {try {} c^ catch (e) {}}');
+    // TODO(brianwilkerson) This should not have a location.
+    await assertOpType(completionLocation: 'Block_statement');
+  }
+
+  Future<void> test_tryStatement_catch_4c1() async {
+    addTestSource('main() {try {} ^ finally {}}');
+    await assertOpType();
+  }
+
+  Future<void> test_tryStatement_catch_4c2() async {
+    addTestSource('main() {try {} c^ finally {}}');
+    // TODO(brianwilkerson) This should not have a location.
+    await assertOpType(completionLocation: 'Block_statement');
+  }
+
+  Future<void> test_tryStatement_catch_5a() async {
+    addTestSource('main() {try {} on ^ finally {}}');
+    await assertOpType(
+        completionLocation: 'CatchClause_exceptionType', typeNames: true);
+  }
+
+  Future<void> test_tryStatement_catch_5b() async {
+    addTestSource('main() {try {} on E^ finally {}}');
+    await assertOpType(
+        completionLocation: 'CatchClause_exceptionType', typeNames: true);
+  }
+
+  Future<void> test_tryStatement_catchClause_onType() async {
+    // TypeName  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on ^ {}}}');
+    await assertOpType(
+        completionLocation: 'CatchClause_exceptionType', typeNames: true);
+  }
+
+  Future<void> test_tryStatement_catchClause_onType_noBrackets() async {
+    // TypeName  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on ^}}');
+    await assertOpType(
+        completionLocation: 'CatchClause_exceptionType', typeNames: true);
+  }
+
+  Future<void> test_tryStatement_catchClause_typed() async {
+    // Block  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on E catch (e) {^}}}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_tryStatement_catchClause_untyped() async {
+    // Block  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} catch (e, s) {^}}}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  Future<void> test_typeArgumentList_empty() async {
     // SimpleIdentifier  BinaryExpression  ExpressionStatement
     addTestSource('main() { C<^> c; }');
-    await assertOpType(typeNames: true);
+    await assertOpType(
+        completionLocation: 'TypeArgumentList_argument', typeNames: true);
   }
 
-  Future<void> test_TypeArgumentList2() async {
+  Future<void> test_typeArgumentList_partial() async {
     // TypeName  TypeArgumentList  TypeName
     addTestSource('main() { C<C^> c; }');
-    await assertOpType(typeNames: true);
+    await assertOpType(
+        completionLocation: 'TypeArgumentList_argument', typeNames: true);
   }
 
-  Future<void> test_TypeParameter() async {
+  Future<void> test_typeParameter_beforeType() async {
     // SimpleIdentifier  TypeParameter  TypeParameterList
     addTestSource('class tezetst <String, ^List> {}');
     await assertOpType();
   }
 
-  Future<void> test_TypeParameterList_empty() async {
+  Future<void> test_typeParameterList_empty() async {
     // SimpleIdentifier  TypeParameter  TypeParameterList
     addTestSource('class tezetst <^> {}');
     await assertOpType();
   }
 
-  Future<void> test_VariableDeclaration_name() async {
+  Future<void> test_variableDeclaration_name() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {var ^}');
     await assertOpType();
   }
 
-  Future<void> test_VariableDeclaration_name_hasSome_parameterizedType() async {
+  Future<void> test_variableDeclaration_name_hasSome_parameterizedType() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {List<int> m^}');
     await assertOpType(varNames: true);
   }
 
-  Future<void> test_VariableDeclaration_name_hasSome_simpleType() async {
+  Future<void> test_variableDeclaration_name_hasSome_simpleType() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {String m^}');
     await assertOpType(varNames: true);
   }
 
-  Future<void> test_VariableDeclarationList_final() async {
+  Future<void> test_variableDeclarationList_final() async {
     // VariableDeclarationList  VariableDeclarationStatement  Block
     addTestSource('main() {final ^}');
-    await assertOpType(typeNames: true);
-  }
-}
-
-/// Common test methods to Dart1/Dart2 versions of OpType tests.
-class OpTypeTestCommon extends AbstractContextTest {
-  String testPath;
-  int completionOffset;
-  OpType visitor;
-
-  void addTestSource(String content) {
-    completionOffset = content.indexOf('^');
-    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
-    var nextOffset = content.indexOf('^', completionOffset + 1);
-    expect(nextOffset, equals(-1), reason: 'too many ^');
-    content = content.substring(0, completionOffset) +
-        content.substring(completionOffset + 1);
-    super.addSource(testPath, content);
-  }
-
-  Future<void> assertOpType(
-      {bool caseLabel = false,
-      bool constructors = false,
-      bool namedArgs = false,
-      bool prefixed = false,
-      bool returnValue = false,
-      bool statementLabel = false,
-      bool staticMethodBody = false,
-      bool typeNames = false,
-      bool varNames = false,
-      bool voidReturn = false,
-      CompletionSuggestionKind kind =
-          CompletionSuggestionKind.INVOCATION}) async {
-    var resolvedUnit = await driver.getResult(testPath);
-
-    var completionTarget =
-        CompletionTarget.forOffset(resolvedUnit.unit, completionOffset);
-    visitor = OpType.forCompletion(completionTarget, completionOffset);
-
-    expect(visitor.includeCaseLabelSuggestions, caseLabel, reason: 'caseLabel');
-    expect(visitor.includeConstructorSuggestions, constructors,
-        reason: 'constructors');
-    expect(visitor.includeNamedArgumentSuggestions, namedArgs,
-        reason: 'namedArgs');
-    expect(visitor.includeReturnValueSuggestions, returnValue,
-        reason: 'returnValue');
-    expect(visitor.includeStatementLabelSuggestions, statementLabel,
-        reason: 'statementLabel');
-    expect(visitor.includeTypeNameSuggestions, typeNames, reason: 'typeNames');
-    expect(visitor.includeVarNameSuggestions, varNames, reason: 'varNames');
-    expect(visitor.includeVoidReturnSuggestions, voidReturn,
-        reason: 'voidReturn');
-    expect(visitor.inStaticMethodBody, staticMethodBody,
-        reason: 'staticMethodBody');
-    expect(visitor.isPrefixed, prefixed, reason: 'prefixed');
-    expect(visitor.suggestKind, kind, reason: 'suggestion kind');
-  }
-
-  @override
-  void setUp() {
-    super.setUp();
-    testPath = convertPath('/completionTest.dart');
-  }
-}
-
-@reflectiveTest
-class OpTypeTestWithExtensionMethods extends OpTypeTestCommon {
-  @override
-  void setUp() {
-    createAnalysisOptionsFile(
-      experiments: [
-        EnableString.extension_methods,
-      ],
-    );
-    super.setUp();
-  }
-
-  Future<void> test_extensionDeclaration_body() async {
-    // ExtensionDeclaration  CompilationUnit
-    addTestSource('extension E on int {^}');
+    // TODO(brianwilkerson) This should probably have a location.
     await assertOpType(typeNames: true);
   }
 
-  Future<void> test_extensionDeclaration_body2() async {
-    // SimpleIdentifier  MethodDeclaration  ExtensionDeclaration
-    addTestSource('extension E on int {^mth() {}}');
-    await assertOpType(typeNames: true);
+  Future<void> test_variableDeclarationStatement_afterSemicolon() async {
+    // VariableDeclarationStatement  Block  BlockFunctionBody
+    addTestSource('class A {var a; x() {var b;^}}');
+    await assertOpType(
+        completionLocation: 'Block_statement',
+        constructors: true,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
   }
 
-  Future<void> test_methodDeclaration_inExtension1() async {
-    // SimpleIdentifier  ExtensionDeclaration  MixinDeclaration
-    addTestSource('extension E on int {const ^Fara();}');
-    await assertOpType(typeNames: true);
+  Future<void> test_variableDeclarationStatement_RHS() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // VariableDeclarationStatement
+    addTestSource('class C {bar(){var f; {var x;} var e = ^}}');
+    await assertOpType(
+        completionLocation: 'VariableDeclaration_initializer',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_methodDeclaration_inExtension2() async {
-    // SimpleIdentifier  ExtensionDeclaration  MixinDeclaration
-    addTestSource('extension E on int {const F^ara();}');
-    await assertOpType(typeNames: true);
+  Future<void> test_variableDeclarationStatement_RHS_missingSemicolon() async {
+    // VariableDeclaration  VariableDeclarationList
+    // VariableDeclarationStatement
+    addTestSource('class C {bar(){var f; {var x;} var e = ^ var g}}');
+    await assertOpType(
+        completionLocation: 'VariableDeclaration_initializer',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
   }
 
-  Future<void> test_methodDeclaration_inExtension_returnType() async {
-    // ExtensionDeclaration  CompilationUnit
-    addTestSource('extension E on int {^ zoo(z) { } String name; }');
-    await assertOpType(typeNames: true);
+  Future<void> test_whileStatement_expression() async {
+    // SimpleIdentifier  WhileStatement  Block
+    addTestSource('mth() { while (b^) {} }}');
+    await assertOpType(
+        completionLocation: 'WhileStatement_condition',
+        constructors: true,
+        returnValue: true,
+        typeNames: true);
+  }
+
+  Future<void> test_withClause_empty() async {
+    // WithClause  ClassDeclaration
+    addTestSource('class x extends Object with ^\n{}');
+    await assertOpType(
+        completionLocation: 'WithClause_mixinType', typeNames: true);
   }
 }
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 80362a4..9d9f4d6 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -18,6 +18,7 @@
   static const String disableTypeInference = '--disable-type-inference';
   static const String disableRtiOptimization = '--disable-rti-optimization';
   static const String dumpInfo = '--dump-info';
+  static const String dumpSsa = '--dump-ssa';
   static const String enableAssertMessage = '--assert-message';
   static const String enableCheckedMode = '--enable-checked-mode';
   static const String enableAsserts = '--enable-asserts';
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 276c347..37094a9 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -477,6 +477,7 @@
     new OptionHandler(Flags.useNewSourceInfo, passThrough),
     new OptionHandler(Flags.useOldRti, passThrough),
     new OptionHandler(Flags.testMode, passThrough),
+    new OptionHandler('${Flags.dumpSsa}=.+', passThrough),
 
     // Experimental features.
     // We don't provide documentation for these yet.
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 6eed483..baa2c18 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -206,6 +206,10 @@
   /// the input's abstract type. The check can only be removed with additional
   /// reasoning, for example, that a dominating check uses the same type
   /// expression.
+  ///
+  /// [nullable] determines if the type in weak or legacy mode should be
+  /// interpreted as nullable. This is passed as `false` for is-tests and `true`
+  /// for as-checks and other contexts (e.g. parameter checks).
   AbstractValueWithPrecision createFromStaticType(DartType type,
       {ClassRelation classRelation = ClassRelation.subtype, bool nullable});
 
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index c3683c5..61b0825 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -268,18 +268,51 @@
   AbstractValueWithPrecision createFromStaticType(DartType type,
       {ClassRelation classRelation = ClassRelation.subtype, bool nullable}) {
     assert(nullable != null);
+
+    if ((classRelation == ClassRelation.subtype ||
+            classRelation == ClassRelation.thisExpression) &&
+        dartTypes.isTopType(type)) {
+      // A cone of a top type includes all values.
+      return AbstractValueWithPrecision(dynamicType, true);
+    }
+
+    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'.
+        return AbstractValueWithPrecision(nullType, true);
+      }
+
+      // Object* is a top type for both 'is' and 'as'. This is handled in the
+      // 'cone of top type' case above.
+
+      return _createFromStaticType(baseType, classRelation, nullable);
+    }
+
+    if (dartTypes.useLegacySubtyping) {
+      // In legacy and weak mode, `String` is nullable depending on context.
+      return _createFromStaticType(type, classRelation, nullable);
+    } else {
+      // In strong mode nullability comes from explicit NullableType.
+      return _createFromStaticType(type, classRelation, false);
+    }
+  }
+
+  AbstractValueWithPrecision _createFromStaticType(
+      DartType type, ClassRelation classRelation, bool nullable) {
+    assert(nullable != null);
+
     AbstractValueWithPrecision finish(TypeMask value, bool isPrecise) {
       return AbstractValueWithPrecision(
           nullable ? value : value.nonNullable(), isPrecise);
     }
 
-    if (type is NullableType) {
-      return createFromStaticType(type.baseType,
-          classRelation: classRelation, nullable: true);
-    }
-
-    // TODO(sra): Handle LegacyType more precisely.
-
     bool isPrecise = true;
     while (type is TypeVariableType) {
       TypeVariableType typeVariable = type;
@@ -287,37 +320,71 @@
           .getTypeVariableBound(typeVariable.element);
       classRelation = ClassRelation.subtype;
       isPrecise = false;
+      if (type is NullableType) {
+        // <A extends B?, B extends num>  ...  null is A --> can be `true`.
+        // <A extends B, B extends num?>  ...  null is A --> can be `true`.
+        nullable = true;
+        type = type.withoutNullability;
+      }
+    }
+
+    if ((classRelation == ClassRelation.thisExpression ||
+            classRelation == ClassRelation.subtype) &&
+        dartTypes.isTopType(type)) {
+      // A cone of a top type includes all values. Since we already tested this
+      // in [createFromStaticType], we get here only for type parameter bounds.
+      return AbstractValueWithPrecision(dynamicType, isPrecise);
     }
 
     if (type is InterfaceType) {
-      if (isPrecise) {
-        // TODO(sra): Could be precise if instantiated-to-bounds.
-        for (DartType argument in type.typeArguments) {
-          if (argument is DynamicType) continue;
+      ClassEntity cls = type.element;
+      List<DartType> arguments = type.typeArguments;
+      if (isPrecise && arguments.isNotEmpty) {
+        // Can we ignore the type arguments?
+        //
+        // For legacy covariance, if the interface type is a generic interface
+        // type and is maximal (i.e. instantiated to bounds), the typemask,
+        // which is based on the class element, is still precise. We check
+        // against Top for the parameter arguments since we don't have a
+        // convenient check for instantation to bounds.
+        //
+        // TODO(sra): Check arguments against bounds.
+        // TODO(sra): Handle other variances.
+        List<Variance> variances = dartTypes.getTypeVariableVariances(cls);
+        for (int i = 0; i < arguments.length; i++) {
+          Variance variance = variances[i];
+          DartType argument = arguments[i];
+          if (variance == Variance.legacyCovariant &&
+              dartTypes.isTopType(argument)) {
+            continue;
+          }
           isPrecise = false;
         }
       }
       switch (classRelation) {
         case ClassRelation.exact:
-          return finish(TypeMask.exact(type.element, _closedWorld), isPrecise);
+          return finish(TypeMask.exact(cls, _closedWorld), isPrecise);
         case ClassRelation.thisExpression:
-          if (!_closedWorld.isUsedAsMixin(type.element)) {
-            return finish(
-                TypeMask.subclass(type.element, _closedWorld), isPrecise);
+          if (!_closedWorld.isUsedAsMixin(cls)) {
+            return finish(TypeMask.subclass(cls, _closedWorld), isPrecise);
           }
           break;
         case ClassRelation.subtype:
           break;
       }
-      return finish(TypeMask.subtype(type.element, _closedWorld), isPrecise);
-    } else if (type is FunctionType) {
+      return finish(TypeMask.subtype(cls, _closedWorld), isPrecise);
+    }
+
+    if (type is FunctionType) {
       return finish(
           TypeMask.subtype(commonElements.functionClass, _closedWorld), false);
-    } else if (type is DynamicType) {
-      return AbstractValueWithPrecision(dynamicType, true);
-    } else {
-      return finish(dynamicType, false);
     }
+
+    if (type is NeverType) {
+      return finish(nullType, isPrecise);
+    }
+
+    return AbstractValueWithPrecision(dynamicType, false);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 7b73e7f..84ff8fe 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -281,6 +281,8 @@
     jsAst.Expression closureConverter;
     _elementEnvironment.forEachParameter(member,
         (DartType type, String name, _) {
+      type = type.withoutNullability;
+
       // If [name] is not in [stubParameters], then the parameter is an optional
       // parameter that was not provided for this stub.
       for (jsAst.Parameter stubParameter in stubParameters) {
@@ -291,8 +293,7 @@
 
             // The parameter type is a function type either directly or through
             // typedef(s).
-            FunctionType functionType = type;
-            int arity = functionType.parameterTypes.length;
+            int arity = type.parameterTypes.length;
             statements.add(js
                 .statement('# = #(#, $arity)', [name, closureConverter, name]));
             break;
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 3e31aa5e..06fc442 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -198,7 +198,8 @@
         ? const MinifiedFixedNames()
         : const FixedNames();
 
-    Tracer tracer = new Tracer(closedWorld, _compiler.outputProvider);
+    Tracer tracer =
+        new Tracer(closedWorld, _compiler.options, _compiler.outputProvider);
     RuntimeTypesEncoder rtiEncoder = new RuntimeTypesEncoderImpl(
         rtiTags,
         closedWorld.nativeData,
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index a218e6a..1f754e04 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -118,6 +118,13 @@
       }
       if (component == null) return null;
 
+      // TODO(sigmund): remove after we unfork the sdk, and force null-safety to
+      // always be considered to be true.
+      if (component.libraries.any((lib) =>
+          lib.isNonNullableByDefault && lib.importUri.scheme == 'dart')) {
+        _options.useNullSafety = true;
+      }
+
       if (_options.cfeOnly) {
         measureSubtask('serialize dill', () {
           _reporter.log('Writing dill to ${_options.outputUri}');
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 11f838f..2f6b7dc 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -199,6 +199,10 @@
   /// after a transitional period.
   bool useDumpInfoBinaryFormat = false;
 
+  /// If set, SSA intermediate form is dumped for methods with names matching
+  /// this RegExp pattern.
+  String dumpSsaPattern = null;
+
   /// Whether we allow passing an extra argument to `assert`, containing a
   /// reason for why an assertion fails. (experimental)
   ///
@@ -332,9 +336,12 @@
   /// Whether to use the new RTI representation (default).
   bool useNewRti = true;
 
-  /// Whether null-safety (non-nullable types) are enabled.
-  bool get useNullSafety =>
-      languageExperiments[fe.ExperimentalFlag.nonNullable];
+  /// 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
   /// weak or strong semantics.
@@ -376,22 +383,11 @@
       void Function(String) onWarning}) {
     Map<fe.ExperimentalFlag, bool> languageExperiments =
         _extractExperiments(options, onError: onError, onWarning: onWarning);
-    if (equalMaps(languageExperiments, fe.defaultExperimentalFlags)) {
-      platformBinaries ??= fe.computePlatformBinariesLocation();
-    } else {
-      // TODO(sigmund): change these defaults before we unfork the sdk.
-      // To unfork the plan is to accept the same platform files regardless of
-      // the experiment flag (it will be enabled in the sdk regardless).
-      if (_hasOption(options, Flags.testMode) &&
-          languageExperiments[fe.ExperimentalFlag.nonNullable]) {
-        var experimentWithoutNullability = Map.of(languageExperiments);
-        experimentWithoutNullability[fe.ExperimentalFlag.nonNullable] = false;
-        if (equalMaps(
-            experimentWithoutNullability, fe.defaultExperimentalFlags)) {
-          platformBinaries ??= fe.computePlatformBinariesLocation();
-        }
-      }
-    }
+
+    // The null safety experiment can result in requiring different experiments
+    // for compiling user code vs. the sdk. To simplify things, we prebuild the
+    // sdk with the correct flags.
+    platformBinaries ??= fe.computePlatformBinariesLocation();
     return new CompilerOptions()
       ..librariesSpecificationUri = librariesSpecificationUri
       ..allowMockCompilation = _hasOption(options, Flags.allowMockCompilation)
@@ -423,6 +419,8 @@
       ..dumpInfo = _hasOption(options, Flags.dumpInfo)
       ..useDumpInfoBinaryFormat =
           _hasOption(options, "${Flags.dumpInfo}=binary")
+      ..dumpSsaPattern =
+          _extractStringOption(options, '${Flags.dumpSsa}=', null)
       ..enableMinification = _hasOption(options, Flags.minify)
       .._disableMinification = _hasOption(options, Flags.noMinify)
       ..enableNativeLiveTypeAnalysis =
@@ -441,8 +439,7 @@
       ..useNewRti = !_hasOption(options, Flags.useOldRti)
       ..generateSourceMap = !_hasOption(options, Flags.noSourceMaps)
       ..outputUri = _extractUriOption(options, '--out=')
-      ..platformBinaries =
-          platformBinaries ?? _extractUriOption(options, '--platform-binaries=')
+      ..platformBinaries = platformBinaries
       ..printLegacyStars = _hasOption(options, Flags.printLegacyStars)
       ..sourceMapUri = _extractUriOption(options, '--source-map=')
       ..omitImplicitChecks = _hasOption(options, Flags.omitImplicitChecks)
@@ -513,6 +510,10 @@
     if (_noLegacyJavaScript) legacyJavaScript = false;
     if (_legacyJavaScript) legacyJavaScript = true;
 
+    if (languageExperiments[fe.ExperimentalFlag.nonNullable]) {
+      useNullSafety = true;
+    }
+
     if (optimizationLevel != null) {
       if (optimizationLevel == 0) {
         disableInlining = true;
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index de9a007..11272be 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -365,6 +365,9 @@
         }
         break;
       case OutputType.debug:
+        if (name == '') {
+          name = out.pathSegments.last;
+        }
         uri = out.resolve('$name.$extension');
         break;
       default:
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 4f2dfa8..1efc55b 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -903,7 +903,7 @@
       // @Native methods have conversion code for function arguments. Rather
       // than insert that code at the inlined call site, call the target on the
       // interceptor.
-      if (parameterType is FunctionType) return true;
+      if (parameterType.withoutNullability is FunctionType) return true;
     }
 
     if (!_closedWorld.annotationsData
@@ -2185,11 +2185,8 @@
       }
 
       if (specialization != null) {
-        AbstractValueWithPrecision checkedType =
-            _abstractValueDomain.createFromStaticType(dartType,
-                nullable: _abstractValueDomain
-                    .isNull(node.checkedAbstractValue.abstractValue)
-                    .isPotentiallyTrue);
+        AbstractValueWithPrecision checkedType = _abstractValueDomain
+            .createFromStaticType(dartType, nullable: false);
         return HIsTestSimple(dartType, checkedType, specialization,
             node.checkedInput, _abstractValueDomain.boolType);
       }
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index 66564af..a02c499 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -5,19 +5,12 @@
 library tracer;
 
 import '../compiler_new.dart' as api;
+import 'options.dart' show CompilerOptions;
 import 'ssa/nodes.dart' as ssa show HGraph;
 import 'ssa/ssa_tracer.dart' show HTracer;
 import 'util/util.dart' show Indentation;
 import 'world.dart' show JClosedWorld;
 
-/// If non-null, we only trace methods whose name match the regexp defined by
-/// the given pattern.
-String get TRACE_FILTER_PATTERN => TRACE_FILTER_PATTERN_FROM_ENVIRONMENT != ''
-    ? TRACE_FILTER_PATTERN_FROM_ENVIRONMENT
-    : TRACE_FILTER_PATTERN_FOR_TEST;
-
-const String TRACE_FILTER_PATTERN_FROM_ENVIRONMENT =
-    String.fromEnvironment("DUMP_IR", defaultValue: "");
 String TRACE_FILTER_PATTERN_FOR_TEST;
 
 /// Dumps the intermediate representation after each phase in a format
@@ -29,14 +22,17 @@
   final api.OutputSink output;
   final RegExp traceFilter;
 
-  Tracer(this.closedWorld, api.CompilerOutput compilerOutput)
-      : traceFilter = TRACE_FILTER_PATTERN == null
-            ? null
-            : new RegExp(TRACE_FILTER_PATTERN),
-        output = TRACE_FILTER_PATTERN != null
-            ? compilerOutput.createOutputSink(
-                'dart', 'cfg', api.OutputType.debug)
-            : null;
+  Tracer._(this.closedWorld, this.traceFilter, this.output);
+
+  factory Tracer(JClosedWorld closedWorld, CompilerOptions options,
+      api.CompilerOutput compilerOutput) {
+    String pattern = options.dumpSsaPattern ?? TRACE_FILTER_PATTERN_FOR_TEST;
+    if (pattern == null) return Tracer._(closedWorld, null, null);
+    var traceFilter = RegExp(pattern);
+    var output =
+        compilerOutput.createOutputSink('', 'cfg', api.OutputType.debug);
+    return Tracer._(closedWorld, traceFilter, output);
+  }
 
   bool get isEnabled => traceFilter != null;
 
diff --git a/pkg/dart_internal/analysis_options.yaml b/pkg/dart_internal/analysis_options.yaml
index 1a46de2..edcd64e 100644
--- a/pkg/dart_internal/analysis_options.yaml
+++ b/pkg/dart_internal/analysis_options.yaml
@@ -1,3 +1,5 @@
 analyzer:
+  errors:
+    import_internal_library: ignore
   strong-mode:
     implicit-casts: false
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index c8d5b3d..29c4d07 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -7,7 +7,7 @@
 import '../utils.dart';
 
 void main() {
-  group('analyze', defineAnalyze, timeout: defaultTimeout);
+  group('analyze', defineAnalyze, timeout: longTimeout);
 }
 
 const String _analyzeDescriptionText = "Analyze the project's Dart code.";
diff --git a/pkg/dartdev/test/commands/create_test.dart b/pkg/dartdev/test/commands/create_test.dart
index 4eaee40..08ff9e3 100644
--- a/pkg/dartdev/test/commands/create_test.dart
+++ b/pkg/dartdev/test/commands/create_test.dart
@@ -12,7 +12,7 @@
 import '../utils.dart';
 
 void main() {
-  group('create', defineCreateTests);
+  group('create', defineCreateTests, timeout: longTimeout);
 }
 
 void defineCreateTests() {
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index 67820a5..c38e3f9 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -9,8 +9,8 @@
 import '../utils.dart';
 
 void main() {
-  group('command', command);
-  group('flag', help);
+  group('command', command, timeout: longTimeout);
+  group('flag', help, timeout: longTimeout);
 }
 
 void command() {
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 74c5c50..15dd356 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_test.dart
@@ -9,7 +9,7 @@
 import '../utils.dart';
 
 void main() {
-  group('format', format);
+  group('format', format, timeout: longTimeout);
 }
 
 void format() {
diff --git a/pkg/dartdev/test/commands/help_test.dart b/pkg/dartdev/test/commands/help_test.dart
index 204e4a0..eef0589 100644
--- a/pkg/dartdev/test/commands/help_test.dart
+++ b/pkg/dartdev/test/commands/help_test.dart
@@ -9,7 +9,7 @@
 import '../utils.dart';
 
 void main() {
-  group('help', help);
+  group('help', help, timeout: longTimeout);
 }
 
 void help() {
diff --git a/pkg/dartdev/test/commands/migrate_test.dart b/pkg/dartdev/test/commands/migrate_test.dart
index 1294f88..c3d2c97 100644
--- a/pkg/dartdev/test/commands/migrate_test.dart
+++ b/pkg/dartdev/test/commands/migrate_test.dart
@@ -8,7 +8,7 @@
 import '../utils.dart';
 
 void main() {
-  group('migrate', defineMigrateTests);
+  group('migrate', defineMigrateTests, timeout: longTimeout);
 }
 
 // TODO(jcollins-g): Set to true and/or remove when when NNBD is enabled in the
diff --git a/pkg/dartdev/test/commands/pub_test.dart b/pkg/dartdev/test/commands/pub_test.dart
index fa49271..b8a98ee 100644
--- a/pkg/dartdev/test/commands/pub_test.dart
+++ b/pkg/dartdev/test/commands/pub_test.dart
@@ -7,7 +7,7 @@
 import '../utils.dart';
 
 void main() {
-  group('pub', pub);
+  group('pub', pub, timeout: longTimeout);
 }
 
 void pub() {
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index 3699c92..214207c 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -9,7 +9,7 @@
 import '../utils.dart';
 
 void main() {
-  group('run', run);
+  group('run', run, timeout: longTimeout);
 }
 
 void run() {
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index e1e9b5c..3f2ea70 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -7,7 +7,7 @@
 import '../utils.dart';
 
 void main() {
-  group('test', defineTest);
+  group('test', defineTest, timeout: longTimeout);
 }
 
 void defineTest() {
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index 24db6fa..f191eaa 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -7,7 +7,10 @@
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
-Timeout defaultTimeout = Timeout(Duration(seconds: 15));
+/// A long [Timeout] is provided for tests that start a process on
+/// `bin/dartdev.dart` as the command is not compiled ahead of time, and each
+/// invocation requires the VM to compile the entire dependency graph.
+const Timeout longTimeout = Timeout(Duration(minutes: 5));
 
 TestProject project({String mainSrc, String analysisOptions}) {
   return TestProject(mainSrc: mainSrc, analysisOptions: analysisOptions);
diff --git a/pkg/dartfix/lib/src/migrate/migrate.dart b/pkg/dartfix/lib/src/migrate/migrate.dart
index ceddcce..a7cb7a4 100644
--- a/pkg/dartfix/lib/src/migrate/migrate.dart
+++ b/pkg/dartfix/lib/src/migrate/migrate.dart
@@ -8,7 +8,7 @@
 import 'package:analysis_server_client/handler/notification_handler.dart';
 import 'package:analysis_server_client/listener/server_listener.dart';
 import 'package:analysis_server_client/protocol.dart';
-import 'package:analysis_server_client/server.dart';
+import 'package:nnbd_migration/isolate_server.dart';
 import 'package:args/command_runner.dart';
 import 'package:cli_util/cli_logging.dart';
 import 'package:nnbd_migration/src/messages.dart';
@@ -88,18 +88,11 @@
 
     Map<String, List<AnalysisError>> fileErrors = {};
 
-    bool enableAsserts = false;
     String instrumentationLogFile;
-    bool profileServer = false;
-    String serverPath = options.serverPath;
-    int servicesPort;
     String sdkPath = options.sdkPath;
     bool stdioPassthrough = false;
 
     if (options.debug) {
-      enableAsserts = true;
-      profileServer = true;
-      servicesPort = 9500;
       stdioPassthrough = true;
       instrumentationLogFile = path.join(
           Directory.systemTemp.createTempSync('migration_debug').path,
@@ -116,11 +109,7 @@
       await server.start(
           clientId: 'dart $name',
           clientVersion: _dartSdkVersion,
-          enableAsserts: enableAsserts,
           instrumentationLogFile: instrumentationLogFile,
-          profileServer: profileServer,
-          serverPath: serverPath,
-          servicesPort: servicesPort,
           sdkPath: sdkPath);
       _ServerNotifications serverNotifications = _ServerNotifications(server);
       await serverNotifications.listenToServer(server);
@@ -200,6 +189,7 @@
       final EditDartfixParams params =
           EditDartfixParams([options.directoryAbsolute]);
       params.includedFixes = ['non-nullable'];
+      params.port = options.previewPort;
       json = await server.send(EDIT_REQUEST_DARTFIX, params.toJson());
       progress.finish(showTiming: true);
     } finally {
@@ -242,6 +232,8 @@
 
     if (options.webPreview) {
       String url = migrationResults.urls.first;
+      assert(migrationResults.urls.length <= 1,
+          'Got unexpected extra preview URLs from server');
 
       logger.stdout(ansi.emphasized('View migration results:'));
 
diff --git a/pkg/dartfix/lib/src/migrate/options.dart b/pkg/dartfix/lib/src/migrate/options.dart
index 20e2e67..f19908d 100644
--- a/pkg/dartfix/lib/src/migrate/options.dart
+++ b/pkg/dartfix/lib/src/migrate/options.dart
@@ -12,6 +12,7 @@
   static const applyChangesOption = 'apply-changes';
   static const debugOption = 'debug';
   static const ignoreErrorsOption = 'ignore-errors';
+  static const previewPortOption = 'preview-port';
   static const sdkPathOption = 'sdk-path';
   static const serverPathOption = 'server-path';
   static const webPreviewOption = 'web-preview';
@@ -20,6 +21,7 @@
   final bool debug;
   final String directory;
   final bool ignoreErrors;
+  final int previewPort;
   final String serverPath;
   final String sdkPath;
   final bool webPreview;
@@ -28,6 +30,8 @@
       : applyChanges = argResults[applyChangesOption] as bool,
         debug = argResults[debugOption] as bool,
         ignoreErrors = argResults[ignoreErrorsOption] as bool,
+        previewPort =
+            int.tryParse(argResults[previewPortOption] as String) ?? 0,
         sdkPath = argResults[sdkPathOption] as String,
         serverPath = argResults[serverPathOption] as String,
         webPreview = argResults['web-preview'] as bool;
@@ -67,6 +71,12 @@
       help: 'Override the SDK path used for migration.',
     );
     argParser.addOption(
+      previewPortOption,
+      defaultsTo: '0',
+      help: 'Run the preview server on the specified port.  If not specified '
+          'or invalid, dynamically allocate a port.',
+    );
+    argParser.addOption(
       serverPathOption,
       hide: true,
       help: 'Override the analysis server path used for migration.',
diff --git a/pkg/dev_compiler/lib/dev_compiler.dart b/pkg/dev_compiler/lib/dev_compiler.dart
index ff98a4d..dedfc72 100644
--- a/pkg/dev_compiler/lib/dev_compiler.dart
+++ b/pkg/dev_compiler/lib/dev_compiler.dart
@@ -4,7 +4,7 @@
 
 // The dev_compiler does not have a publishable public API, instead this is
 // intended for other consumers within the Dart SDK.
-export 'src/compiler/module_builder.dart' show ModuleFormat;
+export 'src/compiler/module_builder.dart' show ModuleFormat, parseModuleFormat;
 export 'src/compiler/shared_command.dart' show SharedCompilerOptions;
 export 'src/kernel/command.dart' show jsProgramToCode;
 export 'src/kernel/compiler.dart' show ProgramCompiler;
diff --git a/pkg/dev_compiler/lib/src/compiler/module_builder.dart b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
index 842287d..da8765a 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_builder.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
@@ -25,15 +25,25 @@
 }
 
 /// Parses a string into a [ModuleFormat].
-ModuleFormat parseModuleFormat(String s) => {
-      'es6': ModuleFormat.es6,
-      'common': ModuleFormat.common,
-      'amd': ModuleFormat.amd,
-      'ddc': ModuleFormat.ddc,
-      // Deprecated:
-      'node': ModuleFormat.common,
-      'legacy': ModuleFormat.ddc
-    }[s];
+///
+/// Throws an [ArgumentError] if the module format is not recognized.
+ModuleFormat parseModuleFormat(String s) {
+  var formats = const {
+    'es6': ModuleFormat.es6,
+    'common': ModuleFormat.common,
+    'amd': ModuleFormat.amd,
+    'ddc': ModuleFormat.ddc,
+    // Deprecated:
+    'node': ModuleFormat.common,
+    'legacy': ModuleFormat.ddc
+  };
+  var selected = formats[s];
+  if (selected == null) {
+    throw ArgumentError('Invalid module format `$s`, allowed formats are: '
+        '`${formats.keys.join(', ')}`');
+  }
+  return selected;
+}
 
 /// Parse the module format option added by [addModuleFormatOptions].
 List<ModuleFormat> parseModuleFormatOption(ArgResults args) {
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index b297574..584850a 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -1038,43 +1038,23 @@
       // * There isn't an obvious place in dart:_runtime were we could place a
       //   method that adds these type tests (similar to addTypeTests()) because
       //   in the bootstrap ordering the Future class hasn't been defined yet.
-      if (_options.enableNullSafety) {
-        var typeParam =
-            TypeParameterType(c.typeParameters[0], Nullability.undetermined);
-        var typeT = visitTypeParameterType(typeParam);
-        var futureOfT = visitInterfaceType(InterfaceType(
-            _coreTypes.futureClass, currentLibrary.nonNullable, [typeParam]));
-        body.add(js.statement('''
-            #.is = function is_FutureOr(o) {
-              return #.is(o) || #.is(o);
-            }
-            ''', [className, typeT, futureOfT]));
-        body.add(js.statement('''
-            #.as = function as_FutureOr(o) {
-              if (#.is(o) || #.is(o)) return o;
-              return #.as(o, this);
-            }
-            ''', [className, typeT, futureOfT, runtimeModule]));
-        return null;
-      } else {
-        var typeParam =
-            TypeParameterType(c.typeParameters[0], Nullability.legacy);
-        var typeT = visitTypeParameterType(typeParam);
-        var futureOfT = visitInterfaceType(InterfaceType(
-            _coreTypes.futureClass, Nullability.legacy, [typeParam]));
-        body.add(js.statement('''
-            #.is = function is_FutureOr(o) {
-              return #.is(o) || #.is(o);
-            }
-            ''', [className, typeT, futureOfT]));
-        body.add(js.statement('''
-            #.as = function as_FutureOr(o) {
-              if (o == null || #.is(o) || #.is(o)) return o;
-              #.castError(o, this);
-            }
-            ''', [className, typeT, futureOfT, runtimeModule]));
-        return null;
-      }
+      var typeParam =
+          TypeParameterType(c.typeParameters[0], Nullability.undetermined);
+      var typeT = visitTypeParameterType(typeParam);
+      var futureOfT = visitInterfaceType(InterfaceType(
+          _coreTypes.futureClass, currentLibrary.nonNullable, [typeParam]));
+      body.add(js.statement('''
+          #.is = function is_FutureOr(o) {
+            return #.is(o) || #.is(o);
+          }
+          ''', [className, typeT, futureOfT]));
+      body.add(js.statement('''
+          #.as = function as_FutureOr(o) {
+            if (#.is(o) || #.is(o)) return o;
+            return #.as(o, this);
+          }
+          ''', [className, typeT, futureOfT, runtimeModule]));
+      return null;
     }
 
     body.add(runtimeStatement('addTypeTests(#)', [className]));
@@ -2574,13 +2554,9 @@
           _coreTypes.futureClass, futureOr.nullability, [typeArgument]);
     } else if (typeArgument is InterfaceType &&
         typeArgument.classNode == _coreTypes.nullClass) {
-      // TODO(40266) Remove this workaround when we unfork dart:_runtime
-      var nullability = _options.enableNullSafety
-          ? Nullability.nullable
-          : currentLibrary.nullable;
       // FutureOr<Null> --> Future<Null>?
-      normalizedType =
-          InterfaceType(_coreTypes.futureClass, nullability, [typeArgument]);
+      normalizedType = InterfaceType(
+          _coreTypes.futureClass, Nullability.nullable, [typeArgument]);
     } else if (futureOr.nullability == Nullability.nullable &&
         typeArgument.nullability == Nullability.nullable) {
       // FutureOr<T?>? --> FutureOr<T?>
@@ -2655,27 +2631,38 @@
     //   * `class A extends B {...}` where B is the InterfaceType.
     //   * Emitting non-null constructor calls.
     // * The InterfaceType is the Null type.
-    if (!emitNullability || type == _coreTypes.nullType) return typeRep;
+    // * The types were written in JS context or as part of the dart:_runtime
+    //   library.
+    if (!emitNullability ||
+        type == _coreTypes.nullType ||
+        // TODO(38701) Remove these once the SDK has unforked and is running
+        // "opted-in"
+        !coreLibrary.isNonNullableByDefault &&
+            (_isInForeignJS || isSdkInternalRuntime(currentLibrary))) {
+      return typeRep;
+    }
 
     if (type.nullability == Nullability.undetermined) {
       throw UnsupportedError('Undetermined Nullability');
     }
-    return _emitNullabilityWrapper(typeRep, type.nullability);
+
+    // Emit non-nullable version directly.
+    typeRep = _emitNullabilityWrapper(typeRep, type.nullability);
+    if (!_cacheTypes || type.nullability == Nullability.nonNullable) {
+      return typeRep;
+    }
+
+    // Hoist the nullable or legacy versions of the type to the top level and
+    // use it everywhere it appears.
+    return _typeTable.nameType(type, typeRep);
   }
 
   /// Wraps [typeRep] in the appropriate wrapper for the given [nullability].
   ///
-  /// NOTE: This is currently a no-op if the null safety experiment is not
-  /// enabled.
-  ///
   /// Non-nullable and undetermined nullability will not cause any wrappers to
   /// be emitted.
   js_ast.Expression _emitNullabilityWrapper(
       js_ast.Expression typeRep, Nullability nullability) {
-    // TODO(nshahan) Cleanup this check once it is safe to always emit the
-    // legacy wrapper.
-    if (!_options.enableNullSafety) return typeRep;
-
     switch (nullability) {
       case Nullability.legacy:
         return runtimeCall('legacy(#)', [typeRep]);
@@ -2798,13 +2785,22 @@
       helperCall = 'fnType(#)';
     }
     var typeRep = runtimeCall(helperCall, [typeParts]);
-    // Avoid caching the nullability of the function type itself so it can be
-    // shared by nullable, non-nullable, and legacy versions at the use site.
+    // First add the type to the type table in its non-nullable form. It can be
+    // reused by the nullable and legacy versions.
     typeRep = _cacheTypes
-        ? _typeTable.nameFunctionType(type, typeRep, lazy: lazy)
+        ? _typeTable.nameFunctionType(
+            type.withNullability(Nullability.nonNullable), typeRep,
+            lazy: lazy)
         : typeRep;
 
-    return _emitNullabilityWrapper(typeRep, type.nullability);
+    if (type.nullability == Nullability.nonNullable) return typeRep;
+
+    // Hoist the nullable or legacy versions of the type to the top level and
+    // use it everywhere it appears.
+    typeRep = _emitNullabilityWrapper(typeRep, type.nullability);
+    return _cacheTypes
+        ? _typeTable.nameFunctionType(type, typeRep, lazy: lazy)
+        : typeRep;
   }
 
   /// Emits an expression that lets you access statics on a [type] from code.
@@ -2846,9 +2842,17 @@
   js_ast.Expression _emitTypeParameterType(TypeParameterType type,
       {bool emitNullability = true}) {
     var typeParam = _emitTypeParameter(type.parameter);
-    if (!emitNullability) return typeParam;
+    if (!emitNullability ||
+        !_cacheTypes ||
+        // Emit non-nullable version directly.
+        type.isPotentiallyNonNullable) {
+      return typeParam;
+    }
 
-    return _emitNullabilityWrapper(typeParam, type.nullability);
+    // Hoist the wrapped version to the top level and use it everywhere this
+    // type appears.
+    return _typeTable.nameType(
+        type, _emitNullabilityWrapper(typeParam, type.nullability));
   }
 
   js_ast.Identifier _emitTypeParameter(TypeParameter t) =>
@@ -4746,8 +4750,16 @@
 
     // Optimize some internal SDK calls.
     if (isSdkInternalRuntime(target.enclosingLibrary)) {
-      if (node.arguments.positional.length == 1) {
-        var name = target.name.name;
+      var name = target.name.name;
+      if (node.arguments.positional.isEmpty) {
+        if (name == 'typeRep') {
+          return _emitType(node.arguments.types.single);
+        }
+        if (name == 'legacyTypeRep') {
+          return _emitType(
+              node.arguments.types.single.withNullability(Nullability.legacy));
+        }
+      } else if (node.arguments.positional.length == 1) {
         var firstArg = node.arguments.positional[0];
         if (name == 'getGenericClass' && firstArg is TypeLiteral) {
           var type = firstArg.type;
@@ -4762,17 +4774,20 @@
           return getExtensionSymbolInternal(firstArg.value);
         }
       } else if (node.arguments.positional.length == 2) {
-        var name = target.name.name;
         var firstArg = node.arguments.positional[0];
         var secondArg = node.arguments.positional[1];
         if (name == '_jsInstanceOf' && secondArg is TypeLiteral) {
-          return js.call('# instanceof #',
-              [_visitExpression(firstArg), _emitType(secondArg.type)]);
+          return js.call('# instanceof #', [
+            _visitExpression(firstArg),
+            _emitType(secondArg.type.withNullability(Nullability.nonNullable))
+          ]);
         }
 
         if (name == '_equalType' && secondArg is TypeLiteral) {
-          return js.call('# === #',
-              [_visitExpression(firstArg), _emitType(secondArg.type)]);
+          return js.call('# === #', [
+            _visitExpression(firstArg),
+            _emitType(secondArg.type.withNullability(Nullability.nonNullable))
+          ]);
         }
       }
     }
diff --git a/pkg/dev_compiler/test/modular_suite.dart b/pkg/dev_compiler/test/modular_suite.dart
index 865cc53..573238d 100644
--- a/pkg/dev_compiler/test/modular_suite.dart
+++ b/pkg/dev_compiler/test/modular_suite.dart
@@ -26,7 +26,7 @@
       _options,
       IOPipeline([
         SourceToSummaryDillStep(),
-        DDKStep(),
+        DDCStep(),
         RunD8(),
       ], cacheSharedModules: true));
 }
@@ -120,7 +120,7 @@
   }
 }
 
-class DDKStep implements IOModularStep {
+class DDCStep implements IOModularStep {
   @override
   List<DataId> get resultData => const [jsId];
 
@@ -139,7 +139,7 @@
   @override
   Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
       List<String> flags) async {
-    if (_options.verbose) print('\nstep: ddk on $module');
+    if (_options.verbose) print('\nstep: ddc on $module');
 
     var transitiveDependencies = computeTransitiveDependencies(module);
     await _createPackagesFile(module, root, transitiveDependencies);
@@ -192,7 +192,7 @@
 
   @override
   void notifyCached(Module module) {
-    if (_options.verbose) print('\ncached step: ddk on $module');
+    if (_options.verbose) print('\ncached step: ddc on $module');
   }
 }
 
diff --git a/pkg/dev_compiler/test/modular_suite_nnbd.dart b/pkg/dev_compiler/test/modular_suite_nnbd.dart
index 4f1b317..41377bc 100644
--- a/pkg/dev_compiler/test/modular_suite_nnbd.dart
+++ b/pkg/dev_compiler/test/modular_suite_nnbd.dart
@@ -21,12 +21,12 @@
   _options = Options.parse(args);
   await _resolveScripts();
   await runSuite(
-      sdkRoot.resolve('tests/compiler/dartdevc/modular/'),
-      'tests/compiler/dartdevc/modular',
+      sdkRoot.resolve('tests/modular/'),
+      'tests/modular',
       _options,
       IOPipeline([
         SourceToSummaryDillStep(),
-        DDKStep(),
+        DDCStep(),
         RunD8(),
       ], cacheSharedModules: true));
 }
@@ -77,7 +77,7 @@
       sources = ['dart:core'];
       extraArgs = [
         '--libraries-file',
-        '$rootScheme:///sdk_nnbd/lib/libraries_nnbd_mix_hack.json'
+        '$rootScheme:///sdk_nnbd/lib/libraries.json',
       ];
       assert(transitiveDependencies.isEmpty);
     } else {
@@ -109,6 +109,10 @@
           .where((m) => !m.isSdk)
           .expand((m) => ['--input-summary', '${toUri(m, dillId)}'])),
       ...(sources.expand((String uri) => ['--source', uri])),
+      // TODO(40266) After unfork of dart:_runtime only need experiment when
+      // compiling SDK. For now always use the Null Safety experiment.
+      '--enable-experiment',
+      'non-nullable',
       ...(flags.expand((String flag) => ['--enable-experiment', flag])),
     ];
 
@@ -123,7 +127,7 @@
   }
 }
 
-class DDKStep implements IOModularStep {
+class DDCStep implements IOModularStep {
   @override
   List<DataId> get resultData => const [jsId];
 
@@ -142,7 +146,7 @@
   @override
   Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
       List<String> flags) async {
-    if (_options.verbose) print('\nstep: ddk on $module');
+    if (_options.verbose) print('\nstep: ddc on $module');
 
     var transitiveDependencies = computeTransitiveDependencies(module);
     await _createPackagesFile(module, root, transitiveDependencies);
@@ -152,11 +156,10 @@
     List<String> extraArgs;
     if (module.isSdk) {
       sources = ['dart:core'];
-      // extraArgs = [];
       extraArgs = [
         '--compile-sdk',
         '--libraries-file',
-        '$rootScheme:///sdk_nnbd/lib/libraries_nnbd_mix_hack.json'
+        '$rootScheme:///sdk_nnbd/lib/libraries.json',
       ];
       assert(transitiveDependencies.isEmpty);
     } else {
@@ -179,7 +182,6 @@
       '--packages=${sdkRoot.toFilePath()}/.packages',
       _dartdevcScript,
       '--kernel',
-      '--summarize-text',
       '--modules=es6',
       '--no-summarize',
       '--no-source-map',
@@ -187,6 +189,10 @@
       rootScheme,
       ...sources,
       ...extraArgs,
+      // TODO(40266) After unfork of dart:_runtime only need experiment when
+      // compiling SDK. For now always use the Null Safety experiment.
+      '--enable-experiment',
+      'non-nullable',
       for (String flag in flags) '--enable-experiment=$flag',
       ...(transitiveDependencies
           .where((m) => !m.isSdk)
@@ -201,7 +207,7 @@
 
   @override
   void notifyCached(Module module) {
-    if (_options.verbose) print('\ncached step: ddk on $module');
+    if (_options.verbose) print('\ncached step: ddc on $module');
   }
 }
 
@@ -238,6 +244,7 @@
     var runjs = '''
     import { dart, _isolate_helper } from 'dart_sdk.js';
     import { main } from 'main.js';
+    dart.strictSubtypeChecks(false);
     _isolate_helper.startRootIsolate(() => {}, []);
     main.main();
     ''';
@@ -310,9 +317,11 @@
   if (module.isPackage) {
     packagesContents.write('${module.name}:${module.packageBase}\n');
   }
+  var unusedNum = 0;
   for (var dependency in transitiveDependencies) {
     if (dependency.isPackage) {
-      packagesContents.write('${dependency.name}:unused\n');
+      unusedNum++;
+      packagesContents.write('${dependency.name}:unused$unusedNum\n');
     }
   }
 
diff --git a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
index b091933..1140c53 100644
--- a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
@@ -1,10 +1,10 @@
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1631|7|5|Superinterfaces don't have a valid override for '&': int.& (int Function(int)), JSNumber.& (num Function(num)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1631|7|5|Superinterfaces don't have a valid override for '<<': int.<< (int Function(int)), JSNumber.<< (num Function(num)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1631|7|5|Superinterfaces don't have a valid override for '>>': int.>> (int Function(int)), JSNumber.>> (num Function(num)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1631|7|5|Superinterfaces don't have a valid override for '\|': int.\| (int Function(int)), JSNumber.\| (num Function(num)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1631|7|5|Superinterfaces don't have a valid override for '^': int.^ (int Function(int)), JSNumber.^ (num Function(num)).
-ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1648|28|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1650|27|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1653|17|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1658|18|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1658|44|1|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1634|7|5|Superinterfaces don't have a valid override for '&': JSNumber.& (num Function(num)), int.& (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1634|7|5|Superinterfaces don't have a valid override for '<<': JSNumber.<< (num Function(num)), int.<< (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1634|7|5|Superinterfaces don't have a valid override for '>>': JSNumber.>> (num Function(num)), int.>> (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1634|7|5|Superinterfaces don't have a valid override for '\|': JSNumber.\| (num Function(num)), int.\| (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1634|7|5|Superinterfaces don't have a valid override for '^': JSNumber.^ (num Function(num)), int.^ (int Function(int)).
+ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1651|28|1|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1653|27|1|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1656|17|1|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1661|18|1|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|STATIC_TYPE_WARNING|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1661|44|1|The operator '&' isn't defined for the type 'JSInt'.
diff --git a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
index 8b13789..80acd97 100644
--- a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
@@ -1 +1,8 @@
-
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|3716|5|94|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|7902|5|97|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|940|5|95|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|973|5|94|Const constructors can't throw exceptions.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|3714|3|5|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|7900|3|5|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|938|3|5|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|971|3|5|Only redirecting factory constructors can be declared to be 'const'.
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index 9945733..cb97bf9 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -26,17 +26,17 @@
 const int enableExtensionMethodsMajorVersion = 2;
 const int enableExtensionMethodsMinorVersion = 6;
 const int enableNonNullableMajorVersion = 2;
-const int enableNonNullableMinorVersion = 8;
+const int enableNonNullableMinorVersion = 9;
 const int enableNonfunctionTypeAliasesMajorVersion = 2;
-const int enableNonfunctionTypeAliasesMinorVersion = 8;
+const int enableNonfunctionTypeAliasesMinorVersion = 9;
 const int enableSetLiteralsMajorVersion = 2;
 const int enableSetLiteralsMinorVersion = 2;
 const int enableSpreadCollectionsMajorVersion = 2;
 const int enableSpreadCollectionsMinorVersion = 2;
 const int enableTripleShiftMajorVersion = 2;
-const int enableTripleShiftMinorVersion = 8;
+const int enableTripleShiftMinorVersion = 9;
 const int enableVarianceMajorVersion = 2;
-const int enableVarianceMinorVersion = 8;
+const int enableVarianceMinorVersion = 9;
 
 ExperimentalFlag parseExperimentalFlag(String flag) {
   switch (flag) {
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index f199738..48303eb 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -132,13 +132,15 @@
   }
 
   List<int> _sdkSummaryBytes;
+  bool _triedLoadingSdkSummary = false;
 
   /// Get the bytes of the SDK outline, if any.
   Future<List<int>> loadSdkSummaryBytes() async {
-    if (_sdkSummaryBytes == null) {
+    if (_sdkSummaryBytes == null && !_triedLoadingSdkSummary) {
       if (sdkSummary == null) return null;
       FileSystemEntity entry = fileSystem.entityForUri(sdkSummary);
       _sdkSummaryBytes = await _readAsBytes(entry);
+      _triedLoadingSdkSummary = true;
     }
     return _sdkSummaryBytes;
   }
@@ -364,8 +366,10 @@
       // TODO(sigmund): throttle # of concurrent operations.
       List<List<int>> allBytes = await Future.wait(
           uris.map((uri) => _readAsBytes(fileSystem.entityForUri(uri))));
-      _additionalDillComponents =
-          allBytes.map((bytes) => loadComponent(bytes, nameRoot)).toList();
+      _additionalDillComponents = allBytes
+          .where((bytes) => bytes != null)
+          .map((bytes) => loadComponent(bytes, nameRoot))
+          .toList();
     }
     return _additionalDillComponents;
   }
@@ -726,7 +730,7 @@
               .withArguments(error.uri, error.message)
               .withoutLocation(),
           Severity.error);
-      return new Uint8List(0);
+      return null;
     }
   }
 }
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 cebb845..fd82ceb 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -21,18 +21,15 @@
         Member,
         MethodInvocation,
         Name,
-        NeverType,
         Nullability,
         Procedure,
         ProcedureKind,
-        RedirectingFactoryConstructor,
         ReturnStatement,
         Supertype,
         ThisExpression,
         TypeParameter,
         TypeParameterType,
         VariableDeclaration,
-        Variance,
         VoidType,
         getAsTypeArguments;
 
@@ -40,13 +37,6 @@
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
-import 'package:kernel/src/bounds_checks.dart'
-    show
-        TypeArgumentIssue,
-        computeVariance,
-        findTypeArgumentIssues,
-        getGenericTypeName;
-
 import 'package:kernel/src/legacy_erasure.dart';
 
 import 'package:kernel/text/text_serialization_verifier.dart';
@@ -56,6 +46,8 @@
 import 'package:kernel/type_environment.dart'
     show SubtypeCheckMode, TypeEnvironment;
 
+import 'package:kernel/src/types.dart' show Types;
+
 import '../dill/dill_member_builder.dart' show DillMemberBuilder;
 
 import '../fasta_codes.dart';
@@ -64,8 +56,6 @@
 
 import '../kernel/kernel_target.dart' show KernelTarget;
 
-import '../kernel/types.dart' show Types;
-
 import '../loader.dart';
 
 import '../modifier.dart';
@@ -202,11 +192,6 @@
 
   void checkSupertypes(CoreTypes coreTypes);
 
-  void checkBoundsInSupertype(
-      Supertype supertype, TypeEnvironment typeEnvironment);
-
-  void checkTypesInOutline(TypeEnvironment typeEnvironment);
-
   void handleSeenCovariant(
       Types types,
       Member declaredMember,
@@ -749,273 +734,6 @@
   }
 
   @override
-  void checkBoundsInSupertype(
-      Supertype supertype, TypeEnvironment typeEnvironment) {
-    SourceLibraryBuilder library = this.library;
-    final DartType bottomType = library.isNonNullableByDefault
-        ? const NeverType(Nullability.nonNullable)
-        : typeEnvironment.nullType;
-
-    Set<TypeArgumentIssue> issues = {};
-    issues.addAll(findTypeArgumentIssues(
-            new InterfaceType(supertype.classNode, library.nonNullable,
-                supertype.typeArguments),
-            typeEnvironment,
-            SubtypeCheckMode.ignoringNullabilities,
-            bottomType,
-            allowSuperBounded: false) ??
-        const []);
-    if (library.isNonNullableByDefault) {
-      issues.addAll(findTypeArgumentIssues(
-              new InterfaceType(supertype.classNode, library.nonNullable,
-                  supertype.typeArguments),
-              typeEnvironment,
-              SubtypeCheckMode.withNullabilities,
-              bottomType,
-              allowSuperBounded: false) ??
-          const []);
-    }
-    for (TypeArgumentIssue issue in issues) {
-      DartType argument = issue.argument;
-      TypeParameter typeParameter = issue.typeParameter;
-      bool inferred = library.inferredTypes.contains(argument);
-      if (argument is FunctionType && argument.typeParameters.length > 0) {
-        if (inferred) {
-          library.reportTypeArgumentIssue(
-              templateGenericFunctionTypeInferredAsActualTypeArgument
-                  .withArguments(argument, library.isNonNullableByDefault),
-              fileUri,
-              charOffset,
-              null);
-        } else {
-          library.reportTypeArgumentIssue(
-              messageGenericFunctionTypeUsedAsActualTypeArgument,
-              fileUri,
-              charOffset,
-              null);
-        }
-      } else {
-        void reportProblem(
-            Template<
-                    Message Function(DartType, DartType, String, String, String,
-                        String, bool)>
-                template) {
-          library.reportTypeArgumentIssue(
-              template.withArguments(
-                  argument,
-                  typeParameter.bound,
-                  typeParameter.name,
-                  getGenericTypeName(issue.enclosingType),
-                  supertype.classNode.name,
-                  name,
-                  library.isNonNullableByDefault),
-              fileUri,
-              charOffset,
-              typeParameter);
-        }
-
-        if (inferred) {
-          reportProblem(templateIncorrectTypeArgumentInSupertypeInferred);
-        } else {
-          reportProblem(templateIncorrectTypeArgumentInSupertype);
-        }
-      }
-    }
-  }
-
-  @override
-  void checkTypesInOutline(TypeEnvironment typeEnvironment) {
-    SourceLibraryBuilder library = this.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(parameter.bound, typeEnvironment,
-              SubtypeCheckMode.ignoringNullabilities, bottomType,
-              allowSuperBounded: true) ??
-          const []);
-      if (library.isNonNullableByDefault) {
-        issues.addAll(findTypeArgumentIssues(parameter.bound, typeEnvironment,
-                SubtypeCheckMode.withNullabilities, bottomType,
-                allowSuperBounded: true) ??
-            const []);
-      }
-      for (TypeArgumentIssue issue in issues) {
-        DartType argument = issue.argument;
-        TypeParameter typeParameter = issue.typeParameter;
-        if (library.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) {
-          library.reportTypeArgumentIssue(
-              messageGenericFunctionTypeUsedAsActualTypeArgument,
-              fileUri,
-              parameter.fileOffset,
-              null);
-        } else {
-          library.reportTypeArgumentIssue(
-              templateIncorrectTypeArgument.withArguments(
-                  argument,
-                  typeParameter.bound,
-                  typeParameter.name,
-                  getGenericTypeName(issue.enclosingType),
-                  library.isNonNullableByDefault),
-              fileUri,
-              parameter.fileOffset,
-              typeParameter);
-        }
-      }
-    }
-
-    // Check in supers.
-    if (cls.supertype != null) {
-      checkBoundsInSupertype(cls.supertype, typeEnvironment);
-    }
-    if (cls.mixedInType != null) {
-      checkBoundsInSupertype(cls.mixedInType, typeEnvironment);
-    }
-    if (cls.implementedTypes != null) {
-      for (Supertype supertype in cls.implementedTypes) {
-        checkBoundsInSupertype(supertype, typeEnvironment);
-      }
-    }
-
-    // Check in members.
-    for (Procedure procedure in cls.procedures) {
-      checkVarianceInFunction(procedure, typeEnvironment, cls.typeParameters);
-      library.checkBoundsInFunctionNode(
-          procedure.function, typeEnvironment, fileUri);
-    }
-    for (Constructor constructor in cls.constructors) {
-      library.checkBoundsInFunctionNode(
-          constructor.function, typeEnvironment, fileUri);
-    }
-    for (RedirectingFactoryConstructor redirecting
-        in cls.redirectingFactoryConstructors) {
-      library.checkBoundsInFunctionNodeParts(
-          typeEnvironment, fileUri, redirecting.fileOffset,
-          typeParameters: redirecting.typeParameters,
-          positionalParameters: redirecting.positionalParameters,
-          namedParameters: redirecting.namedParameters);
-    }
-
-    forEach((String name, Builder builder) {
-      // Check fields.
-      if (builder is FieldBuilder) {
-        checkVarianceInField(
-            builder.field, typeEnvironment, cls.typeParameters);
-        library.checkTypesInField(builder, typeEnvironment);
-      }
-
-      // Check initializers.
-      if (builder is FunctionBuilder &&
-          !builder.isAbstract &&
-          builder.formals != null) {
-        library.checkInitializersInFormals(builder.formals, typeEnvironment);
-      }
-    });
-  }
-
-  void checkVarianceInField(Field field, TypeEnvironment typeEnvironment,
-      List<TypeParameter> typeParameters) {
-    for (TypeParameter typeParameter in typeParameters) {
-      int fieldVariance = computeVariance(typeParameter, field.type);
-      if (field.hasImplicitGetter) {
-        reportVariancePositionIfInvalid(
-            fieldVariance, typeParameter, field.fileUri, field.fileOffset);
-      }
-      if (field.hasImplicitSetter && !field.isCovariant) {
-        fieldVariance = Variance.combine(Variance.contravariant, fieldVariance);
-        reportVariancePositionIfInvalid(
-            fieldVariance, typeParameter, field.fileUri, field.fileOffset);
-      }
-    }
-  }
-
-  void checkVarianceInFunction(Procedure procedure,
-      TypeEnvironment typeEnvironment, List<TypeParameter> typeParameters) {
-    List<TypeParameter> functionTypeParameters =
-        procedure.function.typeParameters;
-    List<VariableDeclaration> positionalParameters =
-        procedure.function.positionalParameters;
-    List<VariableDeclaration> namedParameters =
-        procedure.function.namedParameters;
-    DartType returnType = procedure.function.returnType;
-
-    if (functionTypeParameters != null) {
-      for (TypeParameter functionParameter in functionTypeParameters) {
-        for (TypeParameter typeParameter in typeParameters) {
-          int typeVariance = Variance.combine(Variance.invariant,
-              computeVariance(typeParameter, functionParameter.bound));
-          reportVariancePositionIfInvalid(typeVariance, typeParameter, fileUri,
-              functionParameter.fileOffset);
-        }
-      }
-    }
-    if (positionalParameters != null) {
-      for (VariableDeclaration formal in positionalParameters) {
-        if (!formal.isCovariant) {
-          for (TypeParameter typeParameter in typeParameters) {
-            int formalVariance = Variance.combine(Variance.contravariant,
-                computeVariance(typeParameter, formal.type));
-            reportVariancePositionIfInvalid(
-                formalVariance, typeParameter, fileUri, formal.fileOffset);
-          }
-        }
-      }
-    }
-    if (namedParameters != null) {
-      for (VariableDeclaration named in namedParameters) {
-        for (TypeParameter typeParameter in typeParameters) {
-          int namedVariance = Variance.combine(Variance.contravariant,
-              computeVariance(typeParameter, named.type));
-          reportVariancePositionIfInvalid(
-              namedVariance, typeParameter, fileUri, named.fileOffset);
-        }
-      }
-    }
-    if (returnType != null) {
-      for (TypeParameter typeParameter in typeParameters) {
-        int returnTypeVariance = computeVariance(typeParameter, returnType);
-        reportVariancePositionIfInvalid(returnTypeVariance, typeParameter,
-            fileUri, procedure.function.fileOffset,
-            isReturnType: true);
-      }
-    }
-  }
-
-  void reportVariancePositionIfInvalid(
-      int variance, TypeParameter typeParameter, Uri fileUri, int fileOffset,
-      {bool isReturnType: false}) {
-    SourceLibraryBuilder library = this.library;
-    if (!typeParameter.isLegacyCovariant &&
-        !Variance.greaterThanOrEqual(variance, typeParameter.variance)) {
-      Message message;
-      if (isReturnType) {
-        message = templateInvalidTypeVariableVariancePositionInReturnType
-            .withArguments(Variance.keywordString(typeParameter.variance),
-                typeParameter.name, Variance.keywordString(variance));
-      } else {
-        message = templateInvalidTypeVariableVariancePosition.withArguments(
-            Variance.keywordString(typeParameter.variance),
-            typeParameter.name,
-            Variance.keywordString(variance));
-      }
-      library.reportTypeArgumentIssue(
-          message, fileUri, fileOffset, typeParameter);
-    }
-  }
-
-  @override
   void handleSeenCovariant(
       Types types,
       Member declaredMember,
@@ -1025,8 +743,9 @@
     // When a parameter is covariant we have to check that we also
     // override the same member in all parents.
     for (Supertype supertype in interfaceMember.enclosingClass.supers) {
-      Member m = types.hierarchy.getInterfaceMemberKernel(
-          supertype.classNode, interfaceMember.name, isSetter);
+      Member m = types.hierarchy.getInterfaceMember(
+          supertype.classNode, interfaceMember.name,
+          setter: isSetter);
       if (m != null) {
         callback(declaredMember, m, isSetter);
       }
@@ -1160,7 +879,7 @@
       interfaceSubstitution = Substitution.fromPairs(
           enclosingClass.typeParameters,
           types.hierarchy
-              .getKernelTypeArgumentsAsInstanceOf(thisType, enclosingClass));
+              .getTypeArgumentsAsInstanceOf(thisType, enclosingClass));
     }
 
     if (declaredFunction?.typeParameters?.length !=
@@ -1203,8 +922,13 @@
                 interfaceSubstitution.substituteType(interfaceBound);
           }
           DartType computedBound = substitution.substituteType(interfaceBound);
+          if (!library.isNonNullableByDefault) {
+            computedBound =
+                legacyErasure(types.hierarchy.coreTypes, computedBound);
+          }
           if (!types
-              .isSameTypeKernel(declaredBound, computedBound)
+              .performNullabilityAwareMutualSubtypesCheck(
+                  declaredBound, computedBound)
               .isSubtypeWhenUsingNullabilities()) {
             reportInvalidOverride(
                 isInterfaceCheck,
@@ -1243,7 +967,7 @@
       declaredSubstitution = Substitution.fromPairs(
           enclosingClass.typeParameters,
           types.hierarchy
-              .getKernelTypeArgumentsAsInstanceOf(thisType, enclosingClass));
+              .getTypeArgumentsAsInstanceOf(thisType, enclosingClass));
     }
     return declaredSubstitution;
   }
@@ -1276,11 +1000,11 @@
     DartType subtype = inParameter ? interfaceType : declaredType;
     DartType supertype = inParameter ? declaredType : interfaceType;
 
-    if (types.isSubtypeOfKernel(
+    if (types.isSubtypeOf(
         subtype, supertype, SubtypeCheckMode.withNullabilities)) {
       // No problem--the proper subtyping relation is satisfied.
     } else if (isCovariant &&
-        types.isSubtypeOfKernel(
+        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.
@@ -1289,10 +1013,10 @@
       // been reported.
     } else {
       // Report an error.
-      bool isErrorInNnbdOptedOutMode = !types.isSubtypeOfKernel(
+      bool isErrorInNnbdOptedOutMode = !types.isSubtypeOf(
               subtype, supertype, SubtypeCheckMode.ignoringNullabilities) &&
           (!isCovariant ||
-              !types.isSubtypeOfKernel(
+              !types.isSubtypeOf(
                   supertype, subtype, SubtypeCheckMode.ignoringNullabilities));
       if (isErrorInNnbdOptedOutMode || library.isNonNullableByDefault) {
         String declaredMemberName = '${declaredMember.enclosingClass.name}'
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 9a69677..5cb9fc0 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -674,12 +674,14 @@
         new Field(null, fileUri: fileUri, reference: referenceFrom?.reference)
           ..fileOffset = charOffset
           ..fileEndOffset = charEndOffset
-          ..isNonNullableByDefault = true;
+          ..isNonNullableByDefault = true
+          ..isInternalImplementation = true;
     _lateIsSetField = new Field(null,
         fileUri: fileUri, reference: lateIsSetReferenceFrom?.reference)
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
-      ..isNonNullableByDefault = true;
+      ..isNonNullableByDefault = true
+      ..isInternalImplementation = true;
     _lateGetter = new Procedure(
         null, ProcedureKind.Getter, new FunctionNode(null),
         fileUri: fileUri, reference: getterReferenceFrom?.reference)
@@ -936,11 +938,14 @@
   @override
   List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) {
     List<ClassMember> list = <ClassMember>[
-      new _LateFieldClassMember(fieldBuilder, field),
-      new _LateFieldClassMember(fieldBuilder, _lateGetter)
+      new _LateFieldClassMember(fieldBuilder, field,
+          isInternalImplementation: true),
+      new _LateFieldClassMember(fieldBuilder, _lateGetter,
+          isInternalImplementation: false)
     ];
     if (_lateIsSetField != null) {
-      list.add(new _LateFieldClassMember(fieldBuilder, _lateIsSetField));
+      list.add(new _LateFieldClassMember(fieldBuilder, _lateIsSetField,
+          isInternalImplementation: true));
     }
     return list;
   }
@@ -950,11 +955,11 @@
     List<ClassMember> list = <ClassMember>[];
     if (_lateIsSetField != null) {
       list.add(new _LateFieldClassMember(fieldBuilder, _lateIsSetField,
-          forSetter: true));
+          forSetter: true, isInternalImplementation: true));
     }
     if (_lateSetter != null) {
       list.add(new _LateFieldClassMember(fieldBuilder, _lateSetter,
-          forSetter: true));
+          forSetter: true, isInternalImplementation: false));
     }
     return list;
   }
@@ -1106,8 +1111,12 @@
   @override
   final bool forSetter;
 
+  @override
+  final bool isInternalImplementation;
+
   _LateFieldClassMember(this.fieldBuilder, this._member,
-      {this.forSetter: false});
+      {this.forSetter: false, this.isInternalImplementation})
+      : assert(isInternalImplementation != null);
 
   Member getMember(ClassHierarchyBuilder hierarchy) {
     fieldBuilder._ensureType(hierarchy);
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index edeb46b..2d827d5 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -249,6 +249,9 @@
   bool get isSynthesized => false;
 
   @override
+  bool get isInternalImplementation => false;
+
+  @override
   bool get isInheritableConflict => false;
 
   @override
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 5e8589c..93becfc 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
@@ -156,6 +156,12 @@
   bool get isSourceDeclaration => false;
 
   @override
+  bool get isInternalImplementation {
+    Member member = memberBuilder.member;
+    return member is Field && member.isInternalImplementation;
+  }
+
+  @override
   bool get isProperty =>
       memberBuilder.kind == null ||
       memberBuilder.kind == ProcedureKind.Getter ||
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index e0a4b57..10b6ee9 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -30,6 +30,7 @@
         LibraryDependency,
         LibraryPart,
         Name,
+        NonNullableByDefaultCompiledMode,
         Procedure,
         ProcedureKind,
         ReturnStatement,
@@ -331,11 +332,14 @@
 
       // Output result.
       Procedure mainMethod = componentWithDill == null
-          ? data.userLoadedUriMain
+          ? data.component?.mainMethod
           : componentWithDill.mainMethod;
+      NonNullableByDefaultCompiledMode compiledMode = componentWithDill == null
+          ? data.component?.mode
+          : componentWithDill.mode;
       return context.options.target.configureComponent(
           new Component(libraries: outputLibraries, uriToSource: uriToSource))
-        ..mainMethod = mainMethod
+        ..setMainMethodAndMode(mainMethod?.reference, true, compiledMode)
         ..problemsAsJson = problemsAsJson;
     });
   }
@@ -1491,7 +1495,6 @@
 
         initializedFromDill = true;
         bytesLength += initializationBytes.length;
-        data.userLoadedUriMain = data.component.mainMethod;
         saveComponentProblems(data);
       }
     }
@@ -1522,8 +1525,8 @@
     data.component = new Component(
         libraries: componentToInitializeFrom.libraries,
         uriToSource: componentToInitializeFrom.uriToSource)
-      ..mainMethod = componentToInitializeFrom.mainMethod;
-    data.userLoadedUriMain = componentToInitializeFrom.mainMethod;
+      ..setMainMethodAndMode(componentToInitializeFrom.mainMethod?.reference,
+          true, componentToInitializeFrom.mode);
     saveComponentProblems(data);
 
     bool foundDartCore = false;
@@ -1888,7 +1891,6 @@
 }
 
 class IncrementalCompilerData {
-  Procedure userLoadedUriMain = null;
   Component component = null;
   List<int> initializationBytes = null;
 }
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 e32f0fc..b01af737 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -272,6 +272,11 @@
   ///
   bool get inLateLocalInitializer => _localInitializerState.head;
 
+  Link<bool> _isOrAsOperatorTypeState = const Link<bool>().prepend(false);
+
+  @override
+  bool get inIsOrAsOperatorType => _isOrAsOperatorTypeState.head;
+
   Link<bool> _localInitializerState = const Link<bool>().prepend(false);
 
   List<Initializer> _initializers;
@@ -848,8 +853,7 @@
 
     final ModifierBuilder member = this.member;
     if (!(member is ConstructorBuilder && !member.isExternal)) {
-      // Initializer not allowed. An error will (hopefully) have been created
-      // already.
+      // An error has been reported by the parser.
       initializers = <Initializer>[];
     } else if (node is Initializer) {
       initializers = <Initializer>[node];
@@ -1526,31 +1530,46 @@
     Arguments arguments = pop();
     List<UnresolvedType> typeArguments = pop();
     Object receiver = pop();
-    if (arguments != null && typeArguments != null) {
+    // Delay adding [typeArguments] to [forest] for type aliases: They
+    // must be unaliased to the type arguments of the denoted type.
+    bool isInForest = arguments != null &&
+        typeArguments != null &&
+        (receiver is! TypeUseGenerator ||
+            (receiver is TypeUseGenerator &&
+                receiver.declaration is! TypeAliasBuilder));
+    if (isInForest) {
       assert(forest.argumentsTypeArguments(arguments).isEmpty);
       forest.argumentsSetTypeArguments(
           arguments, buildDartTypeArguments(typeArguments));
     } else {
-      assert(typeArguments == null);
+      assert(typeArguments == null ||
+          (receiver is TypeUseGenerator &&
+              receiver.declaration is TypeAliasBuilder));
     }
     if (receiver is Identifier) {
       Name name = new Name(receiver.name, libraryBuilder.nameOrigin);
       if (arguments == null) {
         push(new IncompletePropertyAccessGenerator(this, beginToken, name));
       } else {
-        push(new SendAccessGenerator(this, beginToken, name, arguments));
+        push(new SendAccessGenerator(
+            this, beginToken, name, typeArguments, arguments,
+            isTypeArgumentsInForest: isInForest));
       }
     } else if (arguments == null) {
       push(receiver);
     } else {
-      push(finishSend(receiver, arguments, beginToken.charOffset));
+      push(finishSend(receiver, typeArguments, arguments, beginToken.charOffset,
+          isTypeArgumentsInForest: isInForest));
     }
   }
 
   @override
-  finishSend(Object receiver, Arguments arguments, int charOffset) {
+  finishSend(Object receiver, List<UnresolvedType> typeArguments,
+      Arguments arguments, int charOffset,
+      {bool isTypeArgumentsInForest = false}) {
     if (receiver is Generator) {
-      return receiver.doInvocation(charOffset, arguments);
+      return receiver.doInvocation(charOffset, typeArguments, arguments,
+          isTypeArgumentsInForest: isTypeArgumentsInForest);
     } else if (receiver is ParserRecovery) {
       return new ParserErrorGenerator(this, null, fasta.messageSyntheticToken);
     } else {
@@ -3220,9 +3239,20 @@
   }
 
   @override
+  void beginAsOperatorType(Token operator) {
+    _isOrAsOperatorTypeState = _isOrAsOperatorTypeState.prepend(true);
+  }
+
+  @override
+  void endAsOperatorType(Token operator) {
+    _isOrAsOperatorTypeState = _isOrAsOperatorTypeState.tail;
+  }
+
+  @override
   void handleAsOperator(Token operator) {
     debugEvent("AsOperator");
-    DartType type = buildDartType(pop());
+    DartType type = buildDartType(pop(),
+        allowPotentiallyConstantType: libraryBuilder.isNonNullableByDefault);
     libraryBuilder.checkBoundsInType(
         type, typeEnvironment, uri, operator.charOffset);
     Expression expression = popForValue();
@@ -3233,9 +3263,20 @@
   }
 
   @override
+  void beginIsOperatorType(Token operator) {
+    _isOrAsOperatorTypeState = _isOrAsOperatorTypeState.prepend(true);
+  }
+
+  @override
+  void endIsOperatorType(Token operator) {
+    _isOrAsOperatorTypeState = _isOrAsOperatorTypeState.tail;
+  }
+
+  @override
   void handleIsOperator(Token isOperator, Token not) {
     debugEvent("IsOperator");
-    DartType type = buildDartType(pop());
+    DartType type = buildDartType(pop(),
+        allowPotentiallyConstantType: libraryBuilder.isNonNullableByDefault);
     Expression operand = popForValue();
     bool isInverted = not != null;
     Expression isExpression = forest.createIsExpression(
@@ -4125,7 +4166,8 @@
       String name,
       List<UnresolvedType> typeArguments,
       int charOffset,
-      Constness constness) {
+      Constness constness,
+      {bool isTypeArgumentsInForest = false}) {
     if (arguments == null) {
       return buildProblem(fasta.messageMissingArgumentList,
           nameToken.charOffset, nameToken.length);
@@ -4136,28 +4178,15 @@
           nameToken.charOffset, nameToken.length);
     }
 
-    if (typeArguments != null) {
-      assert(forest.argumentsTypeArguments(arguments).isEmpty);
-      forest.argumentsSetTypeArguments(
-          arguments, buildDartTypeArguments(typeArguments));
-    }
-
     String errorName;
     LocatedMessage message;
 
     if (type is TypeAliasBuilder) {
       errorName = debugName(type.name, name);
       TypeAliasBuilder aliasBuilder = type;
-      List<TypeBuilder> typeArgumentBuilders = null;
-      if (typeArguments != null) {
-        typeArgumentBuilders = <TypeBuilder>[];
-        for (UnresolvedType unresolvedType in typeArguments) {
-          typeArgumentBuilders.add(unresolvedType?.builder);
-        }
-      }
       int numberOfTypeParameters = aliasBuilder.typeVariables?.length ?? 0;
-      int numberOfTypeArguments = typeArgumentBuilders?.length ?? 0;
-      if (typeArgumentBuilders != null &&
+      int numberOfTypeArguments = typeArguments?.length ?? 0;
+      if (typeArguments != null &&
           numberOfTypeParameters != numberOfTypeArguments) {
         // TODO(eernst): Use position of type arguments, not nameToken.
         return evaluateArgumentsBefore(
@@ -4165,13 +4194,20 @@
             buildProblem(
                 fasta.templateTypeArgumentMismatch
                     .withArguments(numberOfTypeParameters),
-                nameToken.charOffset,
-                nameToken.length));
+                charOffset,
+                noLength));
       }
-      if (typeArgumentBuilders == null) {
-        if (aliasBuilder.typeVariables?.isEmpty ?? true) {
-          typeArgumentBuilders = [];
-        } else {
+      type = aliasBuilder.unaliasDeclaration(null,
+          isInvocation: true,
+          invocationCharOffset: nameToken.charOffset,
+          invocationFileUri: uri);
+      List<TypeBuilder> typeArgumentBuilders = [];
+      if (typeArguments != null) {
+        for (UnresolvedType unresolvedType in typeArguments) {
+          typeArgumentBuilders.add(unresolvedType?.builder);
+        }
+      } else {
+        if (aliasBuilder.typeVariables?.isNotEmpty ?? false) {
           // No type arguments provided to alias, but it is generic.
           typeArgumentBuilders = new List<TypeBuilder>.filled(
               aliasBuilder.typeVariables.length, null,
@@ -4182,7 +4218,6 @@
           }
         }
       }
-      type = aliasBuilder.unaliasDeclaration(typeArgumentBuilders);
       if (type is ClassBuilder) {
         if (typeArguments != null) {
           int numberOfTypeParameters = aliasBuilder.typeVariables?.length ?? 0;
@@ -4210,20 +4245,15 @@
                     nameToken.length,
                     suppressMessage: true));
           }
-          if (unaliasedTypeArgumentBuilders.isEmpty) {
-            forest.argumentsSetTypeArguments(arguments, []);
-          } else {
-            List<DartType> dartTypeArguments = [];
-            if (typeArguments != null) {
-              for (UnresolvedType unresolvedType in typeArguments) {
-                dartTypeArguments
-                    .add(unresolvedType.builder?.build(libraryBuilder));
-              }
-            }
-            forest.argumentsSetTypeArguments(arguments, dartTypeArguments);
+          List<DartType> dartTypeArguments = [];
+          for (TypeBuilder typeBuilder in unaliasedTypeArgumentBuilders) {
+            dartTypeArguments.add(typeBuilder.build(libraryBuilder));
           }
+          assert(forest.argumentsTypeArguments(arguments).isEmpty);
+          forest.argumentsSetTypeArguments(arguments, dartTypeArguments);
         } else {
           if (type.typeVariables?.isEmpty ?? true) {
+            assert(forest.argumentsTypeArguments(arguments).isEmpty);
             forest.argumentsSetTypeArguments(arguments, []);
           } else {
             // No type arguments provided to unaliased class, use defaults.
@@ -4234,10 +4264,17 @@
               result[i] =
                   type.typeVariables[i].defaultType?.build(type.library);
             }
+            assert(forest.argumentsTypeArguments(arguments).isEmpty);
             forest.argumentsSetTypeArguments(arguments, result);
           }
         }
       }
+    } else {
+      if (typeArguments != null && !isTypeArgumentsInForest) {
+        assert(forest.argumentsTypeArguments(arguments).isEmpty);
+        forest.argumentsSetTypeArguments(
+            arguments, buildDartTypeArguments(typeArguments));
+      }
     }
     if (type is ClassBuilder) {
       if (type is EnumBuilder) {
@@ -5780,14 +5817,17 @@
   }
 
   @override
-  UnresolvedType validateTypeUse(
-      UnresolvedType unresolved, bool nonInstanceAccessIsError) {
+  UnresolvedType validateTypeUse(UnresolvedType unresolved,
+      {bool nonInstanceAccessIsError, bool allowPotentiallyConstantType}) {
+    assert(nonInstanceAccessIsError != null);
+    assert(allowPotentiallyConstantType != null);
     TypeBuilder builder = unresolved.builder;
     if (builder is NamedTypeBuilder && builder.declaration.isTypeVariable) {
       TypeVariableBuilder typeParameterBuilder = builder.declaration;
       TypeParameter typeParameter = typeParameterBuilder.parameter;
       LocatedMessage message = _validateTypeUseIsInternal(
-          builder, unresolved.fileUri, unresolved.charOffset);
+          builder, unresolved.fileUri, unresolved.charOffset,
+          allowPotentiallyConstantType: allowPotentiallyConstantType);
       if (message == null) return unresolved;
       return new UnresolvedType(
           new NamedTypeBuilder(
@@ -5798,7 +5838,8 @@
           unresolved.fileUri);
     } else if (builder is FunctionTypeBuilder) {
       LocatedMessage message = _validateTypeUseIsInternal(
-          builder, unresolved.fileUri, unresolved.charOffset);
+          builder, unresolved.fileUri, unresolved.charOffset,
+          allowPotentiallyConstantType: allowPotentiallyConstantType);
       if (message == null) return unresolved;
       // TODO(CFE Team): This should probably be some kind of InvalidType
       // instead of null.
@@ -5809,7 +5850,9 @@
   }
 
   LocatedMessage _validateTypeUseIsInternal(
-      TypeBuilder builder, Uri fileUri, int charOffset) {
+      TypeBuilder builder, Uri fileUri, int charOffset,
+      {bool allowPotentiallyConstantType}) {
+    assert(allowPotentiallyConstantType != null);
     if (builder is NamedTypeBuilder && builder.declaration.isTypeVariable) {
       TypeVariableBuilder typeParameterBuilder = builder.declaration;
       TypeParameter typeParameter = typeParameterBuilder.parameter;
@@ -5823,7 +5866,8 @@
             builder.fileUri ?? fileUri,
             builder.charOffset ?? charOffset,
             typeParameter.name.length);
-      } else if (constantContext == ConstantContext.inferred) {
+      } else if (constantContext == ConstantContext.inferred &&
+          !allowPotentiallyConstantType) {
         message = fasta.messageTypeVariableInConstantContext
             .withLocation(fileUri, charOffset, typeParameter.name.length);
       } else {
@@ -5832,15 +5876,17 @@
       addProblem(message.messageObject, message.charOffset, message.length);
       return message;
     } else if (builder is FunctionTypeBuilder) {
-      LocatedMessage result =
-          _validateTypeUseIsInternal(builder.returnType, fileUri, charOffset);
+      LocatedMessage result = _validateTypeUseIsInternal(
+          builder.returnType, fileUri, charOffset,
+          allowPotentiallyConstantType: allowPotentiallyConstantType);
       if (result != null) {
         return result;
       }
       if (builder.formals != null) {
         for (FormalParameterBuilder formalParameterBuilder in builder.formals) {
           result = _validateTypeUseIsInternal(
-              formalParameterBuilder.type, fileUri, charOffset);
+              formalParameterBuilder.type, fileUri, charOffset,
+              allowPotentiallyConstantType: allowPotentiallyConstantType);
           if (result != null) {
             return result;
           }
@@ -6011,9 +6057,12 @@
 
   @override
   DartType buildDartType(UnresolvedType unresolvedType,
-      {bool nonInstanceAccessIsError: false}) {
+      {bool nonInstanceAccessIsError: false,
+      bool allowPotentiallyConstantType: false}) {
     if (unresolvedType == null) return null;
-    return validateTypeUse(unresolvedType, nonInstanceAccessIsError)
+    return validateTypeUse(unresolvedType,
+            nonInstanceAccessIsError: nonInstanceAccessIsError,
+            allowPotentiallyConstantType: allowPotentiallyConstantType)
         .builder
         ?.build(libraryBuilder);
   }
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 c080b03..f0afbcc 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
@@ -6,7 +6,8 @@
 
 import 'package:kernel/ast.dart' hide MapEntry;
 
-import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/class_hierarchy.dart'
+    show ClassHierarchy, ClassHierarchyBase;
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
@@ -17,6 +18,7 @@
 import 'package:kernel/src/legacy_erasure.dart';
 import 'package:kernel/src/nnbd_top_merge.dart';
 import 'package:kernel/src/norm.dart';
+import 'package:kernel/src/types.dart' show Types;
 
 import '../../testing/id_testing_utils.dart' show typeToText;
 
@@ -81,8 +83,6 @@
 
 import 'kernel_builder.dart' show ImplicitFieldType;
 
-import 'types.dart' show Types;
-
 const bool useConsolidated = true;
 
 const DebugLogger debug =
@@ -222,6 +222,14 @@
 
   bool get needsComputation;
   bool get isSynthesized;
+
+  // If `true` this member is not part of the interface but only part of the
+  // class members.
+  //
+  // This is `true` for instance for synthesized fields added for the late
+  // lowering.
+  bool get isInternalImplementation;
+
   bool get isInheritableConflict;
   ClassMember withParent(ClassBuilder classBuilder);
   bool get hasDeclarations;
@@ -309,7 +317,7 @@
   return aReturnType == bReturnType;
 }
 
-class ClassHierarchyBuilder {
+class ClassHierarchyBuilder implements ClassHierarchyBase {
   final Map<Class, ClassHierarchyNode> nodes = <Class, ClassHierarchyNode>{};
 
   final Map<ClassBuilder, Map<Class, Substitution>> substitutions =
@@ -340,6 +348,9 @@
 
   Types types;
 
+  Map<ClassMember, Map<ClassMember, ClassMember>> inheritanceConflictCache =
+      new Map.identity();
+
   ClassHierarchyBuilder(this.objectClassBuilder, this.loader, this.coreTypes)
       : objectClass = objectClassBuilder.cls,
         futureClass = coreTypes.futureClass,
@@ -354,6 +365,7 @@
     substitutions.clear();
     _overrideChecks.clear();
     _delayedTypeComputations.clear();
+    inheritanceConflictCache.clear();
   }
 
   void registerDelayedTypeComputation(DelayedTypeComputation computation) {
@@ -469,8 +481,8 @@
     return null;
   }
 
-  InterfaceType getKernelTypeAsInstanceOf(
-      InterfaceType type, Class superclass, Library clientLibrary) {
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
+      Library clientLibrary, CoreTypes coreTypes) {
     Class kernelClass = type.classNode;
     if (kernelClass == superclass) return type;
     if (kernelClass == nullClass) {
@@ -491,7 +503,7 @@
         .withNullability(type.nullability);
   }
 
-  List<DartType> getKernelTypeArgumentsAsInstanceOf(
+  List<DartType> getTypeArgumentsAsInstanceOf(
       InterfaceType type, Class superclass) {
     Class kernelClass = type.classNode;
     if (kernelClass == superclass) return type.typeArguments;
@@ -530,10 +542,10 @@
       ClassHierarchyNode node = nodes2[i];
       if (node == null) continue;
       if (nodes1.contains(node)) {
-        DartType candidate1 = getKernelTypeAsInstanceOf(
-            type1, node.classBuilder.cls, clientLibrary);
-        DartType candidate2 = getKernelTypeAsInstanceOf(
-            type2, node.classBuilder.cls, clientLibrary);
+        DartType candidate1 = getTypeAsInstanceOf(
+            type1, node.classBuilder.cls, clientLibrary, coreTypes);
+        DartType candidate2 = getTypeAsInstanceOf(
+            type2, node.classBuilder.cls, clientLibrary, coreTypes);
         if (candidate1 == candidate2) {
           common.add(node);
         }
@@ -549,8 +561,8 @@
     for (int i = 0; i < common.length - 1; i++) {
       ClassHierarchyNode node = common[i];
       if (node.maxInheritancePath != common[i + 1].maxInheritancePath) {
-        return getKernelTypeAsInstanceOf(
-                type1, node.classBuilder.cls, clientLibrary)
+        return getTypeAsInstanceOf(
+                type1, node.classBuilder.cls, clientLibrary, coreTypes)
             .withNullability(
                 uniteNullabilities(type1.nullability, type2.nullability));
       } else {
@@ -563,9 +575,9 @@
         uniteNullabilities(type1.nullability, type2.nullability));
   }
 
-  Member getInterfaceMemberKernel(Class cls, Name name, bool isSetter) {
+  Member getInterfaceMember(Class cls, Name name, {bool setter: false}) {
     return getNodeFromClass(cls)
-        .getInterfaceMember(name, isSetter)
+        .getInterfaceMember(name, setter)
         ?.getMember(this);
   }
 
@@ -640,12 +652,18 @@
       classBuilder.library.loader == hierarchy.loader;
 
   ClassMember checkInheritanceConflict(ClassMember a, ClassMember b) {
+    hierarchy.inheritanceConflictCache[a] ??= new Map.identity();
+    if (hierarchy.inheritanceConflictCache[a].containsKey(b)) {
+      return hierarchy.inheritanceConflictCache[a][b];
+    }
+
     if (a.hasDeclarations) {
       ClassMember result;
       for (int i = 0; i < a.declarations.length; i++) {
         ClassMember d = checkInheritanceConflict(a.declarations[i], b);
         result ??= d;
       }
+      hierarchy.inheritanceConflictCache[a][b] = result;
       return result;
     }
     if (b.hasDeclarations) {
@@ -654,12 +672,15 @@
         ClassMember d = checkInheritanceConflict(a, b.declarations[i]);
         result ??= d;
       }
+      hierarchy.inheritanceConflictCache[a][b] = result;
       return result;
     }
     if (isInheritanceConflict(a, b)) {
       reportInheritanceConflict(a, b);
+      hierarchy.inheritanceConflictCache[a][b] = a;
       return a;
     }
+    hierarchy.inheritanceConflictCache[a][b] = null;
     return null;
   }
 
@@ -731,7 +752,8 @@
             DartType overriddenBound = methodSubstitution
                 .substituteType(overriddenTypeParameters[i].bound);
             if (!hierarchy.types
-                .isSameTypeKernel(declaredBound, overriddenBound)
+                .performNullabilityAwareMutualSubtypesCheck(
+                    declaredBound, overriddenBound)
                 .isSubtypeWhenUsingNullabilities()) {
               debug?.log("Giving up 3");
               continue;
@@ -1949,7 +1971,9 @@
               return result;
             } else {
               if (isNameVisibleIn(interfaceMember.name, classBuilder.library)) {
-                recordAbstractMember(interfaceMember);
+                if (!interfaceMember.isInternalImplementation) {
+                  recordAbstractMember(interfaceMember);
+                }
               }
               if (interfaceMember.isInheritableConflict) {
                 interfaceMember = interfaceMember.withParent(classBuilder);
@@ -2552,13 +2576,14 @@
   @override
   InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
       Library clientLibrary, CoreTypes coreTypes) {
-    return hierarchy.getKernelTypeAsInstanceOf(type, superclass, clientLibrary);
+    return hierarchy.getTypeAsInstanceOf(
+        type, superclass, clientLibrary, coreTypes);
   }
 
   @override
   List<DartType> getTypeArgumentsAsInstanceOf(
       InterfaceType type, Class superclass) {
-    return hierarchy.getKernelTypeArgumentsAsInstanceOf(type, superclass);
+    return hierarchy.getTypeArgumentsAsInstanceOf(type, superclass);
   }
 
   @override
@@ -2570,7 +2595,7 @@
   @override
   bool isSubtypeOf(
       DartType subtype, DartType supertype, SubtypeCheckMode mode) {
-    return hierarchy.types.isSubtypeOfKernel(subtype, supertype, mode);
+    return hierarchy.types.isSubtypeOf(subtype, supertype, mode);
   }
 
   @override
@@ -2676,6 +2701,9 @@
   bool get isSynthesized => true;
 
   @override
+  bool get isInternalImplementation => false;
+
+  @override
   bool get forSetter => isSetter;
 
   @override
@@ -2840,12 +2868,13 @@
     assert(concreteImplementation.isProperty == other.isProperty,
         "Unexpected member combination: $concreteImplementation vs $other");
     List<ClassMember> declarations = <ClassMember>[];
-    if (concreteImplementation.hasDeclarations) {
+    if (concreteImplementation.hasDeclarations &&
+        concreteImplementation.classBuilder == parent) {
       addAllDeclarationsTo(concreteImplementation, declarations);
     } else {
       declarations.add(concreteImplementation);
     }
-    if (other.hasDeclarations) {
+    if (other.hasDeclarations && other.classBuilder == parent) {
       addAllDeclarationsTo(other, declarations);
     } else {
       addDeclarationIfDifferent(other, declarations);
@@ -2932,8 +2961,11 @@
       unhandled("${member.runtimeType}", "$member", classBuilder.charOffset,
           classBuilder.fileUri);
     }
-    InterfaceType instance = hierarchy.getKernelTypeAsInstanceOf(
-        thisType, member.enclosingClass, classBuilder.library.library);
+    InterfaceType instance = hierarchy.getTypeAsInstanceOf(
+        thisType,
+        member.enclosingClass,
+        classBuilder.library.library,
+        hierarchy.coreTypes);
     assert(
         instance != null,
         "No instance of $thisType as ${member.enclosingClass} found for "
@@ -2944,10 +2976,10 @@
   bool isMoreSpecific(ClassHierarchyBuilder hierarchy, DartType a, DartType b) {
     if (isSetter) {
       return hierarchy.types
-          .isSubtypeOfKernel(b, a, SubtypeCheckMode.withNullabilities);
+          .isSubtypeOf(b, a, SubtypeCheckMode.withNullabilities);
     } else {
       return hierarchy.types
-          .isSubtypeOfKernel(a, b, SubtypeCheckMode.withNullabilities);
+          .isSubtypeOf(a, b, SubtypeCheckMode.withNullabilities);
     }
   }
 
@@ -3113,12 +3145,12 @@
     assert(a.isProperty == b.isProperty,
         "Unexpected member combination: $a vs $b");
     List<ClassMember> declarations = <ClassMember>[];
-    if (a.hasDeclarations) {
+    if (a.hasDeclarations && a.classBuilder == parent) {
       addAllDeclarationsTo(a, declarations);
     } else {
       declarations.add(a);
     }
-    if (b.hasDeclarations) {
+    if (b.hasDeclarations && b.classBuilder == parent) {
       addAllDeclarationsTo(b, declarations);
     } else {
       addDeclarationIfDifferent(b, declarations);
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 742cd7e..38e392f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -2122,7 +2122,7 @@
             ..fileOffset = node.fileOffset
             ..flags = node.flags);
     }
-    if (constant is NullConstant) {
+    if (constant is NullConstant && !node.isForNonNullableByDefault) {
       DartType nodeType = node.type;
       return makeBoolConstant(nodeType == typeEnvironment.nullType ||
           nodeType is InterfaceType &&
@@ -2232,27 +2232,28 @@
 
   bool isSubtype(Constant constant, DartType type) {
     DartType constantType = constant.getType(_staticTypeContext);
-    if (targetingJavaScript) {
+    bool result = typeEnvironment.isSubtypeOf(
+        constantType, type, SubtypeCheckMode.withNullabilities);
+    if (targetingJavaScript && !result) {
       if (constantType is InterfaceType &&
-          constantType.classNode == typeEnvironment.coreTypes.intClass &&
-          type is InterfaceType &&
-          type.classNode == typeEnvironment.coreTypes.doubleClass) {
+          constantType.classNode == typeEnvironment.coreTypes.intClass) {
         // With JS semantics, an integer is also a double.
-        return true;
-      }
-
-      if (constantType is InterfaceType &&
-          constantType.classNode == typeEnvironment.coreTypes.doubleClass &&
-          type is InterfaceType &&
-          type.classNode == typeEnvironment.coreTypes.intClass) {
-        double value = (constant as DoubleConstant).value;
-        if (value.isFinite && value == value.truncateToDouble()) {
-          return true;
-        }
+        result = typeEnvironment.isSubtypeOf(
+            new InterfaceType(typeEnvironment.coreTypes.doubleClass,
+                constantType.nullability, const <DartType>[]),
+            type,
+            SubtypeCheckMode.withNullabilities);
+      } else if (intFolder.isInt(constant)) {
+        // With JS semantics, an integer valued double is also an int.
+        result = typeEnvironment.isSubtypeOf(
+            new InterfaceType(typeEnvironment.coreTypes.intClass,
+                constantType.nullability, const <DartType>[]),
+            type,
+            SubtypeCheckMode.withNullabilities);
       }
     }
-    return typeEnvironment.isSubtypeOf(
-        constantType, type, SubtypeCheckMode.withNullabilities);
+
+    return result;
   }
 
   Constant ensureIsSubtype(Constant constant, DartType type, TreeNode node) {
@@ -2367,7 +2368,7 @@
           return report(
               node, templateConstEvalZeroDivisor.withArguments(op, '$a'));
         }
-        return intFolder.truncatingDivide(a, b);
+        return intFolder.truncatingDivide(node, a, b);
       case '%':
         return new DoubleConstant(a % b);
     }
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 9bd4a18..337d61e 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
@@ -10,7 +10,10 @@
 import 'constant_evaluator.dart';
 
 import '../fasta_codes.dart'
-    show templateConstEvalNegativeShift, templateConstEvalZeroDivisor;
+    show
+        templateConstEvalNegativeShift,
+        templateConstEvalTruncateError,
+        templateConstEvalZeroDivisor;
 
 abstract class ConstantIntFolder {
   final ConstantEvaluator evaluator;
@@ -36,7 +39,7 @@
   Constant foldBinaryOperator(MethodInvocation node, String op,
       covariant Constant left, covariant Constant right);
 
-  Constant truncatingDivide(num left, num right);
+  Constant truncatingDivide(MethodInvocation node, num left, num right);
 
   void _checkOperands(MethodInvocation node, String op, num left, num right) {
     if ((op == '<<' || op == '>>' || op == '>>>') && right < 0) {
@@ -120,8 +123,13 @@
   }
 
   @override
-  Constant truncatingDivide(num left, num right) {
-    return new IntConstant(left ~/ right);
+  Constant truncatingDivide(MethodInvocation node, num left, num right) {
+    try {
+      return new IntConstant(left ~/ right);
+    } catch (e) {
+      return evaluator.report(node,
+          templateConstEvalTruncateError.withArguments('$left', '$right'));
+    }
   }
 }
 
@@ -184,7 +192,7 @@
       case '/':
         return new DoubleConstant(a / b);
       case '~/':
-        return truncatingDivide(a, b);
+        return truncatingDivide(node, a, b);
       case '%':
         return new DoubleConstant(a % b);
       case '|':
@@ -220,8 +228,13 @@
   }
 
   @override
-  Constant truncatingDivide(num left, num right) {
-    double result = (left / right).truncateToDouble();
+  Constant truncatingDivide(MethodInvocation node, num left, num right) {
+    double division = (left / right);
+    if (division.isNaN || division.isInfinite) {
+      return evaluator.report(node,
+          templateConstEvalTruncateError.withArguments('$left', '${right}'));
+    }
+    double result = division.truncateToDouble();
     return new DoubleConstant(result == 0.0 ? 0.0 : result);
   }
 }
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 19bcd1f..b392aab 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -211,7 +211,9 @@
   }
 
   /// Returns an expression, generator or initializer for an invocation of this
-  /// subexpression with [arguments] at [offset].
+  /// subexpression with [typeArguments] and [arguments] at [offset]. Callers
+  /// must pass `isInForest: true` iff [typeArguments] have already been added
+  /// to [forest].
   ///
   /// For instance:
   /// * If this is a [PropertyAccessGenerator] for `a.b`, this will create
@@ -224,7 +226,8 @@
   /// If the invocation has explicit type arguments
   /// [buildTypeWithResolvedArguments] called instead.
   /* Expression | Generator | Initializer */ doInvocation(
-      int offset, Arguments arguments);
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false});
 
   /* Expression | Generator */ buildPropertyAccess(
       IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
@@ -405,7 +408,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.forest.createExpressionInvocation(
         adjustForImplicitCall(_plainNameForRead, offset),
         buildSimpleRead(),
@@ -464,7 +469,9 @@
   String get _plainNameForRead => name.name;
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.buildMethodInvocation(receiver, name, arguments, offset);
   }
 
@@ -685,7 +692,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.buildMethodInvocation(
         _forest.createThisExpression(fileOffset), name, arguments, offset);
   }
@@ -787,7 +796,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return unsupported("doInvocation", offset, _uri);
   }
 
@@ -891,7 +902,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     if (_helper.constantContext != ConstantContext.none) {
       // TODO(brianwilkerson) Fix the length
       _helper.addProblem(messageNotAConstantExpression, offset, 1);
@@ -1061,7 +1074,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.forest.createExpressionInvocation(
         arguments.fileOffset, buildSimpleRead(), arguments);
   }
@@ -1162,7 +1177,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.forest
         .createExpressionInvocation(offset, buildSimpleRead(), arguments);
   }
@@ -1261,7 +1278,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.forest
         .createExpressionInvocation(offset, buildSimpleRead(), arguments);
   }
@@ -1426,7 +1445,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     if (_helper.constantContext != ConstantContext.none &&
         !_helper.isIdentical(readTarget)) {
       return _helper.buildProblem(
@@ -1695,7 +1716,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     if (invokeTarget != null) {
       return _helper.buildExtensionMethodInvocation(
           offset,
@@ -2103,7 +2126,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     VariableDeclaration receiverVariable;
     Expression receiverExpression = receiver;
     if (isNullAware) {
@@ -2425,7 +2450,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.forest
         .createExpressionInvocation(offset, buildSimpleRead(), arguments);
   }
@@ -2564,7 +2591,9 @@
     Generator generator =
         _createInstanceAccess(send.token, send.name, isNullAware: isNullAware);
     if (send.arguments != null) {
-      return generator.doInvocation(offsetForToken(send.token), send.arguments);
+      return generator.doInvocation(
+          offsetForToken(send.token), send.typeArguments, send.arguments,
+          isTypeArgumentsInForest: send.isTypeArgumentsInForest);
     } else {
       return generator;
     }
@@ -2574,8 +2603,8 @@
   buildBinaryOperation(Token token, Name binaryName, Expression right) {
     int fileOffset = offsetForToken(token);
     Generator generator = _createInstanceAccess(token, binaryName);
-    return generator.doInvocation(
-        fileOffset, _forest.createArguments(fileOffset, <Expression>[right]));
+    return generator.doInvocation(fileOffset, null,
+        _forest.createArguments(fileOffset, <Expression>[right]));
   }
 
   @override
@@ -2583,13 +2612,16 @@
     int fileOffset = offsetForToken(token);
     Generator generator = _createInstanceAccess(token, unaryName);
     return generator.doInvocation(
-        fileOffset, _forest.createArgumentsEmpty(fileOffset));
+        fileOffset, null, _forest.createArgumentsEmpty(fileOffset));
   }
 
   @override
-  doInvocation(int offset, Arguments arguments) {
+  doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     Generator generator = _createInstanceAccess(token, callName);
-    return generator.doInvocation(offset, arguments);
+    return generator.doInvocation(offset, typeArguments, arguments,
+        isTypeArgumentsInForest: isTypeArgumentsInForest);
   }
 
   @override
@@ -2696,7 +2728,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     if (_forest.argumentsPositional(arguments).length > 0 ||
         _forest.argumentsNamed(arguments).length > 0) {
       _helper.addProblemErrorIfConst(
@@ -2833,8 +2867,12 @@
   }
 
   @override
-  doInvocation(int offset, Arguments arguments) {
-    Object suffix = suffixGenerator.doInvocation(offset, arguments);
+  doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
+    Object suffix = suffixGenerator.doInvocation(
+        offset, typeArguments, arguments,
+        isTypeArgumentsInForest: isTypeArgumentsInForest);
     if (suffix is Expression) {
       return _helper.wrapInDeferredCheck(
           suffix, prefixGenerator.prefix, fileOffset);
@@ -2947,8 +2985,13 @@
     if (arguments != null) {
       argumentBuilders = new List<TypeBuilder>(arguments.length);
       for (int i = 0; i < argumentBuilders.length; i++) {
-        argumentBuilders[i] =
-            _helper.validateTypeUse(arguments[i], false).builder;
+        argumentBuilders[i] = _helper
+            .validateTypeUse(arguments[i],
+                nonInstanceAccessIsError: false,
+                allowPotentiallyConstantType:
+                    _helper.libraryBuilder.isNonNullableByDefault &&
+                        _helper.inIsOrAsOperatorType)
+            .builder;
       }
     }
     return new NamedTypeBuilder(
@@ -3040,9 +3083,10 @@
               send.token,
               arguments,
               name.name,
-              null,
+              send.typeArguments,
               token.charOffset,
-              Constness.implicit);
+              Constness.implicit,
+              isTypeArgumentsInForest: send.isTypeArgumentsInForest);
         }
       } else if (member is AmbiguousBuilder) {
         return _helper.buildProblem(
@@ -3076,14 +3120,18 @@
 
       return arguments == null
           ? generator
-          : generator.doInvocation(offsetForToken(send.token), arguments);
+          : generator.doInvocation(
+              offsetForToken(send.token), send.typeArguments, arguments,
+              isTypeArgumentsInForest: send.isTypeArgumentsInForest);
     } else {
       return super.buildPropertyAccess(send, operatorOffset, isNullAware);
     }
   }
 
   @override
-  doInvocation(int offset, Arguments arguments) {
+  doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     if (declaration.isExtension) {
       ExtensionBuilder extensionBuilder = declaration;
       if (arguments.positional.length != 1 || arguments.named.isNotEmpty) {
@@ -3107,7 +3155,8 @@
           arguments.positional.single, explicitTypeArguments);
     } else {
       return _helper.buildConstructorInvocation(declaration, token, token,
-          arguments, "", null, token.charOffset, Constness.implicit);
+          arguments, "", typeArguments, token.charOffset, Constness.implicit,
+          isTypeArgumentsInForest: isTypeArgumentsInForest);
     }
   }
 }
@@ -3237,7 +3286,9 @@
   }
 
   @override
-  doInvocation(int offset, Arguments arguments) {
+  doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.forest.createExpressionInvocation(
         adjustForImplicitCall(targetName, offset), _createRead(), arguments);
   }
@@ -3290,7 +3341,9 @@
   }
 
   @override
-  doInvocation(int offset, Arguments arguments) {
+  doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return buildError(arguments, offset: offset);
   }
 
@@ -3405,7 +3458,9 @@
   String get _debugName => "UnresolvedNameGenerator";
 
   @override
-  Expression doInvocation(int charOffset, Arguments arguments) {
+  Expression doInvocation(
+      int charOffset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return buildError(arguments, offset: charOffset);
   }
 
@@ -3477,7 +3532,9 @@
   }
 
   @override
-  Expression doInvocation(int charOffset, Arguments arguments) {
+  Expression doInvocation(
+      int charOffset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return unhandled("${runtimeType}", "doInvocation", charOffset, _uri);
   }
 
@@ -3721,7 +3778,8 @@
 
   @override
   /* Expression | Generator | Initializer */ doInvocation(
-      int offset, Arguments arguments) {
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.wrapInLocatedProblem(
         _helper.evaluateArgumentsBefore(
             arguments, _forest.createNullLiteral(fileOffset)),
@@ -3737,7 +3795,9 @@
           "'${send.name.name}' != ${send.token.lexeme}");
       Object result = qualifiedLookup(send.token);
       if (send is SendAccessGenerator) {
-        result = _helper.finishSend(result, send.arguments, fileOffset);
+        result = _helper.finishSend(
+            result, send.typeArguments, send.arguments, fileOffset,
+            isTypeArgumentsInForest: send.isTypeArgumentsInForest);
       }
       if (isNullAware) {
         result = _helper.wrapInLocatedProblem(
@@ -3823,7 +3883,9 @@
   }
 
   @override
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return _helper.throwNoSuchMethodError(_forest.createNullLiteral(offset),
         _plainNameForRead, arguments, fileOffset);
   }
@@ -3923,7 +3985,9 @@
     return <Initializer>[_helper.buildInvalidInitializer(buildProblem())];
   }
 
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return buildProblem();
   }
 
@@ -4112,7 +4176,9 @@
     }
   }
 
-  doInvocation(int offset, Arguments arguments) {
+  doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     if (isInitializer) {
       return buildConstructorInitializer(offset, new Name(""), arguments);
     } else if (isSuper) {
@@ -4274,6 +4340,10 @@
 
   withReceiver(Object receiver, int operatorOffset, {bool isNullAware});
 
+  List<UnresolvedType> get typeArguments => null;
+
+  bool get isTypeArgumentsInForest => true;
+
   Arguments get arguments => null;
 }
 
@@ -4303,7 +4373,10 @@
   }
 
   @override
-  doInvocation(int offset, Arguments arguments) => this;
+  doInvocation(
+          int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+          {bool isTypeArgumentsInForest = false}) =>
+      this;
 
   @override
   Expression buildSimpleRead() {
@@ -4324,13 +4397,19 @@
   final Name name;
 
   @override
+  final List<UnresolvedType> typeArguments;
+
+  @override
+  final bool isTypeArgumentsInForest;
+
+  @override
   final Arguments arguments;
 
   final bool isPotentiallyConstant;
 
-  SendAccessGenerator(
-      ExpressionGeneratorHelper helper, Token token, this.name, this.arguments,
-      {this.isPotentiallyConstant: false})
+  SendAccessGenerator(ExpressionGeneratorHelper helper, Token token, this.name,
+      this.typeArguments, this.arguments,
+      {this.isPotentiallyConstant = false, this.isTypeArgumentsInForest = true})
       : super(helper, token) {
     assert(arguments != null);
   }
@@ -4379,7 +4458,9 @@
     return unsupported("buildPostfixIncrement", offset ?? fileOffset, _uri);
   }
 
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return unsupported("doInvocation", offset, _uri);
   }
 
@@ -4455,7 +4536,9 @@
     return unsupported("buildPostfixIncrement", offset ?? fileOffset, _uri);
   }
 
-  Expression doInvocation(int offset, Arguments arguments) {
+  Expression doInvocation(
+      int offset, List<UnresolvedType> typeArguments, Arguments arguments,
+      {bool isTypeArgumentsInForest = false}) {
     return unsupported("doInvocation", offset, _uri);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 1d4799e..1666a65 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -57,10 +57,15 @@
 
   Member lookupInstanceMember(Name name, {bool isSetter, bool isSuper});
 
+  /// `true` if we are in the type of an as expression.
+  bool get inIsOrAsOperatorType;
+
   scopeLookup(Scope scope, String name, Token token,
       {bool isQualified: false, PrefixBuilder prefix});
 
-  finishSend(Object receiver, Arguments arguments, int offset);
+  finishSend(Object receiver, List<UnresolvedType> typeArguments,
+      Arguments arguments, int offset,
+      {bool isTypeArgumentsInForest = false});
 
   Initializer buildInvalidInitializer(Expression expression, [int offset]);
 
@@ -114,10 +119,11 @@
       String name,
       List<UnresolvedType> typeArguments,
       int charOffset,
-      Constness constness);
+      Constness constness,
+      {bool isTypeArgumentsInForest = false});
 
-  UnresolvedType validateTypeUse(
-      UnresolvedType unresolved, bool nonInstanceAccessIsError);
+  UnresolvedType validateTypeUse(UnresolvedType unresolved,
+      {bool nonInstanceAccessIsError, bool allowPotentiallyConstantType});
 
   void addProblemErrorIfConst(Message message, int charOffset, int length);
 
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 66897dc..597ce2a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -537,11 +537,12 @@
   Substitution _substitutionFor(
       List<TypeParameter> stubTypeParameters, Member candidate, Class class_) {
     Substitution substitution = Substitution.fromInterfaceType(
-        hierarchy.getKernelTypeAsInstanceOf(
+        hierarchy.getTypeAsInstanceOf(
             hierarchy.coreTypes
                 .thisInterfaceType(class_, class_.enclosingLibrary.nonNullable),
             candidate.enclosingClass,
-            class_.enclosingLibrary));
+            class_.enclosingLibrary,
+            hierarchy.coreTypes));
     if (stubTypeParameters != null) {
       // If the stub is generic ensure that type parameters are alpha renamed
       // to the [stubTypeParameters].
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 c237248..e16103f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -3420,15 +3420,16 @@
       {bool isNot}) {
     assert(isNot != null);
     inferrer.flowAnalysis.equalityOp_rightBegin(left);
-    ObjectAccessTarget equalsTarget = inferrer.findInterfaceMember(
-        leftType, equalsName, fileOffset,
-        includeExtensionMethods: true);
+    ObjectAccessTarget objectEqualsTarget =
+        inferrer.getObjectMemberIfNullableReceiver(leftType, equalsName);
+    ObjectAccessTarget equalsTarget = objectEqualsTarget ??
+        inferrer.findInterfaceMember(leftType, equalsName, fileOffset,
+            includeExtensionMethods: true);
 
     bool typeNeeded = !inferrer.isTopLevel;
     ExpressionInferenceResult rightResult = inferrer.inferExpression(
         right, const UnknownType(), typeNeeded,
         isVoidAllowed: false);
-    right = rightResult.expression;
 
     assert(equalsTarget.isInstanceMember);
     if (inferrer.instrumentation != null && leftType == const DynamicType()) {
@@ -3438,6 +3439,11 @@
           'target',
           new InstrumentationValueForMember(equalsTarget.member));
     }
+    DartType rightType =
+        inferrer.getPositionalParameterTypeForTarget(equalsTarget, leftType, 0);
+    right = inferrer.ensureAssignableResult(
+        rightType.withNullability(inferrer.library.nullable), rightResult,
+        errorTemplate: templateArgumentTypeNotAssignable);
 
     Expression equals = new MethodInvocation(
         left,
@@ -3849,9 +3855,12 @@
       {bool isThisReceiver}) {
     assert(isThisReceiver != null);
 
-    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
-        receiverType, propertyName, fileOffset,
-        includeExtensionMethods: true);
+    ObjectAccessTarget objectReadTarget =
+        inferrer.getObjectMemberIfNullableReceiver(receiverType, propertyName);
+
+    ObjectAccessTarget readTarget = objectReadTarget ??
+        inferrer.findInterfaceMember(receiverType, propertyName, fileOffset,
+            includeExtensionMethods: true);
 
     DartType readType = inferrer.getGetterType(readTarget, receiverType);
 
@@ -5600,7 +5609,8 @@
     if (!inferrer.isTopLevel) {
       bool isUnassigned = !inferrer.flowAnalysis.isAssigned(variable);
       if (isUnassigned) {
-        inferrer.dataForTesting?.flowAnalysisResult?.unassignedNodes?.add(node);
+        inferrer.dataForTesting?.flowAnalysisResult?.potentiallyUnassignedNodes
+            ?.add(node);
       }
       bool isDefinitelyUnassigned =
           inferrer.flowAnalysis.isUnassigned(variable);
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 7b2b43a..4688b62 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -26,6 +26,7 @@
         Library,
         Name,
         NamedExpression,
+        NonNullableByDefaultCompiledMode,
         NullLiteral,
         Procedure,
         RedirectingInitializer,
@@ -395,11 +396,29 @@
         AmbiguousBuilder problem = declaration;
         declaration = problem.getFirstDeclaration();
       }
+      NonNullableByDefaultCompiledMode compiledMode = null;
+      if (enableNonNullable) {
+        switch (loader.nnbdMode) {
+          case NnbdMode.Weak:
+            compiledMode = NonNullableByDefaultCompiledMode.Weak;
+            break;
+          case NnbdMode.Strong:
+            compiledMode = NonNullableByDefaultCompiledMode.Strong;
+            break;
+          case NnbdMode.Agnostic:
+            compiledMode = NonNullableByDefaultCompiledMode.Agnostic;
+            break;
+        }
+      } else {
+        compiledMode = NonNullableByDefaultCompiledMode.Disabled;
+      }
       if (declaration is ProcedureBuilder) {
-        component.mainMethod = declaration.actualProcedure;
+        component.setMainMethodAndMode(
+            declaration.actualProcedure?.reference, true, compiledMode);
       } else if (declaration is DillMemberBuilder) {
         if (declaration.member is Procedure) {
-          component.mainMethod = declaration.member;
+          component.setMainMethodAndMode(
+              declaration.member?.reference, true, compiledMode);
         }
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index 30af5bc..643e2e0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -59,8 +59,8 @@
 // variables.  For that case if the type has its declaration set to null and its
 // name matches that of the variable, it's interpreted as an occurrence of a
 // type variable.
-int computeVariance(TypeVariableBuilder variable, TypeBuilder type,
-    LibraryBuilder libraryBuilder) {
+int computeTypeVariableBuilderVariance(TypeVariableBuilder variable,
+    TypeBuilder type, LibraryBuilder libraryBuilder) {
   if (type is NamedTypeBuilder) {
     assert(type.declaration != null);
     TypeDeclarationBuilder declaration = type.declaration;
@@ -79,7 +79,7 @@
                 result,
                 Variance.combine(
                     declaration.cls.typeParameters[i].variance,
-                    computeVariance(
+                    computeTypeVariableBuilderVariance(
                         variable, type.arguments[i], libraryBuilder)));
           }
         }
@@ -97,7 +97,7 @@
               TypeVariableBuilder declarationTypeVariable =
                   declaration.typeVariables[i];
               declarationTypeVariable.variance = visitMarker;
-              int computedVariance = computeVariance(
+              int computedVariance = computeTypeVariableBuilderVariance(
                   declarationTypeVariable, declaration.type, libraryBuilder);
               declarationTypeVariableVariance =
                   declarationTypeVariable.variance = computedVariance;
@@ -120,7 +120,7 @@
             result = Variance.meet(
                 result,
                 Variance.combine(
-                    computeVariance(
+                    computeTypeVariableBuilderVariance(
                         variable, type.arguments[i], libraryBuilder),
                     declarationTypeVariableVariance));
           }
@@ -132,7 +132,9 @@
     int result = Variance.unrelated;
     if (type.returnType != null) {
       result = Variance.meet(
-          result, computeVariance(variable, type.returnType, libraryBuilder));
+          result,
+          computeTypeVariableBuilderVariance(
+              variable, type.returnType, libraryBuilder));
     }
     if (type.typeVariables != null) {
       for (TypeVariableBuilder typeVariable in type.typeVariables) {
@@ -141,7 +143,8 @@
         // of [computeVariance] below is made to simply figure out if [variable]
         // occurs in the bound.
         if (typeVariable.bound != null &&
-            computeVariance(variable, typeVariable.bound, libraryBuilder) !=
+            computeTypeVariableBuilderVariance(
+                    variable, typeVariable.bound, libraryBuilder) !=
                 Variance.unrelated) {
           result = Variance.invariant;
         }
@@ -151,8 +154,10 @@
       for (FormalParameterBuilder formal in type.formals) {
         result = Variance.meet(
             result,
-            Variance.combine(Variance.contravariant,
-                computeVariance(variable, formal.type, libraryBuilder)));
+            Variance.combine(
+                Variance.contravariant,
+                computeTypeVariableBuilderVariance(
+                    variable, formal.type, libraryBuilder)));
       }
     }
     return result;
diff --git a/pkg/front_end/lib/src/fasta/kernel/types.dart b/pkg/front_end/lib/src/fasta/kernel/types.dart
deleted file mode 100644
index 8b87689..0000000
--- a/pkg/front_end/lib/src/fasta/kernel/types.dart
+++ /dev/null
@@ -1,966 +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.
-
-library fasta.types;
-
-import 'package:kernel/ast.dart'
-    show
-        BottomType,
-        Class,
-        DartType,
-        DynamicType,
-        FunctionType,
-        InterfaceType,
-        InvalidType,
-        Library,
-        NamedType,
-        NeverType,
-        Nullability,
-        TypeParameter,
-        TypeParameterType,
-        TypedefType,
-        Variance,
-        VoidType;
-
-import 'package:kernel/core_types.dart';
-
-import 'package:kernel/type_algebra.dart'
-    show Substitution, combineNullabilitiesForSubstitution;
-
-import 'package:kernel/type_environment.dart';
-
-import 'package:kernel/src/future_or.dart';
-
-import 'kernel_builder.dart' show ClassHierarchyBuilder;
-
-class Types implements SubtypeTester {
-  final ClassHierarchyBuilder hierarchy;
-
-  Types(this.hierarchy);
-
-  /// Returns true if [s] is a subtype of [t].
-  bool isSubtypeOfKernel(DartType s, DartType t, SubtypeCheckMode mode) {
-    IsSubtypeOf result = performNullabilityAwareSubtypeCheck(s, t);
-    switch (mode) {
-      case SubtypeCheckMode.withNullabilities:
-        return result.isSubtypeWhenUsingNullabilities();
-      case SubtypeCheckMode.ignoringNullabilities:
-        return result.isSubtypeWhenIgnoringNullabilities();
-      default:
-        throw new StateError("Unhandled subtype checking mode '$mode'");
-    }
-  }
-
-  @override
-  IsSubtypeOf performNullabilityAwareSubtypeCheck(DartType s, DartType t) {
-    if (s is BottomType) {
-      return const IsSubtypeOf.always(); // Rule 3.
-    }
-    if (t is DynamicType) {
-      return const IsSubtypeOf.always(); // Rule 2.
-    }
-    if (t is VoidType) {
-      return const IsSubtypeOf.always(); // Rule 2.
-    }
-    if (t is BottomType) {
-      return const IsSubtypeOf.never();
-    }
-    if (s is NeverType) {
-      return new IsSubtypeOf.basedSolelyOnNullabilities(
-          s, t, hierarchy.futureOrClass);
-    }
-
-    // TODO(dmitryas): Remove InvalidType from subtype relation.
-    if (s is InvalidType) {
-      // InvalidType is a bottom type.
-      return const IsSubtypeOf.always();
-    }
-    if (t is InvalidType) {
-      return const IsSubtypeOf.never();
-    }
-
-    if (t is InterfaceType) {
-      Class cls = t.classNode;
-      if (cls == hierarchy.objectClass &&
-          !(s is InterfaceType && s.classNode == hierarchy.futureOrClass)) {
-        return new IsSubtypeOf.basedSolelyOnNullabilities(
-            s, t, hierarchy.futureOrClass);
-      }
-      if (cls == hierarchy.futureOrClass) {
-        const IsFutureOrSubtypeOf relation = const IsFutureOrSubtypeOf();
-        if (s is DynamicType) {
-          return relation.isDynamicRelated(s, t, this);
-        } else if (s is VoidType) {
-          return relation.isVoidRelated(s, t, this);
-        } else if (s is InterfaceType) {
-          return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(s, t, this)
-              : relation.isInterfaceRelated(s, t, this);
-        } else if (s is FunctionType) {
-          return relation.isFunctionRelated(s, t, this);
-        } else if (s is TypeParameterType) {
-          return s.promotedBound == null
-              ? relation.isTypeParameterRelated(s, t, this)
-              : relation.isIntersectionRelated(s, t, this);
-        } else if (s is TypedefType) {
-          return relation.isTypedefRelated(s, t, this);
-        }
-      } else {
-        const IsInterfaceSubtypeOf relation = const IsInterfaceSubtypeOf();
-        if (s is DynamicType) {
-          return relation.isDynamicRelated(s, t, this);
-        } else if (s is VoidType) {
-          return relation.isVoidRelated(s, t, this);
-        } else if (s is InterfaceType) {
-          return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(s, t, this)
-              : relation.isInterfaceRelated(s, t, this);
-        } else if (s is FunctionType) {
-          return relation.isFunctionRelated(s, t, this);
-        } else if (s is TypeParameterType) {
-          return s.promotedBound == null
-              ? relation.isTypeParameterRelated(s, t, this)
-              : relation.isIntersectionRelated(s, t, this);
-        } else if (s is TypedefType) {
-          return relation.isTypedefRelated(s, t, this);
-        }
-      }
-    } else if (t is FunctionType) {
-      const IsFunctionSubtypeOf relation = const IsFunctionSubtypeOf();
-      if (s is DynamicType) {
-        return relation.isDynamicRelated(s, t, this);
-      } else if (s is VoidType) {
-        return relation.isVoidRelated(s, t, this);
-      } else if (s is InterfaceType) {
-        return s.classNode == hierarchy.futureOrClass
-            ? relation.isFutureOrRelated(s, t, this)
-            : relation.isInterfaceRelated(s, t, this);
-      } else if (s is FunctionType) {
-        return relation.isFunctionRelated(s, t, this);
-      } else if (s is TypeParameterType) {
-        return s.promotedBound == null
-            ? relation.isTypeParameterRelated(s, t, this)
-            : relation.isIntersectionRelated(s, t, this);
-      } else if (s is TypedefType) {
-        return relation.isTypedefRelated(s, t, this);
-      }
-    } else if (t is TypeParameterType) {
-      if (t.promotedBound == null) {
-        const IsTypeParameterSubtypeOf relation =
-            const IsTypeParameterSubtypeOf();
-        if (s is DynamicType) {
-          return relation.isDynamicRelated(s, t, this);
-        } else if (s is VoidType) {
-          return relation.isVoidRelated(s, t, this);
-        } else if (s is InterfaceType) {
-          return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(s, t, this)
-              : relation.isInterfaceRelated(s, t, this);
-        } else if (s is FunctionType) {
-          return relation.isFunctionRelated(s, t, this);
-        } else if (s is TypeParameterType) {
-          return s.promotedBound == null
-              ? relation.isTypeParameterRelated(s, t, this)
-              : relation.isIntersectionRelated(s, t, this);
-        } else if (s is TypedefType) {
-          return relation.isTypedefRelated(s, t, this);
-        }
-      } else {
-        const IsIntersectionSubtypeOf relation =
-            const IsIntersectionSubtypeOf();
-        if (s is DynamicType) {
-          return relation.isDynamicRelated(s, t, this);
-        } else if (s is VoidType) {
-          return relation.isVoidRelated(s, t, this);
-        } else if (s is InterfaceType) {
-          return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(s, t, this)
-              : relation.isInterfaceRelated(s, t, this);
-        } else if (s is FunctionType) {
-          return relation.isFunctionRelated(s, t, this);
-        } else if (s is TypeParameterType) {
-          return s.promotedBound == null
-              ? relation.isTypeParameterRelated(s, t, this)
-              : relation.isIntersectionRelated(s, t, this);
-        } else if (s is TypedefType) {
-          return relation.isTypedefRelated(s, t, this);
-        }
-      }
-    } else if (t is TypedefType) {
-      const IsTypedefSubtypeOf relation = const IsTypedefSubtypeOf();
-      if (s is DynamicType) {
-        return relation.isDynamicRelated(s, t, this);
-      } else if (s is VoidType) {
-        return relation.isVoidRelated(s, t, this);
-      } else if (s is InterfaceType) {
-        return s.classNode == hierarchy.futureOrClass
-            ? relation.isFutureOrRelated(s, t, this)
-            : relation.isInterfaceRelated(s, t, this);
-      } else if (s is FunctionType) {
-        return relation.isFunctionRelated(s, t, this);
-      } else if (s is TypeParameterType) {
-        return s.promotedBound == null
-            ? relation.isTypeParameterRelated(s, t, this)
-            : relation.isIntersectionRelated(s, t, this);
-      } else if (s is TypedefType) {
-        return relation.isTypedefRelated(s, t, this);
-      }
-    } else if (t is NeverType) {
-      const IsNeverTypeSubtypeOf relation = const IsNeverTypeSubtypeOf();
-      if (s is DynamicType) {
-        return relation.isDynamicRelated(s, t, this);
-      } else if (s is VoidType) {
-        return relation.isVoidRelated(s, t, this);
-      } else if (s is InterfaceType) {
-        return relation.isInterfaceRelated(s, t, this);
-      } else if (s is FunctionType) {
-        return relation.isFunctionRelated(s, t, this);
-      } else if (s is TypeParameterType) {
-        return s.promotedBound == null
-            ? relation.isTypeParameterRelated(s, t, this)
-            : relation.isIntersectionRelated(s, t, this);
-      } else if (s is TypedefType) {
-        return relation.isTypedefRelated(s, t, this);
-      }
-    } else {
-      throw "Unhandled type: ${t.runtimeType}";
-    }
-    throw "Unhandled type combination: ${t.runtimeType} ${s.runtimeType}";
-  }
-
-  /// Returns true if all type arguments in [s] and [t] pairwise are subtypes
-  /// with respect to the variance of the corresponding [p] type parameter.
-  IsSubtypeOf areTypeArgumentsOfSubtypeKernel(
-      List<DartType> s, List<DartType> t, List<TypeParameter> p) {
-    if (s.length != t.length || s.length != p.length) {
-      throw "Numbers of type arguments don't match $s $t with parameters $p.";
-    }
-    IsSubtypeOf result = const IsSubtypeOf.always();
-    for (int i = 0; i < s.length; i++) {
-      int variance = p[i].variance;
-      if (variance == Variance.contravariant) {
-        result = result.and(performNullabilityAwareSubtypeCheck(t[i], s[i]));
-        if (!result.isSubtypeWhenIgnoringNullabilities()) {
-          return const IsSubtypeOf.never();
-        }
-      } else if (variance == Variance.invariant) {
-        result = result.and(isSameTypeKernel(s[i], t[i]));
-        if (!result.isSubtypeWhenIgnoringNullabilities()) {
-          return const IsSubtypeOf.never();
-        }
-      } else {
-        result = result.and(performNullabilityAwareSubtypeCheck(s[i], t[i]));
-        if (!result.isSubtypeWhenIgnoringNullabilities()) {
-          return const IsSubtypeOf.never();
-        }
-      }
-    }
-    return result;
-  }
-
-  IsSubtypeOf isSameTypeKernel(DartType s, DartType t) {
-    return performNullabilityAwareSubtypeCheck(s, t)
-        .andSubtypeCheckFor(t, s, this);
-  }
-
-  @override
-  bool isSubtypeOf(
-      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
-    return isSubtypeOfKernel(subtype, supertype, mode);
-  }
-
-  @override
-  Class get futureOrClass => hierarchy.coreTypes.futureOrClass;
-
-  @override
-  Class get functionClass => hierarchy.coreTypes.functionClass;
-
-  @override
-  InterfaceType get functionLegacyRawType =>
-      hierarchy.coreTypes.functionLegacyRawType;
-
-  @override
-  InterfaceType futureType(DartType type, Nullability nullability) {
-    return new InterfaceType(
-        hierarchy.coreTypes.futureClass, nullability, <DartType>[type]);
-  }
-
-  @override
-  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
-      Library clientLibrary, CoreTypes coreTypes) {
-    return hierarchy.getKernelTypeAsInstanceOf(type, superclass, clientLibrary);
-  }
-
-  @override
-  List<DartType> getTypeArgumentsAsInstanceOf(
-      InterfaceType type, Class superclass) {
-    return hierarchy.getKernelTypeArgumentsAsInstanceOf(type, superclass);
-  }
-
-  @override
-  bool isTop(DartType type) {
-    return type is DynamicType ||
-        type is VoidType ||
-        type == objectLegacyRawType ||
-        type == objectNullableRawType;
-  }
-
-  @override
-  InterfaceType get nullType => hierarchy.coreTypes.nullType;
-
-  @override
-  Class get objectClass => hierarchy.coreTypes.objectClass;
-
-  @override
-  InterfaceType get objectLegacyRawType {
-    return hierarchy.coreTypes.objectLegacyRawType;
-  }
-
-  @override
-  InterfaceType get objectNullableRawType {
-    return hierarchy.coreTypes.objectNullableRawType;
-  }
-
-  @override
-  IsSubtypeOf performNullabilityAwareMutualSubtypesCheck(
-      DartType type1, DartType type2) {
-    return isSameTypeKernel(type1, type2);
-  }
-}
-
-abstract class TypeRelation<T extends DartType> {
-  const TypeRelation();
-
-  IsSubtypeOf isDynamicRelated(DynamicType s, T t, Types types);
-
-  IsSubtypeOf isVoidRelated(VoidType s, T t, Types types);
-
-  IsSubtypeOf isInterfaceRelated(InterfaceType s, T t, Types types);
-
-  IsSubtypeOf isIntersectionRelated(
-      TypeParameterType intersection, T t, Types types);
-
-  IsSubtypeOf isFunctionRelated(FunctionType s, T t, Types types);
-
-  IsSubtypeOf isFutureOrRelated(InterfaceType futureOr, T t, Types types);
-
-  IsSubtypeOf isTypeParameterRelated(TypeParameterType s, T t, Types types);
-
-  IsSubtypeOf isTypedefRelated(TypedefType s, T t, Types types);
-}
-
-class IsInterfaceSubtypeOf extends TypeRelation<InterfaceType> {
-  const IsInterfaceSubtypeOf();
-
-  @override
-  IsSubtypeOf isInterfaceRelated(
-      InterfaceType s, InterfaceType t, Types types) {
-    if (s.classNode == types.hierarchy.nullClass) {
-      // This is an optimization, to avoid instantiating unnecessary type
-      // arguments in getKernelTypeAsInstanceOf.
-      return new IsSubtypeOf.basedSolelyOnNullabilities(
-          s, t, types.futureOrClass);
-    }
-    List<DartType> asSupertypeArguments =
-        types.hierarchy.getKernelTypeArgumentsAsInstanceOf(s, t.classNode);
-    if (asSupertypeArguments == null) {
-      return const IsSubtypeOf.never();
-    }
-    return types
-        .areTypeArgumentsOfSubtypeKernel(
-            asSupertypeArguments, t.typeArguments, t.classNode.typeParameters)
-        .and(new IsSubtypeOf.basedSolelyOnNullabilities(
-            s, t, types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isTypeParameterRelated(
-      TypeParameterType s, InterfaceType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s.parameter.bound, t).and(
-        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isFutureOrRelated(
-      InterfaceType futureOr, InterfaceType t, Types types) {
-    List<DartType> arguments = futureOr.typeArguments;
-    // Rules 7.1 and 7.2.
-    return types
-        .performNullabilityAwareSubtypeCheck(arguments.single, t)
-        .andSubtypeCheckFor(
-            new InterfaceType(types.hierarchy.futureClass,
-                Nullability.nonNullable, arguments),
-            t,
-            types)
-        .and(new IsSubtypeOf.basedSolelyOnNullabilities(
-            futureOr, t, types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isIntersectionRelated(
-      TypeParameterType intersection, InterfaceType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(
-        intersection.promotedBound, t); // Rule 12.
-  }
-
-  @override
-  IsSubtypeOf isDynamicRelated(DynamicType s, InterfaceType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isFunctionRelated(FunctionType s, InterfaceType t, Types types) {
-    return t.classNode == types.hierarchy.functionClass
-        ? new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass)
-        : const IsSubtypeOf.never(); // Rule 14.
-  }
-
-  @override
-  IsSubtypeOf isTypedefRelated(TypedefType s, InterfaceType t, Types types) {
-    // Rule 5.
-    return types.performNullabilityAwareSubtypeCheck(s.unalias, t).and(
-        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isVoidRelated(VoidType s, InterfaceType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-}
-
-class IsFunctionSubtypeOf extends TypeRelation<FunctionType> {
-  const IsFunctionSubtypeOf();
-
-  @override
-  IsSubtypeOf isFunctionRelated(FunctionType s, FunctionType t, Types types) {
-    List<TypeParameter> sTypeVariables = s.typeParameters;
-    List<TypeParameter> tTypeVariables = t.typeParameters;
-    if (sTypeVariables.length != tTypeVariables.length) {
-      return const IsSubtypeOf.never();
-    }
-    IsSubtypeOf result = const IsSubtypeOf.always();
-    if (sTypeVariables.isNotEmpty) {
-      // If the function types have type variables, we alpha-rename the type
-      // variables of [s] to use those of [t].
-
-      // As an optimization, we first check if the bounds of the type variables
-      // of the two types on the same positions are mutual subtypes without
-      // alpha-renaming them.
-      List<DartType> typeVariableSubstitution = <DartType>[];
-      for (int i = 0; i < sTypeVariables.length; i++) {
-        TypeParameter sTypeVariable = sTypeVariables[i];
-        TypeParameter tTypeVariable = tTypeVariables[i];
-        result = result.and(
-            types.isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound));
-        typeVariableSubstitution.add(new TypeParameterType.forAlphaRenaming(
-            sTypeVariable, tTypeVariable));
-      }
-      Substitution substitution =
-          Substitution.fromPairs(sTypeVariables, typeVariableSubstitution);
-      // If the bounds aren't the same, we need to try again after computing the
-      // substitution of type variables.
-      if (!result.isSubtypeWhenIgnoringNullabilities()) {
-        result = const IsSubtypeOf.always();
-        for (int i = 0; i < sTypeVariables.length; i++) {
-          TypeParameter sTypeVariable = sTypeVariables[i];
-          TypeParameter tTypeVariable = tTypeVariables[i];
-          result = result.and(types.isSameTypeKernel(
-              substitution.substituteType(sTypeVariable.bound),
-              tTypeVariable.bound));
-          if (!result.isSubtypeWhenIgnoringNullabilities()) {
-            return const IsSubtypeOf.never();
-          }
-        }
-      }
-      s = substitution.substituteType(s.withoutTypeParameters);
-    }
-    result = result.and(
-        types.performNullabilityAwareSubtypeCheck(s.returnType, t.returnType));
-    if (!result.isSubtypeWhenIgnoringNullabilities()) {
-      return const IsSubtypeOf.never();
-    }
-    List<DartType> sPositional = s.positionalParameters;
-    List<DartType> tPositional = t.positionalParameters;
-    if (s.requiredParameterCount > t.requiredParameterCount) {
-      // Rule 15, n1 <= n2.
-      return const IsSubtypeOf.never();
-    }
-    if (sPositional.length < tPositional.length) {
-      // Rule 15, n1 + k1 >= n2 + k2.
-      return const IsSubtypeOf.never();
-    }
-    for (int i = 0; i < tPositional.length; i++) {
-      result = result.and(types.performNullabilityAwareSubtypeCheck(
-          tPositional[i], sPositional[i]));
-      if (!result.isSubtypeWhenIgnoringNullabilities()) {
-        // Rule 15, Tj <: Sj.
-        return const IsSubtypeOf.never();
-      }
-    }
-    List<NamedType> sNamed = s.namedParameters;
-    List<NamedType> tNamed = t.namedParameters;
-    if (sNamed.isNotEmpty || tNamed.isNotEmpty) {
-      // Rule 16, the number of positional parameters must be the same.
-      if (sPositional.length != tPositional.length) {
-        return const IsSubtypeOf.never();
-      }
-      if (s.requiredParameterCount != t.requiredParameterCount) {
-        return const IsSubtypeOf.never();
-      }
-
-      // Rule 16, the parameter names of [t] must be a subset of those of
-      // [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;
-        }
-        if (sCount == sNamed.length) return const IsSubtypeOf.never();
-        result = result.and(types.performNullabilityAwareSubtypeCheck(
-            tNamed[tCount].type, sNamed[sCount].type));
-        if (!result.isSubtypeWhenIgnoringNullabilities()) {
-          return const IsSubtypeOf.never();
-        }
-      }
-    }
-    return result.and(
-        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isInterfaceRelated(InterfaceType s, FunctionType t, Types types) {
-    if (s.classNode == types.hierarchy.nullClass) {
-      // Rule 4.
-      return new IsSubtypeOf.basedSolelyOnNullabilities(
-          s, t, types.futureOrClass);
-    }
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isDynamicRelated(DynamicType s, FunctionType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isFutureOrRelated(
-      InterfaceType futureOr, FunctionType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isIntersectionRelated(
-      TypeParameterType intersection, FunctionType t, Types types) {
-    // Rule 12.
-    return types.performNullabilityAwareSubtypeCheck(
-        intersection.promotedBound, t);
-  }
-
-  @override
-  IsSubtypeOf isTypeParameterRelated(
-      TypeParameterType s, FunctionType t, Types types) {
-    // Rule 13.
-    return types.performNullabilityAwareSubtypeCheck(s.parameter.bound, t).and(
-        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isTypedefRelated(TypedefType s, FunctionType t, Types types) {
-    // Rule 5.
-    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
-  }
-
-  @override
-  IsSubtypeOf isVoidRelated(VoidType s, FunctionType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-}
-
-class IsTypeParameterSubtypeOf extends TypeRelation<TypeParameterType> {
-  const IsTypeParameterSubtypeOf();
-
-  @override
-  IsSubtypeOf isTypeParameterRelated(
-      TypeParameterType s, TypeParameterType t, Types types) {
-    IsSubtypeOf result = const IsSubtypeOf.always();
-    if (s.parameter != t.parameter) {
-      result = types.performNullabilityAwareSubtypeCheck(s.bound, t);
-    }
-    if (s.nullability == Nullability.undetermined &&
-        t.nullability == Nullability.undetermined) {
-      // The two nullabilities are undetermined, but are connected via
-      // additional constraint, namely that they will be equal at run time.
-      return result;
-    }
-    return result.and(
-        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isIntersectionRelated(
-      TypeParameterType intersection, TypeParameterType t, Types types) {
-    // Nullable types aren't promoted to intersection types.
-    // TODO(dmitryas): Uncomment the following when the inference is updated.
-    //assert(intersection.typeParameterTypeNullability != Nullability.nullable);
-
-    // Rule 8.
-    if (intersection.parameter == t.parameter) {
-      if (intersection.nullability == Nullability.undetermined &&
-          t.nullability == Nullability.undetermined) {
-        // The two nullabilities are undetermined, but are connected via
-        // additional constraint, namely that they will be equal at run time.
-        return const IsSubtypeOf.always();
-      }
-      return new IsSubtypeOf.basedSolelyOnNullabilities(
-          intersection, t, types.futureOrClass);
-    }
-
-    // Rule 12.
-    return types.performNullabilityAwareSubtypeCheck(
-        intersection.promotedBound.withNullability(intersection.nullability),
-        t);
-  }
-
-  @override
-  IsSubtypeOf isInterfaceRelated(
-      InterfaceType s, TypeParameterType t, Types types) {
-    if (s.classNode == types.hierarchy.nullClass) {
-      // Rule 4.
-      return new IsSubtypeOf.basedSolelyOnNullabilities(
-          s, t, types.futureOrClass);
-    }
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isDynamicRelated(
-      DynamicType s, TypeParameterType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isFunctionRelated(
-      FunctionType s, TypeParameterType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isFutureOrRelated(
-      InterfaceType futureOr, TypeParameterType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isTypedefRelated(
-      TypedefType s, TypeParameterType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
-  }
-
-  @override
-  IsSubtypeOf isVoidRelated(VoidType s, TypeParameterType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-}
-
-class IsTypedefSubtypeOf extends TypeRelation<TypedefType> {
-  const IsTypedefSubtypeOf();
-
-  @override
-  IsSubtypeOf isInterfaceRelated(InterfaceType s, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
-  }
-
-  @override
-  IsSubtypeOf isDynamicRelated(DynamicType s, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
-  }
-
-  @override
-  IsSubtypeOf isFunctionRelated(FunctionType s, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
-  }
-
-  @override
-  IsSubtypeOf isFutureOrRelated(
-      InterfaceType futureOr, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(futureOr, t.unalias);
-  }
-
-  @override
-  IsSubtypeOf isIntersectionRelated(
-      TypeParameterType intersection, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(intersection, t.unalias);
-  }
-
-  @override
-  IsSubtypeOf isTypeParameterRelated(
-      TypeParameterType s, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
-  }
-
-  @override
-  IsSubtypeOf isTypedefRelated(TypedefType s, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s.unalias, t.unalias);
-  }
-
-  @override
-  IsSubtypeOf isVoidRelated(VoidType s, TypedefType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
-  }
-}
-
-class IsFutureOrSubtypeOf extends TypeRelation<InterfaceType> {
-  const IsFutureOrSubtypeOf();
-
-  @override
-  IsSubtypeOf isInterfaceRelated(
-      InterfaceType s, InterfaceType futureOr, Types types) {
-    List<DartType> arguments = futureOr.typeArguments;
-
-    Nullability unitedNullability =
-        computeNullabilityOfFutureOr(futureOr, types.hierarchy.futureOrClass);
-
-    return types
-        // Rule 11.
-        .performNullabilityAwareSubtypeCheck(
-            s, arguments.single.withNullability(unitedNullability))
-        // Rule 10.
-        .orSubtypeCheckFor(
-            s,
-            new InterfaceType(
-                types.hierarchy.futureClass, unitedNullability, arguments),
-            types);
-  }
-
-  @override
-  IsSubtypeOf isFutureOrRelated(
-      InterfaceType sFutureOr, InterfaceType tFutureOr, Types types) {
-    // This follows from combining rules 7, 10, and 11.
-    DartType sArgument = sFutureOr.typeArguments.single;
-    DartType tArgument = tFutureOr.typeArguments.single;
-    DartType sFutureOfArgument = new InterfaceType(types.hierarchy.futureClass,
-        Nullability.nonNullable, sFutureOr.typeArguments);
-    DartType tFutureOfArgument = new InterfaceType(types.hierarchy.futureClass,
-        Nullability.nonNullable, tFutureOr.typeArguments);
-    Nullability sNullability =
-        computeNullabilityOfFutureOr(sFutureOr, types.hierarchy.futureOrClass);
-    Nullability tNullability =
-        computeNullabilityOfFutureOr(tFutureOr, types.hierarchy.futureOrClass);
-    // The following is an optimized is-subtype-of test for the case where
-    // both LHS and RHS are FutureOrs.  It's based on the following:
-    // FutureOr<X> <: FutureOr<Y> iff X <: Y OR (X <: Future<Y> AND
-    // Future<X> <: Y).
-    //
-    // The correctness of that can be shown as follows:
-    //   1. FutureOr<X> <: Y iff X <: Y AND Future<X> <: Y
-    //   2. X <: FutureOr<Y> iff X <: Y OR X <: Future<Y>
-    //   3. 1,2 => FutureOr<X> <: FutureOr<Y> iff
-    //          (X <: Y OR X <: Future<Y>) AND
-    //            (Future<X> <: Y OR Future<X> <: Future<Y>)
-    //   4. X <: Y iff Future<X> <: Future<Y>
-    //   5. 3,4 => FutureOr<X> <: FutureOr<Y> iff
-    //          (X <: Y OR X <: Future<Y>) AND
-    //            (X <: Y OR Future<X> <: Y) iff
-    //          X <: Y OR (X <: Future<Y> AND Future<X> <: Y)
-    return types
-        .performNullabilityAwareSubtypeCheck(sArgument, tArgument)
-        .or(types
-            .performNullabilityAwareSubtypeCheck(sArgument, tFutureOfArgument)
-            .andSubtypeCheckFor(sFutureOfArgument, tArgument, types))
-        .and(new IsSubtypeOf.basedSolelyOnNullabilities(
-            sFutureOr.withNullability(sNullability),
-            tFutureOr.withNullability(tNullability),
-            types.futureOrClass));
-  }
-
-  @override
-  IsSubtypeOf isDynamicRelated(
-      DynamicType s, InterfaceType futureOr, Types types) {
-    // Rule 11.
-    DartType argument = futureOr.typeArguments.single;
-    return types.performNullabilityAwareSubtypeCheck(
-        s,
-        argument.withNullability(computeNullabilityOfFutureOr(
-            futureOr, types.hierarchy.futureOrClass)));
-  }
-
-  @override
-  IsSubtypeOf isVoidRelated(VoidType s, InterfaceType futureOr, Types types) {
-    // Rule 11.
-    DartType argument = futureOr.typeArguments.single;
-    return types.performNullabilityAwareSubtypeCheck(
-        s,
-        argument.withNullability(computeNullabilityOfFutureOr(
-            futureOr, types.hierarchy.futureOrClass)));
-  }
-
-  @override
-  IsSubtypeOf isTypeParameterRelated(
-      TypeParameterType s, InterfaceType futureOr, Types types) {
-    List<DartType> arguments = futureOr.typeArguments;
-    Nullability unitedNullability =
-        computeNullabilityOfFutureOr(futureOr, types.hierarchy.futureOrClass);
-    // TODO(dmitryas): Revise the original optimization.
-    return types
-        // Rule 11.
-        .performNullabilityAwareSubtypeCheck(
-            s, arguments.single.withNullability(unitedNullability))
-        // Rule 13.
-        .orSubtypeCheckFor(
-            s.parameter.bound.withNullability(
-                combineNullabilitiesForSubstitution(
-                    s.parameter.bound.nullability, s.nullability)),
-            futureOr,
-            types)
-        // Rule 10.
-        .orSubtypeCheckFor(
-            s,
-            new InterfaceType(
-                types.hierarchy.futureClass, unitedNullability, arguments),
-            types);
-  }
-
-  @override
-  IsSubtypeOf isFunctionRelated(
-      FunctionType s, InterfaceType futureOr, Types types) {
-    // Rule 11.
-    DartType argument = futureOr.typeArguments.single;
-    return types.performNullabilityAwareSubtypeCheck(
-        s,
-        argument.withNullability(computeNullabilityOfFutureOr(
-            futureOr, types.hierarchy.futureOrClass)));
-  }
-
-  @override
-  IsSubtypeOf isIntersectionRelated(
-      TypeParameterType intersection, InterfaceType futureOr, Types types) {
-    return isTypeParameterRelated(intersection, futureOr, types) // Rule 8.
-        .orSubtypeCheckFor(
-            intersection.promotedBound, futureOr, types); // Rule 12.
-  }
-
-  @override
-  IsSubtypeOf isTypedefRelated(
-      TypedefType s, InterfaceType futureOr, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s.unalias, futureOr);
-  }
-}
-
-class IsIntersectionSubtypeOf extends TypeRelation<TypeParameterType> {
-  const IsIntersectionSubtypeOf();
-
-  @override
-  IsSubtypeOf isIntersectionRelated(TypeParameterType sIntersection,
-      TypeParameterType tIntersection, Types types) {
-    // Rule 9.
-    return const IsTypeParameterSubtypeOf()
-        .isIntersectionRelated(sIntersection, tIntersection, types)
-        .andSubtypeCheckFor(sIntersection, tIntersection.promotedBound, types);
-  }
-
-  @override
-  IsSubtypeOf isTypeParameterRelated(
-      TypeParameterType s, TypeParameterType intersection, Types types) {
-    // Rule 9.
-    return const IsTypeParameterSubtypeOf()
-        .isTypeParameterRelated(s, intersection, types)
-        .andSubtypeCheckFor(s, intersection.promotedBound, types);
-  }
-
-  @override
-  IsSubtypeOf isInterfaceRelated(
-      InterfaceType s, TypeParameterType intersection, Types types) {
-    if (s.classNode == types.hierarchy.nullClass) {
-      // Rule 4.
-      return new IsSubtypeOf.basedSolelyOnNullabilities(
-          s, intersection, types.futureOrClass);
-    }
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isDynamicRelated(
-      DynamicType s, TypeParameterType intersection, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isFunctionRelated(
-      FunctionType s, TypeParameterType intersection, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isFutureOrRelated(
-      InterfaceType futureOr, TypeParameterType intersection, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  @override
-  IsSubtypeOf isTypedefRelated(
-      TypedefType s, TypeParameterType intersection, Types types) {
-    // Rule 5.
-    return types.performNullabilityAwareSubtypeCheck(s.unalias, intersection);
-  }
-
-  @override
-  IsSubtypeOf isVoidRelated(
-      VoidType s, TypeParameterType intersection, Types types) {
-    return const IsSubtypeOf.never();
-  }
-}
-
-class IsNeverTypeSubtypeOf implements TypeRelation<NeverType> {
-  const IsNeverTypeSubtypeOf();
-
-  IsSubtypeOf isDynamicRelated(DynamicType s, NeverType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  IsSubtypeOf isVoidRelated(VoidType s, NeverType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  IsSubtypeOf isInterfaceRelated(InterfaceType s, NeverType t, Types types) {
-    if (s.classNode == types.hierarchy.nullClass) {
-      if (t.nullability == Nullability.nullable ||
-          t.nullability == Nullability.legacy) {
-        return const IsSubtypeOf.always();
-      }
-      if (t.nullability == Nullability.nonNullable) {
-        return const IsSubtypeOf.never();
-      }
-      throw new StateError(
-          "Unexpected nullability '$t.nullability' of type Never");
-    }
-    return const IsSubtypeOf.never();
-  }
-
-  IsSubtypeOf isIntersectionRelated(
-      TypeParameterType intersection, NeverType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(
-        intersection.promotedBound, t);
-  }
-
-  IsSubtypeOf isFunctionRelated(FunctionType s, NeverType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  IsSubtypeOf isFutureOrRelated(
-      InterfaceType futureOr, NeverType t, Types types) {
-    return const IsSubtypeOf.never();
-  }
-
-  IsSubtypeOf isTypeParameterRelated(
-      TypeParameterType s, NeverType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s.bound, t).and(
-        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
-  }
-
-  IsSubtypeOf isTypedefRelated(TypedefType s, NeverType t, Types types) {
-    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index 97a844a..cd6a3a7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -77,7 +77,10 @@
 
   Library fakeLibrary = new Library(new Uri(scheme: 'evaluate', path: 'source'))
     ..setLanguageVersion(
-        realLibrary.languageVersionMajor, realLibrary.languageVersionMinor);
+        realLibrary.languageVersionMajor, realLibrary.languageVersionMinor)
+    ..isNonNullableByDefault = realLibrary.isNonNullableByDefault
+    ..nonNullableByDefaultCompiledMode =
+        realLibrary.nonNullableByDefaultCompiledMode;
 
   if (procedure.parent is Class) {
     Class realClass = procedure.parent;
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index b5f17b8..635e249 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -653,6 +653,40 @@
   @override
   void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
       Token beginInitializers, Token endToken) {
+    _endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken, false);
+  }
+
+  @override
+  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    _endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken, true);
+  }
+
+  @override
+  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    _endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken, false);
+  }
+
+  @override
+  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    _endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken, false);
+  }
+
+  @override
+  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    _endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken, true);
+  }
+
+  void _endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken, bool isConstructor) {
     debugEvent("Method");
     // TODO(danrubel): Consider removing the beginParam parameter
     // and using bodyToken, but pushing a NullValue on the stack
@@ -663,8 +697,7 @@
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || currentClassIsParserRecovery) return;
     FunctionBuilder builder;
-    if (name is QualifiedName ||
-        (getOrSet == null && name == currentClass?.name)) {
+    if (isConstructor) {
       builder = lookupConstructor(beginToken, name);
     } else {
       builder = lookupBuilder(beginToken, getOrSet, name);
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 04a3998..05b1fac 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -515,8 +515,7 @@
   void handleClassOrMixinImplements(
       Token implementsKeyword, int interfacesCount) {
     debugEvent("ClassOrMixinImplements");
-    push(const FixedNullableList<NamedTypeBuilder>()
-            .pop(stack, interfacesCount) ??
+    push(const FixedNullableList<TypeBuilder>().pop(stack, interfacesCount) ??
         NullValue.TypeBuilderList);
   }
 
@@ -1327,7 +1326,7 @@
   @override
   void endTypeList(int count) {
     debugEvent("TypeList");
-    push(const FixedNullableList<NamedTypeBuilder>().pop(stack, count) ??
+    push(const FixedNullableList<TypeBuilder>().pop(stack, count) ??
         new ParserRecovery(-1));
   }
 
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 bc7ee5e..2f37d76 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
@@ -4,99 +4,43 @@
 
 library fasta.source_class_builder;
 
-import 'package:kernel/ast.dart'
-    show
-        Class,
-        Constructor,
-        Expression,
-        ListLiteral,
-        Member,
-        StaticGet,
-        Supertype,
-        TreeNode,
-        DartType,
-        DynamicType,
-        Field,
-        FunctionNode,
-        Name,
-        Procedure,
-        ProcedureKind,
-        TypeParameter,
-        VariableDeclaration,
-        Variance,
-        VoidType;
-
+import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
 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/type_algebra.dart' show Substitution;
-
 import 'package:kernel/type_algebra.dart' as type_algebra
     show getSubstitutionMap;
-
 import 'package:kernel/type_environment.dart';
 
 import '../builder/builder.dart';
-
 import '../builder/class_builder.dart';
-
 import '../builder/constructor_reference_builder.dart';
-
+import '../builder/field_builder.dart';
 import '../builder/function_builder.dart';
-
 import '../builder/invalid_type_declaration_builder.dart';
-
 import '../builder/library_builder.dart';
-
 import '../builder/member_builder.dart';
-
 import '../builder/metadata_builder.dart';
-
 import '../builder/named_type_builder.dart';
-
 import '../builder/nullability_builder.dart';
-
 import '../builder/procedure_builder.dart';
-
 import '../builder/type_alias_builder.dart';
-
 import '../builder/type_builder.dart';
-
 import '../builder/type_declaration_builder.dart';
-
 import '../builder/type_variable_builder.dart';
 
 import '../dill/dill_member_builder.dart' show DillMemberBuilder;
 
-import '../fasta_codes.dart'
-    show
-        Message,
-        noLength,
-        messageExtendFunction,
-        messageImplementFunction,
-        messageMixinFunction,
-        templateConflictsWithConstructor,
-        templateConflictsWithFactory,
-        templateConflictsWithMember,
-        templateConflictsWithSetter,
-        templateDuplicatedDeclarationUse,
-        templateInvalidTypeVariableInSupertype,
-        templateInvalidTypeVariableInSupertypeWithVariance,
-        templateRedirectionTargetNotFound,
-        templateSupertypeIsIllegal;
+import '../fasta_codes.dart';
 
 import '../kernel/redirecting_factory_body.dart' show redirectingName;
-
 import '../kernel/kernel_builder.dart' show compareProcedures;
-
 import '../kernel/kernel_target.dart' show KernelTarget;
-
 import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
-
-import '../kernel/type_algorithms.dart' show Variance, computeVariance;
+import '../kernel/type_algorithms.dart'
+    show Variance, computeTypeVariableBuilderVariance;
 
 import '../names.dart' show noSuchMethodName;
 
@@ -340,7 +284,8 @@
     if (typeVariables == null || supertype == null) return supertype;
     Message message;
     for (int i = 0; i < typeVariables.length; ++i) {
-      int variance = computeVariance(typeVariables[i], supertype, library);
+      int variance = computeTypeVariableBuilderVariance(
+          typeVariables[i], supertype, library);
       if (!Variance.greaterThanOrEqual(variance, typeVariables[i].variance)) {
         if (typeVariables[i].parameter.isLegacyCovariant) {
           message = templateInvalidTypeVariableInSupertype.withArguments(
@@ -367,6 +312,280 @@
     return supertype;
   }
 
+  void checkVarianceInField(Field field, TypeEnvironment typeEnvironment,
+      List<TypeParameter> typeParameters) {
+    for (TypeParameter typeParameter in typeParameters) {
+      int fieldVariance = computeVariance(typeParameter, field.type);
+      if (field.hasImplicitGetter) {
+        reportVariancePositionIfInvalid(
+            fieldVariance, typeParameter, field.fileUri, field.fileOffset);
+      }
+      if (field.hasImplicitSetter && !field.isCovariant) {
+        fieldVariance = Variance.combine(Variance.contravariant, fieldVariance);
+        reportVariancePositionIfInvalid(
+            fieldVariance, typeParameter, field.fileUri, field.fileOffset);
+      }
+    }
+  }
+
+  void checkVarianceInFunction(Procedure procedure,
+      TypeEnvironment typeEnvironment, List<TypeParameter> typeParameters) {
+    List<TypeParameter> functionTypeParameters =
+        procedure.function.typeParameters;
+    List<VariableDeclaration> positionalParameters =
+        procedure.function.positionalParameters;
+    List<VariableDeclaration> namedParameters =
+        procedure.function.namedParameters;
+    DartType returnType = procedure.function.returnType;
+
+    if (functionTypeParameters != null) {
+      for (TypeParameter functionParameter in functionTypeParameters) {
+        for (TypeParameter typeParameter in typeParameters) {
+          int typeVariance = Variance.combine(Variance.invariant,
+              computeVariance(typeParameter, functionParameter.bound));
+          reportVariancePositionIfInvalid(typeVariance, typeParameter, fileUri,
+              functionParameter.fileOffset);
+        }
+      }
+    }
+    if (positionalParameters != null) {
+      for (VariableDeclaration formal in positionalParameters) {
+        if (!formal.isCovariant) {
+          for (TypeParameter typeParameter in typeParameters) {
+            int formalVariance = Variance.combine(Variance.contravariant,
+                computeVariance(typeParameter, formal.type));
+            reportVariancePositionIfInvalid(
+                formalVariance, typeParameter, fileUri, formal.fileOffset);
+          }
+        }
+      }
+    }
+    if (namedParameters != null) {
+      for (VariableDeclaration named in namedParameters) {
+        for (TypeParameter typeParameter in typeParameters) {
+          int namedVariance = Variance.combine(Variance.contravariant,
+              computeVariance(typeParameter, named.type));
+          reportVariancePositionIfInvalid(
+              namedVariance, typeParameter, fileUri, named.fileOffset);
+        }
+      }
+    }
+    if (returnType != null) {
+      for (TypeParameter typeParameter in typeParameters) {
+        int returnTypeVariance = computeVariance(typeParameter, returnType);
+        reportVariancePositionIfInvalid(returnTypeVariance, typeParameter,
+            fileUri, procedure.function.fileOffset,
+            isReturnType: true);
+      }
+    }
+  }
+
+  void reportVariancePositionIfInvalid(
+      int variance, TypeParameter typeParameter, Uri fileUri, int fileOffset,
+      {bool isReturnType: false}) {
+    SourceLibraryBuilder library = this.library;
+    if (!typeParameter.isLegacyCovariant &&
+        !Variance.greaterThanOrEqual(variance, typeParameter.variance)) {
+      Message message;
+      if (isReturnType) {
+        message = templateInvalidTypeVariableVariancePositionInReturnType
+            .withArguments(Variance.keywordString(typeParameter.variance),
+                typeParameter.name, Variance.keywordString(variance));
+      } else {
+        message = templateInvalidTypeVariableVariancePosition.withArguments(
+            Variance.keywordString(typeParameter.variance),
+            typeParameter.name,
+            Variance.keywordString(variance));
+      }
+      library.reportTypeArgumentIssue(
+          message, fileUri, fileOffset, typeParameter);
+    }
+  }
+
+  void checkBoundsInSupertype(
+      Supertype supertype, TypeEnvironment typeEnvironment) {
+    SourceLibraryBuilder libraryBuilder = this.library;
+    Library library = libraryBuilder.library;
+    final DartType bottomType = library.isNonNullableByDefault
+        ? const NeverType(Nullability.nonNullable)
+        : typeEnvironment.nullType;
+
+    Set<TypeArgumentIssue> issues = {};
+    issues.addAll(findTypeArgumentIssues(
+            library,
+            new InterfaceType(supertype.classNode, library.nonNullable,
+                supertype.typeArguments),
+            typeEnvironment,
+            SubtypeCheckMode.ignoringNullabilities,
+            bottomType,
+            allowSuperBounded: false) ??
+        const []);
+    if (library.isNonNullableByDefault) {
+      issues.addAll(findTypeArgumentIssues(
+              library,
+              new InterfaceType(supertype.classNode, library.nonNullable,
+                  supertype.typeArguments),
+              typeEnvironment,
+              SubtypeCheckMode.withNullabilities,
+              bottomType,
+              allowSuperBounded: false) ??
+          const []);
+    }
+    for (TypeArgumentIssue issue in issues) {
+      DartType argument = issue.argument;
+      TypeParameter typeParameter = issue.typeParameter;
+      bool inferred = libraryBuilder.inferredTypes.contains(argument);
+      if (argument is FunctionType && argument.typeParameters.length > 0) {
+        if (inferred) {
+          libraryBuilder.reportTypeArgumentIssue(
+              templateGenericFunctionTypeInferredAsActualTypeArgument
+                  .withArguments(argument, library.isNonNullableByDefault),
+              fileUri,
+              charOffset,
+              null);
+        } else {
+          libraryBuilder.reportTypeArgumentIssue(
+              messageGenericFunctionTypeUsedAsActualTypeArgument,
+              fileUri,
+              charOffset,
+              null);
+        }
+      } else {
+        void reportProblem(
+            Template<
+                    Message Function(DartType, DartType, String, String, String,
+                        String, bool)>
+                template) {
+          libraryBuilder.reportTypeArgumentIssue(
+              template.withArguments(
+                  argument,
+                  typeParameter.bound,
+                  typeParameter.name,
+                  getGenericTypeName(issue.enclosingType),
+                  supertype.classNode.name,
+                  name,
+                  library.isNonNullableByDefault),
+              fileUri,
+              charOffset,
+              typeParameter);
+        }
+
+        if (inferred) {
+          reportProblem(templateIncorrectTypeArgumentInSupertypeInferred);
+        } else {
+          reportProblem(templateIncorrectTypeArgumentInSupertype);
+        }
+      }
+    }
+  }
+
+  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);
+        }
+      }
+    }
+
+    // Check in supers.
+    if (cls.supertype != null) {
+      checkBoundsInSupertype(cls.supertype, typeEnvironment);
+    }
+    if (cls.mixedInType != null) {
+      checkBoundsInSupertype(cls.mixedInType, typeEnvironment);
+    }
+    if (cls.implementedTypes != null) {
+      for (Supertype supertype in cls.implementedTypes) {
+        checkBoundsInSupertype(supertype, typeEnvironment);
+      }
+    }
+
+    // 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 FieldBuilder) {
+        checkVarianceInField(
+            builder.field, typeEnvironment, cls.typeParameters);
+        libraryBuilder.checkTypesInField(builder, typeEnvironment);
+      }
+
+      // Check initializers.
+      if (builder is FunctionBuilder &&
+          !builder.isAbstract &&
+          builder.formals != null) {
+        libraryBuilder.checkInitializersInFormals(
+            builder.formals, typeEnvironment);
+      }
+    });
+  }
+
   void addSyntheticConstructor(Constructor constructor) {
     String name = constructor.name.name;
     cls.constructors.add(constructor);
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 923c081..bb050e3 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
@@ -133,7 +133,7 @@
 import '../kernel/type_algorithms.dart'
     show
         calculateBounds,
-        computeVariance,
+        computeTypeVariableBuilderVariance,
         findGenericFunctionTypes,
         getNonSimplicityIssuesForDeclaration,
         getNonSimplicityIssuesForTypeVariables,
@@ -410,6 +410,7 @@
     'language_2/',
     'lib_2/',
     'standalone_2/',
+    'vm/dart/', // in runtime/tests
   ];
 
   LanguageVersion get languageVersion => _languageVersion;
@@ -2729,8 +2730,8 @@
       if (declaration is TypeAliasBuilder &&
           declaration.typeVariablesCount > 0) {
         for (TypeVariableBuilder typeParameter in declaration.typeVariables) {
-          typeParameter.variance =
-              computeVariance(typeParameter, declaration.type, this);
+          typeParameter.variance = computeTypeVariableBuilderVariance(
+              typeParameter, declaration.type, this);
           ++count;
         }
       }
@@ -3105,13 +3106,13 @@
           ? const NeverType(Nullability.nonNullable)
           : typeEnvironment.nullType;
       Set<TypeArgumentIssue> issues = {};
-      issues.addAll(findTypeArgumentIssues(returnType, typeEnvironment,
+      issues.addAll(findTypeArgumentIssues(library, returnType, typeEnvironment,
               SubtypeCheckMode.ignoringNullabilities, bottomType,
               allowSuperBounded: true) ??
           const []);
       if (isNonNullableByDefault) {
-        issues.addAll(findTypeArgumentIssues(returnType, typeEnvironment,
-                SubtypeCheckMode.withNullabilities, bottomType,
+        issues.addAll(findTypeArgumentIssues(library, returnType,
+                typeEnvironment, SubtypeCheckMode.withNullabilities, bottomType,
                 allowSuperBounded: true) ??
             const []);
       }
@@ -3187,12 +3188,12 @@
         ? const NeverType(Nullability.nonNullable)
         : typeEnvironment.nullType;
     Set<TypeArgumentIssue> issues = {};
-    issues.addAll(findTypeArgumentIssues(type, typeEnvironment,
+    issues.addAll(findTypeArgumentIssues(library, type, typeEnvironment,
             SubtypeCheckMode.ignoringNullabilities, bottomType,
             allowSuperBounded: allowSuperBounded) ??
         const []);
     if (isNonNullableByDefault) {
-      issues.addAll(findTypeArgumentIssues(type, typeEnvironment,
+      issues.addAll(findTypeArgumentIssues(library, type, typeEnvironment,
               SubtypeCheckMode.withNullabilities, bottomType,
               allowSuperBounded: allowSuperBounded) ??
           const []);
@@ -3255,6 +3256,7 @@
         : typeEnvironment.nullType;
     Set<TypeArgumentIssue> issues = {};
     issues.addAll(findTypeArgumentIssuesForInvocation(
+            library,
             parameters,
             arguments,
             typeEnvironment,
@@ -3263,6 +3265,7 @@
         const []);
     if (isNonNullableByDefault) {
       issues.addAll(findTypeArgumentIssuesForInvocation(
+              library,
               parameters,
               arguments,
               typeEnvironment,
@@ -3340,6 +3343,7 @@
         : typeEnvironment.nullType;
     Set<TypeArgumentIssue> issues = {};
     issues.addAll(findTypeArgumentIssuesForInvocation(
+            library,
             instantiatedMethodParameters,
             arguments.types,
             typeEnvironment,
@@ -3348,6 +3352,7 @@
         const []);
     if (isNonNullableByDefault) {
       issues.addAll(findTypeArgumentIssuesForInvocation(
+              library,
               instantiatedMethodParameters,
               arguments.types,
               typeEnvironment,
@@ -3373,7 +3378,7 @@
         if (declaration.formals != null) {
           checkInitializersInFormals(declaration.formals, typeEnvironment);
         }
-      } else if (declaration is ClassBuilder) {
+      } else if (declaration is SourceClassBuilder) {
         declaration.checkTypesInOutline(typeEnvironment);
       }
     }
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 776f399..5d6a44d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1238,33 +1238,76 @@
 
 print(object) {}
 
-class Iterator {}
+class Iterator<E> {
+  bool moveNext() => null;
+  E get current => null;
+}
 
-class Iterable {}
+class Iterable<E> {
+  Iterator<E> get iterator => null;
+}
 
-class List extends Iterable {
+class List<E> extends Iterable {
+  factory List() => null;
   factory List.unmodifiable(elements) => null;
+  factory List.filled(int length, E fill, {bool growable = false}) => null;
+  void add(E) {}
+  E operator [](int index) => null;
 }
 
-class Map extends Iterable {
-  factory Map.unmodifiable(other) => null;
+class _GrowableList<E> {
+  factory _GrowableList() => null;
 }
 
+class _List<E> {
+  factory _List() => null;
+}
+
+class MapEntry<K, V> {
+  K key;
+  V value;
+}
+
+abstract class Map<K, V> extends Iterable {
+  factory Map.unmodifiable(other) => null;
+  Iterable<MapEntry<K, V>> get entries;
+  void operator []=(K key, V value) {}
+}
+
+abstract class _ImmutableMap<K, V> implements Map<K, V> {
+  dynamic _kvPairs;
+}
+
+abstract class pragma {
+  String name;
+  Object options;
+}
+
+class AbstractClassInstantiationError {}
+
 class NoSuchMethodError {
   NoSuchMethodError.withInvocation(receiver, invocation);
 }
 
+class StackTrace {}
+
 class Null {}
 
 class Object {
+  const Object();
   noSuchMethod(invocation) => null;
+  bool operator==(dynamic) {}
 }
 
 class String {}
 
 class Symbol {}
 
-class Set {}
+class Set<E> {
+  factory Set() = Set<E>._fake;
+  external factory Set._fake();
+  void add(E) {}
+}
 
 class Type {}
 
@@ -1296,6 +1339,10 @@
 const String defaultDartAsyncSource = """
 _asyncErrorWrapperHelper(continuation) {}
 
+void _asyncStarListenHelper(var object, var awaiter) {}
+
+void _asyncStarMoveNextHelper(var stream) {}
+
 _asyncStackTraceHelper(async_op) {}
 
 _asyncThenWrapperHelper(continuation) {}
@@ -1316,7 +1363,7 @@
   get stream => null;
 }
 
-class Completer {
+abstract class Completer {
   factory Completer.sync() => null;
 
   get future;
@@ -1326,7 +1373,7 @@
   completeError(error, [stackTrace]);
 }
 
-class Future {
+class Future<T> {
   factory Future.microtask(computation) => null;
 }
 
@@ -1339,6 +1386,8 @@
   complete([value]) {}
 
   completeError(error, [stackTrace]) {}
+
+  void start(void Function() f) {}
 }
 
 class Stream {}
@@ -1367,6 +1416,8 @@
 class Symbol {
   const Symbol(String name);
 }
+
+T unsafeCast<T>(Object v) {}
 """;
 
 /// A minimal implementation of dart:typed_data that is sufficient to create an
diff --git a/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart b/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart
new file mode 100644
index 0000000..26ea347
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/type_inference/factor_type.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:kernel/ast.dart' hide MapEntry;
+import 'package:kernel/type_environment.dart';
+
+/// Computes the "remainder" of [T] when [S] has been removed from consideration
+/// by an instance check.  This operation is used for type promotion during flow
+/// analysis.
+DartType factorType(TypeEnvironment typeEnvironment, DartType T, DartType S) {
+  // * If T <: S then Never
+  if (typeEnvironment.isSubtypeOf(T, S, SubtypeCheckMode.withNullabilities)) {
+    return const NeverType(Nullability.nonNullable);
+  }
+
+  // * Else if T is R? and Null <: S then factor(R, S)
+  // * Else if T is R? then factor(R, S)?
+  if (T.nullability == Nullability.nullable) {
+    DartType R = T.withNullability(Nullability.nonNullable);
+    DartType factor_RS = factorType(typeEnvironment, R, S);
+    if (typeEnvironment.isSubtypeOf(
+        typeEnvironment.nullType, S, SubtypeCheckMode.withNullabilities)) {
+      return factor_RS;
+    } else {
+      return factor_RS.withNullability(Nullability.nullable);
+    }
+  }
+
+  // * Else if T is R* and Null <: S then factor(R, S)
+  // * Else if T is R* then factor(R, S)*
+  if (T.nullability == Nullability.legacy) {
+    DartType R = T.withNullability(Nullability.nonNullable);
+    DartType factor_RS = factorType(typeEnvironment, R, S);
+    if (typeEnvironment.isSubtypeOf(
+        typeEnvironment.nullType, S, SubtypeCheckMode.withNullabilities)) {
+      return factor_RS;
+    } else {
+      return factor_RS.withNullability(Nullability.legacy);
+    }
+  }
+
+  // * Else if T is FutureOr<R> and Future<R> <: S then factor(R, S)
+  // * Else if T is FutureOr<R> and R <: S then factor(Future<R>, S)
+  if (T is InterfaceType && T.classNode == typeEnvironment.futureOrClass) {
+    DartType R = T.typeArguments[0];
+    DartType future_R = typeEnvironment.futureType(R, Nullability.nonNullable);
+    if (typeEnvironment.isSubtypeOf(
+        future_R, S, SubtypeCheckMode.withNullabilities)) {
+      return factorType(typeEnvironment, R, S);
+    }
+    if (typeEnvironment.isSubtypeOf(R, S, SubtypeCheckMode.withNullabilities)) {
+      return factorType(typeEnvironment, future_R, S);
+    }
+  }
+
+  return T;
+}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
index 8e1c904..e2d8911 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
@@ -407,8 +407,14 @@
 
     // DOWN(T1, T2) = T1 if T1 <: T2.
     // DOWN(T1, T2) = T2 if T2 <: T1.
+
+    // We use the non-nullable variants of the two types to determine T1 <: T2
+    // 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.withNullability(Nullability.nonNullable);
     DartType nonNullableType2 = type2.withNullability(Nullability.nonNullable);
+
     if (isSubtypeOf(nonNullableType1, nonNullableType2,
         SubtypeCheckMode.withNullabilities)) {
       return type1.withNullability(
@@ -755,14 +761,26 @@
         "Expected type1 to be an interface type, got '${type1.runtimeType}'.");
     assert(type2 is InterfaceType,
         "Expected type2 to be an interface type, got '${type2.runtimeType}'.");
-    if (isSubtypeOf(type1, type2, SubtypeCheckMode.withNullabilities)) {
+
+    // We use the non-nullable variants of the two interfaces types to determine
+    // 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.withNullability(Nullability.nonNullable);
+    InterfaceType nonNonNullableType2 =
+        type2.withNullability(Nullability.nonNullable);
+
+    if (isSubtypeOf(nonNonNullableType1, nonNonNullableType2,
+        SubtypeCheckMode.withNullabilities)) {
       return type2.withNullability(
           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(type2, type1, SubtypeCheckMode.withNullabilities)) {
+    if (isSubtypeOf(nonNonNullableType2, nonNonNullableType1,
+        SubtypeCheckMode.withNullabilities)) {
       return type1.withNullability(
           uniteNullabilities(type1.nullability, type2.nullability));
     }
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 7b57b07..b33a2df 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
@@ -236,7 +236,7 @@
 
   /// The list of [Expression]s representing variable accesses that occur before
   /// the corresponding variable has been definitely assigned.
-  final List<TreeNode> unassignedNodes = [];
+  final List<TreeNode> potentiallyUnassignedNodes = [];
 
   /// The list of [Expression]s representing variable accesses that occur when
   /// the corresponding variable has been definitely unassigned.
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 2010a5b..c8b7fa4 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
@@ -717,12 +717,14 @@
       DartType expectedType, ExpressionInferenceResult result,
       {int fileOffset,
       bool isVoidAllowed: false,
-      bool isReturnFromAsync: false}) {
+      bool isReturnFromAsync: false,
+      Template<Message Function(DartType, DartType, bool)> errorTemplate}) {
     return ensureAssignable(
         expectedType, result.inferredType, result.expression,
         fileOffset: fileOffset,
         isVoidAllowed: isVoidAllowed,
-        isReturnFromAsync: isReturnFromAsync);
+        isReturnFromAsync: isReturnFromAsync,
+        errorTemplate: errorTemplate);
   }
 
   /// Ensures that [expressionType] is assignable to [contextType].
@@ -1034,23 +1036,10 @@
 
     if (receiverType is FunctionType && name == callName) {
       return const ObjectAccessTarget.callFunction();
-    }
-
-    Class classNode = receiverType is InterfaceType
-        ? receiverType.classNode
-        : coreTypes.objectClass;
-    Member interfaceMember =
-        _getInterfaceMember(classNode, name, setter, fileOffset);
-    ObjectAccessTarget target;
-    if (interfaceMember != null) {
-      target = new ObjectAccessTarget.interfaceMember(interfaceMember);
-    } else if (receiverType is DynamicType) {
-      target = const ObjectAccessTarget.dynamic();
     } else if (receiverType is NeverType) {
       switch (receiverType.nullability) {
         case Nullability.nonNullable:
-          target = const ObjectAccessTarget.never();
-          break;
+          return const ObjectAccessTarget.never();
         case Nullability.nullable:
         case Nullability.legacy:
           // Never? and Never* are equivalent to Null.
@@ -1064,6 +1053,17 @@
               fileOffset,
               library.fileUri);
       }
+    }
+    Class classNode = receiverType is InterfaceType
+        ? receiverType.classNode
+        : coreTypes.objectClass;
+    Member interfaceMember =
+        _getInterfaceMember(classNode, name, setter, fileOffset);
+    ObjectAccessTarget target;
+    if (interfaceMember != null) {
+      target = new ObjectAccessTarget.interfaceMember(interfaceMember);
+    } else if (receiverType is DynamicType) {
+      target = const ObjectAccessTarget.dynamic();
     } else if (receiverType is InvalidType) {
       target = const ObjectAccessTarget.invalid();
     } else if (receiverType is InterfaceType &&
@@ -1213,6 +1213,54 @@
     return target;
   }
 
+  /// Returns the Object member by given [name] if [receiverType] is potentially
+  /// nullable.
+  ///
+  /// This method is used to infer nullable calls to Object member against the
+  /// Object member signature and not the overridden signature.
+  ///
+  /// If the member is procedure that isn't applicable with the provided
+  /// [arguments], `null` is returned. This is a special casing that ensures
+  /// that calls that wouldn't match the Object member regardless of typing
+  /// will be reported as nullable access of the overridden member instead of
+  /// inapplicable access to the Object member.
+  ObjectAccessTarget getObjectMemberIfNullableReceiver(
+      DartType receiverType, Name name,
+      [Arguments arguments]) {
+    if (isNonNullableByDefault &&
+        receiverType is! DynamicType &&
+        receiverType is! InvalidType &&
+        isPotentiallyNullable(receiverType, coreTypes.futureOrClass)) {
+      ObjectAccessTarget target = findInterfaceMember(
+          coreTypes.objectNonNullableRawType, name, -1,
+          instrumented: false);
+      if (target.isUnresolved) {
+        // No member found.
+        return null;
+      }
+      Member member = target.member;
+      if (arguments != null &&
+          member is Procedure &&
+          member.kind == ProcedureKind.Method) {
+        // A method is called.
+        FunctionNode function = member.function;
+        if (arguments.positional.length >
+            function.positionalParameters.length) {
+          // The call is not going to match the Object member so we report
+          // a problem on the nullable access instead.
+          return null;
+        }
+        if (arguments.named.isNotEmpty && function.namedParameters.isEmpty) {
+          // The call is not going to match the Object member so we report
+          // a problem on the nullable access instead.
+          return null;
+        }
+      }
+      return target;
+    }
+    return null;
+  }
+
   /// True if [Object]'s member called [name] can be called with the arguments.
   ///
   /// Checks for the arity and the types of the arguments and tells if an
@@ -1890,6 +1938,10 @@
     Member equalsMember =
         findInterfaceMember(variable.type, equalsName, variable.fileOffset)
             .member;
+    // Ensure operator == member even for `Never`.
+    equalsMember ??= findInterfaceMember(const DynamicType(), equalsName, -1,
+            instrumented: false)
+        .member;
     return new NullAwareGuard(
         variable, variable.fileOffset, equalsMember, this);
   }
@@ -2686,7 +2738,7 @@
         isImplicitCall: isImplicitCall);
     assert(name != equalsName);
     return createNullAwareExpressionInferenceResult(
-        result.inferredType,
+        const NeverType(Nullability.nonNullable),
         result.applyResult(new MethodInvocation(receiver, name, arguments)
           ..fileOffset = fileOffset),
         nullAwareGuards);
@@ -3115,9 +3167,13 @@
       List<VariableDeclaration> hoistedExpressions}) {
     assert(isExpressionInvocation != null);
     assert(isImplicitCall != null);
-    ObjectAccessTarget target = findInterfaceMember(
-        receiverType, name, fileOffset,
-        instrumented: true, includeExtensionMethods: true);
+
+    ObjectAccessTarget objectReadTarget =
+        getObjectMemberIfNullableReceiver(receiverType, name, arguments);
+
+    ObjectAccessTarget target = objectReadTarget ??
+        findInterfaceMember(receiverType, name, fileOffset,
+            instrumented: true, includeExtensionMethods: true);
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
         Member member = target.member;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
index 94ac593..e05eba1 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
@@ -94,7 +94,7 @@
 
   @override
   String toStringInternal() {
-    return "";
+    return "<unknown-type>";
   }
 }
 
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 c0a489b..97af6cc 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
@@ -102,7 +102,9 @@
 
 class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
     with StandardBounds {
-  TypeSchemaEnvironment(CoreTypes coreTypes, ClassHierarchy hierarchy)
+  final ClassHierarchy hierarchy;
+
+  TypeSchemaEnvironment(CoreTypes coreTypes, this.hierarchy)
       : super(coreTypes, hierarchy);
 
   Class get functionClass => coreTypes.functionClass;
@@ -364,7 +366,7 @@
       unwrappedSupertype =
           (unwrappedSupertype as InterfaceType).typeArguments.single;
     }
-    if (subtype == coreTypes.nullType && unwrappedSupertype is UnknownType) {
+    if (unwrappedSupertype is UnknownType) {
       return const IsSubtypeOf.always();
     }
     return super.performNullabilityAwareSubtypeCheck(subtype, supertype);
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 09a048d..ff03fe7 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -462,6 +462,9 @@
 
   void visitNeverType(NeverType node) {
     sb.write('Never');
+    if (node.nullability != Nullability.nonNullable) {
+      sb.write(nullabilityToText(node.nullability, typeRepresentation));
+    }
   }
 
   void visitInterfaceType(InterfaceType node) {
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 7f5e3f8..5558bde 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -122,6 +122,8 @@
 ConstEvalNullValue/example: Fail
 ConstEvalStartingPoint/analyzerCode: Fail # This is just used for displaying the starting point.
 ConstEvalStartingPoint/example: Fail # This is just used for displaying the starting point.
+ConstEvalTruncateError/analyzerCode: Fail
+ConstEvalTruncateError/example: Fail
 ConstEvalUnevaluated/analyzerCode: Fail
 ConstEvalUnevaluated/example: Fail
 ConstEvalZeroDivisor/example: Fail
@@ -163,8 +165,6 @@
 DirectiveAfterDeclaration/part_wrapped_script2: Fail
 DirectiveAfterDeclaration/script1: Fail
 DirectiveAfterDeclaration/script2: Fail
-DuplicateDeferred/example: Fail
-DuplicatePrefix/example: Fail
 DuplicatedDeclarationUse/analyzerCode: Fail # No corresponding analyzer code.
 DuplicatedDeclarationUse/part_wrapped_script1: Fail
 DuplicatedDeclarationUse/part_wrapped_script2: Fail
@@ -172,6 +172,7 @@
 DuplicatedDeclarationUse/script2: Fail # Wrong error.
 DuplicatedDefinition/analyzerCode: Fail
 DuplicatedDefinition/example: Fail
+DuplicateDeferred/example: Fail
 DuplicatedExport/part_wrapped_script: Fail # Exporting file in the (now) part.
 DuplicatedExportInType/analyzerCode: Fail
 DuplicatedExportInType/example: Fail
@@ -183,6 +184,7 @@
 DuplicatedName/example: Fail
 DuplicatedNamedArgument/example: Fail
 DuplicatedParameterName/example: Fail
+DuplicatePrefix/example: Fail
 Encoding/analyzerCode: Fail
 EnumConstantSameNameAsEnclosing/example: Fail
 EnumInstantiation/example: Fail
@@ -254,6 +256,7 @@
 ExternalFactoryRedirection/example: Fail
 ExternalFactoryWithBody/part_wrapped_script1: Fail
 ExternalFactoryWithBody/script1: Fail
+ExtraneousModifier/part_wrapped_script1: Fail
 ExtraneousModifier/part_wrapped_script10: Fail
 ExtraneousModifier/part_wrapped_script11: Fail
 ExtraneousModifier/part_wrapped_script12: Fail
@@ -262,15 +265,15 @@
 ExtraneousModifier/part_wrapped_script17: Fail
 ExtraneousModifier/part_wrapped_script18: Fail
 ExtraneousModifier/part_wrapped_script19: Fail
-ExtraneousModifier/part_wrapped_script1: Fail
-ExtraneousModifier/part_wrapped_script20: Fail
 ExtraneousModifier/part_wrapped_script2: Fail
+ExtraneousModifier/part_wrapped_script20: Fail
 ExtraneousModifier/part_wrapped_script3: Fail
 ExtraneousModifier/part_wrapped_script4: Fail
 ExtraneousModifier/part_wrapped_script5: Fail
 ExtraneousModifier/part_wrapped_script7: Fail
 ExtraneousModifier/part_wrapped_script8: Fail
 ExtraneousModifier/part_wrapped_script9: Fail
+ExtraneousModifier/script1: Fail
 ExtraneousModifier/script10: Fail
 ExtraneousModifier/script11: Fail
 ExtraneousModifier/script12: Fail
@@ -279,9 +282,8 @@
 ExtraneousModifier/script17: Fail
 ExtraneousModifier/script18: Fail
 ExtraneousModifier/script19: Fail
-ExtraneousModifier/script1: Fail
-ExtraneousModifier/script20: Fail
 ExtraneousModifier/script2: Fail
+ExtraneousModifier/script20: Fail
 ExtraneousModifier/script3: Fail
 ExtraneousModifier/script4: Fail
 ExtraneousModifier/script5: Fail
@@ -377,10 +379,10 @@
 IncompatibleRedirecteeFunctionType/part_wrapped_script6: Fail
 IncompatibleRedirecteeFunctionType/script6: Fail # Triggers multiple errors.
 IncompatibleRedirecteeFunctionTypeWarning/example: Fail
+IncorrectTypeArgumentInferredWarning/example: Fail
 IncorrectTypeArgumentInReturnTypeWarning/example: Fail
 IncorrectTypeArgumentInSupertypeInferredWarning/example: Fail
 IncorrectTypeArgumentInSupertypeWarning/example: Fail
-IncorrectTypeArgumentInferredWarning/example: Fail
 IncorrectTypeArgumentQualifiedInferredWarning/example: Fail
 IncorrectTypeArgumentQualifiedWarning/example: Fail
 IncorrectTypeArgumentWarning/example: Fail
@@ -481,9 +483,6 @@
 NamedMixinOverride/example: Fail
 NativeClauseShouldBeAnnotation/example: Fail
 NoFormals/example: Fail
-NoSuchNamedParameter/example: Fail
-NoUnnamedConstructorInObject/analyzerCode: Fail
-NoUnnamedConstructorInObject/example: Fail
 NonAgnosticConstant/analyzerCode: Fail
 NonAgnosticConstant/example: Fail
 NonAsciiIdentifier/expression: Fail
@@ -491,7 +490,6 @@
 NonConstConstructor/example: Fail
 NonConstFactory/example: Fail
 NonInstanceTypeVariableUse/example: Fail
-NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
 NonNullableInNullAware/analyzerCode: Fail
 NonNullableInNullAware/example: Fail
 NonNullableLateDefinitelyAssignedError/analyzerCode: Fail
@@ -501,14 +499,17 @@
 NonNullableNotAssignedWarning/example: Fail
 NonNullableOptOut/analyzerCode: Fail
 NonNullableOptOut/example: Fail
+NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
 NonPartOfDirectiveInPart/part_wrapped_script1: Fail
 NonPartOfDirectiveInPart/script1: Fail
+NoSuchNamedParameter/example: Fail
 NotAConstantExpression/example: Fail
-NotAType/example: Fail
 NotAnLvalue/example: Fail
+NotAType/example: Fail
 NotBinaryOperator/analyzerCode: Fail
 NotConstantExpression/example: Fail
-NullAwareCascadeOutOfOrder/example: Fail
+NoUnnamedConstructorInObject/analyzerCode: Fail
+NoUnnamedConstructorInObject/example: Fail
 NullableExpressionCallError/analyzerCode: Fail
 NullableExpressionCallError/example: Fail
 NullableExpressionCallWarning/analyzerCode: Fail
@@ -541,6 +542,7 @@
 NullableTearoffError/example: Fail
 NullableTearoffWarning/analyzerCode: Fail
 NullableTearoffWarning/example: Fail
+NullAwareCascadeOutOfOrder/example: Fail
 OperatorMinusParameterMismatch/example: Fail
 OperatorParameterMismatch0/analyzerCode: Fail
 OperatorParameterMismatch0/example: Fail
@@ -630,13 +632,13 @@
 StackOverflow/example: Fail
 SuperAsExpression/example: Fail
 SuperAsIdentifier/example: Fail
-SuperNullAware/example: Fail
 SuperclassHasNoDefaultConstructor/example: Fail
 SuperclassHasNoGetter/example: Fail
 SuperclassHasNoMethod/example: Fail
 SuperclassHasNoSetter/example: Fail
 SuperclassMethodArgumentMismatch/analyzerCode: Fail
 SuperclassMethodArgumentMismatch/example: Fail
+SuperNullAware/example: Fail
 SupertypeIsFunction/analyzerCode: Fail
 SupertypeIsFunction/example: Fail
 SupertypeIsIllegal/example: Fail
@@ -660,14 +662,14 @@
 TypeArgumentMismatch/example: Fail
 TypeArgumentsOnTypeVariable/part_wrapped_script1: Fail
 TypeArgumentsOnTypeVariable/script1: Fail
-TypeNotFound/example: Fail
-TypeVariableDuplicatedName/example: Fail
-TypeVariableSameNameAsEnclosing/example: Fail
 TypedefNotFunction/example: Fail
 TypedefNotType/example: Fail # Feature not yet enabled by default.
 TypedefNullableType/analyzerCode: Fail
 TypedefTypeVariableNotConstructor/analyzerCode: Fail # Feature not yet enabled by default.
 TypedefTypeVariableNotConstructor/example: Fail # Feature not yet enabled by default.
+TypeNotFound/example: Fail
+TypeVariableDuplicatedName/example: Fail
+TypeVariableSameNameAsEnclosing/example: Fail
 UnexpectedToken/part_wrapped_script1: Fail
 UnexpectedToken/script1: Fail
 UnmatchedToken/part_wrapped_script1: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index a8a30c3..7b38839 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -129,6 +129,9 @@
 ConstEvalNegativeShift:
   template: "Binary operator '#string' on '#string2' requires non-negative operand, but was '#string3'."
 
+ConstEvalTruncateError:
+  template: "Binary operator '#string ~/ #string2' results is Infinity or NaN."
+
 ConstEvalInvalidMethodInvocation:
   template: "The method '#string' can't be invoked on '#constant' in a constant expression."
   analyzerCode: UNDEFINED_OPERATOR
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart
new file mode 100644
index 0000000..50f35ac
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_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.md file.
+
+class A<T> {}
+
+mixin M<T> {}
+
+class DND1 extends Object with M<dynamic> Function()> {
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.expect
new file mode 100644
index 0000000..d5d26ac
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.expect
@@ -0,0 +1,89 @@
+Problems reported:
+
+parser/error_recovery/issue_41265.crash:9:53: Unexpected token '>'.
+class DND1 extends Object with M<dynamic> Function()> {
+                                                    ^
+
+beginCompilationUnit(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(A, classOrMixinDeclaration)
+    beginTypeVariables(<)
+      beginMetadataStar(T)
+      endMetadataStar(0)
+      handleIdentifier(T, typeVariableDeclaration)
+      beginTypeVariable(T)
+        handleTypeVariablesDefined(T, 1)
+        handleNoType(T)
+      endTypeVariable(>, 0, null, null)
+    endTypeVariables(<, >)
+    beginClassDeclaration(class, null, A)
+      handleNoType(>)
+      handleClassExtends(null)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+      endClassOrMixinBody(DeclarationKind.Class, 0, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration(mixin)
+  beginMetadataStar(mixin)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(mixin)
+    handleIdentifier(M, classOrMixinDeclaration)
+    beginTypeVariables(<)
+      beginMetadataStar(T)
+      endMetadataStar(0)
+      handleIdentifier(T, typeVariableDeclaration)
+      beginTypeVariable(T)
+        handleTypeVariablesDefined(T, 1)
+        handleNoType(T)
+      endTypeVariable(>, 0, null, null)
+    endTypeVariables(<, >)
+    beginMixinDeclaration(mixin, M)
+      handleMixinOn(null, 0)
+      handleClassOrMixinImplements(null, 0)
+      handleMixinHeader(mixin)
+      beginClassOrMixinBody(DeclarationKind.Mixin, {)
+      endClassOrMixinBody(DeclarationKind.Mixin, 0, {, })
+    endMixinDeclaration(mixin, })
+  endTopLevelDeclaration(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(DND1, classOrMixinDeclaration)
+    handleNoTypeVariables(extends)
+    beginClassDeclaration(class, null, DND1)
+      handleIdentifier(Object, typeReference)
+      handleNoTypeArguments(with)
+      handleType(Object, null)
+      handleClassExtends(extends)
+      beginTypeList(M)
+        handleNoTypeVariables(()
+        beginFunctionType(M)
+          handleIdentifier(M, typeReference)
+          beginTypeArguments(<)
+            handleIdentifier(dynamic, typeReference)
+            handleNoTypeArguments(>)
+            handleType(dynamic, null)
+          endTypeArguments(1, <, >)
+          handleType(M, null)
+          beginFormalParameters((, MemberKind.GeneralizedFunctionType)
+          endFormalParameters(0, (, ), MemberKind.GeneralizedFunctionType)
+        endFunctionType(Function, null)
+      endTypeList(1)
+      handleClassWithClause(with)
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      handleRecoverableError(Message[UnexpectedToken, Unexpected token '>'., null, {token: >}], >, >)
+      handleNoType(>)
+      handleClassExtends(null)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleRecoverClassHeader()
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+      endClassOrMixinBody(DeclarationKind.Class, 0, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+endCompilationUnit(3, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.intertwined.expect
new file mode 100644
index 0000000..52766bc
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.intertwined.expect
@@ -0,0 +1,143 @@
+parseUnit(class)
+  skipErrorTokens(class)
+  listener: beginCompilationUnit(class)
+  syntheticPreviousToken(class)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(, class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(A, classOrMixinDeclaration)
+        listener: beginTypeVariables(<)
+        listener: beginMetadataStar(T)
+        listener: endMetadataStar(0)
+        listener: handleIdentifier(T, typeVariableDeclaration)
+        listener: beginTypeVariable(T)
+        listener: handleTypeVariablesDefined(T, 1)
+        listener: handleNoType(T)
+        listener: endTypeVariable(>, 0, null, null)
+        listener: endTypeVariables(<, >)
+        listener: beginClassDeclaration(class, null, A)
+        parseClass(>, class, class, A)
+          parseClassHeaderOpt(>, class, class)
+            parseClassExtendsOpt(>)
+              listener: handleNoType(>)
+              listener: handleClassExtends(null)
+            parseWithClauseOpt(>)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(>)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(>, DeclarationKind.Class, A)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 0, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration(mixin)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(mixin)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(}, mixin, Instance of 'DirectiveContext')
+      parseTopLevelKeywordModifiers(}, mixin)
+      parseMixin(mixin)
+        listener: beginClassOrNamedMixinApplicationPrelude(mixin)
+        ensureIdentifier(mixin, classOrMixinDeclaration)
+          listener: handleIdentifier(M, classOrMixinDeclaration)
+        listener: beginTypeVariables(<)
+        listener: beginMetadataStar(T)
+        listener: endMetadataStar(0)
+        listener: handleIdentifier(T, typeVariableDeclaration)
+        listener: beginTypeVariable(T)
+        listener: handleTypeVariablesDefined(T, 1)
+        listener: handleNoType(T)
+        listener: endTypeVariable(>, 0, null, null)
+        listener: endTypeVariables(<, >)
+        listener: beginMixinDeclaration(mixin, M)
+        parseMixinHeaderOpt(>, mixin)
+          parseMixinOnOpt(>)
+            listener: handleMixinOn(null, 0)
+          parseClassOrMixinImplementsOpt(>)
+            listener: handleClassOrMixinImplements(null, 0)
+          listener: handleMixinHeader(mixin)
+        parseClassOrMixinOrExtensionBody(>, DeclarationKind.Mixin, M)
+          listener: beginClassOrMixinBody(DeclarationKind.Mixin, {)
+          notEofOrValue(}, })
+          listener: endClassOrMixinBody(DeclarationKind.Mixin, 0, {, })
+        listener: endMixinDeclaration(mixin, })
+  listener: endTopLevelDeclaration(class)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(}, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(}, class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(DND1, classOrMixinDeclaration)
+        listener: handleNoTypeVariables(extends)
+        listener: beginClassDeclaration(class, null, DND1)
+        parseClass(DND1, class, class, DND1)
+          parseClassHeaderOpt(DND1, class, class)
+            parseClassExtendsOpt(DND1)
+              listener: handleIdentifier(Object, typeReference)
+              listener: handleNoTypeArguments(with)
+              listener: handleType(Object, null)
+              listener: handleClassExtends(extends)
+            parseWithClauseOpt(Object)
+              parseTypeList(with)
+                listener: beginTypeList(M)
+                listener: handleNoTypeVariables(()
+                listener: beginFunctionType(M)
+                ensureIdentifier(with, typeReference)
+                  listener: handleIdentifier(M, typeReference)
+                listener: beginTypeArguments(<)
+                listener: handleIdentifier(dynamic, typeReference)
+                listener: handleNoTypeArguments(>)
+                listener: handleType(dynamic, null)
+                listener: endTypeArguments(1, <, >)
+                listener: handleType(M, null)
+                parseFormalParametersRequiredOpt(Function, MemberKind.GeneralizedFunctionType)
+                  parseFormalParametersRest((, MemberKind.GeneralizedFunctionType)
+                    listener: beginFormalParameters((, MemberKind.GeneralizedFunctionType)
+                    listener: endFormalParameters(0, (, ), MemberKind.GeneralizedFunctionType)
+                listener: endFunctionType(Function, null)
+                listener: endTypeList(1)
+              listener: handleClassWithClause(with)
+            parseClassOrMixinImplementsOpt())
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassHeaderRecovery(DND1, class, class)
+            parseClassHeaderOpt(DND1, class, class)
+              parseClassExtendsOpt(DND1)
+              parseWithClauseOpt(Object)
+                parseTypeList(with)
+                  ensureIdentifier(with, typeReference)
+                  parseFormalParametersRequiredOpt(Function, MemberKind.GeneralizedFunctionType)
+                    parseFormalParametersRest((, MemberKind.GeneralizedFunctionType)
+              parseClassOrMixinImplementsOpt())
+            skipUnexpectedTokenOpt(), [extends, with, implements, {])
+              reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
+                listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token '>'., null, {token: >}], >, >)
+            parseClassExtendsOpt(>)
+              listener: handleNoType(>)
+              listener: handleClassExtends(null)
+            parseWithClauseOpt(>)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(>)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleRecoverClassHeader()
+          ensureBlock(>, null, class declaration)
+          parseClassOrMixinOrExtensionBody(>, DeclarationKind.Class, DND1)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 0, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(class)
+  listener: endCompilationUnit(3, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.parser.expect
new file mode 100644
index 0000000..0f00c7a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.parser.expect
@@ -0,0 +1,15 @@
+class A<T> {}
+
+mixin M<T> {}
+
+class DND1 extends Object with M<dynamic> Function()> {
+}
+
+
+class[KeywordToken] A[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]}[SimpleToken]
+
+mixin[KeywordToken] M[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] DND1[StringToken] extends[KeywordToken] Object[StringToken] with[KeywordToken] M[StringToken]<[BeginToken]dynamic[KeywordToken]>[SimpleToken] Function[KeywordToken]([BeginToken])[SimpleToken]>[SimpleToken] {[BeginToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.scanner.expect
new file mode 100644
index 0000000..0f00c7a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.scanner.expect
@@ -0,0 +1,15 @@
+class A<T> {}
+
+mixin M<T> {}
+
+class DND1 extends Object with M<dynamic> Function()> {
+}
+
+
+class[KeywordToken] A[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]}[SimpleToken]
+
+mixin[KeywordToken] M[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] DND1[StringToken] extends[KeywordToken] Object[StringToken] with[KeywordToken] M[StringToken]<[BeginToken]dynamic[KeywordToken]>[SimpleToken] Function[KeywordToken]([BeginToken])[SimpleToken]>[SimpleToken] {[BeginToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.expect
index 21feac2..3392c1f 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.expect
@@ -24,9 +24,11 @@
       handleNoArguments(])
       handleSend(logKey, ])
       handleIndexedExpression(null, [, ])
-      handleIdentifier(Logger, typeReference)
-      handleNoTypeArguments(?)
-      handleType(Logger, ?)
+      beginAsOperatorType(as)
+        handleIdentifier(Logger, typeReference)
+        handleNoTypeArguments(?)
+        handleType(Logger, ?)
+      endAsOperatorType(as)
       handleAsOperator(as)
       beginBinaryExpression(??)
       handleIdentifier(_default, expression)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.intertwined.expect
index 938f7a6..6193bf7 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39697.dart.intertwined.expect
@@ -61,10 +61,12 @@
                               listener: handleSend(logKey, ])
                   listener: handleIndexedExpression(null, [, ])
                 parseAsOperatorRest(])
+                  listener: beginAsOperatorType(as)
                   computeTypeAfterIsOrAs(as)
                   listener: handleIdentifier(Logger, typeReference)
                   listener: handleNoTypeArguments(?)
                   listener: handleType(Logger, ?)
+                  listener: endAsOperatorType(as)
                   listener: handleAsOperator(as)
                   skipChainedAsIsOperators(?)
                 listener: beginBinaryExpression(??)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.expect
index 428d1b6..0656ee2 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.expect
@@ -24,9 +24,11 @@
       handleNoArguments(])
       handleSend(logKey, ])
       handleIndexedExpression(null, [, ])
-      handleIdentifier(Logger, typeReference)
-      handleNoTypeArguments(?)
-      handleType(Logger, ?)
+      beginAsOperatorType(as)
+        handleIdentifier(Logger, typeReference)
+        handleNoTypeArguments(?)
+        handleType(Logger, ?)
+      endAsOperatorType(as)
       handleAsOperator(as)
       handleParenthesizedExpression(()
       beginBinaryExpression(??)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.intertwined.expect
index 8e1f84f..08ff17d 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39697_prime.dart.intertwined.expect
@@ -69,10 +69,12 @@
                                               listener: handleSend(logKey, ])
                                   listener: handleIndexedExpression(null, [, ])
                                 parseAsOperatorRest(])
+                                  listener: beginAsOperatorType(as)
                                   computeTypeAfterIsOrAs(as)
                                   listener: handleIdentifier(Logger, typeReference)
                                   listener: handleNoTypeArguments(?)
                                   listener: handleType(Logger, ?)
+                                  listener: endAsOperatorType(as)
                                   listener: handleAsOperator(as)
                                   skipChainedAsIsOperators(?)
                             ensureCloseParen(?, ()
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.expect
index 04ba926..ba78b91 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.expect
@@ -59,9 +59,11 @@
             handleNoTypeArguments(as)
             handleNoArguments(as)
             handleSend(o, as)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(?)
-            handleType(String, ?)
+            beginAsOperatorType(as)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(?)
+              handleType(String, ?)
+            endAsOperatorType(as)
             handleAsOperator(as)
             handleAssignmentExpression(=)
           endInitializer(,)
@@ -108,9 +110,11 @@
             handleNoTypeArguments(is)
             handleNoArguments(is)
             handleSend(o, is)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(?)
-            handleType(String, null)
+            beginIsOperatorType(is)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(?)
+              handleType(String, null)
+            endIsOperatorType(is)
             handleIsOperator(is, null)
             beginConditionalExpression(?)
               handleIdentifier(o, expression)
@@ -170,9 +174,11 @@
             handleNoTypeArguments(is)
             handleNoArguments(is)
             handleSend(o, is)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(?)
-            handleType(String, ?)
+            beginIsOperatorType(is)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(?)
+              handleType(String, ?)
+            endIsOperatorType(is)
             handleIsOperator(is, null)
             beginConditionalExpression(?)
               handleIdentifier(o, expression)
@@ -232,9 +238,11 @@
             handleNoTypeArguments(as)
             handleNoArguments(as)
             handleSend(o, as)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(?)
-            handleType(String, null)
+            beginAsOperatorType(as)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(?)
+              handleType(String, null)
+            endAsOperatorType(as)
             handleAsOperator(as)
             beginConditionalExpression(?)
               handleIdentifier(o, expression)
@@ -294,9 +302,11 @@
             handleNoTypeArguments(as)
             handleNoArguments(as)
             handleSend(o, as)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(?)
-            handleType(String, ?)
+            beginAsOperatorType(as)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(?)
+              handleType(String, ?)
+            endAsOperatorType(as)
             handleAsOperator(as)
             beginConditionalExpression(?)
               handleIdentifier(o, expression)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.intertwined.expect
index 12268f2..e271d8f 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40834_01.dart.intertwined.expect
@@ -119,10 +119,12 @@
                                         listener: handleNoArguments(as)
                                       listener: handleSend(o, as)
                               parseAsOperatorRest(o)
+                                listener: beginAsOperatorType(as)
                                 computeTypeAfterIsOrAs(as)
                                 listener: handleIdentifier(String, typeReference)
                                 listener: handleNoTypeArguments(?)
                                 listener: handleType(String, ?)
+                                listener: endAsOperatorType(as)
                                 listener: handleAsOperator(as)
                                 skipChainedAsIsOperators(?)
                             listener: handleAssignmentExpression(=)
@@ -223,10 +225,12 @@
                                         listener: handleNoArguments(is)
                                       listener: handleSend(o, is)
                               parseIsOperatorRest(o)
+                                listener: beginIsOperatorType(is)
                                 computeTypeAfterIsOrAs(is)
                                 listener: handleIdentifier(String, typeReference)
                                 listener: handleNoTypeArguments(?)
                                 listener: handleType(String, null)
+                                listener: endIsOperatorType(is)
                                 listener: handleIsOperator(is, null)
                                 skipChainedAsIsOperators(String)
                               parseConditionalExpressionRest(String)
@@ -360,10 +364,12 @@
                                         listener: handleNoArguments(is)
                                       listener: handleSend(o, is)
                               parseIsOperatorRest(o)
+                                listener: beginIsOperatorType(is)
                                 computeTypeAfterIsOrAs(is)
                                 listener: handleIdentifier(String, typeReference)
                                 listener: handleNoTypeArguments(?)
                                 listener: handleType(String, ?)
+                                listener: endIsOperatorType(is)
                                 listener: handleIsOperator(is, null)
                                 skipChainedAsIsOperators(?)
                               parseConditionalExpressionRest(?)
@@ -497,10 +503,12 @@
                                         listener: handleNoArguments(as)
                                       listener: handleSend(o, as)
                               parseAsOperatorRest(o)
+                                listener: beginAsOperatorType(as)
                                 computeTypeAfterIsOrAs(as)
                                 listener: handleIdentifier(String, typeReference)
                                 listener: handleNoTypeArguments(?)
                                 listener: handleType(String, null)
+                                listener: endAsOperatorType(as)
                                 listener: handleAsOperator(as)
                                 skipChainedAsIsOperators(String)
                               parseConditionalExpressionRest(String)
@@ -634,10 +642,12 @@
                                         listener: handleNoArguments(as)
                                       listener: handleSend(o, as)
                               parseAsOperatorRest(o)
+                                listener: beginAsOperatorType(as)
                                 computeTypeAfterIsOrAs(as)
                                 listener: handleIdentifier(String, typeReference)
                                 listener: handleNoTypeArguments(?)
                                 listener: handleType(String, ?)
+                                listener: endAsOperatorType(as)
                                 listener: handleAsOperator(as)
                                 skipChainedAsIsOperators(?)
                               parseConditionalExpressionRest(?)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.expect
index 6872f75..188a65b 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.expect
@@ -59,9 +59,11 @@
             handleNoTypeArguments(as)
             handleNoArguments(as)
             handleSend(o, as)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(,)
-            handleType(String, null)
+            beginAsOperatorType(as)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(,)
+              handleType(String, null)
+            endAsOperatorType(as)
             handleAsOperator(as)
             handleAssignmentExpression(=)
           endInitializer(,)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.intertwined.expect
index a584066..edd176f 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40834_02.dart.intertwined.expect
@@ -119,10 +119,12 @@
                                         listener: handleNoArguments(as)
                                       listener: handleSend(o, as)
                               parseAsOperatorRest(o)
+                                listener: beginAsOperatorType(as)
                                 computeTypeAfterIsOrAs(as)
                                 listener: handleIdentifier(String, typeReference)
                                 listener: handleNoTypeArguments(,)
                                 listener: handleType(String, null)
+                                listener: endAsOperatorType(as)
                                 listener: handleAsOperator(as)
                                 skipChainedAsIsOperators(String)
                             listener: handleAssignmentExpression(=)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.expect
index 8571be3..d54c20a 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.expect
@@ -67,9 +67,11 @@
               handleNoTypeArguments(as)
               handleNoArguments(as)
               handleSend(o, as)
-              handleIdentifier(String, typeReference)
-              handleNoTypeArguments(?)
-              handleType(String, ?)
+              beginAsOperatorType(as)
+                handleIdentifier(String, typeReference)
+                handleNoTypeArguments(?)
+                handleType(String, ?)
+              endAsOperatorType(as)
               handleAsOperator(as)
               handleConditionalExpressionColon()
               handleLiteralNull(null)
@@ -115,9 +117,11 @@
             handleNoTypeArguments(is)
             handleNoArguments(is)
             handleSend(x, is)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(?)
-            handleType(String, ?)
+            beginIsOperatorType(is)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(?)
+              handleType(String, ?)
+            endIsOperatorType(is)
             handleIsOperator(is, null)
             beginConditionalExpression(?)
               handleLiteralInt(4)
@@ -170,9 +174,11 @@
             handleNoTypeArguments(is)
             handleNoArguments(is)
             handleSend(x, is)
-            handleIdentifier(String, typeReference)
-            handleNoTypeArguments(?)
-            handleType(String, null)
+            beginIsOperatorType(is)
+              handleIdentifier(String, typeReference)
+              handleNoTypeArguments(?)
+              handleType(String, null)
+            endIsOperatorType(is)
             handleIsOperator(is, null)
             beginConditionalExpression(?)
               handleLiteralInt(4)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.intertwined.expect
index 883e69d..af51107 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40834_03.dart.intertwined.expect
@@ -140,10 +140,12 @@
                                               listener: handleNoArguments(as)
                                             listener: handleSend(o, as)
                                     parseAsOperatorRest(o)
+                                      listener: beginAsOperatorType(as)
                                       computeTypeAfterIsOrAs(as)
                                       listener: handleIdentifier(String, typeReference)
                                       listener: handleNoTypeArguments(?)
                                       listener: handleType(String, ?)
+                                      listener: endAsOperatorType(as)
                                       listener: handleAsOperator(as)
                                       skipChainedAsIsOperators(?)
                                 ensureColon(?)
@@ -247,10 +249,12 @@
                                           listener: handleNoArguments(is)
                                         listener: handleSend(x, is)
                                 parseIsOperatorRest(x)
+                                  listener: beginIsOperatorType(is)
                                   computeTypeAfterIsOrAs(is)
                                   listener: handleIdentifier(String, typeReference)
                                   listener: handleNoTypeArguments(?)
                                   listener: handleType(String, ?)
+                                  listener: endIsOperatorType(is)
                                   listener: handleIsOperator(is, null)
                                   skipChainedAsIsOperators(?)
                                 parseConditionalExpressionRest(?)
@@ -384,10 +388,12 @@
                                           listener: handleNoArguments(is)
                                         listener: handleSend(x, is)
                                 parseIsOperatorRest(x)
+                                  listener: beginIsOperatorType(is)
                                   computeTypeAfterIsOrAs(is)
                                   listener: handleIdentifier(String, typeReference)
                                   listener: handleNoTypeArguments(?)
                                   listener: handleType(String, null)
+                                  listener: endIsOperatorType(is)
                                   listener: handleIsOperator(is, null)
                                   skipChainedAsIsOperators(String)
                                 parseConditionalExpressionRest(String)
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index cc63ae0..dd1b0c5 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -8,7 +8,7 @@
 environment:
   sdk: '>=2.2.2 <3.0.0'
 dependencies:
-  _fe_analyzer_shared: 1.0.0
+  _fe_analyzer_shared: ^2.0.0
   kernel: 0.3.29
   package_config:
     path: ../../third_party/pkg_tested/package_config/
diff --git a/pkg/front_end/test/analyser_ignored/load_dill_twice_test.dart b/pkg/front_end/test/analyser_ignored/load_dill_twice_test.dart
index bda78e9..ba07019 100644
--- a/pkg/front_end/test/analyser_ignored/load_dill_twice_test.dart
+++ b/pkg/front_end/test/analyser_ignored/load_dill_twice_test.dart
@@ -18,6 +18,10 @@
 
   Component c = new Component();
   new BinaryBuilder(bytes).readComponent(c);
+  // Print once to lazy-load whatever it needs to lazy-load to print.
+  // This *might* change the textual representation because references can be
+  // created.
+  componentToString(c);
   String loadedOnceString = componentToString(c);
   new BinaryBuilder(bytes).readComponent(c);
   String loadedTwiceString = componentToString(c);
@@ -76,4 +80,5 @@
 
     exit(1);
   }
+  print("OK");
 }
diff --git a/pkg/front_end/test/binary_md_dill_reader.dart b/pkg/front_end/test/binary_md_dill_reader.dart
index ab2c574..01cf4d9 100644
--- a/pkg/front_end/test/binary_md_dill_reader.dart
+++ b/pkg/front_end/test/binary_md_dill_reader.dart
@@ -117,7 +117,7 @@
 
     // Skip to the start of the index.
     _binaryOffset = _dillContent.length -
-        ((numLibs + 1) + 9 /* number of fixed fields */) * 4;
+        ((numLibs + 1) + 10 /* number of fixed fields */) * 4;
 
     // Read index.
     binaryOffsetForSourceTable = _peekUint32();
@@ -133,6 +133,8 @@
     binaryOffsetForConstantTable = _peekUint32();
     _binaryOffset += 4;
     mainMethodReference = _peekUint32();
+    _binaryOffset += 4;
+    /*int compilationMode = */ _peekUint32();
 
     _binaryOffset = binaryOffsetForStringTable;
     var saved = _readingInstructions["ComponentFile"];
@@ -439,7 +441,7 @@
           instruction == "Byte[] 8bitAlignment;") {
         // Special-case 8-byte alignment.
         int sizeWithoutPadding = _binaryOffset +
-            ((numLibs + 1) + 9 /* number of fixed fields */) * 4;
+            ((numLibs + 1) + 10 /* number of fixed fields */) * 4;
         int padding = 8 - sizeWithoutPadding % 8;
         if (padding == 8) padding = 0;
         _binaryOffset += padding;
diff --git a/pkg/front_end/test/compile_dart2js_with_no_sdk_test.dart b/pkg/front_end/test/compile_dart2js_with_no_sdk_test.dart
new file mode 100644
index 0000000..4939c11
--- /dev/null
+++ b/pkg/front_end/test/compile_dart2js_with_no_sdk_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:front_end/src/api_prototype/compiler_options.dart';
+
+import 'incremental_load_from_dill_suite.dart'
+    show TestIncrementalCompiler, getOptions;
+
+main() async {
+  final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
+  CompilerOptions options = getOptions();
+  options.sdkSummary = options.sdkSummary.resolve("nonexisting.dill");
+  options.librariesSpecificationUri = null;
+  int diagnosticCount = 0;
+  options.onDiagnostic = (DiagnosticMessage message) {
+    // ignoring
+    diagnosticCount++;
+  };
+  TestIncrementalCompiler compiler =
+      new TestIncrementalCompiler(options, dart2jsUrl);
+  await compiler.computeDelta();
+  print("Got a total of $diagnosticCount diagnostics.");
+  if (diagnosticCount < 10000) {
+    // We currently get 43.000+.
+    throw "Less diagnostics than expected.";
+  }
+}
diff --git a/pkg/front_end/test/explicit_creation_test.dart b/pkg/front_end/test/explicit_creation_test.dart
index c6d3fca..fd6ded1 100644
--- a/pkg/front_end/test/explicit_creation_test.dart
+++ b/pkg/front_end/test/explicit_creation_test.dart
@@ -224,7 +224,8 @@
       String name,
       List<UnresolvedType> typeArguments,
       int charOffset,
-      Constness constness) {
+      Constness constness,
+      {bool isTypeArgumentsInForest = false}) {
     Token maybeNewOrConst = nameToken.previous;
     bool doReport = true;
     if (maybeNewOrConst is KeywordToken) {
@@ -247,7 +248,8 @@
           nameToken.length);
     }
     return super.buildConstructorInvocation(type, nameToken, nameLastToken,
-        arguments, name, typeArguments, charOffset, constness);
+        arguments, name, typeArguments, charOffset, constness,
+        isTypeArgumentsInForest: isTypeArgumentsInForest);
   }
 }
 
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 6158ba6..356924f 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -170,7 +170,7 @@
     check("IncompleteErrorGenerator(offset: 4, message: Unspecified)",
         new IncompleteErrorGenerator(helper, token, message));
     check("SendAccessGenerator(offset: 4, name: bar, arguments: (\"arg\"))",
-        new SendAccessGenerator(helper, token, name, arguments));
+        new SendAccessGenerator(helper, token, name, null, arguments));
     check("IncompletePropertyAccessGenerator(offset: 4, name: bar)",
         new IncompletePropertyAccessGenerator(helper, token, name));
     check(
diff --git a/pkg/front_end/test/fasta/object_supertype_test.dart b/pkg/front_end/test/fasta/object_supertype_test.dart
index 3d13824..1f37142 100644
--- a/pkg/front_end/test/fasta/object_supertype_test.dart
+++ b/pkg/front_end/test/fasta/object_supertype_test.dart
@@ -51,7 +51,9 @@
       }));
 
   fs.entityForUri(base.resolve("sdk/lib/core/core.dart")).writeAsStringSync(
-      defaultDartCoreSource.replaceAll("class Object {", "$objectHeader"));
+      defaultDartCoreSource
+          .replaceAll("class Object {", "$objectHeader")
+          .replaceAll("const Object();", ""));
 
   final List<DiagnosticMessage> messages = <DiagnosticMessage>[];
 
diff --git a/pkg/front_end/test/fasta/parser/parser.status b/pkg/front_end/test/fasta/parser/parser.status
index 94d326c3..741a8c4 100644
--- a/pkg/front_end/test/fasta/parser/parser.status
+++ b/pkg/front_end/test/fasta/parser/parser.status
@@ -2,7 +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.md file.
 
+issue23520: Fail
+issue28367: Fail
 pkg/analyzer_cli/test/data/file_with_error: Fail
+pkg/front_end/test/fasta/function_type_recovery: Fail
 pkg/front_end/test/fasta/rasta/bad_interpolation: Fail
 pkg/front_end/test/fasta/rasta/issue_000032: Fail
 pkg/front_end/test/fasta/rasta/issue_000035: Fail
@@ -47,15 +50,15 @@
 runtime/lib/core_patch: Fail
 runtime/lib/date_patch: Fail
 runtime/lib/developer: Fail
-runtime/lib/double: Fail
 runtime/lib/double_patch: Fail
+runtime/lib/double: Fail
 runtime/lib/errors_patch: Fail
-runtime/lib/function: Fail
 runtime/lib/function_patch: Fail
+runtime/lib/function: Fail
 runtime/lib/growable_array: Fail
 runtime/lib/identical_patch: Fail
-runtime/lib/integers: Fail
 runtime/lib/integers_patch: Fail
+runtime/lib/integers: Fail
 runtime/lib/internal_patch: Fail
 runtime/lib/isolate_patch: Fail
 runtime/lib/lib_prefix: Fail
@@ -71,8 +74,8 @@
 runtime/lib/string_patch: Fail
 runtime/lib/timeline: Fail
 runtime/lib/type_patch: Fail
-runtime/lib/typed_data: Fail
 runtime/lib/typed_data_patch: Fail
+runtime/lib/typed_data: Fail
 runtime/lib/uri_patch: Fail
 runtime/lib/vmservice_patch: Fail
 runtime/lib/weak_property: Fail
@@ -117,40 +120,6 @@
 tests/co19/src/Language/Classes/Constructors/Generative_Constructors/initializers_t16: Fail
 tests/co19/src/Language/Classes/Constructors/Generative_Constructors/syntax_t03: Fail
 tests/co19/src/Language/Classes/Constructors/Generative_Constructors/syntax_t06: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t02: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t03: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t04: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t05: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t06: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t07: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t08: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t09: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t10: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t11: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t12: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t13: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t14: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t15: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t16: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t17: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t18: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t19: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t20: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t21: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t22: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/optional_parameter_t05: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/optional_parameter_t07: Fail
-tests/co19/src/Language/Classes/Instance_Methods/Operators/syntax_t02: Fail
-tests/co19/src/Language/Classes/Setters/name_t08: Fail
-tests/co19/src/Language/Classes/Setters/name_t09: Fail
-tests/co19/src/Language/Classes/Setters/name_t10: Fail
-tests/co19/src/Language/Classes/Setters/name_t11: Fail
-tests/co19/src/Language/Classes/Setters/name_t12: Fail
-tests/co19/src/Language/Classes/Setters/name_t13: Fail
-tests/co19/src/Language/Classes/Setters/name_t14: Fail
-tests/co19/src/Language/Classes/Setters/name_t15: Fail
-tests/co19/src/Language/Classes/Superclasses/wrong_superclass_t06: Fail
-tests/co19/src/Language/Classes/Superinterfaces/syntax_t02: Fail
 tests/co19/src/Language/Classes/declarations_t12: Fail
 tests/co19/src/Language/Classes/declarations_t13: Fail
 tests/co19/src/Language/Classes/declarations_t14: Fail
@@ -192,6 +161,30 @@
 tests/co19/src/Language/Classes/definition_t19: Fail
 tests/co19/src/Language/Classes/definition_t21: Fail
 tests/co19/src/Language/Classes/definition_t22: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t02: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t03: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t04: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t05: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t06: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t07: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t08: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t09: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t10: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t11: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t12: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t13: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t14: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t15: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t16: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t17: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t18: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t19: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t20: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t21: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/allowed_names_t22: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/optional_parameter_t05: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/optional_parameter_t07: Fail
+tests/co19/src/Language/Classes/Instance_Methods/Operators/syntax_t02: Fail
 tests/co19/src/Language/Classes/member_definition_t01: Fail
 tests/co19/src/Language/Classes/member_definition_t02: Fail
 tests/co19/src/Language/Classes/member_definition_t04: Fail
@@ -218,14 +211,24 @@
 tests/co19/src/Language/Classes/method_definition_t08: Fail
 tests/co19/src/Language/Classes/method_definition_t09: Fail
 tests/co19/src/Language/Classes/mixins_t02: Fail
+tests/co19/src/Language/Classes/Setters/name_t08: Fail
+tests/co19/src/Language/Classes/Setters/name_t09: Fail
+tests/co19/src/Language/Classes/Setters/name_t10: Fail
+tests/co19/src/Language/Classes/Setters/name_t11: Fail
+tests/co19/src/Language/Classes/Setters/name_t12: Fail
+tests/co19/src/Language/Classes/Setters/name_t13: Fail
+tests/co19/src/Language/Classes/Setters/name_t14: Fail
+tests/co19/src/Language/Classes/Setters/name_t15: Fail
+tests/co19/src/Language/Classes/Superclasses/wrong_superclass_t06: Fail
+tests/co19/src/Language/Classes/Superinterfaces/syntax_t02: Fail
 tests/co19/src/Language/Enums/syntax_t04: Fail
 tests/co19/src/Language/Enums/syntax_t05: Fail
 tests/co19/src/Language/Enums/syntax_t06: Fail
 tests/co19/src/Language/Enums/syntax_t07: Fail
 tests/co19/src/Language/Enums/syntax_t08: Fail
 tests/co19/src/Language/Enums/syntax_t09: Fail
-tests/co19/src/Language/Errors_and_Warnings/compile_error_lib: Fail
 tests/co19/src/Language/Errors_and_Warnings/compile_error_lib_p2: Fail
+tests/co19/src/Language/Errors_and_Warnings/compile_error_lib: Fail
 tests/co19/src/Language/Errors_and_Warnings/compile_error_t01: Fail
 tests/co19/src/Language/Errors_and_Warnings/compile_error_t02: Fail
 tests/co19/src/Language/Errors_and_Warnings/compile_error_t03: Fail
@@ -667,15 +670,6 @@
 tests/co19/src/Language/Expressions/Shift/syntax_t05: Fail
 tests/co19/src/Language/Expressions/Shift/syntax_t06: Fail
 tests/co19/src/Language/Expressions/Shift/syntax_t07: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t02: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t03: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t08: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t09: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t10: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t11: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t14: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t15: Fail
-tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t16: Fail
 tests/co19/src/Language/Expressions/Strings/multi_line_t02: Fail
 tests/co19/src/Language/Expressions/Strings/multi_line_t03: Fail
 tests/co19/src/Language/Expressions/Strings/multi_line_t04: Fail
@@ -714,6 +708,15 @@
 tests/co19/src/Language/Expressions/Strings/multi_line_t40: Fail
 tests/co19/src/Language/Expressions/Strings/multi_line_t42: Fail
 tests/co19/src/Language/Expressions/Strings/multi_line_t44: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t02: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t03: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t08: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t09: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t10: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t11: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t14: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t15: Fail
+tests/co19/src/Language/Expressions/Strings/String_Interpolation/syntax_t16: Fail
 tests/co19/src/Language/Expressions/Strings/string_literal_t02: Fail
 tests/co19/src/Language/Expressions/Strings/string_literal_t03: Fail
 tests/co19/src/Language/Expressions/Strings/string_literal_t04: Fail
@@ -818,6 +821,21 @@
 tests/co19/src/Language/Generics/syntax_t15: Fail
 tests/co19/src/Language/Generics/syntax_t17: Fail
 tests/co19/src/Language/Interfaces/Superinterfaces/definition_t05: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t15_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t16_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t17_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t18_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t19_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t20_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t21_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t22_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t23_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t24_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t25_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t26_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t27_lib: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t28: Fail
+tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t29_lib: Fail
 tests/co19/src/Language/Libraries_and_Scripts/Exports/syntax_t01_lib: Fail
 tests/co19/src/Language/Libraries_and_Scripts/Exports/syntax_t04_lib: Fail
 tests/co19/src/Language/Libraries_and_Scripts/Exports/syntax_t05_lib: Fail
@@ -892,21 +910,6 @@
 tests/co19/src/Language/Libraries_and_Scripts/Scripts/top_level_syntax_t16: Fail
 tests/co19/src/Language/Libraries_and_Scripts/Scripts/top_level_syntax_t17: Fail
 tests/co19/src/Language/Libraries_and_Scripts/Scripts/top_level_syntax_t18: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t15_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t16_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t17_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t18_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t19_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t20_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t21_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t22_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t23_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t24_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t25_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t26_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t27_lib: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t28: Fail
-tests/co19/src/Language/Libraries_and_Scripts/definition_syntax_t29_lib: Fail
 tests/co19/src/Language/Libraries_and_Scripts/top_level_syntax_t02_lib: Fail
 tests/co19/src/Language/Libraries_and_Scripts/top_level_syntax_t03_lib: Fail
 tests/co19/src/Language/Libraries_and_Scripts/top_level_syntax_t04_lib: Fail
@@ -1466,6 +1469,10 @@
 tests/co19/src/Language/Statements/While/syntax_t02: Fail
 tests/co19/src/Language/Statements/While/syntax_t03: Fail
 tests/co19/src/Language/Statements/While/syntax_t04: Fail
+tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t07: Fail
+tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t08: Fail
+tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t09: Fail
+tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t10: Fail
 tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield/location_t01: Fail
 tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield/location_t03: Fail
 tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield/location_t05: Fail
@@ -1473,10 +1480,6 @@
 tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield/syntax_t08: Fail
 tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield/syntax_t09: Fail
 tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield/syntax_t10: Fail
-tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t07: Fail
-tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t08: Fail
-tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t09: Fail
-tests/co19/src/Language/Statements/Yield_and_Yield_Each/Yield_Each/syntax_t10: Fail
 tests/co19/src/Language/Types/Static_Types/syntax_t01: Fail
 tests/co19/src/Language/Types/Static_Types/syntax_t02: Fail
 tests/co19/src/Language/Types/Static_Types/syntax_t03: Fail
@@ -1533,16 +1536,15 @@
 tests/co19/src/Language/Variables/syntax_t22: Fail
 tests/co19/src/Language/Variables/syntax_t23: Fail
 tests/co19/src/LibTest/html/HttpRequest/responseType_A01_t03: Fail
-tests/co19/src/WebPlatformTest/dom/nodes/DOMImplementation-createHTMLDocument_t01: Fail
 tests/co19/src/WebPlatformTest/dom/nodes/Document-createElement_t01: Fail
+tests/co19/src/WebPlatformTest/dom/nodes/DOMImplementation-createHTMLDocument_t01: Fail
 tests/co19/src/WebPlatformTest/dom/nodes/Element-childElementCount-nochild_t01: Fail
-tests/compiler/dart2js/data/one_line_dart_program: Fail
-tests/compiler/dart2js_extra/LayoutTests_fast_mediastream_getusermedia_t01_test: Fail
 tests/compiler/dart2js_extra/deferred_custom_loader_test: Fail
 tests/compiler/dart2js_extra/empty_negative_test: Fail
-tests/compiler/dart2js_extra/invalid_annotation2_test: Fail
 tests/compiler/dart2js_extra/invalid_annotation_test: Fail
+tests/compiler/dart2js_extra/invalid_annotation2_test: Fail
 tests/compiler/dart2js_extra/invalid_length_negative_test: Fail
+tests/compiler/dart2js_extra/LayoutTests_fast_mediastream_getusermedia_t01_test: Fail
 tests/compiler/dart2js_extra/switch_test: Fail
 tests/compiler/dart2js_extra/timer_negative_test: Fail
 tests/compiler/dart2js_extra/typed_locals_test: Fail
@@ -1558,8 +1560,8 @@
 tests/compiler/dart2js_native/event_loop_test: Fail
 tests/compiler/dart2js_native/fake_thing_2_test: Fail
 tests/compiler/dart2js_native/fake_thing_test: Fail
-tests/compiler/dart2js_native/field_type2_test: Fail
 tests/compiler/dart2js_native/field_type_test: Fail
+tests/compiler/dart2js_native/field_type2_test: Fail
 tests/compiler/dart2js_native/fixup_get_tag_test: Fail
 tests/compiler/dart2js_native/hash_code_test: Fail
 tests/compiler/dart2js_native/issue9182_test: Fail
@@ -1585,12 +1587,12 @@
 tests/compiler/dart2js_native/native_equals_frog_test: Fail
 tests/compiler/dart2js_native/native_exception2_test: Fail
 tests/compiler/dart2js_native/native_exceptions1_frog_test: Fail
+tests/compiler/dart2js_native/native_field_invocation_test: Fail
 tests/compiler/dart2js_native/native_field_invocation2_test: Fail
 tests/compiler/dart2js_native/native_field_invocation3_test: Fail
 tests/compiler/dart2js_native/native_field_invocation4_test: Fail
 tests/compiler/dart2js_native/native_field_invocation5_test: Fail
 tests/compiler/dart2js_native/native_field_invocation6_test: Fail
-tests/compiler/dart2js_native/native_field_invocation_test: Fail
 tests/compiler/dart2js_native/native_field_name_test: Fail
 tests/compiler/dart2js_native/native_field_optimization_test: Fail
 tests/compiler/dart2js_native/native_field_rename_1_frog_test: Fail
@@ -1605,18 +1607,18 @@
 tests/compiler/dart2js_native/native_missing_method1_frog_test: Fail
 tests/compiler/dart2js_native/native_missing_method2_frog_test: Fail
 tests/compiler/dart2js_native/native_mixin_field_test: Fail
+tests/compiler/dart2js_native/native_mixin_multiple_test: Fail
 tests/compiler/dart2js_native/native_mixin_multiple2_test: Fail
 tests/compiler/dart2js_native/native_mixin_multiple3_test: Fail
-tests/compiler/dart2js_native/native_mixin_multiple_test: Fail
 tests/compiler/dart2js_native/native_mixin_test: Fail
 tests/compiler/dart2js_native/native_mixin_with_plain_test: Fail
 tests/compiler/dart2js_native/native_named_constructors2_frog_test: Fail
 tests/compiler/dart2js_native/native_named_constructors3_frog_test: Fail
+tests/compiler/dart2js_native/native_no_such_method_exception_frog_test: Fail
 tests/compiler/dart2js_native/native_no_such_method_exception2_frog_test: Fail
 tests/compiler/dart2js_native/native_no_such_method_exception3_frog_test: Fail
 tests/compiler/dart2js_native/native_no_such_method_exception4_frog_test: Fail
 tests/compiler/dart2js_native/native_no_such_method_exception5_frog_test: Fail
-tests/compiler/dart2js_native/native_no_such_method_exception_frog_test: Fail
 tests/compiler/dart2js_native/native_novel_html_test: Fail
 tests/compiler/dart2js_native/native_null_closure_frog_test: Fail
 tests/compiler/dart2js_native/native_null_frog_test: Fail
@@ -1624,8 +1626,8 @@
 tests/compiler/dart2js_native/native_testing: Fail
 tests/compiler/dart2js_native/native_to_string_frog_test: Fail
 tests/compiler/dart2js_native/native_use_native_name_in_table_frog_test: Fail
-tests/compiler/dart2js_native/native_wrapping_function3_frog_test: Fail
 tests/compiler/dart2js_native/native_wrapping_function_frog_test: Fail
+tests/compiler/dart2js_native/native_wrapping_function3_frog_test: Fail
 tests/compiler/dart2js_native/oddly_named_fields_test: Fail
 tests/compiler/dart2js_native/runtimetype_test: Fail
 tests/compiler/dart2js_native/static_methods_test: Fail
@@ -1641,12 +1643,160 @@
 tests/compiler/dart2js_native/subclassing_type_test: Fail
 tests/compiler/dart2js_native/super_call_test: Fail
 tests/compiler/dart2js_native/super_property_test: Fail
-tests/corelib/from_environment_const_type_test: Fail
-tests/corelib/from_environment_const_type_undefined_test: Fail
-tests/corelib/symbol_reserved_word_test: Fail
+tests/compiler/dart2js/data/one_line_dart_program: Fail
 tests/corelib_strong/from_environment_const_type_test: Fail
 tests/corelib_strong/from_environment_const_type_undefined_test: Fail
 tests/corelib_strong/symbol_reserved_word_test: Fail
+tests/corelib/from_environment_const_type_test: Fail
+tests/corelib/from_environment_const_type_undefined_test: Fail
+tests/corelib/symbol_reserved_word_test: Fail
+tests/language_2/abstract_syntax_test: Fail
+tests/language_2/arg_param_trailing_comma_test: Fail
+tests/language_strong/argument_definition_test: Fail
+tests/language_strong/assign_instance_method_negative_test: Fail
+tests/language_strong/async_await_syntax_test: Fail
+tests/language_strong/await_backwards_compatibility_test: Fail
+tests/language_strong/bad_constructor_test: Fail
+tests/language_strong/bad_initializer1_negative_test: Fail
+tests/language_strong/bad_initializer2_negative_test: Fail
+tests/language_strong/bad_named_constructor_negative_test: Fail
+tests/language_strong/bad_raw_string_test: Fail
+tests/language_strong/black_listed_test: Fail
+tests/language_strong/body_less_constructor_wrong_arg_negative_test: Fail
+tests/language_strong/built_in_identifier_prefix_test: Fail
+tests/language_strong/built_in_identifier_test: Fail
+tests/language_strong/cascade_test: Fail
+tests/language_strong/class_cycle2_test: Fail
+tests/language_strong/class_keyword_test: Fail
+tests/language_strong/class_syntax_test: Fail
+tests/language_strong/closure_call_wrong_argument_count_negative_test: Fail
+tests/language_strong/compile_time_constant13_test: Fail
+tests/language_strong/const_counter_negative_test: Fail
+tests/language_strong/const_native_factory_test: Fail
+tests/language_strong/const_optional_args_negative_test: Fail
+tests/language_strong/constructor_call_wrong_argument_count_negative_test: Fail
+tests/language_strong/constructor_initializer_test: Fail
+tests/language_strong/constructor_name_test: Fail
+tests/language_strong/constructor_redirect1_negative_test: Fail
+tests/language_strong/constructor_redirect2_negative_test: Fail
+tests/language_strong/constructor_setter_negative_test: Fail
+tests/language_strong/constructor3_negative_test: Fail
+tests/language_strong/cyclic_typedef_test: Fail
+tests/language_strong/deferred_type_dependency_test: Fail
+tests/language_strong/duplicate_export_negative_test: Fail
+tests/language_strong/duplicate_interface_negative_test: Fail
+tests/language_strong/enum_is_keyword_test: Fail
+tests/language_strong/enum_syntax_test: Fail
+tests/language_strong/export_ambiguous_main_negative_test: Fail
+tests/language_strong/extend_type_parameter_negative_test: Fail
+tests/language_strong/extend_type_parameter2_negative_test: Fail
+tests/language_strong/external_test: Fail
+tests/language_strong/factory_negative_test: Fail
+tests/language_strong/factory2_negative_test: Fail
+tests/language_strong/field_method4_negative_test: Fail
+tests/language_strong/field1_negative_test: Fail
+tests/language_strong/field2_negative_test: Fail
+tests/language_strong/field3a_negative_test: Fail
+tests/language_strong/field4_negative_test: Fail
+tests/language_strong/field5_negative_test: Fail
+tests/language_strong/field6_negative_test: Fail
+tests/language_strong/field6a_negative_test: Fail
+tests/language_strong/function_syntax_test: Fail
+tests/language_strong/function_type_parameter_negative_test: Fail
+tests/language_strong/function_type_parameter2_negative_test: Fail
+tests/language_strong/get_set_syntax_test: Fail
+tests/language_strong/getter_declaration_negative_test: Fail
+tests/language_strong/illegal_declaration_test: Fail
+tests/language_strong/import_combinators_negative_test: Fail
+tests/language_strong/inst_field_initializer1_negative_test: Fail
+tests/language_strong/instance_call_wrong_argument_count_negative_test: Fail
+tests/language_strong/instance_method_negative_test: Fail
+tests/language_strong/instance_method2_negative_test: Fail
+tests/language_strong/interface_cycle_test: Fail
+tests/language_strong/interface_static_non_final_fields_negative_test: Fail
+tests/language_strong/interface2_negative_test: Fail
+tests/language_strong/keyword_type_expression_test: Fail
+tests/language_strong/label2_negative_test: Fail
+tests/language_strong/label3_negative_test: Fail
+tests/language_strong/label5_negative_test: Fail
+tests/language_strong/label6_negative_test: Fail
+tests/language_strong/library_negative_test: Fail
+tests/language_strong/list_literal_syntax_test: Fail
+tests/language_strong/list_literal2_negative_test: Fail
+tests/language_strong/literal_unary_plus_test: Fail
+tests/language_strong/main_test: Fail
+tests/language_strong/malformed_inheritance_test: Fail
+tests/language_strong/malformed_test: Fail
+tests/language_strong/map_literal2_negative_test: Fail
+tests/language_strong/metadata_test: Fail
+tests/language_strong/method_override2_test: Fail
+tests/language_strong/mixin_forwarding_constructor4_test: Fail
+tests/language_strong/mixin_illegal_syntax_test: Fail
+tests/language_strong/mixin_invalid_inheritance1_test: Fail
+tests/language_strong/named_constructor_test: Fail
+tests/language_strong/named_parameters_aggregated_test: Fail
+tests/language_strong/no_such_method_negative_test: Fail
+tests/language_strong/non_const_super_negative_test: Fail
+tests/language_strong/null_test: Fail
+tests/language_strong/number_identifier_test: Fail
+tests/language_strong/override_field_method1_negative_test: Fail
+tests/language_strong/override_field_method2_negative_test: Fail
+tests/language_strong/override_field_method4_negative_test: Fail
+tests/language_strong/override_field_method5_negative_test: Fail
+tests/language_strong/override_inheritance_generic_test: Fail
+tests/language_strong/parameter_default_test: Fail
+tests/language_strong/parameter_initializer1_negative_test: Fail
+tests/language_strong/parameter_initializer2_negative_test: Fail
+tests/language_strong/parameter_initializer3_negative_test: Fail
+tests/language_strong/parameter_initializer4_negative_test: Fail
+tests/language_strong/parameter_initializer6_negative_test: Fail
+tests/language_strong/prefix1_negative_test: Fail
+tests/language_strong/prefix10_negative_test: Fail
+tests/language_strong/prefix11_negative_test: Fail
+tests/language_strong/prefix12_negative_test: Fail
+tests/language_strong/prefix13_negative_test: Fail
+tests/language_strong/prefix15_negative_test: Fail
+tests/language_strong/prefix2_negative_test: Fail
+tests/language_strong/prefix3_negative_test: Fail
+tests/language_strong/prefix4_negative_test: Fail
+tests/language_strong/prefix5_negative_test: Fail
+tests/language_strong/prefix6_negative_test: Fail
+tests/language_strong/prefix7_negative_test: Fail
+tests/language_strong/prefix8_negative_test: Fail
+tests/language_strong/private_member1_negative_test: Fail
+tests/language_strong/private_member2_negative_test: Fail
+tests/language_strong/private_member3_negative_test: Fail
+tests/language_strong/regress_23051_test: Fail
+tests/language_strong/script1_negative_test: Fail
+tests/language_strong/script2_negative_test: Fail
+tests/language_strong/source_self_negative_test: Fail
+tests/language_strong/static_call_wrong_argument_count_negative_test: Fail
+tests/language_strong/static_parameter_test: Fail
+tests/language_strong/static_top_level_test: Fail
+tests/language_strong/string_interpolation9_test: Fail
+tests/language_strong/string_unicode1_negative_test: Fail
+tests/language_strong/string_unicode2_negative_test: Fail
+tests/language_strong/string_unicode3_negative_test: Fail
+tests/language_strong/string_unicode4_negative_test: Fail
+tests/language_strong/switch1_negative_test: Fail
+tests/language_strong/switch3_negative_test: Fail
+tests/language_strong/switch4_negative_test: Fail
+tests/language_strong/switch5_negative_test: Fail
+tests/language_strong/switch7_negative_test: Fail
+tests/language_strong/sync_generator2_test: Fail
+tests/language_strong/syntax_test: Fail
+tests/language_strong/tearoff_basic_test: Fail
+tests/language_strong/tearoff_constructor_basic_test: Fail
+tests/language_strong/try_catch_on_syntax_test: Fail
+tests/language_strong/try_catch_syntax_test: Fail
+tests/language_strong/type_variable_bounds2_test: Fail
+tests/language_strong/type_variable_static_context_negative_test: Fail
+tests/language_strong/unbalanced_brace_test: Fail
+tests/language_strong/unresolved_in_factory_negative_test: Fail
+tests/language_strong/unresolved_top_level_method_negative_test: Fail
+tests/language_strong/unresolved_top_level_var_negative_test: Fail
+tests/language_strong/unsigned_right_shift_test: Fail
+tests/language_strong/variable_declaration_metadata_test: Fail
 tests/language/argument_definition_test: Fail
 tests/language/assert_initializer_test: Fail
 tests/language/assign_instance_method_negative_test: Fail
@@ -1656,6 +1806,7 @@
 tests/language/bad_initializer1_negative_test: Fail
 tests/language/bad_initializer2_negative_test: Fail
 tests/language/bad_named_constructor_negative_test: Fail
+tests/language/bad_raw_string_test: Fail
 tests/language/bad_typedef_test: Fail
 tests/language/black_listed_test: Fail
 tests/language/body_less_constructor_wrong_arg_negative_test: Fail
@@ -1670,13 +1821,13 @@
 tests/language/const_getter_test: Fail
 tests/language/const_native_factory_test: Fail
 tests/language/const_optional_args_negative_test: Fail
-tests/language/constructor3_negative_test: Fail
 tests/language/constructor_call_wrong_argument_count_negative_test: Fail
 tests/language/constructor_initializer_test: Fail
 tests/language/constructor_name_test: Fail
 tests/language/constructor_redirect1_negative_test: Fail
 tests/language/constructor_redirect2_negative_test: Fail
 tests/language/constructor_setter_negative_test: Fail
+tests/language/constructor3_negative_test: Fail
 tests/language/covariant_test: Fail
 tests/language/cyclic_typedef_test: Fail
 tests/language/deferred_type_dependency_test: Fail
@@ -1685,11 +1836,12 @@
 tests/language/enum_is_keyword_test: Fail
 tests/language/enum_syntax_test: Fail
 tests/language/export_ambiguous_main_negative_test: Fail
-tests/language/extend_type_parameter2_negative_test: Fail
 tests/language/extend_type_parameter_negative_test: Fail
+tests/language/extend_type_parameter2_negative_test: Fail
 tests/language/external_test: Fail
-tests/language/factory2_negative_test: Fail
 tests/language/factory_negative_test: Fail
+tests/language/factory2_negative_test: Fail
+tests/language/field_method4_negative_test: Fail
 tests/language/field1_negative_test: Fail
 tests/language/field2_negative_test: Fail
 tests/language/field3a_negative_test: Fail
@@ -1697,29 +1849,29 @@
 tests/language/field5_negative_test: Fail
 tests/language/field6_negative_test: Fail
 tests/language/field6a_negative_test: Fail
-tests/language/field_method4_negative_test: Fail
 tests/language/function_syntax_test: Fail
-tests/language/function_type_parameter2_negative_test: Fail
 tests/language/function_type_parameter_negative_test: Fail
+tests/language/function_type_parameter2_negative_test: Fail
+tests/language/generic_function_typedef2_test: Fail
 tests/language/get_set_syntax_test: Fail
 tests/language/getter_declaration_negative_test: Fail
 tests/language/illegal_declaration_test: Fail
 tests/language/import_combinators_negative_test: Fail
 tests/language/inst_field_initializer1_negative_test: Fail
 tests/language/instance_call_wrong_argument_count_negative_test: Fail
-tests/language/instance_method2_negative_test: Fail
 tests/language/instance_method_negative_test: Fail
-tests/language/interface2_negative_test: Fail
+tests/language/instance_method2_negative_test: Fail
 tests/language/interface_cycle_test: Fail
 tests/language/interface_static_non_final_fields_negative_test: Fail
+tests/language/interface2_negative_test: Fail
 tests/language/keyword_type_expression_test: Fail
 tests/language/label2_negative_test: Fail
 tests/language/label3_negative_test: Fail
 tests/language/label5_negative_test: Fail
 tests/language/label6_negative_test: Fail
 tests/language/library_negative_test: Fail
-tests/language/list_literal2_negative_test: Fail
 tests/language/list_literal_syntax_test: Fail
+tests/language/list_literal2_negative_test: Fail
 tests/language/literal_unary_plus_test: Fail
 tests/language/main_test: Fail
 tests/language/malformed_inheritance_test: Fail
@@ -1731,9 +1883,9 @@
 tests/language/mixin_forwarding_constructor4_test: Fail
 tests/language/mixin_illegal_syntax_test: Fail
 tests/language/mixin_invalid_inheritance1_test: Fail
+tests/language/mixin_supertype_subclass_test: Fail
 tests/language/mixin_supertype_subclass2_test: Fail
 tests/language/mixin_supertype_subclass4_test: Fail
-tests/language/mixin_supertype_subclass_test: Fail
 tests/language/named_constructor_test: Fail
 tests/language/named_parameters_aggregated_test: Fail
 tests/language/no_such_method_negative_test: Fail
@@ -1752,12 +1904,12 @@
 tests/language/parameter_initializer4_negative_test: Fail
 tests/language/parameter_initializer5_negative_test: Fail
 tests/language/parameter_initializer6_negative_test: Fail
+tests/language/prefix1_negative_test: Fail
 tests/language/prefix10_negative_test: Fail
 tests/language/prefix11_negative_test: Fail
 tests/language/prefix12_negative_test: Fail
 tests/language/prefix13_negative_test: Fail
 tests/language/prefix15_negative_test: Fail
-tests/language/prefix1_negative_test: Fail
 tests/language/prefix2_negative_test: Fail
 tests/language/prefix3_negative_test: Fail
 tests/language/prefix4_negative_test: Fail
@@ -1807,152 +1959,12 @@
 tests/language/variable_declaration_metadata_test: Fail
 tests/language/vm/debug_break_enabled_vm_test: Fail
 tests/language/vm/debug_break_vm_test: Fail
-tests/language_2/abstract_syntax_test: Fail
-tests/language_2/arg_param_trailing_comma_test: Fail
-tests/language_strong/argument_definition_test: Fail
-tests/language_strong/assign_instance_method_negative_test: Fail
-tests/language_strong/async_await_syntax_test: Fail
-tests/language_strong/await_backwards_compatibility_test: Fail
-tests/language_strong/bad_constructor_test: Fail
-tests/language_strong/bad_initializer1_negative_test: Fail
-tests/language_strong/bad_initializer2_negative_test: Fail
-tests/language_strong/bad_named_constructor_negative_test: Fail
-tests/language_strong/black_listed_test: Fail
-tests/language_strong/body_less_constructor_wrong_arg_negative_test: Fail
-tests/language_strong/built_in_identifier_prefix_test: Fail
-tests/language_strong/built_in_identifier_test: Fail
-tests/language_strong/cascade_test: Fail
-tests/language_strong/class_cycle2_test: Fail
-tests/language_strong/class_keyword_test: Fail
-tests/language_strong/class_syntax_test: Fail
-tests/language_strong/closure_call_wrong_argument_count_negative_test: Fail
-tests/language_strong/compile_time_constant13_test: Fail
-tests/language_strong/const_counter_negative_test: Fail
-tests/language_strong/const_native_factory_test: Fail
-tests/language_strong/const_optional_args_negative_test: Fail
-tests/language_strong/constructor3_negative_test: Fail
-tests/language_strong/constructor_call_wrong_argument_count_negative_test: Fail
-tests/language_strong/constructor_initializer_test: Fail
-tests/language_strong/constructor_name_test: Fail
-tests/language_strong/constructor_redirect1_negative_test: Fail
-tests/language_strong/constructor_redirect2_negative_test: Fail
-tests/language_strong/constructor_setter_negative_test: Fail
-tests/language_strong/cyclic_typedef_test: Fail
-tests/language_strong/deferred_type_dependency_test: Fail
-tests/language_strong/duplicate_export_negative_test: Fail
-tests/language_strong/duplicate_interface_negative_test: Fail
-tests/language_strong/enum_is_keyword_test: Fail
-tests/language_strong/enum_syntax_test: Fail
-tests/language_strong/export_ambiguous_main_negative_test: Fail
-tests/language_strong/extend_type_parameter2_negative_test: Fail
-tests/language_strong/extend_type_parameter_negative_test: Fail
-tests/language_strong/external_test: Fail
-tests/language_strong/factory2_negative_test: Fail
-tests/language_strong/factory_negative_test: Fail
-tests/language_strong/field1_negative_test: Fail
-tests/language_strong/field2_negative_test: Fail
-tests/language_strong/field3a_negative_test: Fail
-tests/language_strong/field4_negative_test: Fail
-tests/language_strong/field5_negative_test: Fail
-tests/language_strong/field6_negative_test: Fail
-tests/language_strong/field6a_negative_test: Fail
-tests/language_strong/field_method4_negative_test: Fail
-tests/language_strong/function_syntax_test: Fail
-tests/language_strong/function_type_parameter2_negative_test: Fail
-tests/language_strong/function_type_parameter_negative_test: Fail
-tests/language_strong/get_set_syntax_test: Fail
-tests/language_strong/getter_declaration_negative_test: Fail
-tests/language_strong/illegal_declaration_test: Fail
-tests/language_strong/import_combinators_negative_test: Fail
-tests/language_strong/inst_field_initializer1_negative_test: Fail
-tests/language_strong/instance_call_wrong_argument_count_negative_test: Fail
-tests/language_strong/instance_method2_negative_test: Fail
-tests/language_strong/instance_method_negative_test: Fail
-tests/language_strong/interface2_negative_test: Fail
-tests/language_strong/interface_cycle_test: Fail
-tests/language_strong/interface_static_non_final_fields_negative_test: Fail
-tests/language_strong/keyword_type_expression_test: Fail
-tests/language_strong/label2_negative_test: Fail
-tests/language_strong/label3_negative_test: Fail
-tests/language_strong/label5_negative_test: Fail
-tests/language_strong/label6_negative_test: Fail
-tests/language_strong/library_negative_test: Fail
-tests/language_strong/list_literal2_negative_test: Fail
-tests/language_strong/list_literal_syntax_test: Fail
-tests/language_strong/literal_unary_plus_test: Fail
-tests/language_strong/main_test: Fail
-tests/language_strong/malformed_inheritance_test: Fail
-tests/language_strong/malformed_test: Fail
-tests/language_strong/map_literal2_negative_test: Fail
-tests/language_strong/metadata_test: Fail
-tests/language_strong/method_override2_test: Fail
-tests/language_strong/mixin_forwarding_constructor4_test: Fail
-tests/language_strong/mixin_illegal_syntax_test: Fail
-tests/language_strong/mixin_invalid_inheritance1_test: Fail
-tests/language_strong/named_constructor_test: Fail
-tests/language_strong/named_parameters_aggregated_test: Fail
-tests/language_strong/no_such_method_negative_test: Fail
-tests/language_strong/non_const_super_negative_test: Fail
-tests/language_strong/null_test: Fail
-tests/language_strong/number_identifier_test: Fail
-tests/language_strong/override_field_method1_negative_test: Fail
-tests/language_strong/override_field_method2_negative_test: Fail
-tests/language_strong/override_field_method4_negative_test: Fail
-tests/language_strong/override_field_method5_negative_test: Fail
-tests/language_strong/override_inheritance_generic_test: Fail
-tests/language_strong/parameter_default_test: Fail
-tests/language_strong/parameter_initializer1_negative_test: Fail
-tests/language_strong/parameter_initializer2_negative_test: Fail
-tests/language_strong/parameter_initializer3_negative_test: Fail
-tests/language_strong/parameter_initializer4_negative_test: Fail
-tests/language_strong/parameter_initializer6_negative_test: Fail
-tests/language_strong/prefix10_negative_test: Fail
-tests/language_strong/prefix11_negative_test: Fail
-tests/language_strong/prefix12_negative_test: Fail
-tests/language_strong/prefix13_negative_test: Fail
-tests/language_strong/prefix15_negative_test: Fail
-tests/language_strong/prefix1_negative_test: Fail
-tests/language_strong/prefix2_negative_test: Fail
-tests/language_strong/prefix3_negative_test: Fail
-tests/language_strong/prefix4_negative_test: Fail
-tests/language_strong/prefix5_negative_test: Fail
-tests/language_strong/prefix6_negative_test: Fail
-tests/language_strong/prefix7_negative_test: Fail
-tests/language_strong/prefix8_negative_test: Fail
-tests/language_strong/private_member1_negative_test: Fail
-tests/language_strong/private_member2_negative_test: Fail
-tests/language_strong/private_member3_negative_test: Fail
-tests/language_strong/regress_23051_test: Fail
-tests/language_strong/script1_negative_test: Fail
-tests/language_strong/script2_negative_test: Fail
-tests/language_strong/source_self_negative_test: Fail
-tests/language_strong/static_call_wrong_argument_count_negative_test: Fail
-tests/language_strong/static_parameter_test: Fail
-tests/language_strong/static_top_level_test: Fail
-tests/language_strong/string_interpolation9_test: Fail
-tests/language_strong/string_unicode1_negative_test: Fail
-tests/language_strong/string_unicode2_negative_test: Fail
-tests/language_strong/string_unicode3_negative_test: Fail
-tests/language_strong/string_unicode4_negative_test: Fail
-tests/language_strong/switch1_negative_test: Fail
-tests/language_strong/switch3_negative_test: Fail
-tests/language_strong/switch4_negative_test: Fail
-tests/language_strong/switch5_negative_test: Fail
-tests/language_strong/switch7_negative_test: Fail
-tests/language_strong/sync_generator2_test: Fail
-tests/language_strong/syntax_test: Fail
-tests/language_strong/tearoff_basic_test: Fail
-tests/language_strong/tearoff_constructor_basic_test: Fail
-tests/language_strong/try_catch_on_syntax_test: Fail
-tests/language_strong/try_catch_syntax_test: Fail
-tests/language_strong/type_variable_bounds2_test: Fail
-tests/language_strong/type_variable_static_context_negative_test: Fail
-tests/language_strong/unbalanced_brace_test: Fail
-tests/language_strong/unresolved_in_factory_negative_test: Fail
-tests/language_strong/unresolved_top_level_method_negative_test: Fail
-tests/language_strong/unresolved_top_level_var_negative_test: Fail
-tests/language_strong/unsigned_right_shift_test: Fail
-tests/language_strong/variable_declaration_metadata_test: Fail
+tests/lib_strong/mirrors/metadata_allowed_values_test: Fail
+tests/lib_strong/mirrors/metadata_scope_test: Fail
+tests/lib_strong/mirrors/mirror_in_static_init_test: Fail
+tests/lib_strong/mirrors/other_declarations_location_test: Fail
+tests/lib_strong/mirrors/syntax_error_test: Fail
+tests/lib_strong/mirrors/typevariable_mirror_metadata_test: Fail
 tests/lib/async/future_or_bad_type_test: Fail
 tests/lib/mirrors/metadata_allowed_values_test: Fail
 tests/lib/mirrors/metadata_scope_test: Fail
@@ -1960,12 +1972,6 @@
 tests/lib/mirrors/other_declarations_location_test: Fail
 tests/lib/mirrors/syntax_error_test: Fail
 tests/lib/mirrors/typevariable_mirror_metadata_test: Fail
-tests/lib_strong/mirrors/metadata_allowed_values_test: Fail
-tests/lib_strong/mirrors/metadata_scope_test: Fail
-tests/lib_strong/mirrors/mirror_in_static_init_test: Fail
-tests/lib_strong/mirrors/other_declarations_location_test: Fail
-tests/lib_strong/mirrors/syntax_error_test: Fail
-tests/lib_strong/mirrors/typevariable_mirror_metadata_test: Fail
 tests/standalone/io/snapshot_fail_script: Fail
 tests/standalone/io/test_extension: Fail
 tests/standalone/io/test_relative_extension: Fail
@@ -1975,10 +1981,3 @@
 third_party/pkg/resource/test/loader_data_test: Fail
 third_party/pkg/resource/test/loader_file_test: Fail
 third_party/pkg/resource/test/loader_http_test: Fail
-
-issue23520: Fail
-issue28367: Fail
-pkg/front_end/test/fasta/function_type_recovery: Fail
-tests/language/bad_raw_string_test: Fail
-tests/language/generic_function_typedef2_test: Fail
-tests/language_strong/bad_raw_string_test: Fail
diff --git a/pkg/front_end/test/fasta/scanner/scanner.status b/pkg/front_end/test/fasta/scanner/scanner.status
index 33d4d5e..4cdc798 100644
--- a/pkg/front_end/test/fasta/scanner/scanner.status
+++ b/pkg/front_end/test/fasta/scanner/scanner.status
@@ -6,121 +6,6 @@
 tests/compiler/dart2js_extra/empty_negative_test: Fail
 tests/compiler/dart2js_extra/invalid_length_negative_test: Fail
 tests/compiler/dart2js_extra/timer_negative_test: Fail
-tests/language/assign_instance_method_negative_test: Fail
-tests/language/bad_initializer1_negative_test: Fail
-tests/language/bad_initializer2_negative_test: Fail
-tests/language/bad_named_constructor_negative_test: Fail
-tests/language/body_less_constructor_wrong_arg_negative_test: Fail
-tests/language/closure_call_wrong_argument_count_negative_test: Fail
-tests/language/const_counter_negative_test: Fail
-tests/language/const_optional_args_negative_test: Fail
-tests/language/constructor3_negative_test: Fail
-tests/language/constructor_call_wrong_argument_count_negative_test: Fail
-tests/language/constructor_redirect1_negative_test: Fail
-tests/language/constructor_redirect2_negative_test: Fail
-tests/language/constructor_setter_negative_test: Fail
-tests/language/deep_nesting1_negative_test: Fail
-tests/language/deep_nesting2_negative_test: Fail
-tests/language/duplicate_export_negative_test: Fail
-tests/language/duplicate_interface_negative_test: Fail
-tests/language/export_ambiguous_main_negative_test: Fail
-tests/language/extend_type_parameter2_negative_test: Fail
-tests/language/extend_type_parameter_negative_test: Fail
-tests/language/factory2_negative_test: Fail
-tests/language/factory3_negative_test: Fail
-tests/language/factory_negative_test: Fail
-tests/language/field1_negative_test: Fail
-tests/language/field2_negative_test: Fail
-tests/language/field3_negative_test: Fail
-tests/language/field3a_negative_test: Fail
-tests/language/field4_negative_test: Fail
-tests/language/field5_negative_test: Fail
-tests/language/field6_negative_test: Fail
-tests/language/field6a_negative_test: Fail
-tests/language/field_method4_negative_test: Fail
-tests/language/function_type_parameter2_negative_test: Fail
-tests/language/function_type_parameter_negative_test: Fail
-tests/language/getter_declaration_negative_test: Fail
-tests/language/import_combinators_negative_test: Fail
-tests/language/inst_field_initializer1_negative_test: Fail
-tests/language/instance_call_wrong_argument_count_negative_test: Fail
-tests/language/instance_method2_negative_test: Fail
-tests/language/instance_method_negative_test: Fail
-tests/language/interface2_negative_test: Fail
-tests/language/interface_injection1_negative_test: Fail
-tests/language/interface_injection2_negative_test: Fail
-tests/language/interface_static_method_negative_test: Fail
-tests/language/interface_static_non_final_fields_negative_test: Fail
-tests/language/is_not_class1_negative_test: Fail
-tests/language/is_not_class4_negative_test: Fail
-tests/language/issue1578_negative_test: Fail
-tests/language/label2_negative_test: Fail
-tests/language/label3_negative_test: Fail
-tests/language/label5_negative_test: Fail
-tests/language/label6_negative_test: Fail
-tests/language/label8_negative_test: Fail
-tests/language/library_negative_test: Fail
-tests/language/list_literal2_negative_test: Fail
-tests/language/list_literal_negative_test: Fail
-tests/language/map_literal2_negative_test: Fail
-tests/language/map_literal_negative_test: Fail
-tests/language/new_expression1_negative_test: Fail
-tests/language/new_expression2_negative_test: Fail
-tests/language/new_expression3_negative_test: Fail
-tests/language/no_such_method_negative_test: Fail
-tests/language/non_const_super_negative_test: Fail
-tests/language/operator1_negative_test: Fail
-tests/language/operator2_negative_test: Fail
-tests/language/override_field_method1_negative_test: Fail
-tests/language/override_field_method2_negative_test: Fail
-tests/language/override_field_method4_negative_test: Fail
-tests/language/override_field_method5_negative_test: Fail
-tests/language/parameter_initializer1_negative_test: Fail
-tests/language/parameter_initializer2_negative_test: Fail
-tests/language/parameter_initializer3_negative_test: Fail
-tests/language/parameter_initializer4_negative_test: Fail
-tests/language/parameter_initializer5_negative_test: Fail
-tests/language/parameter_initializer6_negative_test: Fail
-tests/language/prefix10_negative_test: Fail
-tests/language/prefix11_negative_test: Fail
-tests/language/prefix12_negative_test: Fail
-tests/language/prefix13_negative_test: Fail
-tests/language/prefix15_negative_test: Fail
-tests/language/prefix18_negative_test: Fail
-tests/language/prefix1_negative_test: Fail
-tests/language/prefix2_negative_test: Fail
-tests/language/prefix3_negative_test: Fail
-tests/language/prefix4_negative_test: Fail
-tests/language/prefix5_negative_test: Fail
-tests/language/prefix6_negative_test: Fail
-tests/language/prefix7_negative_test: Fail
-tests/language/prefix8_negative_test: Fail
-tests/language/private_member1_negative_test: Fail
-tests/language/private_member2_negative_test: Fail
-tests/language/private_member3_negative_test: Fail
-tests/language/script1_negative_test: Fail
-tests/language/script2_negative_test: Fail
-tests/language/source_self_negative_test: Fail
-tests/language/static_call_wrong_argument_count_negative_test: Fail
-tests/language/string_escape4_negative_test: Fail
-tests/language/string_interpolate1_negative_test: Fail
-tests/language/string_interpolate2_negative_test: Fail
-tests/language/string_unicode1_negative_test: Fail
-tests/language/string_unicode2_negative_test: Fail
-tests/language/string_unicode3_negative_test: Fail
-tests/language/string_unicode4_negative_test: Fail
-tests/language/switch1_negative_test: Fail
-tests/language/switch3_negative_test: Fail
-tests/language/switch4_negative_test: Fail
-tests/language/switch5_negative_test: Fail
-tests/language/switch7_negative_test: Fail
-tests/language/test_negative_test: Fail
-tests/language/type_variable_static_context_negative_test: Fail
-tests/language/unary_plus_negative_test: Fail
-tests/language/unhandled_exception_negative_test: Fail
-tests/language/unresolved_in_factory_negative_test: Fail
-tests/language/unresolved_top_level_method_negative_test: Fail
-tests/language/unresolved_top_level_var_negative_test: Fail
 tests/language_strong/assign_instance_method_negative_test: Fail
 tests/language_strong/bad_initializer1_negative_test: Fail
 tests/language_strong/bad_initializer2_negative_test: Fail
@@ -129,19 +14,20 @@
 tests/language_strong/closure_call_wrong_argument_count_negative_test: Fail
 tests/language_strong/const_counter_negative_test: Fail
 tests/language_strong/const_optional_args_negative_test: Fail
-tests/language_strong/constructor3_negative_test: Fail
 tests/language_strong/constructor_call_wrong_argument_count_negative_test: Fail
 tests/language_strong/constructor_redirect1_negative_test: Fail
 tests/language_strong/constructor_redirect2_negative_test: Fail
 tests/language_strong/constructor_setter_negative_test: Fail
+tests/language_strong/constructor3_negative_test: Fail
 tests/language_strong/duplicate_export_negative_test: Fail
 tests/language_strong/duplicate_interface_negative_test: Fail
 tests/language_strong/export_ambiguous_main_negative_test: Fail
-tests/language_strong/extend_type_parameter2_negative_test: Fail
 tests/language_strong/extend_type_parameter_negative_test: Fail
+tests/language_strong/extend_type_parameter2_negative_test: Fail
+tests/language_strong/factory_negative_test: Fail
 tests/language_strong/factory2_negative_test: Fail
 tests/language_strong/factory3_negative_test: Fail
-tests/language_strong/factory_negative_test: Fail
+tests/language_strong/field_method4_negative_test: Fail
 tests/language_strong/field1_negative_test: Fail
 tests/language_strong/field2_negative_test: Fail
 tests/language_strong/field3_negative_test: Fail
@@ -150,20 +36,19 @@
 tests/language_strong/field5_negative_test: Fail
 tests/language_strong/field6_negative_test: Fail
 tests/language_strong/field6a_negative_test: Fail
-tests/language_strong/field_method4_negative_test: Fail
-tests/language_strong/function_type_parameter2_negative_test: Fail
 tests/language_strong/function_type_parameter_negative_test: Fail
+tests/language_strong/function_type_parameter2_negative_test: Fail
 tests/language_strong/getter_declaration_negative_test: Fail
 tests/language_strong/import_combinators_negative_test: Fail
 tests/language_strong/inst_field_initializer1_negative_test: Fail
 tests/language_strong/instance_call_wrong_argument_count_negative_test: Fail
-tests/language_strong/instance_method2_negative_test: Fail
 tests/language_strong/instance_method_negative_test: Fail
-tests/language_strong/interface2_negative_test: Fail
+tests/language_strong/instance_method2_negative_test: Fail
 tests/language_strong/interface_injection1_negative_test: Fail
 tests/language_strong/interface_injection2_negative_test: Fail
 tests/language_strong/interface_static_method_negative_test: Fail
 tests/language_strong/interface_static_non_final_fields_negative_test: Fail
+tests/language_strong/interface2_negative_test: Fail
 tests/language_strong/is_not_class1_negative_test: Fail
 tests/language_strong/is_not_class4_negative_test: Fail
 tests/language_strong/issue1578_negative_test: Fail
@@ -173,10 +58,10 @@
 tests/language_strong/label6_negative_test: Fail
 tests/language_strong/label8_negative_test: Fail
 tests/language_strong/library_negative_test: Fail
-tests/language_strong/list_literal2_negative_test: Fail
 tests/language_strong/list_literal_negative_test: Fail
-tests/language_strong/map_literal2_negative_test: Fail
+tests/language_strong/list_literal2_negative_test: Fail
 tests/language_strong/map_literal_negative_test: Fail
+tests/language_strong/map_literal2_negative_test: Fail
 tests/language_strong/new_expression1_negative_test: Fail
 tests/language_strong/new_expression2_negative_test: Fail
 tests/language_strong/new_expression3_negative_test: Fail
@@ -193,13 +78,13 @@
 tests/language_strong/parameter_initializer3_negative_test: Fail
 tests/language_strong/parameter_initializer4_negative_test: Fail
 tests/language_strong/parameter_initializer6_negative_test: Fail
+tests/language_strong/prefix1_negative_test: Fail
 tests/language_strong/prefix10_negative_test: Fail
 tests/language_strong/prefix11_negative_test: Fail
 tests/language_strong/prefix12_negative_test: Fail
 tests/language_strong/prefix13_negative_test: Fail
 tests/language_strong/prefix15_negative_test: Fail
 tests/language_strong/prefix18_negative_test: Fail
-tests/language_strong/prefix1_negative_test: Fail
 tests/language_strong/prefix2_negative_test: Fail
 tests/language_strong/prefix3_negative_test: Fail
 tests/language_strong/prefix4_negative_test: Fail
@@ -239,4 +124,119 @@
 tests/language_strong/unresolved_in_factory_negative_test: Fail
 tests/language_strong/unresolved_top_level_method_negative_test: Fail
 tests/language_strong/unresolved_top_level_var_negative_test: Fail
+tests/language/assign_instance_method_negative_test: Fail
+tests/language/bad_initializer1_negative_test: Fail
+tests/language/bad_initializer2_negative_test: Fail
+tests/language/bad_named_constructor_negative_test: Fail
+tests/language/body_less_constructor_wrong_arg_negative_test: Fail
+tests/language/closure_call_wrong_argument_count_negative_test: Fail
+tests/language/const_counter_negative_test: Fail
+tests/language/const_optional_args_negative_test: Fail
+tests/language/constructor_call_wrong_argument_count_negative_test: Fail
+tests/language/constructor_redirect1_negative_test: Fail
+tests/language/constructor_redirect2_negative_test: Fail
+tests/language/constructor_setter_negative_test: Fail
+tests/language/constructor3_negative_test: Fail
+tests/language/deep_nesting1_negative_test: Fail
+tests/language/deep_nesting2_negative_test: Fail
+tests/language/duplicate_export_negative_test: Fail
+tests/language/duplicate_interface_negative_test: Fail
+tests/language/export_ambiguous_main_negative_test: Fail
+tests/language/extend_type_parameter_negative_test: Fail
+tests/language/extend_type_parameter2_negative_test: Fail
+tests/language/factory_negative_test: Fail
+tests/language/factory2_negative_test: Fail
+tests/language/factory3_negative_test: Fail
+tests/language/field_method4_negative_test: Fail
+tests/language/field1_negative_test: Fail
+tests/language/field2_negative_test: Fail
+tests/language/field3_negative_test: Fail
+tests/language/field3a_negative_test: Fail
+tests/language/field4_negative_test: Fail
+tests/language/field5_negative_test: Fail
+tests/language/field6_negative_test: Fail
+tests/language/field6a_negative_test: Fail
+tests/language/function_type_parameter_negative_test: Fail
+tests/language/function_type_parameter2_negative_test: Fail
+tests/language/getter_declaration_negative_test: Fail
+tests/language/import_combinators_negative_test: Fail
+tests/language/inst_field_initializer1_negative_test: Fail
+tests/language/instance_call_wrong_argument_count_negative_test: Fail
+tests/language/instance_method_negative_test: Fail
+tests/language/instance_method2_negative_test: Fail
+tests/language/interface_injection1_negative_test: Fail
+tests/language/interface_injection2_negative_test: Fail
+tests/language/interface_static_method_negative_test: Fail
+tests/language/interface_static_non_final_fields_negative_test: Fail
+tests/language/interface2_negative_test: Fail
+tests/language/is_not_class1_negative_test: Fail
+tests/language/is_not_class4_negative_test: Fail
+tests/language/issue1578_negative_test: Fail
+tests/language/label2_negative_test: Fail
+tests/language/label3_negative_test: Fail
+tests/language/label5_negative_test: Fail
+tests/language/label6_negative_test: Fail
+tests/language/label8_negative_test: Fail
+tests/language/library_negative_test: Fail
+tests/language/list_literal_negative_test: Fail
+tests/language/list_literal2_negative_test: Fail
+tests/language/map_literal_negative_test: Fail
+tests/language/map_literal2_negative_test: Fail
+tests/language/new_expression1_negative_test: Fail
+tests/language/new_expression2_negative_test: Fail
+tests/language/new_expression3_negative_test: Fail
+tests/language/no_such_method_negative_test: Fail
+tests/language/non_const_super_negative_test: Fail
+tests/language/operator1_negative_test: Fail
+tests/language/operator2_negative_test: Fail
+tests/language/override_field_method1_negative_test: Fail
+tests/language/override_field_method2_negative_test: Fail
+tests/language/override_field_method4_negative_test: Fail
+tests/language/override_field_method5_negative_test: Fail
+tests/language/parameter_initializer1_negative_test: Fail
+tests/language/parameter_initializer2_negative_test: Fail
+tests/language/parameter_initializer3_negative_test: Fail
+tests/language/parameter_initializer4_negative_test: Fail
+tests/language/parameter_initializer5_negative_test: Fail
+tests/language/parameter_initializer6_negative_test: Fail
+tests/language/prefix1_negative_test: Fail
+tests/language/prefix10_negative_test: Fail
+tests/language/prefix11_negative_test: Fail
+tests/language/prefix12_negative_test: Fail
+tests/language/prefix13_negative_test: Fail
+tests/language/prefix15_negative_test: Fail
+tests/language/prefix18_negative_test: Fail
+tests/language/prefix2_negative_test: Fail
+tests/language/prefix3_negative_test: Fail
+tests/language/prefix4_negative_test: Fail
+tests/language/prefix5_negative_test: Fail
+tests/language/prefix6_negative_test: Fail
+tests/language/prefix7_negative_test: Fail
+tests/language/prefix8_negative_test: Fail
+tests/language/private_member1_negative_test: Fail
+tests/language/private_member2_negative_test: Fail
+tests/language/private_member3_negative_test: Fail
+tests/language/script1_negative_test: Fail
+tests/language/script2_negative_test: Fail
+tests/language/source_self_negative_test: Fail
+tests/language/static_call_wrong_argument_count_negative_test: Fail
+tests/language/string_escape4_negative_test: Fail
+tests/language/string_interpolate1_negative_test: Fail
+tests/language/string_interpolate2_negative_test: Fail
+tests/language/string_unicode1_negative_test: Fail
+tests/language/string_unicode2_negative_test: Fail
+tests/language/string_unicode3_negative_test: Fail
+tests/language/string_unicode4_negative_test: Fail
+tests/language/switch1_negative_test: Fail
+tests/language/switch3_negative_test: Fail
+tests/language/switch4_negative_test: Fail
+tests/language/switch5_negative_test: Fail
+tests/language/switch7_negative_test: Fail
+tests/language/test_negative_test: Fail
+tests/language/type_variable_static_context_negative_test: Fail
+tests/language/unary_plus_negative_test: Fail
+tests/language/unhandled_exception_negative_test: Fail
+tests/language/unresolved_in_factory_negative_test: Fail
+tests/language/unresolved_top_level_method_negative_test: Fail
+tests/language/unresolved_top_level_var_negative_test: Fail
 tests/standalone/io/process_exit_negative_test: Fail
diff --git a/pkg/front_end/test/fasta/type_inference/factor_type_test.dart b/pkg/front_end/test/fasta/type_inference/factor_type_test.dart
new file mode 100644
index 0000000..184c9f1
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_inference/factor_type_test.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:_fe_analyzer_shared/src/flow_analysis/factory_type_test_helper.dart';
+import 'package:expect/expect.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/fasta/type_inference/factor_type.dart';
+import 'package:front_end/src/kernel_generator_impl.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/type_environment.dart';
+
+import 'package:front_end/src/testing/compiler_common.dart';
+
+class FactorTypeTest extends FactorTypeTestMixin<DartType> {
+  final TypeEnvironment typeEnvironment;
+
+  FactorTypeTest(this.typeEnvironment);
+
+  CoreTypes get coreTypes => typeEnvironment.coreTypes;
+
+  void run() {
+    test_futureOr();
+    test_object();
+    test_subtype();
+  }
+
+  @override
+  void expect(
+      DartType T, DartType S, String actualResult, String expectedResult) {
+    Expect.equals(
+        expectedResult, actualResult, "Unexpected result for factor($T, $S)");
+  }
+
+  @override
+  DartType factor(DartType T, DartType S) {
+    return factorType(typeEnvironment, T, S);
+  }
+
+  @override
+  DartType futureNone(DartType type) =>
+      new InterfaceType(coreTypes.futureClass, Nullability.nonNullable, [type]);
+
+  @override
+  DartType futureOrNone(DartType type) => new InterfaceType(
+      coreTypes.futureOrClass, Nullability.nonNullable, [type]);
+
+  @override
+  DartType get intNone => coreTypes.intNonNullableRawType;
+
+  @override
+  DartType get intQuestion => coreTypes.intNullableRawType;
+
+  @override
+  DartType get intStar => coreTypes.intLegacyRawType;
+
+  @override
+  DartType get nullNone => coreTypes.nullType;
+
+  @override
+  DartType get numNone => coreTypes.numNonNullableRawType;
+
+  @override
+  DartType get numQuestion => coreTypes.numNullableRawType;
+
+  @override
+  DartType get numStar => coreTypes.numLegacyRawType;
+
+  @override
+  DartType get objectNone => coreTypes.objectNonNullableRawType;
+
+  @override
+  DartType get objectQuestion => coreTypes.objectNullableRawType;
+
+  @override
+  DartType get objectStar => coreTypes.objectLegacyRawType;
+
+  @override
+  DartType get stringNone => coreTypes.stringNonNullableRawType;
+
+  @override
+  DartType get stringQuestion => coreTypes.stringNullableRawType;
+
+  @override
+  DartType get stringStar => coreTypes.stringLegacyRawType;
+
+  @override
+  String typeString(DartType type) =>
+      typeToText(type, TypeRepresentation.analyzerNonNullableByDefault);
+}
+
+main() async {
+  CompilerOptions options = new CompilerOptions()
+    ..experimentalFlags[ExperimentalFlag.nonNullable] = true;
+  InternalCompilerResult result = await compileScript('',
+      options: options, requireMain: false, retainDataForTesting: true);
+  new FactorTypeTest(
+          new TypeEnvironment(result.coreTypes, result.classHierarchy))
+      .run();
+}
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 306c52f..168cf74 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
@@ -473,6 +473,30 @@
     testLower("B*", "A", "B");
     testLower("B?", "A", "B");
     testLower("B", "A", "B");
+
+    testLower("Iterable<A>*", "List<B>*", "List<B>*");
+    testLower("Iterable<A>*", "List<B>?", "List<B>*");
+    testLower("Iterable<A>*", "List<B>", "List<B>");
+
+    testLower("Iterable<A>?", "List<B>*", "List<B>*");
+    testLower("Iterable<A>?", "List<B>?", "List<B>?");
+    testLower("Iterable<A>?", "List<B>", "List<B>");
+
+    testLower("Iterable<A>", "List<B>*", "List<B>");
+    testLower("Iterable<A>", "List<B>?", "List<B>");
+    testLower("Iterable<A>", "List<B>", "List<B>");
+
+    testLower("List<B>*", "Iterable<A>*", "List<B>*");
+    testLower("List<B>?", "Iterable<A>*", "List<B>*");
+    testLower("List<B>", "Iterable<A>*", "List<B>");
+
+    testLower("List<B>*", "Iterable<A>?", "List<B>*");
+    testLower("List<B>?", "Iterable<A>?", "List<B>?");
+    testLower("List<B>", "Iterable<A>?", "List<B>");
+
+    testLower("List<B>*", "Iterable<A>", "List<B>");
+    testLower("List<B>?", "Iterable<A>", "List<B>");
+    testLower("List<B>", "Iterable<A>", "List<B>");
   }
 
   void test_lower_bound_top() {
@@ -840,11 +864,20 @@
     testUpper("List<B*>", "Iterable<A*>", "Iterable<A*>");
     testUpper("List<B*>", "Iterable<A?>", "Iterable<A?>");
     testUpper("List<B*>", "Iterable<A>", "Iterable<A>");
+    testUpper("List<B>*", "Iterable<A>*", "Iterable<A>*");
+    testUpper("List<B>*", "Iterable<A>?", "Iterable<A>?");
+    testUpper("List<B>*", "Iterable<A>", "Iterable<A>*");
+    testUpper("List<B>?", "Iterable<A>*", "Iterable<A>?");
+    testUpper("List<B>?", "Iterable<A>?", "Iterable<A>?");
+    testUpper("List<B>?", "Iterable<A>", "Iterable<A>?");
 
     // UP(T1, T2) = T2 if T1 <: T2
     //   Note that both types must be class types at this point
     testUpper("List<B?>", "Iterable<A*>", "Iterable<A*>");
     testUpper("List<B?>", "Iterable<A?>", "Iterable<A?>");
+    testUpper("List<B>?", "Iterable<A>*", "Iterable<A>?");
+    testUpper("List<B>?", "Iterable<A>?", "Iterable<A>?");
+    testUpper("List<B>?", "Iterable<A>", "Iterable<A>?");
     // UP(C0<T0, ..., Tn>, C1<S0, ..., Sk>)
     //     = least upper bound of two interfaces as in Dart 1.
     testUpper("List<B?>", "Iterable<A>", "Object");
@@ -854,22 +887,31 @@
     testUpper("List<B>", "Iterable<A*>", "Iterable<A*>");
     testUpper("List<B>", "Iterable<A?>", "Iterable<A?>");
     testUpper("List<B>", "Iterable<A>", "Iterable<A>");
+    testUpper("List<B>", "Iterable<A>*", "Iterable<A>*");
+    testUpper("List<B>", "Iterable<A>?", "Iterable<A>?");
 
     // UP(T1, T2) = T1 if T2 <: T1
     //   Note that both types must be class types at this point
     testUpper("Iterable<A*>", "List<B*>", "Iterable<A*>");
     testUpper("Iterable<A*>", "List<B?>", "Iterable<A*>");
     testUpper("Iterable<A*>", "List<B>", "Iterable<A*>");
+    testUpper("Iterable<A>*", "List<B>*", "Iterable<A>*");
+    testUpper("Iterable<A>*", "List<B>?", "Iterable<A>?");
+    testUpper("Iterable<A>*", "List<B>", "Iterable<A>*");
 
     // UP(T1, T2) = T1 if T2 <: T1
     //   Note that both types must be class types at this point
     testUpper("Iterable<A?>", "List<B*>", "Iterable<A?>");
     testUpper("Iterable<A?>", "List<B?>", "Iterable<A?>");
     testUpper("Iterable<A?>", "List<B>", "Iterable<A?>");
+    testUpper("Iterable<A>?", "List<B>*", "Iterable<A>?");
+    testUpper("Iterable<A>?", "List<B>?", "Iterable<A>?");
+    testUpper("Iterable<A>?", "List<B>", "Iterable<A>?");
 
     // UP(T1, T2) = T1 if T2 <: T1
     //   Note that both types must be class types at this point
     testUpper("Iterable<A>", "List<B*>", "Iterable<A>");
+    testUpper("Iterable<A>", "List<B>*", "Iterable<A>*");
     // UP(C0<T0, ..., Tn>, C1<S0, ..., Sk>)
     //     = least upper bound of two interfaces as in Dart 1.
     testUpper("Iterable<A>", "List<B?>", "Object");
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 910a00b..55d81db 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.dart
@@ -248,7 +248,6 @@
     isSubtype('Future<int*>*', 'FutureOr<num*>*');
     isSubtype('Future<int*>*', 'FutureOr<Object*>*');
     isSubtype('FutureOr<int*>*', 'FutureOr<int*>*');
-    isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
     isSubtype('FutureOr<int*>*', 'Object*');
     isSubtype('Null', 'FutureOr<num?>');
     isSubtype('Null', 'FutureOr<num>?');
@@ -265,6 +264,14 @@
     isSubtype('FutureOr<X>', 'FutureOr<Future<X>>',
         typeParameters: 'X extends Future<Future<X>>');
 
+    isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
+    isSubtype('FutureOr<A>', 'FutureOr<B>', typeParameters: 'B,A extends B');
+
+    isSubtype('X', 'FutureOr<int>',
+        typeParameters: 'X extends FutureOr<int*>*');
+    isSubtype('X*', 'FutureOr<int>',
+        typeParameters: 'X extends FutureOr<int*>*');
+
     isSubtype('num?', 'FutureOr<FutureOr<FutureOr<num>>?>');
     isSubtype('Future<num>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
     isSubtype('Future<Future<num>>?', 'FutureOr<FutureOr<FutureOr<num>>?>');
@@ -282,6 +289,16 @@
     isSubtype('FutureOr<num>?', 'FutureOr<num?>');
     isObliviousSubtype('FutureOr<num?>', 'FutureOr<num>?');
 
+    isSubtype('List<FutureOr<List<dynamic>>>',
+        'List<FutureOr<List<FutureOr<dynamic>>>>');
+    isSubtype('List<FutureOr<List<FutureOr<dynamic>>>>',
+        'List<FutureOr<List<dynamic>>>');
+
+    isSubtype('X', 'FutureOr<List<X>>',
+        typeParameters: 'X extends FutureOr<List<X>>');
+    isNotSubtype('X', 'FutureOr<List<X>>',
+        typeParameters: 'X extends List<FutureOr<X>>');
+
     isSubtype('dynamic', 'FutureOr<Object?>');
     isSubtype('dynamic', 'FutureOr<Object>?');
     isSubtype('void', 'FutureOr<Object?>');
diff --git a/pkg/front_end/test/fasta/types/subtypes_benchmark.dart b/pkg/front_end/test/fasta/types/subtypes_benchmark.dart
index c869e7c..8a81b61 100644
--- a/pkg/front_end/test/fasta/types/subtypes_benchmark.dart
+++ b/pkg/front_end/test/fasta/types/subtypes_benchmark.dart
@@ -108,8 +108,8 @@
     List<SubtypeCheck> checks, ClassHierarchyBuilder hierarchy) {
   for (int i = 0; i < checks.length; i++) {
     SubtypeCheck check = checks[i];
-    bool isSubtype = hierarchy.types.isSubtypeOfKernel(
-        check.s, check.t, SubtypeCheckMode.ignoringNullabilities);
+    bool isSubtype = hierarchy.types
+        .isSubtypeOf(check.s, check.t, SubtypeCheckMode.ignoringNullabilities);
     if (isSubtype != check.isSubtype) {
       throw "Check failed: $check";
     }
diff --git a/pkg/front_end/test/id_tests/assigned_variables_test.dart b/pkg/front_end/test/id_tests/assigned_variables_test.dart
index cdff0ce..51832e2 100644
--- a/pkg/front_end/test/id_tests/assigned_variables_test.dart
+++ b/pkg/front_end/test/id_tests/assigned_variables_test.dart
@@ -100,7 +100,7 @@
   const _AssignedVariablesDataInterpreter();
 
   @override
-  String getText(_Data actualData) {
+  String getText(_Data actualData, [String indentation]) {
     var parts = <String>[];
     if (actualData.declared.isNotEmpty) {
       parts.add('declared=${_setToString(actualData.declared)}');
diff --git a/pkg/front_end/test/id_tests/definite_assignment_test.dart b/pkg/front_end/test/id_tests/definite_assignment_test.dart
index cb48f84..68b66ed 100644
--- a/pkg/front_end/test/id_tests/definite_assignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_assignment_test.dart
@@ -67,7 +67,7 @@
   String computeNodeValue(Id id, TreeNode node) {
     if (node is VariableGet) {
       TreeNode alias = _sourceLoaderDataForTesting.toOriginal(node);
-      if (_flowResult.unassignedNodes.contains(alias)) {
+      if (_flowResult.potentiallyUnassignedNodes.contains(alias)) {
         return 'unassigned';
       }
     }
diff --git a/pkg/front_end/test/id_tests/inheritance_test.dart b/pkg/front_end/test/id_tests/inheritance_test.dart
index 33de8fd..a042a8a 100644
--- a/pkg/front_end/test/id_tests/inheritance_test.dart
+++ b/pkg/front_end/test/id_tests/inheritance_test.dart
@@ -132,8 +132,17 @@
           type = substitution
               .substituteType(member.function.positionalParameters.single.type);
         } else {
-          type = substitution.substituteType(member.function
-              .computeThisFunctionType(member.enclosingLibrary.nonNullable));
+          Nullability functionTypeNullability;
+          if (node.enclosingLibrary.isNonNullableByDefault) {
+            functionTypeNullability = member.enclosingLibrary.nonNullable;
+          } else {
+            // We don't create a member signature when the member is just
+            // a substitution. We should still take the nullability to be
+            // legacy, though.
+            functionTypeNullability = node.enclosingLibrary.nonNullable;
+          }
+          type = substitution.substituteType(
+              member.function.computeThisFunctionType(functionTypeNullability));
         }
       } else if (member is Field) {
         type = substitution.substituteType(member.type);
diff --git a/pkg/front_end/test/id_tests/reachability_test.dart b/pkg/front_end/test/id_tests/reachability_test.dart
index e0cb2cd..1cdf867 100644
--- a/pkg/front_end/test/id_tests/reachability_test.dart
+++ b/pkg/front_end/test/id_tests/reachability_test.dart
@@ -117,7 +117,8 @@
   const _ReachabilityDataInterpreter();
 
   @override
-  String getText(Set<_ReachabilityAssertion> actualData) =>
+  String getText(Set<_ReachabilityAssertion> actualData,
+          [String indentation]) =>
       _sortedRepresentation(_toStrings(actualData));
 
   @override
diff --git a/pkg/front_end/test/id_tests/type_promotion_test.dart b/pkg/front_end/test/id_tests/type_promotion_test.dart
index 58dd40f..5e963c7 100644
--- a/pkg/front_end/test/id_tests/type_promotion_test.dart
+++ b/pkg/front_end/test/id_tests/type_promotion_test.dart
@@ -61,7 +61,7 @@
   const _TypePromotionDataInterpreter();
 
   @override
-  String getText(DartType actualData) =>
+  String getText(DartType actualData, [String indentation]) =>
       typeToText(actualData, TypeRepresentation.analyzerNonNullableByDefault);
 
   @override
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index c236ac1..db3e01e 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -2,33 +2,32 @@
 # 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.
 
-src/api_unstable/bazel_worker/ImportsTwice: Fail
-src/fasta/incremental_compiler/ImportsTwice: Fail
-src/fasta/kernel/body_builder/ImportsTwice: Fail
-src/fasta/kernel/expression_generator_helper/ImportsTwice: Fail
-src/fasta/parser/parser/ImportsTwice: Fail
-src/fasta/scanner/abstract_scanner/ImportsTwice: Fail
-src/fasta/scanner/recover/ImportsTwice: Fail
-src/fasta/scanner/string_scanner/ImportsTwice: Fail
-src/fasta/scanner/token/ImportsTwice: Fail
-src/fasta/scanner/utf8_bytes_scanner/ImportsTwice: Fail
-src/fasta/source/source_class_builder/ImportsTwice: Fail
-src/fasta/source/value_kinds/ImportsTwice: Fail
-src/fasta/type_inference/type_constraint_gatherer/ImportsTwice: Fail
-src/fasta/type_inference/type_inferrer/ImportsTwice: Fail
-
 src/api_prototype/compiler_options/Exports: Fail
 src/api_prototype/constant_evaluator/Exports: Fail
 src/api_prototype/front_end/Exports: Fail
 src/api_prototype/incremental_kernel_generator/Exports: Fail
+src/api_unstable/bazel_worker/ImportsTwice: Fail
 src/fasta/fasta_codes/Exports: Fail
+src/fasta/incremental_compiler/ImportsTwice: Fail
+src/fasta/kernel/body_builder/ImportsTwice: Fail
 src/fasta/kernel/constant_evaluator/ExplicitType: Pass
+src/fasta/kernel/expression_generator_helper/ImportsTwice: Fail
 src/fasta/kernel/kernel_api/Exports: Fail
 src/fasta/kernel/kernel_ast_api/Exports: Fail
 src/fasta/kernel/kernel_builder/Exports: Fail
 src/fasta/kernel/type_algorithms/Exports: Fail
 src/fasta/messages/Exports: Fail
 src/fasta/parser/Exports: Fail
+src/fasta/parser/parser/ImportsTwice: Fail
+src/fasta/scanner/abstract_scanner/ImportsTwice: Fail
 src/fasta/scanner/Exports: Fail
+src/fasta/scanner/recover/ImportsTwice: Fail
+src/fasta/scanner/string_scanner/ImportsTwice: Fail
+src/fasta/scanner/token/ImportsTwice: Fail
+src/fasta/scanner/utf8_bytes_scanner/ImportsTwice: Fail
 src/fasta/source/scope_listener/Exports: Fail
+src/fasta/source/source_class_builder/ImportsTwice: Fail
+src/fasta/source/value_kinds/ImportsTwice: Fail
+src/fasta/type_inference/type_constraint_gatherer/ImportsTwice: Fail
+src/fasta/type_inference/type_inferrer/ImportsTwice: Fail
 src/testing/id_testing_helper/Exports: Fail
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index 25cf6c1..144ea05 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -1644,6 +1644,18 @@
     doPrint('endWhileStatement(' '$whileKeyword, ' '$endToken)');
   }
 
+  void beginAsOperatorType(Token operator) {
+    seen(operator);
+    doPrint('beginAsOperatorType(' '$operator)');
+    indent++;
+  }
+
+  void endAsOperatorType(Token operator) {
+    indent--;
+    seen(operator);
+    doPrint('endAsOperatorType(' '$operator)');
+  }
+
   void handleAsOperator(Token operator) {
     seen(operator);
     doPrint('handleAsOperator(' '$operator)');
@@ -1775,6 +1787,18 @@
         '$closeSquareBracket)');
   }
 
+  void beginIsOperatorType(Token operator) {
+    seen(operator);
+    doPrint('beginIsOperatorType(' '$operator)');
+    indent++;
+  }
+
+  void endIsOperatorType(Token operator) {
+    indent--;
+    seen(operator);
+    doPrint('endIsOperatorType(' '$operator)');
+  }
+
   void handleIsOperator(Token isOperator, Token not) {
     seen(isOperator);
     seen(not);
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 26b64c8..93a4423 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -43,6 +43,7 @@
 ap
 api
 app
+applicable
 arg
 args
 argument1
@@ -141,6 +142,7 @@
 carets
 carriage
 cascades
+casing
 cast
 casted
 casts
@@ -205,6 +207,7 @@
 config
 configs
 configured
+consideration
 constness
 consult
 consumers
@@ -300,7 +303,6 @@
 dispatched
 divided
 dmitryas
-dupdate
 doc
 docs
 dom
@@ -313,6 +315,7 @@
 dquote
 dst
 dummy
+dupdate
 e
 easy
 ecma
@@ -343,6 +346,7 @@
 equation
 erasure
 es
+established
 estimate
 eval
 excludes
@@ -481,6 +485,7 @@
 imply
 implying
 importantly
+inapplicable
 inc
 incomparable
 inconsistency
@@ -684,6 +689,7 @@
 o
 oauth
 obj
+obligated
 observatory
 observe
 obstruct
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 87d9f28..aae076c 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -1369,6 +1369,7 @@
 identity
 ie
 if
+ignorable
 ignorant
 ignore
 ignored
@@ -1446,6 +1447,7 @@
 inferring
 infers
 infinite
+infinity
 infix
 info
 inform
@@ -1875,6 +1877,7 @@
 names
 namespace
 naming
+nan
 narrow
 narrower
 native
@@ -2556,6 +2559,7 @@
 searching
 second
 section
+security
 see
 seeing
 seem
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 46fad1f..44f1f77 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -61,6 +61,7 @@
 bots
 bowtie
 boz
+bq
 brand
 brave
 brown
@@ -133,6 +134,7 @@
 detector
 deviation
 dfast
+di
 dictionaries
 dictionary
 differences
@@ -159,6 +161,7 @@
 dumping
 dupe
 durations
+dw
 dyn
 e's
 e2e
@@ -272,6 +275,7 @@
 isolate
 isolates
 issue41210b
+issue41436c
 iter
 joo
 jumped
diff --git a/pkg/front_end/test/split_dill_test.dart b/pkg/front_end/test/split_dill_test.dart
index dee8bf3..55f52ba 100644
--- a/pkg/front_end/test/split_dill_test.dart
+++ b/pkg/front_end/test/split_dill_test.dart
@@ -38,7 +38,8 @@
     Component libComponent = new Component(nameRoot: component.root);
     libComponent.libraries.add(lib);
     libComponent.uriToSource.addAll(component.uriToSource);
-    libComponent.mainMethod = component.mainMethod;
+    libComponent.setMainMethodAndMode(
+        component.mainMethodName, true, component.mode);
     libComponents.add(serializeComponent(libComponent));
   }
   print("Serialized ${libComponents.length} separate library components "
diff --git a/pkg/front_end/testcases/expression/spread_element.expression.yaml.expect b/pkg/front_end/testcases/expression/spread_element.expression.yaml.expect
index 522353c..1a1c5a8 100644
--- a/pkg/front_end/testcases/expression/spread_element.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/spread_element.expression.yaml.expect
@@ -4,7 +4,7 @@
   return block {
     final dart.core::List<dart.core::String*>* #t1 = <dart.core::String*>[];
     {
-      dart.core::Iterator<dart.core::String*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::String*>*>(main::listOfStrings).{dart.core::Iterable::iterator};
+      dart.core::Iterator<dart.core::String*>* :sync-for-iterator = main::listOfStrings.{dart.core::Iterable::iterator};
       for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
         final dart.core::String* #t2 = :sync-for-iterator.{dart.core::Iterator::current};
         #t1.{dart.core::List::add}(#t2);
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 47f973b..9b085ee 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
@@ -18,8 +18,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -41,13 +41,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
index bcb6ce3..81805ba 100644
--- a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -32,13 +32,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
index a4a39f8..c86613d 100644
--- a/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -25,21 +25,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method asyncString2() → asy::Future<core::String*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -52,13 +52,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method syncStarString() → core::Iterable<core::String*>* /* originally sync* */ {
@@ -101,8 +101,8 @@
   asy::_AsyncStarStreamController<core::String*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -128,7 +128,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -145,8 +145,8 @@
   asy::_AsyncStarStreamController<core::String*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -163,7 +163,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -180,8 +180,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -195,12 +195,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
index 2d6ae21..bdf5176 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
@@ -22,8 +22,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -56,13 +56,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 
diff --git a/pkg/front_end/testcases/general/await.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await.dart.strong.transformed.expect
index a4fa440..8c66908 100644
--- a/pkg/front_end/testcases/general/await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/await.dart.strong.transformed.expect
@@ -8,8 +8,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -23,12 +23,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
index 8a2da7f..dfafacd 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
@@ -50,8 +50,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -93,21 +93,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method topLevelMembers() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -144,21 +144,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method instanceMembers() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -196,21 +196,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method others() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -248,21 +248,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method conditionals() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -320,21 +320,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method asserts() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -344,7 +344,7 @@
       #L6:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Function*>*>(<core::Function*>[#C1, #C2]).{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t26 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -393,21 +393,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method controlFlow() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -423,7 +423,7 @@
       #L7:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Function*>*>(<core::Function*>[#C1, #C2]).{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t33 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -539,8 +539,8 @@
                 final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
                 asy::FutureOr<dynamic>* :return_value;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -555,13 +555,13 @@
                     asy::_completeOnAsyncReturn(:async_completer, :return_value);
                     return;
                   }
-                  on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                  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.start(:async_op);
+                :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
                 return :async_completer.{asy::Completer::future};
               }).call(), :async_op_then, :async_op_error, :async_op) in null;
               self::expect(42, :result);
@@ -569,8 +569,8 @@
                 final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
                 asy::FutureOr<dynamic>* :return_value;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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 
@@ -583,13 +583,13 @@
                     asy::_completeOnAsyncReturn(:async_completer, :return_value);
                     return;
                   }
-                  on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                  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.start(:async_op);
+                :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
                 return :async_completer.{asy::Completer::future};
               }).call(), :async_op_then, :async_op_error, :async_op) in null;
               self::expect(42, :result);
@@ -597,8 +597,8 @@
                 asy::_AsyncStarStreamController<core::int*>* :controller;
                 dynamic :controller_stream;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -616,7 +616,7 @@
                       }
                       return;
                     }
-                    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                    on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                       :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
                     }
                   finally {
@@ -636,8 +636,8 @@
                 asy::_AsyncStarStreamController<core::int*>* :controller;
                 dynamic :controller_stream;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -655,7 +655,7 @@
                       }
                       return;
                     }
-                    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                    on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                       :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
                     }
                   finally {
@@ -678,21 +678,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method future<T extends core::Object* = dynamic>(self::future::T* value) → asy::FutureOr<self::future::T*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<self::future::T*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::future::T*>();
   asy::FutureOr<self::future::T*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -705,13 +705,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method id<T extends core::Object* = dynamic>(self::id::T* value) → asy::FutureOr<self::id::T*>*
@@ -720,8 +720,8 @@
   asy::_AsyncStarStreamController<core::int*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -738,7 +738,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -755,8 +755,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -784,13 +784,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
index be2d683..72c6420 100644
--- a/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
@@ -14,8 +14,8 @@
     final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
     asy::FutureOr<core::List<core::int*>*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -31,21 +31,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   method _m() → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -58,13 +58,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -72,8 +72,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -87,13 +87,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect
index ca4c8a8..895484d 100644
--- a/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect
@@ -13,8 +13,8 @@
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -27,12 +27,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
index 052b974..fa92a38 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
@@ -25,8 +25,8 @@
   final asy::_AsyncAwaitCompleter<core::List<core::Object*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::Object*>*>();
   asy::FutureOr<core::List<core::Object*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -39,13 +39,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method f2() → core::List<core::Object*>*
@@ -54,8 +54,8 @@
   final asy::_AsyncAwaitCompleter<core::Object*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Object*>();
   asy::FutureOr<core::Object*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -68,21 +68,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method foo() → asy::Future<self::X*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<self::X*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::X*>();
   asy::FutureOr<self::X*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -101,21 +101,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → asy::Future<void>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<void>* :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
   asy::FutureOr<void>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -129,12 +129,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect
index d20f094..1164433 100644
--- a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -27,13 +27,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 
diff --git a/pkg/front_end/testcases/general/constant_truncate.dart b/pkg/front_end/testcases/general/constant_truncate.dart
new file mode 100644
index 0000000..2f2e792
--- /dev/null
+++ b/pkg/front_end/testcases/general/constant_truncate.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 a0 = 0 ~/ 0; // error
+const a1 = 0.0 ~/ 0; // error
+const a2 = -0.0 ~/ 0; // error
+const a3 = double.nan ~/ 0; // error
+const a4 = double.infinity ~/ 0; // error
+const a5 = double.negativeInfinity ~/ 0; // error
+
+const b0 = 0 ~/ 0.0; // error
+const b1 = 0.0 ~/ 0.0; // error
+const b2 = -0.0 ~/ 0.0; // error
+const b3 = double.nan ~/ 0.0; // error
+const b4 = double.infinity ~/ 0.0; // error
+const b5 = double.negativeInfinity ~/ 0.0; // error
+
+const c0 = 0 ~/ -0.0; // error
+const c1 = 0.0 ~/ -0.0; // error
+const c2 = -0.0 ~/ -0.0; // error
+const c3 = double.nan ~/ -0.0; // error
+const c4 = double.infinity ~/ -0.0; // error
+const c5 = double.negativeInfinity ~/ -0.0; // error
+
+const d0 = 0 ~/ double.nan; // error
+const d1 = 0.0 ~/ double.nan; // error
+const d2 = -0.0 ~/ double.nan; // error
+const d3 = double.nan ~/ double.nan; // error
+const d4 = double.infinity ~/ double.nan; // error
+const d5 = double.negativeInfinity ~/ double.nan; // error
+
+const e0 = 0 ~/ double.infinity; // ok
+const e1 = 0.0 ~/ double.infinity; // ok
+const e2 = -0.0 ~/ double.infinity; // ok
+const e3 = double.nan ~/ double.infinity; // error
+const e4 = double.infinity ~/ double.infinity; // error
+const e5 = double.negativeInfinity ~/ double.infinity; // error
+
+const f0 = 0 ~/ double.negativeInfinity; // ok
+const f1 = 0.0 ~/ double.negativeInfinity; // ok
+const f2 = -0.0 ~/ double.negativeInfinity; // ok
+const f3 = double.nan ~/ double.negativeInfinity; // error
+const f4 = double.infinity ~/ double.negativeInfinity; // error
+const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
+
+main() {
+  test(0, 0, () => a0);
+  test(0.0, 0, () => a1);
+  test(-0.0, 0, () => a2);
+  test(double.nan, 0, () => a3);
+  test(double.infinity, 0, () => a4);
+  test(double.negativeInfinity, 0, () => a5);
+
+  test(0, 0.0, () => b0);
+  test(0.0, 0.0, () => b1);
+  test(-0.0, 0.0, () => b2);
+  test(double.nan, 0.0, () => b3);
+  test(double.infinity, 0.0, () => b4);
+  test(double.negativeInfinity, 0.0, () => b5);
+
+  test(0, -0.0, () => c0);
+  test(0.0, -0.0, () => c1);
+  test(-0.0, -0.0, () => c2);
+  test(double.nan, -0.0, () => c3);
+  test(double.infinity, -0.0, () => c4);
+  test(double.negativeInfinity, -0.0, () => c5);
+
+  test(0, double.nan, () => d0);
+  test(0.0, double.nan, () => d1);
+  test(-0.0, double.nan, () => d2);
+  test(double.nan, double.nan, () => d3);
+  test(double.infinity, double.nan, () => d4);
+  test(double.negativeInfinity, double.nan, () => d5);
+
+  test(0, double.infinity, () => e0);
+  test(0.0, double.infinity, () => e1);
+  test(-0.0, double.infinity, () => e2);
+  test(double.nan, double.infinity, () => e3);
+  test(double.infinity, double.infinity, () => e4);
+  test(double.negativeInfinity, double.infinity, () => e5);
+
+  test(0, double.negativeInfinity, () => f0);
+  test(0.0, double.negativeInfinity, () => f1);
+  test(-0.0, double.negativeInfinity, () => f2);
+  test(double.nan, double.negativeInfinity, () => f3);
+  test(double.infinity, double.negativeInfinity, () => f4);
+  test(double.negativeInfinity, double.negativeInfinity, () => f5);
+}
+
+void test(num a, num b, num Function() f) {
+  num result;
+  try {
+    result = a ~/ b;
+    print('$a ~/ $b = $result');
+  } catch (e) {
+    print('$a ~/ $b throws $e');
+    throws(f);
+    return;
+  }
+  expect(f(), result);
+}
+
+void expect(expected, actual) {
+  if (expected != actual) {
+    throw 'Expected $expected, actual $actual';
+  }
+}
+
+void throws(num Function() f) {
+  try {
+    f();
+  } catch (e) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/general/constant_truncate.dart.outline.expect b/pkg/front_end/testcases/general/constant_truncate.dart.outline.expect
new file mode 100644
index 0000000..579ea4a
--- /dev/null
+++ b/pkg/front_end/testcases/general/constant_truncate.dart.outline.expect
@@ -0,0 +1,48 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* a0 = 0.{core::num::~/}(0);
+static const field core::int* a1 = 0.0.{core::double::~/}(0);
+static const field core::int* a2 = 0.0.{core::double::unary-}().{core::double::~/}(0);
+static const field core::int* a3 = core::double::nan.{core::double::~/}(0);
+static const field core::int* a4 = core::double::infinity.{core::double::~/}(0);
+static const field core::int* a5 = core::double::negativeInfinity.{core::double::~/}(0);
+static const field core::int* b0 = 0.{core::num::~/}(0.0);
+static const field core::int* b1 = 0.0.{core::double::~/}(0.0);
+static const field core::int* b2 = 0.0.{core::double::unary-}().{core::double::~/}(0.0);
+static const field core::int* b3 = core::double::nan.{core::double::~/}(0.0);
+static const field core::int* b4 = core::double::infinity.{core::double::~/}(0.0);
+static const field core::int* b5 = core::double::negativeInfinity.{core::double::~/}(0.0);
+static const field core::int* c0 = 0.{core::num::~/}(0.0.{core::double::unary-}());
+static const field core::int* c1 = 0.0.{core::double::~/}(0.0.{core::double::unary-}());
+static const field core::int* c2 = 0.0.{core::double::unary-}().{core::double::~/}(0.0.{core::double::unary-}());
+static const field core::int* c3 = core::double::nan.{core::double::~/}(0.0.{core::double::unary-}());
+static const field core::int* c4 = core::double::infinity.{core::double::~/}(0.0.{core::double::unary-}());
+static const field core::int* c5 = core::double::negativeInfinity.{core::double::~/}(0.0.{core::double::unary-}());
+static const field core::int* d0 = 0.{core::num::~/}(core::double::nan);
+static const field core::int* d1 = 0.0.{core::double::~/}(core::double::nan);
+static const field core::int* d2 = 0.0.{core::double::unary-}().{core::double::~/}(core::double::nan);
+static const field core::int* d3 = core::double::nan.{core::double::~/}(core::double::nan);
+static const field core::int* d4 = core::double::infinity.{core::double::~/}(core::double::nan);
+static const field core::int* d5 = core::double::negativeInfinity.{core::double::~/}(core::double::nan);
+static const field core::int* e0 = 0.{core::num::~/}(core::double::infinity);
+static const field core::int* e1 = 0.0.{core::double::~/}(core::double::infinity);
+static const field core::int* e2 = 0.0.{core::double::unary-}().{core::double::~/}(core::double::infinity);
+static const field core::int* e3 = core::double::nan.{core::double::~/}(core::double::infinity);
+static const field core::int* e4 = core::double::infinity.{core::double::~/}(core::double::infinity);
+static const field core::int* e5 = core::double::negativeInfinity.{core::double::~/}(core::double::infinity);
+static const field core::int* f0 = 0.{core::num::~/}(core::double::negativeInfinity);
+static const field core::int* f1 = 0.0.{core::double::~/}(core::double::negativeInfinity);
+static const field core::int* f2 = 0.0.{core::double::unary-}().{core::double::~/}(core::double::negativeInfinity);
+static const field core::int* f3 = core::double::nan.{core::double::~/}(core::double::negativeInfinity);
+static const field core::int* f4 = core::double::infinity.{core::double::~/}(core::double::negativeInfinity);
+static const field core::int* f5 = core::double::negativeInfinity.{core::double::~/}(core::double::negativeInfinity);
+static method main() → dynamic
+  ;
+static method test(core::num* a, core::num* b, () →* core::num* f) → void
+  ;
+static method expect(dynamic expected, dynamic actual) → void
+  ;
+static method throws(() →* core::num* f) → void
+  ;
diff --git a/pkg/front_end/testcases/general/constant_truncate.dart.strong.expect b/pkg/front_end/testcases/general/constant_truncate.dart.strong.expect
new file mode 100644
index 0000000..5e6673e
--- /dev/null
+++ b/pkg/front_end/testcases/general/constant_truncate.dart.strong.expect
@@ -0,0 +1,415 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:5:14: Error: Constant evaluation error:
+// const a0 = 0 ~/ 0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:5:14: Context: Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.
+// const a0 = 0 ~/ 0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:5:7: Context: While analyzing:
+// const a0 = 0 ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:6:16: Error: Constant evaluation error:
+// const a1 = 0.0 ~/ 0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:6:16: Context: Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.
+// const a1 = 0.0 ~/ 0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:6:7: Context: While analyzing:
+// const a1 = 0.0 ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:7:17: Error: Constant evaluation error:
+// const a2 = -0.0 ~/ 0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:7:17: Context: Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.
+// const a2 = -0.0 ~/ 0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:7:7: Context: While analyzing:
+// const a2 = -0.0 ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:8:23: Error: Constant evaluation error:
+// const a3 = double.nan ~/ 0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:8:23: Context: Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.
+// const a3 = double.nan ~/ 0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:8:7: Context: While analyzing:
+// const a3 = double.nan ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:9:28: Error: Constant evaluation error:
+// const a4 = double.infinity ~/ 0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:9:28: Context: Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.
+// const a4 = double.infinity ~/ 0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:9:7: Context: While analyzing:
+// const a4 = double.infinity ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:10:36: Error: Constant evaluation error:
+// const a5 = double.negativeInfinity ~/ 0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:10:36: Context: Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.
+// const a5 = double.negativeInfinity ~/ 0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:10:7: Context: While analyzing:
+// const a5 = double.negativeInfinity ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:12:14: Error: Constant evaluation error:
+// const b0 = 0 ~/ 0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:12:14: Context: Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.
+// const b0 = 0 ~/ 0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:12:7: Context: While analyzing:
+// const b0 = 0 ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:13:16: Error: Constant evaluation error:
+// const b1 = 0.0 ~/ 0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:13:16: Context: Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.
+// const b1 = 0.0 ~/ 0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:13:7: Context: While analyzing:
+// const b1 = 0.0 ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:14:17: Error: Constant evaluation error:
+// const b2 = -0.0 ~/ 0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:14:17: Context: Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.
+// const b2 = -0.0 ~/ 0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:14:7: Context: While analyzing:
+// const b2 = -0.0 ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:15:23: Error: Constant evaluation error:
+// const b3 = double.nan ~/ 0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:15:23: Context: Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.
+// const b3 = double.nan ~/ 0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:15:7: Context: While analyzing:
+// const b3 = double.nan ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:16:28: Error: Constant evaluation error:
+// const b4 = double.infinity ~/ 0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:16:28: Context: Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.
+// const b4 = double.infinity ~/ 0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:16:7: Context: While analyzing:
+// const b4 = double.infinity ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:17:36: Error: Constant evaluation error:
+// const b5 = double.negativeInfinity ~/ 0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:17:36: Context: Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.
+// const b5 = double.negativeInfinity ~/ 0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:17:7: Context: While analyzing:
+// const b5 = double.negativeInfinity ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:19:14: Error: Constant evaluation error:
+// const c0 = 0 ~/ -0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:19:14: Context: Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.
+// const c0 = 0 ~/ -0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:19:7: Context: While analyzing:
+// const c0 = 0 ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:20:16: Error: Constant evaluation error:
+// const c1 = 0.0 ~/ -0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:20:16: Context: Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.
+// const c1 = 0.0 ~/ -0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:20:7: Context: While analyzing:
+// const c1 = 0.0 ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:21:17: Error: Constant evaluation error:
+// const c2 = -0.0 ~/ -0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:21:17: Context: Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.
+// const c2 = -0.0 ~/ -0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:21:7: Context: While analyzing:
+// const c2 = -0.0 ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:22:23: Error: Constant evaluation error:
+// const c3 = double.nan ~/ -0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:22:23: Context: Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.
+// const c3 = double.nan ~/ -0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:22:7: Context: While analyzing:
+// const c3 = double.nan ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:23:28: Error: Constant evaluation error:
+// const c4 = double.infinity ~/ -0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:23:28: Context: Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.
+// const c4 = double.infinity ~/ -0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:23:7: Context: While analyzing:
+// const c4 = double.infinity ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:24:36: Error: Constant evaluation error:
+// const c5 = double.negativeInfinity ~/ -0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:24:36: Context: Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.
+// const c5 = double.negativeInfinity ~/ -0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:24:7: Context: While analyzing:
+// const c5 = double.negativeInfinity ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:26:14: Error: Constant evaluation error:
+// const d0 = 0 ~/ double.nan; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:26:14: Context: Binary operator '0 ~/ NaN' results is Infinity or NaN.
+// const d0 = 0 ~/ double.nan; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:26:7: Context: While analyzing:
+// const d0 = 0 ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:27:16: Error: Constant evaluation error:
+// const d1 = 0.0 ~/ double.nan; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:27:16: Context: Binary operator '0.0 ~/ NaN' results is Infinity or NaN.
+// const d1 = 0.0 ~/ double.nan; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:27:7: Context: While analyzing:
+// const d1 = 0.0 ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:28:17: Error: Constant evaluation error:
+// const d2 = -0.0 ~/ double.nan; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:28:17: Context: Binary operator '-0.0 ~/ NaN' results is Infinity or NaN.
+// const d2 = -0.0 ~/ double.nan; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:28:7: Context: While analyzing:
+// const d2 = -0.0 ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:29:23: Error: Constant evaluation error:
+// const d3 = double.nan ~/ double.nan; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:29:23: Context: Binary operator 'NaN ~/ NaN' results is Infinity or NaN.
+// const d3 = double.nan ~/ double.nan; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:29:7: Context: While analyzing:
+// const d3 = double.nan ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:30:28: Error: Constant evaluation error:
+// const d4 = double.infinity ~/ double.nan; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:30:28: Context: Binary operator 'Infinity ~/ NaN' results is Infinity or NaN.
+// const d4 = double.infinity ~/ double.nan; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:30:7: Context: While analyzing:
+// const d4 = double.infinity ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:31:36: Error: Constant evaluation error:
+// const d5 = double.negativeInfinity ~/ double.nan; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:31:36: Context: Binary operator '-Infinity ~/ NaN' results is Infinity or NaN.
+// const d5 = double.negativeInfinity ~/ double.nan; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:31:7: Context: While analyzing:
+// const d5 = double.negativeInfinity ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:36:23: Error: Constant evaluation error:
+// const e3 = double.nan ~/ double.infinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:36:23: Context: Binary operator 'NaN ~/ Infinity' results is Infinity or NaN.
+// const e3 = double.nan ~/ double.infinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:36:7: Context: While analyzing:
+// const e3 = double.nan ~/ double.infinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:37:28: Error: Constant evaluation error:
+// const e4 = double.infinity ~/ double.infinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:37:28: Context: Binary operator 'Infinity ~/ Infinity' results is Infinity or NaN.
+// const e4 = double.infinity ~/ double.infinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:37:7: Context: While analyzing:
+// const e4 = double.infinity ~/ double.infinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:38:36: Error: Constant evaluation error:
+// const e5 = double.negativeInfinity ~/ double.infinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:38:36: Context: Binary operator '-Infinity ~/ Infinity' results is Infinity or NaN.
+// const e5 = double.negativeInfinity ~/ double.infinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:38:7: Context: While analyzing:
+// const e5 = double.negativeInfinity ~/ double.infinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:43:23: Error: Constant evaluation error:
+// const f3 = double.nan ~/ double.negativeInfinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:43:23: Context: Binary operator 'NaN ~/ -Infinity' results is Infinity or NaN.
+// const f3 = double.nan ~/ double.negativeInfinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:43:7: Context: While analyzing:
+// const f3 = double.nan ~/ double.negativeInfinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:44:28: Error: Constant evaluation error:
+// const f4 = double.infinity ~/ double.negativeInfinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:44:28: Context: Binary operator 'Infinity ~/ -Infinity' results is Infinity or NaN.
+// const f4 = double.infinity ~/ double.negativeInfinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:44:7: Context: While analyzing:
+// const f4 = double.infinity ~/ double.negativeInfinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:45:36: Error: Constant evaluation error:
+// const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:45:36: Context: Binary operator '-Infinity ~/ -Infinity' results is Infinity or NaN.
+// const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:45:7: Context: While analyzing:
+// const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
+//       ^
+//
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* a0 = invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a1 = invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a2 = invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a3 = invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a4 = invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a5 = invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b0 = invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b1 = invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b2 = invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b3 = invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b4 = invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b5 = invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c0 = invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c1 = invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c2 = invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c3 = invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c4 = invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c5 = invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* d0 = invalid-expression "Binary operator '0 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d1 = invalid-expression "Binary operator '0.0 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d2 = invalid-expression "Binary operator '-0.0 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d3 = invalid-expression "Binary operator 'NaN ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d4 = invalid-expression "Binary operator 'Infinity ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d5 = invalid-expression "Binary operator '-Infinity ~/ NaN' results is Infinity or NaN.";
+static const field core::int* e0 = #C1;
+static const field core::int* e1 = #C1;
+static const field core::int* e2 = #C1;
+static const field core::int* e3 = invalid-expression "Binary operator 'NaN ~/ Infinity' results is Infinity or NaN.";
+static const field core::int* e4 = invalid-expression "Binary operator 'Infinity ~/ Infinity' results is Infinity or NaN.";
+static const field core::int* e5 = invalid-expression "Binary operator '-Infinity ~/ Infinity' results is Infinity or NaN.";
+static const field core::int* f0 = #C1;
+static const field core::int* f1 = #C1;
+static const field core::int* f2 = #C1;
+static const field core::int* f3 = invalid-expression "Binary operator 'NaN ~/ -Infinity' results is Infinity or NaN.";
+static const field core::int* f4 = invalid-expression "Binary operator 'Infinity ~/ -Infinity' results is Infinity or NaN.";
+static const field core::int* f5 = invalid-expression "Binary operator '-Infinity ~/ -Infinity' results is Infinity or NaN.";
+static method main() → dynamic {
+  self::test(0, 0, () → core::int* => invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0, 0, () → core::int* => invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0.{core::double::unary-}(), 0, () → core::int* => invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C2, 0, () → core::int* => invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C3, 0, () → core::int* => invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C4, 0, () → core::int* => invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(0, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0.{core::double::unary-}(), 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C2, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C3, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C4, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(0, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0.{core::double::unary-}(), 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C2, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C3, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C4, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(0, #C2, () → core::int* => invalid-expression "Binary operator '0 ~/ NaN' results is Infinity or NaN.");
+  self::test(0.0, #C2, () → core::int* => invalid-expression "Binary operator '0.0 ~/ NaN' results is Infinity or NaN.");
+  self::test(0.0.{core::double::unary-}(), #C2, () → core::int* => invalid-expression "Binary operator '-0.0 ~/ NaN' results is Infinity or NaN.");
+  self::test(#C2, #C2, () → core::int* => invalid-expression "Binary operator 'NaN ~/ NaN' results is Infinity or NaN.");
+  self::test(#C3, #C2, () → core::int* => invalid-expression "Binary operator 'Infinity ~/ NaN' results is Infinity or NaN.");
+  self::test(#C4, #C2, () → core::int* => invalid-expression "Binary operator '-Infinity ~/ NaN' results is Infinity or NaN.");
+  self::test(0, #C3, () → core::int* => #C1);
+  self::test(0.0, #C3, () → core::int* => #C1);
+  self::test(0.0.{core::double::unary-}(), #C3, () → core::int* => #C1);
+  self::test(#C2, #C3, () → core::int* => invalid-expression "Binary operator 'NaN ~/ Infinity' results is Infinity or NaN.");
+  self::test(#C3, #C3, () → core::int* => invalid-expression "Binary operator 'Infinity ~/ Infinity' results is Infinity or NaN.");
+  self::test(#C4, #C3, () → core::int* => invalid-expression "Binary operator '-Infinity ~/ Infinity' results is Infinity or NaN.");
+  self::test(0, #C4, () → core::int* => #C1);
+  self::test(0.0, #C4, () → core::int* => #C1);
+  self::test(0.0.{core::double::unary-}(), #C4, () → core::int* => #C1);
+  self::test(#C2, #C4, () → core::int* => invalid-expression "Binary operator 'NaN ~/ -Infinity' results is Infinity or NaN.");
+  self::test(#C3, #C4, () → core::int* => invalid-expression "Binary operator 'Infinity ~/ -Infinity' results is Infinity or NaN.");
+  self::test(#C4, #C4, () → core::int* => invalid-expression "Binary operator '-Infinity ~/ -Infinity' results is Infinity or NaN.");
+}
+static method test(core::num* a, core::num* b, () →* core::num* f) → void {
+  core::num* result;
+  try {
+    result = a.{core::num::~/}(b);
+    core::print("${a} ~/ ${b} = ${result}");
+  }
+  on dynamic catch(final dynamic e) {
+    core::print("${a} ~/ ${b} throws ${e}");
+    self::throws(f);
+    return;
+  }
+  self::expect(f.call(), result);
+}
+static method expect(dynamic expected, dynamic actual) → void {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Expected ${expected}, actual ${actual}";
+  }
+}
+static method throws(() →* core::num* f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic e) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 0
+  #C2 = NaN
+  #C3 = Infinity
+  #C4 = -Infinity
+}
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
new file mode 100644
index 0000000..5e6673e
--- /dev/null
+++ b/pkg/front_end/testcases/general/constant_truncate.dart.strong.transformed.expect
@@ -0,0 +1,415 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:5:14: Error: Constant evaluation error:
+// const a0 = 0 ~/ 0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:5:14: Context: Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.
+// const a0 = 0 ~/ 0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:5:7: Context: While analyzing:
+// const a0 = 0 ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:6:16: Error: Constant evaluation error:
+// const a1 = 0.0 ~/ 0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:6:16: Context: Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.
+// const a1 = 0.0 ~/ 0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:6:7: Context: While analyzing:
+// const a1 = 0.0 ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:7:17: Error: Constant evaluation error:
+// const a2 = -0.0 ~/ 0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:7:17: Context: Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.
+// const a2 = -0.0 ~/ 0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:7:7: Context: While analyzing:
+// const a2 = -0.0 ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:8:23: Error: Constant evaluation error:
+// const a3 = double.nan ~/ 0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:8:23: Context: Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.
+// const a3 = double.nan ~/ 0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:8:7: Context: While analyzing:
+// const a3 = double.nan ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:9:28: Error: Constant evaluation error:
+// const a4 = double.infinity ~/ 0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:9:28: Context: Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.
+// const a4 = double.infinity ~/ 0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:9:7: Context: While analyzing:
+// const a4 = double.infinity ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:10:36: Error: Constant evaluation error:
+// const a5 = double.negativeInfinity ~/ 0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:10:36: Context: Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.
+// const a5 = double.negativeInfinity ~/ 0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:10:7: Context: While analyzing:
+// const a5 = double.negativeInfinity ~/ 0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:12:14: Error: Constant evaluation error:
+// const b0 = 0 ~/ 0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:12:14: Context: Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.
+// const b0 = 0 ~/ 0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:12:7: Context: While analyzing:
+// const b0 = 0 ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:13:16: Error: Constant evaluation error:
+// const b1 = 0.0 ~/ 0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:13:16: Context: Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.
+// const b1 = 0.0 ~/ 0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:13:7: Context: While analyzing:
+// const b1 = 0.0 ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:14:17: Error: Constant evaluation error:
+// const b2 = -0.0 ~/ 0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:14:17: Context: Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.
+// const b2 = -0.0 ~/ 0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:14:7: Context: While analyzing:
+// const b2 = -0.0 ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:15:23: Error: Constant evaluation error:
+// const b3 = double.nan ~/ 0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:15:23: Context: Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.
+// const b3 = double.nan ~/ 0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:15:7: Context: While analyzing:
+// const b3 = double.nan ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:16:28: Error: Constant evaluation error:
+// const b4 = double.infinity ~/ 0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:16:28: Context: Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.
+// const b4 = double.infinity ~/ 0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:16:7: Context: While analyzing:
+// const b4 = double.infinity ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:17:36: Error: Constant evaluation error:
+// const b5 = double.negativeInfinity ~/ 0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:17:36: Context: Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.
+// const b5 = double.negativeInfinity ~/ 0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:17:7: Context: While analyzing:
+// const b5 = double.negativeInfinity ~/ 0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:19:14: Error: Constant evaluation error:
+// const c0 = 0 ~/ -0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:19:14: Context: Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.
+// const c0 = 0 ~/ -0.0; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:19:7: Context: While analyzing:
+// const c0 = 0 ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:20:16: Error: Constant evaluation error:
+// const c1 = 0.0 ~/ -0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:20:16: Context: Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.
+// const c1 = 0.0 ~/ -0.0; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:20:7: Context: While analyzing:
+// const c1 = 0.0 ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:21:17: Error: Constant evaluation error:
+// const c2 = -0.0 ~/ -0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:21:17: Context: Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.
+// const c2 = -0.0 ~/ -0.0; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:21:7: Context: While analyzing:
+// const c2 = -0.0 ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:22:23: Error: Constant evaluation error:
+// const c3 = double.nan ~/ -0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:22:23: Context: Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.
+// const c3 = double.nan ~/ -0.0; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:22:7: Context: While analyzing:
+// const c3 = double.nan ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:23:28: Error: Constant evaluation error:
+// const c4 = double.infinity ~/ -0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:23:28: Context: Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.
+// const c4 = double.infinity ~/ -0.0; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:23:7: Context: While analyzing:
+// const c4 = double.infinity ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:24:36: Error: Constant evaluation error:
+// const c5 = double.negativeInfinity ~/ -0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:24:36: Context: Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.
+// const c5 = double.negativeInfinity ~/ -0.0; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:24:7: Context: While analyzing:
+// const c5 = double.negativeInfinity ~/ -0.0; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:26:14: Error: Constant evaluation error:
+// const d0 = 0 ~/ double.nan; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:26:14: Context: Binary operator '0 ~/ NaN' results is Infinity or NaN.
+// const d0 = 0 ~/ double.nan; // error
+//              ^
+// pkg/front_end/testcases/general/constant_truncate.dart:26:7: Context: While analyzing:
+// const d0 = 0 ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:27:16: Error: Constant evaluation error:
+// const d1 = 0.0 ~/ double.nan; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:27:16: Context: Binary operator '0.0 ~/ NaN' results is Infinity or NaN.
+// const d1 = 0.0 ~/ double.nan; // error
+//                ^
+// pkg/front_end/testcases/general/constant_truncate.dart:27:7: Context: While analyzing:
+// const d1 = 0.0 ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:28:17: Error: Constant evaluation error:
+// const d2 = -0.0 ~/ double.nan; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:28:17: Context: Binary operator '-0.0 ~/ NaN' results is Infinity or NaN.
+// const d2 = -0.0 ~/ double.nan; // error
+//                 ^
+// pkg/front_end/testcases/general/constant_truncate.dart:28:7: Context: While analyzing:
+// const d2 = -0.0 ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:29:23: Error: Constant evaluation error:
+// const d3 = double.nan ~/ double.nan; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:29:23: Context: Binary operator 'NaN ~/ NaN' results is Infinity or NaN.
+// const d3 = double.nan ~/ double.nan; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:29:7: Context: While analyzing:
+// const d3 = double.nan ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:30:28: Error: Constant evaluation error:
+// const d4 = double.infinity ~/ double.nan; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:30:28: Context: Binary operator 'Infinity ~/ NaN' results is Infinity or NaN.
+// const d4 = double.infinity ~/ double.nan; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:30:7: Context: While analyzing:
+// const d4 = double.infinity ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:31:36: Error: Constant evaluation error:
+// const d5 = double.negativeInfinity ~/ double.nan; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:31:36: Context: Binary operator '-Infinity ~/ NaN' results is Infinity or NaN.
+// const d5 = double.negativeInfinity ~/ double.nan; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:31:7: Context: While analyzing:
+// const d5 = double.negativeInfinity ~/ double.nan; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:36:23: Error: Constant evaluation error:
+// const e3 = double.nan ~/ double.infinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:36:23: Context: Binary operator 'NaN ~/ Infinity' results is Infinity or NaN.
+// const e3 = double.nan ~/ double.infinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:36:7: Context: While analyzing:
+// const e3 = double.nan ~/ double.infinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:37:28: Error: Constant evaluation error:
+// const e4 = double.infinity ~/ double.infinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:37:28: Context: Binary operator 'Infinity ~/ Infinity' results is Infinity or NaN.
+// const e4 = double.infinity ~/ double.infinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:37:7: Context: While analyzing:
+// const e4 = double.infinity ~/ double.infinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:38:36: Error: Constant evaluation error:
+// const e5 = double.negativeInfinity ~/ double.infinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:38:36: Context: Binary operator '-Infinity ~/ Infinity' results is Infinity or NaN.
+// const e5 = double.negativeInfinity ~/ double.infinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:38:7: Context: While analyzing:
+// const e5 = double.negativeInfinity ~/ double.infinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:43:23: Error: Constant evaluation error:
+// const f3 = double.nan ~/ double.negativeInfinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:43:23: Context: Binary operator 'NaN ~/ -Infinity' results is Infinity or NaN.
+// const f3 = double.nan ~/ double.negativeInfinity; // error
+//                       ^
+// pkg/front_end/testcases/general/constant_truncate.dart:43:7: Context: While analyzing:
+// const f3 = double.nan ~/ double.negativeInfinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:44:28: Error: Constant evaluation error:
+// const f4 = double.infinity ~/ double.negativeInfinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:44:28: Context: Binary operator 'Infinity ~/ -Infinity' results is Infinity or NaN.
+// const f4 = double.infinity ~/ double.negativeInfinity; // error
+//                            ^
+// pkg/front_end/testcases/general/constant_truncate.dart:44:7: Context: While analyzing:
+// const f4 = double.infinity ~/ double.negativeInfinity; // error
+//       ^
+//
+// pkg/front_end/testcases/general/constant_truncate.dart:45:36: Error: Constant evaluation error:
+// const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:45:36: Context: Binary operator '-Infinity ~/ -Infinity' results is Infinity or NaN.
+// const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
+//                                    ^
+// pkg/front_end/testcases/general/constant_truncate.dart:45:7: Context: While analyzing:
+// const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
+//       ^
+//
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* a0 = invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a1 = invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a2 = invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a3 = invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a4 = invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* a5 = invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b0 = invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b1 = invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b2 = invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b3 = invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b4 = invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* b5 = invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c0 = invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c1 = invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c2 = invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c3 = invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c4 = invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* c5 = invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* d0 = invalid-expression "Binary operator '0 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d1 = invalid-expression "Binary operator '0.0 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d2 = invalid-expression "Binary operator '-0.0 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d3 = invalid-expression "Binary operator 'NaN ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d4 = invalid-expression "Binary operator 'Infinity ~/ NaN' results is Infinity or NaN.";
+static const field core::int* d5 = invalid-expression "Binary operator '-Infinity ~/ NaN' results is Infinity or NaN.";
+static const field core::int* e0 = #C1;
+static const field core::int* e1 = #C1;
+static const field core::int* e2 = #C1;
+static const field core::int* e3 = invalid-expression "Binary operator 'NaN ~/ Infinity' results is Infinity or NaN.";
+static const field core::int* e4 = invalid-expression "Binary operator 'Infinity ~/ Infinity' results is Infinity or NaN.";
+static const field core::int* e5 = invalid-expression "Binary operator '-Infinity ~/ Infinity' results is Infinity or NaN.";
+static const field core::int* f0 = #C1;
+static const field core::int* f1 = #C1;
+static const field core::int* f2 = #C1;
+static const field core::int* f3 = invalid-expression "Binary operator 'NaN ~/ -Infinity' results is Infinity or NaN.";
+static const field core::int* f4 = invalid-expression "Binary operator 'Infinity ~/ -Infinity' results is Infinity or NaN.";
+static const field core::int* f5 = invalid-expression "Binary operator '-Infinity ~/ -Infinity' results is Infinity or NaN.";
+static method main() → dynamic {
+  self::test(0, 0, () → core::int* => invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0, 0, () → core::int* => invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0.{core::double::unary-}(), 0, () → core::int* => invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C2, 0, () → core::int* => invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C3, 0, () → core::int* => invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C4, 0, () → core::int* => invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(0, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0.{core::double::unary-}(), 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C2, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C3, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C4, 0.0, () → core::int* => invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(0, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(0.0.{core::double::unary-}(), 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '-0.0' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C2, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on 'NaN' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C3, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on 'Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(#C4, 0.0.{core::double::unary-}(), () → core::int* => invalid-expression "Binary operator '~/' on '-Infinity' requires non-zero divisor, but divisor was '0'.");
+  self::test(0, #C2, () → core::int* => invalid-expression "Binary operator '0 ~/ NaN' results is Infinity or NaN.");
+  self::test(0.0, #C2, () → core::int* => invalid-expression "Binary operator '0.0 ~/ NaN' results is Infinity or NaN.");
+  self::test(0.0.{core::double::unary-}(), #C2, () → core::int* => invalid-expression "Binary operator '-0.0 ~/ NaN' results is Infinity or NaN.");
+  self::test(#C2, #C2, () → core::int* => invalid-expression "Binary operator 'NaN ~/ NaN' results is Infinity or NaN.");
+  self::test(#C3, #C2, () → core::int* => invalid-expression "Binary operator 'Infinity ~/ NaN' results is Infinity or NaN.");
+  self::test(#C4, #C2, () → core::int* => invalid-expression "Binary operator '-Infinity ~/ NaN' results is Infinity or NaN.");
+  self::test(0, #C3, () → core::int* => #C1);
+  self::test(0.0, #C3, () → core::int* => #C1);
+  self::test(0.0.{core::double::unary-}(), #C3, () → core::int* => #C1);
+  self::test(#C2, #C3, () → core::int* => invalid-expression "Binary operator 'NaN ~/ Infinity' results is Infinity or NaN.");
+  self::test(#C3, #C3, () → core::int* => invalid-expression "Binary operator 'Infinity ~/ Infinity' results is Infinity or NaN.");
+  self::test(#C4, #C3, () → core::int* => invalid-expression "Binary operator '-Infinity ~/ Infinity' results is Infinity or NaN.");
+  self::test(0, #C4, () → core::int* => #C1);
+  self::test(0.0, #C4, () → core::int* => #C1);
+  self::test(0.0.{core::double::unary-}(), #C4, () → core::int* => #C1);
+  self::test(#C2, #C4, () → core::int* => invalid-expression "Binary operator 'NaN ~/ -Infinity' results is Infinity or NaN.");
+  self::test(#C3, #C4, () → core::int* => invalid-expression "Binary operator 'Infinity ~/ -Infinity' results is Infinity or NaN.");
+  self::test(#C4, #C4, () → core::int* => invalid-expression "Binary operator '-Infinity ~/ -Infinity' results is Infinity or NaN.");
+}
+static method test(core::num* a, core::num* b, () →* core::num* f) → void {
+  core::num* result;
+  try {
+    result = a.{core::num::~/}(b);
+    core::print("${a} ~/ ${b} = ${result}");
+  }
+  on dynamic catch(final dynamic e) {
+    core::print("${a} ~/ ${b} throws ${e}");
+    self::throws(f);
+    return;
+  }
+  self::expect(f.call(), result);
+}
+static method expect(dynamic expected, dynamic actual) → void {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Expected ${expected}, actual ${actual}";
+  }
+}
+static method throws(() →* core::num* f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic e) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 0
+  #C2 = NaN
+  #C3 = Infinity
+  #C4 = -Infinity
+}
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 7bd3d63..9cdff84 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
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method main() → dynamic {
@@ -18,14 +17,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t1.{core::List::add}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -48,14 +47,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t2.{core::Set::add}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t2.{core::Set::add}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -78,14 +77,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t3.{core::Map::[]=}(4, 4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Map::[]=}(i, i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
index 1c89f63..0057f19 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
@@ -424,8 +424,8 @@
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
-import "dart:_internal" as _in;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 class A extends core::Object {
   synthetic constructor •() → self::A*
@@ -496,7 +496,7 @@
   core::List<core::int*>* list20 = block {
     final core::List<core::int*>* #t10 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         #t10.{core::List::add}(#t11);
@@ -506,7 +506,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t12 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t13 = :sync-for-iterator.{core::Iterator::current};
         #t12.{core::Set::add}(#t13);
@@ -517,7 +517,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t14 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t15 = :sync-for-iterator.{core::Iterator::current};
         #t14.{core::Map::[]=}(#t15.{core::MapEntry::key}, #t15.{core::MapEntry::value});
@@ -528,7 +528,7 @@
   core::List<dynamic>* list21 = block {
     final core::List<dynamic>* #t16 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t17 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::List::add}(#t17);
@@ -538,7 +538,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t18 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t19 = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::Set::add}(#t19);
@@ -549,7 +549,7 @@
   core::Map<core::String*, dynamic>* map21 = block {
     final core::Map<core::String*, dynamic>* #t20 = <core::String*, dynamic>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, dynamic>* #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
@@ -560,7 +560,7 @@
   core::List<core::List<core::int*>*>* list22 = block {
     final core::List<core::List<core::int*>*>* #t22 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t23 = :sync-for-iterator.{core::Iterator::current};
         #t22.{core::List::add}(#t23);
@@ -570,7 +570,7 @@
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t24 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t25 = :sync-for-iterator.{core::Iterator::current};
         #t24.{core::Set::add}(#t25);
@@ -581,7 +581,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t26 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t27 = :sync-for-iterator.{core::Iterator::current};
         #t26.{core::Map::[]=}(#t27.{core::MapEntry::key}, #t27.{core::MapEntry::value});
@@ -593,7 +593,7 @@
     final core::List<core::int*>* #t28 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t29 = :sync-for-iterator.{core::Iterator::current};
           #t28.{core::List::add}(#t29);
@@ -604,7 +604,7 @@
     final core::Set<core::int*>* #t30 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t31 = :sync-for-iterator.{core::Iterator::current};
           #t30.{core::Set::add}(#t31);
@@ -616,7 +616,7 @@
     final core::Map<core::String*, core::int*>* #t32 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t33 = :sync-for-iterator.{core::Iterator::current};
           #t32.{core::Map::[]=}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
@@ -628,7 +628,7 @@
     final core::List<dynamic>* #t34 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t35 = :sync-for-iterator.{core::Iterator::current};
           #t34.{core::List::add}(#t35);
@@ -639,7 +639,7 @@
     final core::Set<dynamic>* #t36 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t37 = :sync-for-iterator.{core::Iterator::current};
           #t36.{core::Set::add}(#t37);
@@ -651,7 +651,7 @@
     final core::Map<core::String*, dynamic>* #t38 = <core::String*, dynamic>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, dynamic>* #t39 = :sync-for-iterator.{core::Iterator::current};
           #t38.{core::Map::[]=}(#t39.{core::MapEntry::key}, #t39.{core::MapEntry::value});
@@ -663,7 +663,7 @@
     final core::List<core::List<core::int*>*>* #t40 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t41 = :sync-for-iterator.{core::Iterator::current};
           #t40.{core::List::add}(#t41);
@@ -674,7 +674,7 @@
     final core::Set<core::List<core::int*>*>* #t42 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t43 = :sync-for-iterator.{core::Iterator::current};
           #t42.{core::Set::add}(#t43);
@@ -686,7 +686,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t44 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t45 = :sync-for-iterator.{core::Iterator::current};
           #t44.{core::Map::[]=}(#t45.{core::MapEntry::key}, #t45.{core::MapEntry::value});
@@ -697,7 +697,7 @@
   core::List<core::List<core::int*>*>* list40 = block {
     final core::List<core::List<core::int*>*>* #t46 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t47 = :sync-for-iterator.{core::Iterator::current};
         #t46.{core::List::add}(#t47);
@@ -707,7 +707,7 @@
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t48 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t49 = :sync-for-iterator.{core::Iterator::current};
         #t48.{core::Set::add}(#t49);
@@ -721,7 +721,7 @@
   core::List<core::List<core::int*>*>* list41 = block {
     final core::List<core::List<core::int*>*>* #t50 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t51 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t52 = #t51.{core::Set::add}(<core::int*>[]) in #t51).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t51 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t52 = #t51.{core::Set::add}(<core::int*>[]) in #t51).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t53 = :sync-for-iterator.{core::Iterator::current};
         #t50.{core::List::add}(#t53);
@@ -731,7 +731,7 @@
   core::Set<core::List<core::int*>*>* set41 = block {
     final core::Set<core::List<core::int*>*>* #t54 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t55 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t56 = #t55.{core::Set::add}(<core::int*>[]) in #t55).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t55 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t56 = #t55.{core::Set::add}(<core::int*>[]) in #t55).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t57 = :sync-for-iterator.{core::Iterator::current};
         #t54.{core::Set::add}(#t57);
@@ -743,7 +743,7 @@
     final core::List<core::List<core::int*>*>* #t58 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t59 = :sync-for-iterator.{core::Iterator::current};
           #t58.{core::List::add}(#t59);
@@ -754,7 +754,7 @@
     final core::Set<core::List<core::int*>*>* #t60 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t61 = :sync-for-iterator.{core::Iterator::current};
           #t60.{core::Set::add}(#t61);
@@ -766,7 +766,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t62 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t63 = :sync-for-iterator.{core::Iterator::current};
           #t62.{core::Map::[]=}(#t63.{core::MapEntry::key}, #t63.{core::MapEntry::value});
@@ -777,7 +777,7 @@
   core::List<core::int*>* list50 = block {
     final core::List<core::int*>* #t64 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t65 = :sync-for-iterator.{core::Iterator::current};
         #t64.{core::List::add}(#t65);
@@ -787,7 +787,7 @@
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t66 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t67 = :sync-for-iterator.{core::Iterator::current};
         #t66.{core::Set::add}(#t67);
@@ -798,7 +798,7 @@
   core::Map<core::String*, core::int*>* map50 = block {
     final core::Map<core::String*, core::int*>* #t68 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t69 = :sync-for-iterator.{core::Iterator::current};
         #t68.{core::Map::[]=}(#t69.{core::MapEntry::key}, #t69.{core::MapEntry::value});
@@ -809,7 +809,7 @@
   core::List<core::int*>* list51 = block {
     final core::List<core::int*>* #t70 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t71 = col::LinkedHashSet::•<core::int*>() in #t71).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t71 = col::LinkedHashSet::•<core::int*>() in #t71).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t72 = :sync-for-iterator.{core::Iterator::current};
         #t70.{core::List::add}(#t72);
@@ -819,7 +819,7 @@
   core::Set<core::int*>* set51 = block {
     final core::Set<core::int*>* #t73 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>() in #t74).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>() in #t74).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t75 = :sync-for-iterator.{core::Iterator::current};
         #t73.{core::Set::add}(#t75);
@@ -831,7 +831,7 @@
     final core::List<core::int*>* #t76 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t77 = :sync-for-iterator.{core::Iterator::current};
           #t76.{core::List::add}(#t77);
@@ -842,7 +842,7 @@
     final core::Set<core::int*>* #t78 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t79 = :sync-for-iterator.{core::Iterator::current};
           #t78.{core::Set::add}(#t79);
@@ -854,7 +854,7 @@
     final core::Map<core::String*, core::int*>* #t80 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t81 = :sync-for-iterator.{core::Iterator::current};
           #t80.{core::Map::[]=}(#t81.{core::MapEntry::key}, #t81.{core::MapEntry::value});
@@ -865,7 +865,7 @@
   core::List<core::List<core::int*>*>* list60 = block {
     final core::List<core::List<core::int*>*>* #t82 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t83 = :sync-for-iterator.{core::Iterator::current};
         #t82.{core::List::add}(#t83);
@@ -875,7 +875,7 @@
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t84 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t85 = :sync-for-iterator.{core::Iterator::current};
         #t84.{core::Set::add}(#t85);
@@ -886,7 +886,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t86 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t87 = :sync-for-iterator.{core::Iterator::current};
         #t86.{core::Map::[]=}(#t87.{core::MapEntry::key}, #t87.{core::MapEntry::value});
@@ -898,7 +898,7 @@
     final core::List<core::List<core::int*>*>* #t88 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t89 = :sync-for-iterator.{core::Iterator::current};
           #t88.{core::List::add}(#t89);
@@ -909,7 +909,7 @@
     final core::Set<core::List<core::int*>*>* #t90 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t91 = :sync-for-iterator.{core::Iterator::current};
           #t90.{core::Set::add}(#t91);
@@ -921,7 +921,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t92 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t93 = :sync-for-iterator.{core::Iterator::current};
           #t92.{core::Map::[]=}(#t93.{core::MapEntry::key}, #t93.{core::MapEntry::value});
@@ -979,14 +979,14 @@
   core::List<core::num*>* list81 = block {
     final core::List<core::num*>* #t101 = <core::num*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t102 = :sync-for-iterator.{core::Iterator::current};
         #t101.{core::List::add}(#t102);
       }
     }
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t103 = :sync-for-iterator.{core::Iterator::current};
         #t101.{core::List::add}(#t103);
@@ -996,14 +996,14 @@
   core::Set<core::num*>* set81 = block {
     final core::Set<core::num*>* #t104 = col::LinkedHashSet::•<core::num*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t105 = :sync-for-iterator.{core::Iterator::current};
         #t104.{core::Set::add}(#t105);
       }
     }
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t106 = :sync-for-iterator.{core::Iterator::current};
         #t104.{core::Set::add}(#t106);
@@ -1014,14 +1014,14 @@
   core::Map<core::String*, core::num*>* map81 = block {
     final core::Map<core::String*, core::num*>* #t107 = <core::String*, core::num*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapToInt.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapToInt.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t108 = :sync-for-iterator.{core::Iterator::current};
         #t107.{core::Map::[]=}(#t108.{core::MapEntry::key}, #t108.{core::MapEntry::value});
       }
     }
     else {
-      core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::double*>*>*>(mapToDouble.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = mapToDouble.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t109 = :sync-for-iterator.{core::Iterator::current};
         #t107.{core::Map::[]=}(#t109.{core::MapEntry::key}, #t109.{core::MapEntry::value});
@@ -1032,14 +1032,14 @@
   core::List<dynamic>* list82 = block {
     final core::List<dynamic>* #t110 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t111 = :sync-for-iterator.{core::Iterator::current};
         #t110.{core::List::add}(#t111);
       }
     }
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t112 = :sync-for-iterator.{core::Iterator::current};
         #t110.{core::List::add}(#t112);
@@ -1049,14 +1049,14 @@
   core::Set<dynamic>* set82 = block {
     final core::Set<dynamic>* #t113 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t114 = :sync-for-iterator.{core::Iterator::current};
         #t113.{core::Set::add}(#t114);
       }
     }
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t115 = :sync-for-iterator.{core::Iterator::current};
         #t113.{core::Set::add}(#t115);
@@ -1072,7 +1072,7 @@
   var map82 = {if (oracle(\"foo\")) ...mapToInt else ...dynVar, null};
                                      ^");
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t117 = :sync-for-iterator.{core::Iterator::current};
         #t116.{core::Set::add}(#t117);
@@ -1085,7 +1085,7 @@
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t118.{core::List::add}(42);
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t119 = :sync-for-iterator.{core::Iterator::current};
         #t118.{core::List::add}(#t119);
@@ -1095,7 +1095,7 @@
   core::Set<core::num*>* set83 = block {
     final core::Set<core::num*>* #t120 = col::LinkedHashSet::•<core::num*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t121 = :sync-for-iterator.{core::Iterator::current};
         #t120.{core::Set::add}(#t121);
@@ -1108,7 +1108,7 @@
   core::Map<core::String*, core::num*>* map83 = block {
     final core::Map<core::String*, core::num*>* #t122 = <core::String*, core::num*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapToInt.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapToInt.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t123 = :sync-for-iterator.{core::Iterator::current};
         #t122.{core::Map::[]=}(#t123.{core::MapEntry::key}, #t123.{core::MapEntry::value});
@@ -1138,7 +1138,7 @@
   core::List<core::int*>* list91 = block {
     final core::List<core::int*>* #t127 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t128 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1151,7 +1151,7 @@
   core::Set<core::int*>* set91 = block {
     final core::Set<core::int*>* #t130 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t131 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1165,7 +1165,7 @@
   core::Map<core::String*, core::int*>* map91 = block {
     final core::Map<core::String*, core::int*>* #t133 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t134 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1220,9 +1220,9 @@
   block {
     final core::List<core::int*>* #t146 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t147 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:90:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t147 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:90:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[if (oracle(\"foo\")) ...[\"bar\"]];
-                               ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                               ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t148 = :sync-for-iterator.{core::Iterator::current};
         #t146.{core::List::add}(#t148);
@@ -1232,9 +1232,9 @@
   block {
     final core::Set<core::int*>* #t149 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t150 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:91:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t150 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:91:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{if (oracle(\"foo\")) ...[\"bar\"], null};
-                               ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                               ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t151 = :sync-for-iterator.{core::Iterator::current};
         #t149.{core::Set::add}(#t151);
@@ -1245,9 +1245,9 @@
   block {
     final core::Map<core::String*, core::int*>* #t152 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": let final<BottomType> #t153 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:92:47: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": let final<BottomType> #t153 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:92:47: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <String, int>{if (oracle(\"foo\")) ...{\"bar\": \"bar\"}, \"baz\": null};
-                                              ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}).{core::Iterable::iterator};
+                                              ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t154 = :sync-for-iterator.{core::Iterator::current};
         #t152.{core::Map::[]=}(#t154.{core::MapEntry::key}, #t154.{core::MapEntry::value});
@@ -1509,7 +1509,7 @@
   core::List<core::int*>* list20 = block {
     final core::List<core::int*>* #t197 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t198 = :sync-for-iterator.{core::Iterator::current};
         #t197.{core::List::add}(#t198);
@@ -1519,7 +1519,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t199 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t200 = :sync-for-iterator.{core::Iterator::current};
         #t199.{core::Set::add}(#t200);
@@ -1530,7 +1530,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t201 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t202 = :sync-for-iterator.{core::Iterator::current};
         #t201.{core::Map::[]=}(#t202.{core::MapEntry::key}, #t202.{core::MapEntry::value});
@@ -1541,7 +1541,7 @@
   core::List<dynamic>* list21 = block {
     final core::List<dynamic>* #t203 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t204 = :sync-for-iterator.{core::Iterator::current};
         #t203.{core::List::add}(#t204);
@@ -1551,7 +1551,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t205 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t206 = :sync-for-iterator.{core::Iterator::current};
         #t205.{core::Set::add}(#t206);
@@ -1562,7 +1562,7 @@
   core::Map<core::String*, dynamic>* map21 = block {
     final core::Map<core::String*, dynamic>* #t207 = <core::String*, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, dynamic>* #t208 = :sync-for-iterator.{core::Iterator::current};
         #t207.{core::Map::[]=}(#t208.{core::MapEntry::key}, #t208.{core::MapEntry::value});
@@ -1573,7 +1573,7 @@
   core::List<core::List<core::int*>*>* list22 = block {
     final core::List<core::List<core::int*>*>* #t209 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t210 = :sync-for-iterator.{core::Iterator::current};
         #t209.{core::List::add}(#t210);
@@ -1583,7 +1583,7 @@
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t211 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t212 = :sync-for-iterator.{core::Iterator::current};
         #t211.{core::Set::add}(#t212);
@@ -1594,7 +1594,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t213 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t214 = :sync-for-iterator.{core::Iterator::current};
         #t213.{core::Map::[]=}(#t214.{core::MapEntry::key}, #t214.{core::MapEntry::value});
@@ -1606,7 +1606,7 @@
     final core::List<core::int*>* #t215 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t216 = :sync-for-iterator.{core::Iterator::current};
           #t215.{core::List::add}(#t216);
@@ -1617,7 +1617,7 @@
     final core::Set<core::int*>* #t217 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t218 = :sync-for-iterator.{core::Iterator::current};
           #t217.{core::Set::add}(#t218);
@@ -1629,7 +1629,7 @@
     final core::Map<core::String*, core::int*>* #t219 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t220 = :sync-for-iterator.{core::Iterator::current};
           #t219.{core::Map::[]=}(#t220.{core::MapEntry::key}, #t220.{core::MapEntry::value});
@@ -1641,7 +1641,7 @@
     final core::List<dynamic>* #t221 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t222 = :sync-for-iterator.{core::Iterator::current};
           #t221.{core::List::add}(#t222);
@@ -1652,7 +1652,7 @@
     final core::Set<dynamic>* #t223 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t224 = :sync-for-iterator.{core::Iterator::current};
           #t223.{core::Set::add}(#t224);
@@ -1664,7 +1664,7 @@
     final core::Map<core::String*, dynamic>* #t225 = <core::String*, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, dynamic>* #t226 = :sync-for-iterator.{core::Iterator::current};
           #t225.{core::Map::[]=}(#t226.{core::MapEntry::key}, #t226.{core::MapEntry::value});
@@ -1676,7 +1676,7 @@
     final core::List<core::List<core::int*>*>* #t227 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t228 = :sync-for-iterator.{core::Iterator::current};
           #t227.{core::List::add}(#t228);
@@ -1687,7 +1687,7 @@
     final core::Set<core::List<core::int*>*>* #t229 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t230 = :sync-for-iterator.{core::Iterator::current};
           #t229.{core::Set::add}(#t230);
@@ -1699,7 +1699,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t231 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t232 = :sync-for-iterator.{core::Iterator::current};
           #t231.{core::Map::[]=}(#t232.{core::MapEntry::key}, #t232.{core::MapEntry::value});
@@ -1710,7 +1710,7 @@
   core::List<core::List<core::int*>*>* list40 = block {
     final core::List<core::List<core::int*>*>* #t233 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t234 = :sync-for-iterator.{core::Iterator::current};
         #t233.{core::List::add}(#t234);
@@ -1720,7 +1720,7 @@
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t235 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t236 = :sync-for-iterator.{core::Iterator::current};
         #t235.{core::Set::add}(#t236);
@@ -1731,7 +1731,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map40 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t237 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t238 = :sync-for-iterator.{core::Iterator::current};
         #t237.{core::Map::[]=}(#t238.{core::MapEntry::key}, #t238.{core::MapEntry::value});
@@ -1742,7 +1742,7 @@
   core::List<core::List<core::int*>*>* list41 = block {
     final core::List<core::List<core::int*>*>* #t239 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t240 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t241 = #t240.{core::Set::add}(<core::int*>[]) in #t240).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t240 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t241 = #t240.{core::Set::add}(<core::int*>[]) in #t240).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t242 = :sync-for-iterator.{core::Iterator::current};
         #t239.{core::List::add}(#t242);
@@ -1752,7 +1752,7 @@
   core::Set<core::List<core::int*>*>* set41 = block {
     final core::Set<core::List<core::int*>*>* #t243 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t244 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t245 = #t244.{core::Set::add}(<core::int*>[]) in #t244).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t244 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t245 = #t244.{core::Set::add}(<core::int*>[]) in #t244).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t246 = :sync-for-iterator.{core::Iterator::current};
         #t243.{core::Set::add}(#t246);
@@ -1764,7 +1764,7 @@
     final core::List<core::List<core::int*>*>* #t247 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t248 = :sync-for-iterator.{core::Iterator::current};
           #t247.{core::List::add}(#t248);
@@ -1775,7 +1775,7 @@
     final core::Set<core::List<core::int*>*>* #t249 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t250 = :sync-for-iterator.{core::Iterator::current};
           #t249.{core::Set::add}(#t250);
@@ -1787,7 +1787,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t251 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t252 = :sync-for-iterator.{core::Iterator::current};
           #t251.{core::Map::[]=}(#t252.{core::MapEntry::key}, #t252.{core::MapEntry::value});
@@ -1798,7 +1798,7 @@
   core::List<core::int*>* list50 = block {
     final core::List<core::int*>* #t253 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t254 = :sync-for-iterator.{core::Iterator::current};
         #t253.{core::List::add}(#t254);
@@ -1808,7 +1808,7 @@
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t255 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t256 = :sync-for-iterator.{core::Iterator::current};
         #t255.{core::Set::add}(#t256);
@@ -1819,7 +1819,7 @@
   core::Map<core::String*, core::int*>* map50 = block {
     final core::Map<core::String*, core::int*>* #t257 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t258 = :sync-for-iterator.{core::Iterator::current};
         #t257.{core::Map::[]=}(#t258.{core::MapEntry::key}, #t258.{core::MapEntry::value});
@@ -1830,7 +1830,7 @@
   core::List<core::int*>* list51 = block {
     final core::List<core::int*>* #t259 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t260 = col::LinkedHashSet::•<core::int*>() in #t260).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t260 = col::LinkedHashSet::•<core::int*>() in #t260).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t261 = :sync-for-iterator.{core::Iterator::current};
         #t259.{core::List::add}(#t261);
@@ -1840,7 +1840,7 @@
   core::Set<core::int*>* set51 = block {
     final core::Set<core::int*>* #t262 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t263 = col::LinkedHashSet::•<core::int*>() in #t263).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t263 = col::LinkedHashSet::•<core::int*>() in #t263).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t264 = :sync-for-iterator.{core::Iterator::current};
         #t262.{core::Set::add}(#t264);
@@ -1852,7 +1852,7 @@
     final core::List<core::int*>* #t265 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t266 = :sync-for-iterator.{core::Iterator::current};
           #t265.{core::List::add}(#t266);
@@ -1863,7 +1863,7 @@
     final core::Set<core::int*>* #t267 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t268 = :sync-for-iterator.{core::Iterator::current};
           #t267.{core::Set::add}(#t268);
@@ -1874,7 +1874,7 @@
   core::List<core::List<core::int*>*>* list60 = block {
     final core::List<core::List<core::int*>*>* #t269 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t270 = :sync-for-iterator.{core::Iterator::current};
         #t269.{core::List::add}(#t270);
@@ -1884,7 +1884,7 @@
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t271 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t272 = :sync-for-iterator.{core::Iterator::current};
         #t271.{core::Set::add}(#t272);
@@ -1895,7 +1895,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t273 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t274 = :sync-for-iterator.{core::Iterator::current};
         #t273.{core::Map::[]=}(#t274.{core::MapEntry::key}, #t274.{core::MapEntry::value});
@@ -1907,7 +1907,7 @@
     final core::List<core::List<core::int*>*>* #t275 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t276 = :sync-for-iterator.{core::Iterator::current};
           #t275.{core::List::add}(#t276);
@@ -1918,7 +1918,7 @@
     final core::Set<core::List<core::int*>*>* #t277 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t278 = :sync-for-iterator.{core::Iterator::current};
           #t277.{core::Set::add}(#t278);
@@ -1930,7 +1930,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t279 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t280 = :sync-for-iterator.{core::Iterator::current};
           #t279.{core::Map::[]=}(#t280.{core::MapEntry::key}, #t280.{core::MapEntry::value});
@@ -2005,14 +2005,14 @@
     final core::List<core::num*>* #t290 = <core::num*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t291 = :sync-for-iterator.{core::Iterator::current};
           #t290.{core::List::add}(#t291);
         }
       }
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t292 = :sync-for-iterator.{core::Iterator::current};
           #t290.{core::List::add}(#t292);
@@ -2023,14 +2023,14 @@
     final core::Set<core::num*>* #t293 = col::LinkedHashSet::•<core::num*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t294 = :sync-for-iterator.{core::Iterator::current};
           #t293.{core::Set::add}(#t294);
         }
       }
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t295 = :sync-for-iterator.{core::Iterator::current};
           #t293.{core::Set::add}(#t295);
@@ -2042,14 +2042,14 @@
     final core::Map<core::String*, core::num*>* #t296 = <core::String*, core::num*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t297 = :sync-for-iterator.{core::Iterator::current};
           #t296.{core::Map::[]=}(#t297.{core::MapEntry::key}, #t297.{core::MapEntry::value});
         }
       }
       else {
-        core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::double*>*>*>(mapStringDouble.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = mapStringDouble.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t298 = :sync-for-iterator.{core::Iterator::current};
           #t296.{core::Map::[]=}(#t298.{core::MapEntry::key}, #t298.{core::MapEntry::value});
@@ -2061,14 +2061,14 @@
     final core::List<dynamic>* #t299 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t300 = :sync-for-iterator.{core::Iterator::current};
           #t299.{core::List::add}(#t300);
         }
       }
       else {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t301 = :sync-for-iterator.{core::Iterator::current};
           #t299.{core::List::add}(#t301);
@@ -2079,14 +2079,14 @@
     final core::Set<dynamic>* #t302 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t303 = :sync-for-iterator.{core::Iterator::current};
           #t302.{core::Set::add}(#t303);
         }
       }
       else {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t304 = :sync-for-iterator.{core::Iterator::current};
           #t302.{core::Set::add}(#t304);
@@ -2098,14 +2098,14 @@
     final core::Map<dynamic, dynamic>* #t305 = <dynamic, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, dynamic>* #t306 = :sync-for-iterator.{core::Iterator::current};
           #t305.{core::Map::[]=}(#t306.{core::MapEntry::key}, #t306.{core::MapEntry::value});
         }
       }
       else {
-        core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, dynamic>* #t307 = :sync-for-iterator.{core::Iterator::current};
           #t305.{core::Map::[]=}(#t307.{core::MapEntry::key}, #t307.{core::MapEntry::value});
@@ -2119,7 +2119,7 @@
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t308.{core::List::add}(42);
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t309 = :sync-for-iterator.{core::Iterator::current};
           #t308.{core::List::add}(#t309);
@@ -2130,7 +2130,7 @@
     final core::Set<core::num*>* #t310 = col::LinkedHashSet::•<core::num*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t311 = :sync-for-iterator.{core::Iterator::current};
           #t310.{core::Set::add}(#t311);
@@ -2144,7 +2144,7 @@
     final core::Map<core::String*, core::num*>* #t312 = <core::String*, core::num*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t313 = :sync-for-iterator.{core::Iterator::current};
           #t312.{core::Map::[]=}(#t313.{core::MapEntry::key}, #t313.{core::MapEntry::value});
@@ -2174,7 +2174,7 @@
   core::List<core::int*>* list91 = block {
     final core::List<core::int*>* #t317 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t318 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2187,7 +2187,7 @@
   core::Set<core::int*>* set91 = block {
     final core::Set<core::int*>* #t320 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t321 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2201,7 +2201,7 @@
   core::Map<core::String*, core::int*>* map91 = block {
     final core::Map<core::String*, core::int*>* #t323 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t324 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2231,7 +2231,7 @@
   core::List<core::int*>* list110 = block {
     final core::List<core::int*>* #t333 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t333.{core::List::add}(i);
@@ -2241,7 +2241,7 @@
   core::Set<core::int*>* set110 = block {
     final core::Set<core::int*>* #t334 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t334.{core::Set::add}(i);
@@ -2252,7 +2252,7 @@
   core::Map<core::String*, core::int*>* map110 = block {
     final core::Map<core::String*, core::int*>* #t335 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t335.{core::Map::[]=}("bar", i);
@@ -2263,7 +2263,7 @@
   core::List<core::int*>* list120 = block {
     final core::List<core::int*>* #t336 = <core::int*>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t336.{core::List::add}(i as{TypeError,ForDynamic} core::int*);
@@ -2273,7 +2273,7 @@
   core::Set<core::int*>* set120 = block {
     final core::Set<core::int*>* #t337 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t337.{core::Set::add}(i as{TypeError,ForDynamic} core::int*);
@@ -2284,7 +2284,7 @@
   core::Map<core::String*, core::int*>* map120 = block {
     final core::Map<core::String*, core::int*>* #t338 = <core::String*, core::int*>{};
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t338.{core::Map::[]=}("bar", i as{TypeError,ForDynamic} core::int*);
@@ -2312,8 +2312,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -2354,9 +2354,9 @@
         block {
           final core::List<core::int*>* #t350 = <core::int*>[];
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t351 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:213:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t351 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:213:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"]];
-                                                ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                                ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t352 = :sync-for-iterator.{core::Iterator::current};
               #t350.{core::List::add}(#t352);
@@ -2366,9 +2366,9 @@
         block {
           final core::Set<core::int*>* #t353 = col::LinkedHashSet::•<core::int*>();
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t354 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:214:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t354 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:214:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"], null};
-                                                ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                                ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t355 = :sync-for-iterator.{core::Iterator::current};
               #t353.{core::Set::add}(#t355);
@@ -2379,11 +2379,11 @@
         block {
           final core::Map<core::int*, core::int*>* #t356 = <core::int*, core::int*>{};
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(<core::int*, core::int*>{let final<BottomType> #t357 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:215:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = <core::int*, core::int*>{let final<BottomType> #t357 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:215:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...{\"bar\": \"bar\"}, \"baz\": null};
                                                      ^" in "bar" as{TypeError} core::int*: let final<BottomType> #t358 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:215:61: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...{\"bar\": \"bar\"}, \"baz\": null};
-                                                            ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}).{core::Iterable::iterator};
+                                                            ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}.{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::MapEntry<core::int*, core::int*>* #t359 = :sync-for-iterator.{core::Iterator::current};
               #t356.{core::Map::[]=}(#t359.{core::MapEntry::key}, #t359.{core::MapEntry::value});
@@ -2519,7 +2519,7 @@
         block {
           final core::List<core::int*>* #t376 = <core::int*>[];
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t377 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2534,7 +2534,7 @@
         block {
           final core::Set<core::int*>* #t378 = col::LinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t379 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2550,7 +2550,7 @@
         block {
           final core::Map<core::String*, core::int*>* #t380 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t381 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2566,7 +2566,7 @@
         core::List<dynamic>* list10 = block {
           final core::List<dynamic>* #t382 = <dynamic>[];
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t383 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:234:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t383 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:234:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var list10 = [for (var i in \"not iterable\") i];
                               ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2579,7 +2579,7 @@
         core::Set<dynamic>* set10 = block {
           final core::Set<dynamic>* #t384 = col::LinkedHashSet::•<dynamic>();
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t385 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:235:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t385 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:235:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var set10 = {for (var i in \"not iterable\") i, null};
                              ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2593,7 +2593,7 @@
         core::Map<core::String*, dynamic>* map10 = block {
           final core::Map<core::String*, dynamic>* #t386 = <core::String*, dynamic>{};
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t387 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:236:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t387 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:236:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var map10 = {for (var i in \"not iterable\") \"bar\": i, \"baz\": null};
                              ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2607,11 +2607,11 @@
         core::List<core::int*>* list20 = block {
           final core::List<core::int*>* #t388 = <core::int*>[];
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t389 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:237:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t389 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:237:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
                                ^" in "not" as{TypeError} core::int*, let final<BottomType> #t390 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:237:39: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
-                                      ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                      ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t388.{core::List::add}(i);
@@ -2621,11 +2621,11 @@
         core::Set<core::int*>* set20 = block {
           final core::Set<core::int*>* #t391 = col::LinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t392 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:238:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t392 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:238:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t393 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:238:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
-                                     ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t391.{core::Set::add}(i);
@@ -2636,11 +2636,11 @@
         core::Map<core::String*, core::int*>* map20 = block {
           final core::Map<core::String*, core::int*>* #t394 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t395 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:239:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t395 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:239:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t396 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:239:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
-                                     ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t394.{core::Map::[]=}("bar", i);
@@ -2650,7 +2650,7 @@
         } =>#t394;
         final core::List<dynamic>* #t397 = <dynamic>[];
         {
-          dynamic :stream = let final<BottomType> #t398 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:240:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t398 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:240:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var list30 = [await for (var i in \"not stream\") i];
                                     ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2677,7 +2677,7 @@
         core::List<dynamic>* list30 = block {} =>#t397;
         final core::Set<dynamic>* #t402 = col::LinkedHashSet::•<dynamic>();
         {
-          dynamic :stream = let final<BottomType> #t403 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:241:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t403 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:241:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var set30 = {await for (var i in \"not stream\") i, null};
                                    ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2706,7 +2706,7 @@
         } =>#t402;
         final core::Map<core::String*, dynamic>* #t407 = <core::String*, dynamic>{};
         {
-          dynamic :stream = let final<BottomType> #t408 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:242:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t408 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:242:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var map30 = {await for (var i in \"not stream\") \"bar\": i, \"baz\": null};
                                    ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2735,7 +2735,7 @@
         } =>#t407;
         final core::List<core::int*>* #t412 = <core::int*>[];
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t413 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:243:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t413 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:243:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
                                                          ^" in "not" as{TypeError} core::int*, let final<BottomType> #t414 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:243:65: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
@@ -2763,7 +2763,7 @@
         core::List<core::int*>* list40 = block {} =>#t412;
         final core::Set<core::int*>* #t418 = col::LinkedHashSet::•<core::int*>();
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t419 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:244:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t419 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:244:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t420 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:244:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
@@ -2793,7 +2793,7 @@
         } =>#t418;
         final core::Map<core::String*, core::int*>* #t424 = <core::String*, core::int*>{};
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t425 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:245:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t425 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:245:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t426 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:245:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
@@ -2865,13 +2865,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method testForElementErrorsNotAsync(asy::Stream<core::int*>* stream) → dynamic {
diff --git a/pkg/front_end/testcases/general/covariant_equals.dart b/pkg/front_end/testcases/general/covariant_equals.dart
new file mode 100644
index 0000000..474dfbd
--- /dev/null
+++ b/pkg/front_end/testcases/general/covariant_equals.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.
+
+class A {
+  bool operator ==(covariant A other) => true;
+}
+
+class B extends A {
+  bool operator ==(other) => true;
+}
+
+class C<T> {
+  bool operator ==(covariant C<T> other) => true;
+}
+
+class D extends C<int> {}
+
+main() {}
+
+test(A a, B b, C c_dynamic, C<int> c_int, C<String> c_string, D d) {
+  a == a; // ok
+  a == b; // ok
+  a == c_dynamic; // error
+  a == c_int; // error
+  a == c_string; // error
+  a == d; // error
+
+  b == a; // ok
+  b == b; // ok
+  b == c_dynamic; // error
+  b == c_int; // error
+  b == c_string; // error
+  b == d; // error
+
+  c_dynamic == a; // error
+  c_dynamic == b; // error
+  c_dynamic == c_dynamic; // ok
+  c_dynamic == c_int; // ok
+  c_dynamic == c_string; // ok
+  c_dynamic == d; // ok
+
+  c_int == a; // error
+  c_int == b; // error
+  c_int == c_dynamic; // ok
+  c_int == c_int; // ok
+  c_int == c_string; // error
+  c_int == d; // ok}
+
+  c_string == a; // error
+  c_string == b; // error
+  c_string == c_dynamic; // ok
+  c_string == c_int; // error
+  c_string == c_string; // ok
+  c_string == d; // error
+
+  d == a; // error
+  d == b; // error
+  d == c_dynamic; // ok
+  d == c_int; // ok
+  d == c_string; // error
+  d == d; // ok
+}
diff --git a/pkg/front_end/testcases/general/covariant_equals.dart.outline.expect b/pkg/front_end/testcases/general/covariant_equals.dart.outline.expect
new file mode 100644
index 0000000..d521bc4
--- /dev/null
+++ b/pkg/front_end/testcases/general/covariant_equals.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    ;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    ;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    ;
+}
+static method main() → dynamic
+  ;
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/covariant_equals.dart.strong.expect b/pkg/front_end/testcases/general/covariant_equals.dart.strong.expect
new file mode 100644
index 0000000..aa641a4
--- /dev/null
+++ b/pkg/front_end/testcases/general/covariant_equals.dart.strong.expect
@@ -0,0 +1,266 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+//  - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError} self::A*);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError} self::A*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_dynamic as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+ - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError} self::C<core::String*>*);
+  d.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(d);
+}
diff --git a/pkg/front_end/testcases/general/covariant_equals.dart.strong.transformed.expect b/pkg/front_end/testcases/general/covariant_equals.dart.strong.transformed.expect
new file mode 100644
index 0000000..aa641a4
--- /dev/null
+++ b/pkg/front_end/testcases/general/covariant_equals.dart.strong.transformed.expect
@@ -0,0 +1,266 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+//  - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/general/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError} self::A*);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError} self::A*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_dynamic as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+ - 'D' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError} self::C<core::String*>*);
+  d.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/general/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(d);
+}
diff --git a/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.expect b/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.expect
index 6211e60..2bac3e8 100644
--- a/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.expect
+++ b/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.expect
@@ -11,6 +11,6 @@
 import "dart:core";
 
 static method testDynamic() → invalid-type
-  return 0 as{TypeError} invalid-type;
+  return 0;
 static method testVoid() → void {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.transformed.expect b/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.transformed.expect
index 6211e60..2bac3e8 100644
--- a/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/dynamic_and_void.dart.strong.transformed.expect
@@ -11,6 +11,6 @@
 import "dart:core";
 
 static method testDynamic() → invalid-type
-  return 0 as{TypeError} invalid-type;
+  return 0;
 static method testVoid() → void {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart
new file mode 100644
index 0000000..fb84c75
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart
@@ -0,0 +1,5 @@
+Future<void> f() => Future.value();
+
+void g() {
+  await f();
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.outline.expect
new file mode 100644
index 0000000..338ee14
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:async" as asy;
+
+static method f() → asy::Future<void>*
+  ;
+static method g() → void
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.strong.expect
new file mode 100644
index 0000000..7569116
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.strong.expect
@@ -0,0 +1,18 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart:4:3: Error: 'await' can only be used in 'async' or 'async*' methods.
+//   await f();
+//   ^^^^^
+//
+import self as self;
+import "dart:async" as asy;
+
+static method f() → asy::Future<void>*
+  return asy::Future::value<void>();
+static method g() → void {
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart:4:3: Error: 'await' can only be used in 'async' or 'async*' methods.
+  await f();
+  ^^^^^";
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.strong.transformed.expect
new file mode 100644
index 0000000..7569116
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart:4:3: Error: 'await' can only be used in 'async' or 'async*' methods.
+//   await f();
+//   ^^^^^
+//
+import self as self;
+import "dart:async" as asy;
+
+static method f() → asy::Future<void>*
+  return asy::Future::value<void>();
+static method g() → void {
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/await_not_in_async.dart:4:3: Error: 'await' can only be used in 'async' or 'async*' methods.
+  await f();
+  ^^^^^";
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart
new file mode 100644
index 0000000..18fd65a
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart
@@ -0,0 +1,41 @@
+class Foo {
+  foo.x() {
+    // Not OK.
+  }
+  foo.x() : initializer = true {
+    // Not OK.
+  }
+  foo() : initializer = true {
+    // Not OK.
+  }
+  get Foo => 0;
+  get Foo {
+    return 0;
+  }
+  get Foo.X => 0;
+  get Foo.X {
+    return 0;
+  }
+  get Foo : bla = null => 0;
+  get Foo.X : bla = null {
+    return 0;
+  }
+  set Foo => 0;
+  set Foo {
+    return 0;
+  }
+  set Foo.X => 0;
+  set Foo.X {
+    return 0;
+  }
+  set Foo : bla = null => 0;
+  set Foo.X : bla = null {
+    return 0;
+  }
+  external Foo() : bla = null;
+  external Foo.X() : bla = null {
+    return 0;
+  }
+  int Foo;
+  int A, Foo, B;
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.outline.expect
new file mode 100644
index 0000000..19f76f8
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.outline.expect
@@ -0,0 +1,266 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:2:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:3: Error: 'Foo.x' is already declared in this scope.
+//   foo.x() : initializer = true {
+//   ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:2:3: Context: Previous declaration of 'Foo.x'.
+//   foo.x() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:8:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:11:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Error: 'Foo' is already declared in this scope.
+//   get Foo {
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:11:7: Context: Previous declaration of 'Foo'.
+//   get Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Error: 'Foo.X' is already declared in this scope.
+//   get Foo.X {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X => 0;
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo : bla = null => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X : bla = null {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X : bla = null {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Error: 'Foo.X' is already declared in this scope.
+//   get Foo.X : bla = null {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: 'Foo' is already declared in this scope.
+//   set Foo {
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Context: Previous declaration of 'Foo'.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X => 0;
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X : bla = null {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X => 0;
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo : bla = null => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Error: 'Foo' is already declared in this scope.
+//   set Foo : bla = null => 0;
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:7: Context: Previous declaration of 'Foo'.
+//   get Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X : bla = null {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X : bla = null {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X : bla = null {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:35:18: Error: An external constructor can't have any initializers.
+//   external Foo() : bla = null;
+//                  ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:35:12: Error: 'Foo' is already declared in this scope.
+//   external Foo() : bla = null;
+//            ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Context: Previous declaration of 'Foo'.
+//   set Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:33: Error: An external or native method can't have a body.
+//   external Foo.X() : bla = null {
+//                                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:20: Error: An external constructor can't have any initializers.
+//   external Foo.X() : bla = null {
+//                    ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:12: Error: 'Foo.X' is already declared in this scope.
+//   external Foo.X() : bla = null {
+//            ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X : bla = null {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   int Foo;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Error: 'Foo' is already declared in this scope.
+//   int Foo;
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Context: Previous declaration of 'Foo'.
+//   get Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   int A, Foo, B;
+//          ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: 'Foo' is already declared in this scope.
+//   int A, Foo, B;
+//          ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Context: Previous declaration of 'Foo'.
+//   int Foo;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: Conflicts with member 'Foo'.
+//   set Foo {
+//       ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: Conflicts with setter 'Foo'.
+//   int A, Foo, B;
+//          ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field core::int* A;
+  field core::int* B;
+  constructor x() → self::Foo*
+    ;
+  constructor foo() → self::Foo*
+    ;
+  constructor X() → self::Foo*
+    ;
+  constructor •() → self::Foo*
+    ;
+  get Foo() → dynamic
+    ;
+  set Foo(dynamic #synthetic) → void
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.strong.expect
new file mode 100644
index 0000000..ed0fc2e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.strong.expect
@@ -0,0 +1,363 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:2:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:3: Error: 'Foo.x' is already declared in this scope.
+//   foo.x() : initializer = true {
+//   ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:2:3: Context: Previous declaration of 'Foo.x'.
+//   foo.x() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:8:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:11:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Error: 'Foo' is already declared in this scope.
+//   get Foo {
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:11:7: Context: Previous declaration of 'Foo'.
+//   get Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Error: 'Foo.X' is already declared in this scope.
+//   get Foo.X {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X => 0;
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo : bla = null => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X : bla = null {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X : bla = null {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Error: 'Foo.X' is already declared in this scope.
+//   get Foo.X : bla = null {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: 'Foo' is already declared in this scope.
+//   set Foo {
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Context: Previous declaration of 'Foo'.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X => 0;
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X : bla = null {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X => 0;
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo : bla = null => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Error: 'Foo' is already declared in this scope.
+//   set Foo : bla = null => 0;
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:7: Context: Previous declaration of 'Foo'.
+//   get Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X : bla = null {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X : bla = null {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X : bla = null {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:35:18: Error: An external constructor can't have any initializers.
+//   external Foo() : bla = null;
+//                  ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:35:12: Error: 'Foo' is already declared in this scope.
+//   external Foo() : bla = null;
+//            ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Context: Previous declaration of 'Foo'.
+//   set Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:33: Error: An external or native method can't have a body.
+//   external Foo.X() : bla = null {
+//                                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:20: Error: An external constructor can't have any initializers.
+//   external Foo.X() : bla = null {
+//                    ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:12: Error: 'Foo.X' is already declared in this scope.
+//   external Foo.X() : bla = null {
+//            ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X : bla = null {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   int Foo;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Error: 'Foo' is already declared in this scope.
+//   int Foo;
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Context: Previous declaration of 'Foo'.
+//   get Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   int A, Foo, B;
+//          ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: 'Foo' is already declared in this scope.
+//   int A, Foo, B;
+//          ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Context: Previous declaration of 'Foo'.
+//   int Foo;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: Conflicts with member 'Foo'.
+//   set Foo {
+//       ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: Conflicts with setter 'Foo'.
+//   int A, Foo, B;
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:13: Error: 'initializer' isn't an instance field of this class.
+//   foo.x() : initializer = true {
+//             ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:8:11: Error: 'initializer' isn't an instance field of this class.
+//   foo() : initializer = true {
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:16: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   get Foo.X => 0;
+//                ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:17:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:13: Error: 'bla' isn't an instance field of this class.
+//   get Foo : bla = null => 0;
+//             ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:27: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   get Foo : bla = null => 0;
+//                           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:15: Error: 'bla' isn't an instance field of this class.
+//   get Foo.X : bla = null {
+//               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:21:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:11: Error: A setter should have exactly one formal parameter.
+//   set Foo => 0;
+//           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:25:12: Error: Can't return a value from a void function.
+//     return 0;
+//            ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:11: Error: A setter should have exactly one formal parameter.
+//   set Foo {
+//           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:16: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   set Foo.X => 0;
+//                ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:29:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:13: Error: 'bla' isn't an instance field of this class.
+//   set Foo : bla = null => 0;
+//             ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:27: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   set Foo : bla = null => 0;
+//                           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:15: Error: 'bla' isn't an instance field of this class.
+//   set Foo.X : bla = null {
+//               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:33:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:37:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field core::int* A = null;
+  field core::int* B = null;
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:8:11: Error: 'initializer' isn't an instance field of this class.
+  foo() : initializer = true {
+          ^^^^^^^^^^^" {}
+  constructor X() → self::Foo*
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:16: Error: Constructors can't have a return type.
+Try removing the return type.
+  get Foo.X => 0;
+               ^";
+  constructor •() → self::Foo*
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:13: Error: 'bla' isn't an instance field of this class.
+  get Foo : bla = null => 0;
+            ^^^"
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:27: Error: Constructors can't have a return type.
+Try removing the return type.
+  get Foo : bla = null => 0;
+                          ^";
+  get Foo() → dynamic
+    return 0;
+  set Foo(dynamic #synthetic) → void {
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:11: Error: A setter should have exactly one formal parameter.
+  set Foo => 0;
+          ^";
+    return 0;
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..ed0fc2e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart.strong.transformed.expect
@@ -0,0 +1,363 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:2:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:3: Error: 'Foo.x' is already declared in this scope.
+//   foo.x() : initializer = true {
+//   ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:2:3: Context: Previous declaration of 'Foo.x'.
+//   foo.x() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:8:3: Error: The name of a constructor must match the name of the enclosing class.
+//   foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:11:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Error: 'Foo' is already declared in this scope.
+//   get Foo {
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:11:7: Context: Previous declaration of 'Foo'.
+//   get Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Error: 'Foo.X' is already declared in this scope.
+//   get Foo.X {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X => 0;
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo : bla = null => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   get Foo.X : bla = null {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.X : bla = null {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Error: 'Foo.X' is already declared in this scope.
+//   get Foo.X : bla = null {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:16:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: 'Foo' is already declared in this scope.
+//   set Foo {
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:7: Context: Previous declaration of 'Foo'.
+//   set Foo => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X => 0;
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:7: Context: Previous declaration of 'Foo.X'.
+//   get Foo.X : bla = null {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X => 0;
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo : bla = null => 0;
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Error: 'Foo' is already declared in this scope.
+//   set Foo : bla = null => 0;
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:7: Context: Previous declaration of 'Foo'.
+//   get Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   set Foo.X : bla = null {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.X : bla = null {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Error: 'Foo.X' is already declared in this scope.
+//   set Foo.X : bla = null {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:28:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:35:18: Error: An external constructor can't have any initializers.
+//   external Foo() : bla = null;
+//                  ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:35:12: Error: 'Foo' is already declared in this scope.
+//   external Foo() : bla = null;
+//            ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:7: Context: Previous declaration of 'Foo'.
+//   set Foo : bla = null => 0;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:33: Error: An external or native method can't have a body.
+//   external Foo.X() : bla = null {
+//                                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:20: Error: An external constructor can't have any initializers.
+//   external Foo.X() : bla = null {
+//                    ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:36:12: Error: 'Foo.X' is already declared in this scope.
+//   external Foo.X() : bla = null {
+//            ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:7: Context: Previous declaration of 'Foo.X'.
+//   set Foo.X : bla = null {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   int Foo;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Error: 'Foo' is already declared in this scope.
+//   int Foo;
+//       ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:12:7: Context: Previous declaration of 'Foo'.
+//   get Foo {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   int A, Foo, B;
+//          ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: 'Foo' is already declared in this scope.
+//   int A, Foo, B;
+//          ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:39:7: Context: Previous declaration of 'Foo'.
+//   int Foo;
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:7: Error: Conflicts with member 'Foo'.
+//   set Foo {
+//       ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:40:10: Error: Conflicts with setter 'Foo'.
+//   int A, Foo, B;
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:5:13: Error: 'initializer' isn't an instance field of this class.
+//   foo.x() : initializer = true {
+//             ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:8:11: Error: 'initializer' isn't an instance field of this class.
+//   foo() : initializer = true {
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:16: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   get Foo.X => 0;
+//                ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:17:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:13: Error: 'bla' isn't an instance field of this class.
+//   get Foo : bla = null => 0;
+//             ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:27: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   get Foo : bla = null => 0;
+//                           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:20:15: Error: 'bla' isn't an instance field of this class.
+//   get Foo.X : bla = null {
+//               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:21:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:11: Error: A setter should have exactly one formal parameter.
+//   set Foo => 0;
+//           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:25:12: Error: Can't return a value from a void function.
+//     return 0;
+//            ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:24:11: Error: A setter should have exactly one formal parameter.
+//   set Foo {
+//           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:27:16: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   set Foo.X => 0;
+//                ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:29:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:13: Error: 'bla' isn't an instance field of this class.
+//   set Foo : bla = null => 0;
+//             ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:31:27: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   set Foo : bla = null => 0;
+//                           ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:32:15: Error: 'bla' isn't an instance field of this class.
+//   set Foo.X : bla = null {
+//               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:33:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:37:5: Error: Constructors can't have a return type.
+// Try removing the return type.
+//     return 0;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field core::int* A = null;
+  field core::int* B = null;
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:8:11: Error: 'initializer' isn't an instance field of this class.
+  foo() : initializer = true {
+          ^^^^^^^^^^^" {}
+  constructor X() → self::Foo*
+    : super core::Object::•()
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:15:16: Error: Constructors can't have a return type.
+Try removing the return type.
+  get Foo.X => 0;
+               ^";
+  constructor •() → self::Foo*
+    : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:13: Error: 'bla' isn't an instance field of this class.
+  get Foo : bla = null => 0;
+            ^^^"
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:19:27: Error: Constructors can't have a return type.
+Try removing the return type.
+  get Foo : bla = null => 0;
+                          ^";
+  get Foo() → dynamic
+    return 0;
+  set Foo(dynamic #synthetic) → void {
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_general.crash_dart:23:11: Error: A setter should have exactly one formal parameter.
+  set Foo => 0;
+          ^";
+    return 0;
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart
new file mode 100644
index 0000000..9025e56
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart
@@ -0,0 +1,11 @@
+class Foo {
+  get foo.x() {
+    // Not OK.
+  }
+  get foo.x() : initializer = true {
+    // Not OK.
+  }
+  get foo() : initializer = true {
+    // Not OK.
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.outline.expect
new file mode 100644
index 0000000..fe0b497
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.outline.expect
@@ -0,0 +1,52 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo.x() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo.x() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:7: Error: 'Foo.x' is already declared in this scope.
+//   get foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:7: Context: Previous declaration of 'Foo.x'.
+//   get foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get foo() : initializer = true {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo() : initializer = true {
+//   ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    ;
+  constructor foo() → self::Foo*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.strong.expect
new file mode 100644
index 0000000..869b1d2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.strong.expect
@@ -0,0 +1,62 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo.x() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo.x() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:7: Error: 'Foo.x' is already declared in this scope.
+//   get foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:7: Context: Previous declaration of 'Foo.x'.
+//   get foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get foo() : initializer = true {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:17: Error: 'initializer' isn't an instance field of this class.
+//   get foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+//   get foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+  get foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..869b1d2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart.strong.transformed.expect
@@ -0,0 +1,62 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo.x() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo.x() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:7: Error: 'Foo.x' is already declared in this scope.
+//   get foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:2:7: Context: Previous declaration of 'Foo.x'.
+//   get foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get foo() : initializer = true {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:7: Error: The name of a constructor must match the name of the enclosing class.
+//   get foo() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:5:17: Error: 'initializer' isn't an instance field of this class.
+//   get foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+//   get foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_get.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+  get foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart
new file mode 100644
index 0000000..2c827a6
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart
@@ -0,0 +1,11 @@
+class Foo {
+  void foo.x() {
+    // Not OK.
+  }
+  void foo.x() : initializer = true {
+    // Not OK.
+  }
+  void foo() : initializer = true {
+    // Not OK.
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.outline.expect
new file mode 100644
index 0000000..38d4897
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.outline.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo.x() {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo.x() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo.x() : initializer = true {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo.x() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:8: Error: 'Foo.x' is already declared in this scope.
+//   void foo.x() : initializer = true {
+//        ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:8: Context: Previous declaration of 'Foo.x'.
+//   void foo.x() {
+//        ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo() : initializer = true {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo() : initializer = true {
+//   ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    ;
+  constructor foo() → self::Foo*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.strong.expect
new file mode 100644
index 0000000..3864448
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.strong.expect
@@ -0,0 +1,57 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo.x() {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo.x() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo.x() : initializer = true {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo.x() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:8: Error: 'Foo.x' is already declared in this scope.
+//   void foo.x() : initializer = true {
+//        ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:8: Context: Previous declaration of 'Foo.x'.
+//   void foo.x() {
+//        ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo() : initializer = true {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:18: Error: 'initializer' isn't an instance field of this class.
+//   void foo.x() : initializer = true {
+//                  ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:16: Error: 'initializer' isn't an instance field of this class.
+//   void foo() : initializer = true {
+//                ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:16: Error: 'initializer' isn't an instance field of this class.
+  void foo() : initializer = true {
+               ^^^^^^^^^^^" {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..3864448
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart.strong.transformed.expect
@@ -0,0 +1,57 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo.x() {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo.x() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo.x() : initializer = true {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo.x() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:8: Error: 'Foo.x' is already declared in this scope.
+//   void foo.x() : initializer = true {
+//        ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:2:8: Context: Previous declaration of 'Foo.x'.
+//   void foo.x() {
+//        ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:8: Error: The name of a constructor must match the name of the enclosing class.
+//   void foo() : initializer = true {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void foo() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:5:18: Error: 'initializer' isn't an instance field of this class.
+//   void foo.x() : initializer = true {
+//                  ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:16: Error: 'initializer' isn't an instance field of this class.
+//   void foo() : initializer = true {
+//                ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_return_type.crash_dart:8:16: Error: 'initializer' isn't an instance field of this class.
+  void foo() : initializer = true {
+               ^^^^^^^^^^^" {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart
new file mode 100644
index 0000000..4ecd30e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart
@@ -0,0 +1,11 @@
+class Foo {
+  set foo.x() {
+    // Not OK.
+  }
+  set foo.x() : initializer = true {
+    // Not OK.
+  }
+  set foo() : initializer = true {
+    // Not OK.
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.outline.expect
new file mode 100644
index 0000000..7fc2664
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.outline.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo.x() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo.x() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:7: Error: 'Foo.x' is already declared in this scope.
+//   set foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:7: Context: Previous declaration of 'Foo.x'.
+//   set foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo() : initializer = true {
+//   ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    ;
+  constructor foo() → self::Foo*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.strong.expect
new file mode 100644
index 0000000..2a38c47
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.strong.expect
@@ -0,0 +1,57 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo.x() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo.x() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:7: Error: 'Foo.x' is already declared in this scope.
+//   set foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:7: Context: Previous declaration of 'Foo.x'.
+//   set foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:17: Error: 'initializer' isn't an instance field of this class.
+//   set foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+//   set foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+  set foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..2a38c47
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart.strong.transformed.expect
@@ -0,0 +1,57 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo.x() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo.x() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:7: Error: 'Foo.x' is already declared in this scope.
+//   set foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:2:7: Context: Previous declaration of 'Foo.x'.
+//   set foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:7: Error: The name of a constructor must match the name of the enclosing class.
+//   set foo() : initializer = true {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:5:17: Error: 'initializer' isn't an instance field of this class.
+//   set foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+//   set foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  constructor foo() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_bad_name_set.crash_dart:8:15: Error: 'initializer' isn't an instance field of this class.
+  set foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart
new file mode 100644
index 0000000..5921c10
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart
@@ -0,0 +1,14 @@
+class Foo {
+  get Foo() {
+    // Not OK.
+  }
+  get Foo() : initializer = true {
+    // Not OK.
+  }
+  get Foo.x() {
+    // Not OK.
+  }
+  get Foo.x() : initializer = true {
+    // Not OK.
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.outline.expect
new file mode 100644
index 0000000..edb2408
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.outline.expect
@@ -0,0 +1,52 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:2:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get Foo() {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:2:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get Foo() : initializer = true {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:8:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:7: Error: 'Foo.x' is already declared in this scope.
+//   get Foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:8:7: Context: Previous declaration of 'Foo.x'.
+//   get Foo.x() {
+//       ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    ;
+  constructor x() → self::Foo*
+    ;
+  get Foo() → dynamic
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.strong.expect
new file mode 100644
index 0000000..5abfca6
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.strong.expect
@@ -0,0 +1,61 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:2:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get Foo() {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:2:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get Foo() : initializer = true {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:8:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:7: Error: 'Foo.x' is already declared in this scope.
+//   get Foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:8:7: Context: Previous declaration of 'Foo.x'.
+//   get Foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+//   get Foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:17: Error: 'initializer' isn't an instance field of this class.
+//   get Foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+  get Foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  get Foo() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.strong.transformed.expect
new file mode 100644
index 0000000..5abfca6
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart.strong.transformed.expect
@@ -0,0 +1,61 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:2:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get Foo() {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:2:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   get Foo() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:10: Error: A getter can't have formal parameters.
+// Try removing '(...)'.
+//   get Foo() : initializer = true {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:8:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:3: Error: Constructors can't be a getter.
+// Try removing 'get'.
+//   get Foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:7: Error: 'Foo.x' is already declared in this scope.
+//   get Foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:8:7: Context: Previous declaration of 'Foo.x'.
+//   get Foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+//   get Foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:11:17: Error: 'initializer' isn't an instance field of this class.
+//   get Foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_get.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+  get Foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  get Foo() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart
new file mode 100644
index 0000000..6a532a0
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart
@@ -0,0 +1,14 @@
+class Foo {
+  Foo() {
+    // OK.
+  }
+  Foo() : initializer = true {
+    // OK.
+  }
+  Foo.x() {
+    // OK.
+  }
+  Foo.x() : initializer = true {
+    // OK.
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.outline.expect
new file mode 100644
index 0000000..8613684
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:5:3: Error: 'Foo' is already declared in this scope.
+//   Foo() : initializer = true {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:2:3: Context: Previous declaration of 'Foo'.
+//   Foo() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:11:3: Error: 'Foo.x' is already declared in this scope.
+//   Foo.x() : initializer = true {
+//   ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:8:3: Context: Previous declaration of 'Foo.x'.
+//   Foo.x() {
+//   ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    ;
+  constructor x() → self::Foo*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.strong.expect
new file mode 100644
index 0000000..3544a52
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.strong.expect
@@ -0,0 +1,35 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:5:3: Error: 'Foo' is already declared in this scope.
+//   Foo() : initializer = true {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:2:3: Context: Previous declaration of 'Foo'.
+//   Foo() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:11:3: Error: 'Foo.x' is already declared in this scope.
+//   Foo.x() : initializer = true {
+//   ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:8:3: Context: Previous declaration of 'Foo.x'.
+//   Foo.x() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:5:11: Error: 'initializer' isn't an instance field of this class.
+//   Foo() : initializer = true {
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:11:13: Error: 'initializer' isn't an instance field of this class.
+//   Foo.x() : initializer = true {
+//             ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : super core::Object::•() {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.strong.transformed.expect
new file mode 100644
index 0000000..3544a52
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart.strong.transformed.expect
@@ -0,0 +1,35 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:5:3: Error: 'Foo' is already declared in this scope.
+//   Foo() : initializer = true {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:2:3: Context: Previous declaration of 'Foo'.
+//   Foo() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:11:3: Error: 'Foo.x' is already declared in this scope.
+//   Foo.x() : initializer = true {
+//   ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:8:3: Context: Previous declaration of 'Foo.x'.
+//   Foo.x() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:5:11: Error: 'initializer' isn't an instance field of this class.
+//   Foo() : initializer = true {
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_ok.dart:11:13: Error: 'initializer' isn't an instance field of this class.
+//   Foo.x() : initializer = true {
+//             ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : super core::Object::•() {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart
new file mode 100644
index 0000000..44d5847
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart
@@ -0,0 +1,14 @@
+class Foo {
+  Foo() / : super() {
+    // Not OK.
+  }
+  Foo()./ : super() {
+    // Not OK.
+  }
+  foo() / : super() {
+    // Not OK.
+  }
+  foo()./ : super() {
+    // Not OK.
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.outline.expect
new file mode 100644
index 0000000..e8c9145
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.outline.expect
@@ -0,0 +1,146 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Expected '{' before this.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: The name of a constructor must match the name of the enclosing class.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Operator '/' should have exactly one parameter.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:8: Error: Expected '{' before this.
+//   Foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:3: Error: 'Foo' is already declared in this scope.
+//   Foo()./ : super() {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:3: Context: Previous declaration of 'Foo'.
+//   Foo() / : super() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:8: Error: Expected a class member, but got '.'.
+//   Foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: The name of a constructor must match the name of the enclosing class.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: Operator '/' should have exactly one parameter.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: 'Foo./' is already declared in this scope.
+//   Foo()./ : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Context: Previous declaration of 'Foo./'.
+//   Foo() / : super() {
+//         ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Expected '{' before this.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: The name of a constructor must match the name of the enclosing class.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Operator '/' should have exactly one parameter.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: 'Foo./' is already declared in this scope.
+//   foo() / : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Context: Previous declaration of 'Foo./'.
+//   Foo()./ : super() {
+//         ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:8: Error: Expected '{' before this.
+//   foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:3: Error: 'foo' is already declared in this scope.
+//   foo()./ : super() {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:3: Context: Previous declaration of 'foo'.
+//   foo() / : super() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:8: Error: Expected a class member, but got '.'.
+//   foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: The name of a constructor must match the name of the enclosing class.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: Operator '/' should have exactly one parameter.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: 'Foo./' is already declared in this scope.
+//   foo()./ : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Context: Previous declaration of 'Foo./'.
+//   foo() / : super() {
+//         ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    ;
+  constructor /() → self::Foo*
+    ;
+  method foo() → dynamic
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.strong.expect
new file mode 100644
index 0000000..c7113bf
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.strong.expect
@@ -0,0 +1,145 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Expected '{' before this.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: The name of a constructor must match the name of the enclosing class.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Operator '/' should have exactly one parameter.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:8: Error: Expected '{' before this.
+//   Foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:3: Error: 'Foo' is already declared in this scope.
+//   Foo()./ : super() {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:3: Context: Previous declaration of 'Foo'.
+//   Foo() / : super() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:8: Error: Expected a class member, but got '.'.
+//   Foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: The name of a constructor must match the name of the enclosing class.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: Operator '/' should have exactly one parameter.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: 'Foo./' is already declared in this scope.
+//   Foo()./ : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Context: Previous declaration of 'Foo./'.
+//   Foo() / : super() {
+//         ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Expected '{' before this.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: The name of a constructor must match the name of the enclosing class.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Operator '/' should have exactly one parameter.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: 'Foo./' is already declared in this scope.
+//   foo() / : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Context: Previous declaration of 'Foo./'.
+//   Foo()./ : super() {
+//         ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:8: Error: Expected '{' before this.
+//   foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:3: Error: 'foo' is already declared in this scope.
+//   foo()./ : super() {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:3: Context: Previous declaration of 'foo'.
+//   foo() / : super() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:8: Error: Expected a class member, but got '.'.
+//   foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: The name of a constructor must match the name of the enclosing class.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: Operator '/' should have exactly one parameter.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: 'Foo./' is already declared in this scope.
+//   foo()./ : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Context: Previous declaration of 'Foo./'.
+//   foo() / : super() {
+//         ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : super core::Object::•() {}
+  constructor /() → self::Foo*
+    : super core::Object::•() {}
+  method foo() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..c7113bf
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart.strong.transformed.expect
@@ -0,0 +1,145 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Expected '{' before this.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: The name of a constructor must match the name of the enclosing class.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Error: Operator '/' should have exactly one parameter.
+//   Foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:8: Error: Expected '{' before this.
+//   Foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:3: Error: 'Foo' is already declared in this scope.
+//   Foo()./ : super() {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:3: Context: Previous declaration of 'Foo'.
+//   Foo() / : super() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:8: Error: Expected a class member, but got '.'.
+//   Foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: The name of a constructor must match the name of the enclosing class.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: Operator '/' should have exactly one parameter.
+//   Foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Error: 'Foo./' is already declared in this scope.
+//   Foo()./ : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:2:9: Context: Previous declaration of 'Foo./'.
+//   Foo() / : super() {
+//         ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Expected '{' before this.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: The name of a constructor must match the name of the enclosing class.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: Operator '/' should have exactly one parameter.
+//   foo() / : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Error: 'Foo./' is already declared in this scope.
+//   foo() / : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:5:9: Context: Previous declaration of 'Foo./'.
+//   Foo()./ : super() {
+//         ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:8: Error: Expected '{' before this.
+//   foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:3: Error: 'foo' is already declared in this scope.
+//   foo()./ : super() {
+//   ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:3: Context: Previous declaration of 'foo'.
+//   foo() / : super() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:8: Error: Expected a class member, but got '.'.
+//   foo()./ : super() {
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: The name of a constructor must match the name of the enclosing class.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: Operator '/' should have exactly one parameter.
+//   foo()./ : super() {
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:11:9: Error: 'Foo./' is already declared in this scope.
+//   foo()./ : super() {
+//         ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator.crash_dart:8:9: Context: Previous declaration of 'Foo./'.
+//   foo() / : super() {
+//         ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : super core::Object::•() {}
+  constructor /() → self::Foo*
+    : super core::Object::•() {}
+  method foo() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart
new file mode 100644
index 0000000..fd9a67c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart
@@ -0,0 +1,14 @@
+class Foo {
+  void Foo() {
+    // Not OK.
+  }
+  void Foo() : initializer = true {
+    // Not OK.
+  }
+  void Foo.x() {
+    // Not OK.
+  }
+  void Foo.x() : initializer = true {
+    // Not OK.
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.outline.expect
new file mode 100644
index 0000000..ff6c7df
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.outline.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:2:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:8: Error: 'Foo' is already declared in this scope.
+//   void Foo() : initializer = true {
+//        ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:2:8: Context: Previous declaration of 'Foo'.
+//   void Foo() {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:8:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo.x() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo.x() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:8: Error: 'Foo.x' is already declared in this scope.
+//   void Foo.x() : initializer = true {
+//        ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:8:8: Context: Previous declaration of 'Foo.x'.
+//   void Foo.x() {
+//        ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    ;
+  constructor x() → self::Foo*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.strong.expect
new file mode 100644
index 0000000..20c0062
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.strong.expect
@@ -0,0 +1,55 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:2:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:8: Error: 'Foo' is already declared in this scope.
+//   void Foo() : initializer = true {
+//        ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:2:8: Context: Previous declaration of 'Foo'.
+//   void Foo() {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:8:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo.x() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo.x() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:8: Error: 'Foo.x' is already declared in this scope.
+//   void Foo.x() : initializer = true {
+//        ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:8:8: Context: Previous declaration of 'Foo.x'.
+//   void Foo.x() {
+//        ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:16: Error: 'initializer' isn't an instance field of this class.
+//   void Foo() : initializer = true {
+//                ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:18: Error: 'initializer' isn't an instance field of this class.
+//   void Foo.x() : initializer = true {
+//                  ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : super core::Object::•() {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..20c0062
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart.strong.transformed.expect
@@ -0,0 +1,55 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:2:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:8: Error: 'Foo' is already declared in this scope.
+//   void Foo() : initializer = true {
+//        ^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:2:8: Context: Previous declaration of 'Foo'.
+//   void Foo() {
+//        ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:8:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo.x() {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:3: Error: Constructors can't have a return type.
+// Try removing the return type.
+//   void Foo.x() : initializer = true {
+//   ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:8: Error: 'Foo.x' is already declared in this scope.
+//   void Foo.x() : initializer = true {
+//        ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:8:8: Context: Previous declaration of 'Foo.x'.
+//   void Foo.x() {
+//        ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:5:16: Error: 'initializer' isn't an instance field of this class.
+//   void Foo() : initializer = true {
+//                ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_return_type.dart:11:18: Error: 'initializer' isn't an instance field of this class.
+//   void Foo.x() : initializer = true {
+//                  ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : super core::Object::•() {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart
new file mode 100644
index 0000000..6f5b73e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart
@@ -0,0 +1,14 @@
+class Foo {
+  set Foo() {
+    // Not OK.
+  }
+  set Foo() : initializer = true {
+    // Not OK.
+  }
+  set Foo.x() {
+    // Not OK.
+  }
+  set Foo.x() : initializer = true {
+    // Not OK.
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.outline.expect
new file mode 100644
index 0000000..59ce93c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.outline.expect
@@ -0,0 +1,42 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:2:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:5:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:8:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:7: Error: 'Foo.x' is already declared in this scope.
+//   set Foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:8:7: Context: Previous declaration of 'Foo.x'.
+//   set Foo.x() {
+//       ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    ;
+  constructor x() → self::Foo*
+    ;
+  set Foo(dynamic #synthetic) → void
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.strong.expect
new file mode 100644
index 0000000..5995c47
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.strong.expect
@@ -0,0 +1,60 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:2:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:5:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:8:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:7: Error: 'Foo.x' is already declared in this scope.
+//   set Foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:8:7: Context: Previous declaration of 'Foo.x'.
+//   set Foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:2:10: Error: A setter should have exactly one formal parameter.
+//   set Foo() {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+//   set Foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:17: Error: 'initializer' isn't an instance field of this class.
+//   set Foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+  set Foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  set Foo(dynamic #synthetic) → void {
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:2:10: Error: A setter should have exactly one formal parameter.
+  set Foo() {
+         ^";
+    {}
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.strong.transformed.expect
new file mode 100644
index 0000000..5995c47
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart.strong.transformed.expect
@@ -0,0 +1,60 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:2:7: Error: A class member can't have the same name as the enclosing class.
+// Try renaming the member.
+//   set Foo() {
+//       ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:5:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:8:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.x() {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:3: Error: Constructors can't be a setter.
+// Try removing 'set'.
+//   set Foo.x() : initializer = true {
+//   ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:7: Error: 'Foo.x' is already declared in this scope.
+//   set Foo.x() : initializer = true {
+//       ^^^^^
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:8:7: Context: Previous declaration of 'Foo.x'.
+//   set Foo.x() {
+//       ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:2:10: Error: A setter should have exactly one formal parameter.
+//   set Foo() {
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+//   set Foo() : initializer = true {
+//               ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:11:17: Error: 'initializer' isn't an instance field of this class.
+//   set Foo.x() : initializer = true {
+//                 ^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  constructor •() → self::Foo*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:5:15: Error: 'initializer' isn't an instance field of this class.
+  set Foo() : initializer = true {
+              ^^^^^^^^^^^" {}
+  constructor x() → self::Foo*
+    : super core::Object::•() {}
+  set Foo(dynamic #synthetic) → void {
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_set.dart:2:10: Error: A setter should have exactly one formal parameter.
+  set Foo() {
+         ^";
+    {}
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart
new file mode 100644
index 0000000..19771e9
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart
@@ -0,0 +1,3 @@
+main() async {
+  await for () {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.outline.expect
new file mode 100644
index 0000000..6a28c0d
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.outline.expect
@@ -0,0 +1,5 @@
+library;
+import self as self;
+
+static method main() → dynamic
+  ;
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
new file mode 100644
index 0000000..e8becc5
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: Expected an identifier, but got ')'.
+//   await for () {}
+//              ^
+//
+// pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: Expected 'in' before this.
+//   await for () {}
+//              ^
+//
+import self as self;
+import "dart:async" as asy;
+
+static method main() → dynamic async {
+  await for (final dynamic #t1 in invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: This couldn't be parsed.
+  await for () {}
+             ^" as{TypeError,ForDynamic} asy::Stream<dynamic>*) {
+    invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: This couldn't be parsed.
+  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
new file mode 100644
index 0000000..a9a80da
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.transformed.expect
@@ -0,0 +1,74 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: Expected an identifier, but got ')'.
+//   await for () {}
+//              ^
+//
+// pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: Expected 'in' before this.
+//   await for () {}
+//              ^
+//
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        {
+          asy::Stream<dynamic>* :stream = invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: This couldn't be parsed.
+  await for () {}
+             ^" 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)) {
+                final dynamic #t3 = :for-iterator.{asy::_StreamIterator::current};
+                {
+                  invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: This couldn't be parsed.
+  await for () {}
+             ^";
+                }
+              }
+              else
+                break #L2;
+            }
+          finally
+            if(!:for-iterator.{asy::_StreamIterator::_subscription}.{core::Object::==}(null)) {
+              [yield] let dynamic #t4 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(), :async_op_then, :async_op_error, :async_op) in null;
+              :result;
+            }
+        }
+      }
+      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/error_recovery/empty_for.dart b/pkg/front_end/testcases/general/error_recovery/empty_for.dart
new file mode 100644
index 0000000..3c33ee5
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_for.dart
@@ -0,0 +1,3 @@
+main() {
+  for () {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_for.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.outline.expect
new file mode 100644
index 0000000..6a28c0d
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.outline.expect
@@ -0,0 +1,5 @@
+library;
+import self as self;
+
+static method main() → dynamic
+  ;
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
new file mode 100644
index 0000000..3bb7f2e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.expect
@@ -0,0 +1,23 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: Expected an identifier, but got ')'.
+//   for () {}
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: Expected ';' after this.
+//   for () {}
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  for (final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: This couldn't be parsed.
+  for () {}
+       ^"; invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: This couldn't be parsed.
+  for () {}
+       ^" as{TypeError,ForDynamic} core::bool*; ) {
+  }
+}
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
new file mode 100644
index 0000000..3bb7f2e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.transformed.expect
@@ -0,0 +1,23 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: Expected an identifier, but got ')'.
+//   for () {}
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: Expected ';' after this.
+//   for () {}
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  for (final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: This couldn't be parsed.
+  for () {}
+       ^"; invalid-expression "pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: This couldn't be parsed.
+  for () {}
+       ^" as{TypeError,ForDynamic} core::bool*; ) {
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart
new file mode 100644
index 0000000..c6672ff
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart
@@ -0,0 +1 @@
+f() { m(T<R(<Z
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.outline.expect
new file mode 100644
index 0000000..2aafef5
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:12: Error: Can't find ')' to match '('.
+// f() { m(T<R(<Z
+//            ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:10: Error: Can't find '>' to match '<'.
+// f() { m(T<R(<Z
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:8: Error: Can't find ')' to match '('.
+// f() { m(T<R(<Z
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:5: Error: Can't find '}' to match '{'.
+// f() { m(T<R(<Z
+//     ^
+//
+import self as self;
+
+static method f() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.strong.expect
new file mode 100644
index 0000000..3b6f734
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.strong.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:12: Error: Can't find ')' to match '('.
+// f() { m(T<R(<Z
+//            ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:10: Error: Can't find '>' to match '<'.
+// f() { m(T<R(<Z
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:8: Error: Can't find ')' to match '('.
+// f() { m(T<R(<Z
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:5: Error: Can't find '}' to match '{'.
+// f() { m(T<R(<Z
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:14: Error: 'Z' isn't a type.
+// f() { m(T<R(<Z
+//              ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:15: Error: Expected '[' before this.
+// f() { m(T<R(<Z
+//               ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:11: Error: Method not found: 'R'.
+// f() { m(T<R(<Z
+//           ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:9: Error: Getter not found: 'T'.
+// f() { m(T<R(<Z
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:7: Error: Method not found: 'm'.
+// f() { m(T<R(<Z
+//       ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:15: Error: Expected ';' after this.
+// f() { m(T<R(<Z
+//               ^...
+//
+import self as self;
+
+static method f() → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:7: Error: Method not found: 'm'.
+f() { m(T<R(<Z
+      ^";
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..3b6f734
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart.strong.transformed.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:12: Error: Can't find ')' to match '('.
+// f() { m(T<R(<Z
+//            ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:10: Error: Can't find '>' to match '<'.
+// f() { m(T<R(<Z
+//          ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:8: Error: Can't find ')' to match '('.
+// f() { m(T<R(<Z
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:5: Error: Can't find '}' to match '{'.
+// f() { m(T<R(<Z
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:14: Error: 'Z' isn't a type.
+// f() { m(T<R(<Z
+//              ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:15: Error: Expected '[' before this.
+// f() { m(T<R(<Z
+//               ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:11: Error: Method not found: 'R'.
+// f() { m(T<R(<Z
+//           ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:9: Error: Getter not found: 'T'.
+// f() { m(T<R(<Z
+//         ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:7: Error: Method not found: 'm'.
+// f() { m(T<R(<Z
+//       ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:15: Error: Expected ';' after this.
+// f() { m(T<R(<Z
+//               ^...
+//
+import self as self;
+
+static method f() → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/issue_38415.crash_dart:1:7: Error: Method not found: 'm'.
+f() { m(T<R(<Z
+      ^";
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart
new file mode 100644
index 0000000..7094494
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart
@@ -0,0 +1 @@
+n<S e(
\ No newline at end of file
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
new file mode 100644
index 0000000..74ed3a8
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.outline.expect
@@ -0,0 +1,42 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:6: Error: Can't find ')' to match '('.
+// n<S e(
+//      ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:2: Error: Can't find '>' to match '<'.
+// n<S e(
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:3: Error: Expected '>' after this.
+// n<S e(
+//   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected an identifier, but got ''.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected '{' before this.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:3: Error: Type 'S' not found.
+// n<S e(
+//   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:1: Error: Type 'n' not found.
+// n<S e(
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:1: Error: Expected 0 type arguments.
+// n<S e(
+// ^
+//
+import self as self;
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
new file mode 100644
index 0000000..74ed3a8
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.expect
@@ -0,0 +1,42 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:6: Error: Can't find ')' to match '('.
+// n<S e(
+//      ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:2: Error: Can't find '>' to match '<'.
+// n<S e(
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:3: Error: Expected '>' after this.
+// n<S e(
+//   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected an identifier, but got ''.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected '{' before this.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:3: Error: Type 'S' not found.
+// n<S e(
+//   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:1: Error: Type 'n' not found.
+// n<S e(
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:1: Error: Expected 0 type arguments.
+// n<S e(
+// ^
+//
+import self as self;
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
new file mode 100644
index 0000000..74ed3a8
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.transformed.expect
@@ -0,0 +1,42 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:6: Error: Can't find ')' to match '('.
+// n<S e(
+//      ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:2: Error: Can't find '>' to match '<'.
+// n<S e(
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:3: Error: Expected '>' after this.
+// n<S e(
+//   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected an identifier, but got ''.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected '{' before this.
+// n<S e(
+//       ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:3: Error: Type 'S' not found.
+// n<S e(
+//   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:1: Error: Type 'n' not found.
+// n<S e(
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:1: Error: Expected 0 type arguments.
+// n<S e(
+// ^
+//
+import self as self;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart
new file mode 100644
index 0000000..9ec285b
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart
@@ -0,0 +1,4 @@
+class A{
+    co <{
+    }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.outline.expect
new file mode 100644
index 0000000..295fe3d
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.outline.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: Operator '<' should have exactly one parameter.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:5: Error: Type 'co' not found.
+//     co <{
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+  operator <() → invalid-type
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.strong.expect
new file mode 100644
index 0000000..b4527e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.strong.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: Operator '<' should have exactly one parameter.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:5: Error: Type 'co' not found.
+//     co <{
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator <() → invalid-type {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..b4527e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:8: Error: Operator '<' should have exactly one parameter.
+//     co <{
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026.crash_dart:2:5: Error: Type 'co' not found.
+//     co <{
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator <() → invalid-type {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart
new file mode 100644
index 0000000..e5a6c50
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart
@@ -0,0 +1,4 @@
+class A{
+    co operator <{
+    }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.outline.expect
new file mode 100644
index 0000000..ae9916b
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.outline.expect
@@ -0,0 +1,26 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     co operator <{
+//                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:17: Error: Operator '<' should have exactly one parameter.
+//     co operator <{
+//                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:5: Error: Type 'co' not found.
+//     co operator <{
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+  operator <() → invalid-type
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.strong.expect
new file mode 100644
index 0000000..8d68a65
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     co operator <{
+//                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:17: Error: Operator '<' should have exactly one parameter.
+//     co operator <{
+//                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:5: Error: Type 'co' not found.
+//     co operator <{
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator <() → invalid-type {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..8d68a65
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:17: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     co operator <{
+//                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:17: Error: Operator '<' should have exactly one parameter.
+//     co operator <{
+//                 ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39026_prime.crash_dart:2:5: Error: Type 'co' not found.
+//     co operator <{
+//     ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator <() → invalid-type {}
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart
new file mode 100644
index 0000000..efd5943
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart
@@ -0,0 +1 @@
+typedef F<Glib.=
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.outline.expect
new file mode 100644
index 0000000..97e06f2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:11: Error: Expected '>' after this.
+// typedef F<Glib.=
+//           ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:17: Error: Expected a type, but got ''.
+// typedef F<Glib.=
+//                 ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:17: Error: Expected ';' after this.
+// typedef F<Glib.=
+//                 ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:16: Error: Can't create typedef from non-function type.
+// typedef F<Glib.=
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated Glib extends core::Object* = dynamic> = invalid-type;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.strong.expect
new file mode 100644
index 0000000..97e06f2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.strong.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:11: Error: Expected '>' after this.
+// typedef F<Glib.=
+//           ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:17: Error: Expected a type, but got ''.
+// typedef F<Glib.=
+//                 ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:17: Error: Expected ';' after this.
+// typedef F<Glib.=
+//                 ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:16: Error: Can't create typedef from non-function type.
+// typedef F<Glib.=
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated Glib extends core::Object* = dynamic> = invalid-type;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..97e06f2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:11: Error: Expected '>' after this.
+// typedef F<Glib.=
+//           ^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:17: Error: Expected a type, but got ''.
+// typedef F<Glib.=
+//                 ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:17: Error: Expected ';' after this.
+// typedef F<Glib.=
+//                 ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39033.crash_dart:1:16: Error: Can't create typedef from non-function type.
+// typedef F<Glib.=
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated Glib extends core::Object* = dynamic> = invalid-type;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart
new file mode 100644
index 0000000..7e8a2e8
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart
@@ -0,0 +1 @@
+{<[](
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.outline.expect
new file mode 100644
index 0000000..19f98e21
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.outline.expect
@@ -0,0 +1,21 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:5: Error: Can't find ')' to match '('.
+// {<[](
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:2: Error: Can't find '>' to match '<'.
+// {<[](
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:1: Error: Can't find '}' to match '{'.
+// {<[](
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:1: Error: Expected a declaration, but got '{'.
+// {<[](
+// ^
+//
+import self as self;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.strong.expect
new file mode 100644
index 0000000..19f98e21
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.strong.expect
@@ -0,0 +1,21 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:5: Error: Can't find ')' to match '('.
+// {<[](
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:2: Error: Can't find '>' to match '<'.
+// {<[](
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:1: Error: Can't find '}' to match '{'.
+// {<[](
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:1: Error: Expected a declaration, but got '{'.
+// {<[](
+// ^
+//
+import self as self;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..19f98e21
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:5: Error: Can't find ')' to match '('.
+// {<[](
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:2: Error: Can't find '>' to match '<'.
+// {<[](
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:1: Error: Can't find '}' to match '{'.
+// {<[](
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058.crash_dart:1:1: Error: Expected a declaration, but got '{'.
+// {<[](
+// ^
+//
+import self as self;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart
new file mode 100644
index 0000000..e042400
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart
@@ -0,0 +1 @@
+{<[]()>}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.outline.expect
new file mode 100644
index 0000000..3866d3c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.outline.expect
@@ -0,0 +1,9 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart:1:1: Error: Expected a declaration, but got '{'.
+// {<[]()>}
+// ^
+//
+import self as self;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.strong.expect
new file mode 100644
index 0000000..3866d3c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.strong.expect
@@ -0,0 +1,9 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart:1:1: Error: Expected a declaration, but got '{'.
+// {<[]()>}
+// ^
+//
+import self as self;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..3866d3c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart.strong.transformed.expect
@@ -0,0 +1,9 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39058_prime.crash_dart:1:1: Error: Expected a declaration, but got '{'.
+// {<[]()>}
+// ^
+//
+import self as self;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39060.dart b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart
new file mode 100644
index 0000000..b8fb0cdb
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart
@@ -0,0 +1,3 @@
+main() {
+  {s A<}>
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.outline.expect
new file mode 100644
index 0000000..6a28c0d
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.outline.expect
@@ -0,0 +1,5 @@
+library;
+import self as self;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.expect
new file mode 100644
index 0000000..7981214
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:4: Error: 's' isn't a type.
+//   {s A<}>
+//    ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:6: Error: Expected ';' after this.
+//   {s A<}>
+//      ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:8: Error: Expected a type, but got '}'.
+//   {s A<}>
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:8: Error: This couldn't be parsed.
+//   {s A<}>
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:3:1: Error: Expected '[' before this.
+// }
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:3:1: Error: Expected ';' after this.
+// }
+// ^
+//
+import self as self;
+
+static method main() → dynamic {
+  {
+    invalid-type A;
+    <invalid-type>[];
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.transformed.expect
new file mode 100644
index 0000000..7981214
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:4: Error: 's' isn't a type.
+//   {s A<}>
+//    ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:6: Error: Expected ';' after this.
+//   {s A<}>
+//      ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:8: Error: Expected a type, but got '}'.
+//   {s A<}>
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:2:8: Error: This couldn't be parsed.
+//   {s A<}>
+//        ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:3:1: Error: Expected '[' before this.
+// }
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39060.dart:3:1: Error: Expected ';' after this.
+// }
+// ^
+//
+import self as self;
+
+static method main() → dynamic {
+  {
+    invalid-type A;
+    <invalid-type>[];
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart
new file mode 100644
index 0000000..70bdad5
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart
@@ -0,0 +1 @@
+() async => a b < c $? >
\ No newline at end of file
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
new file mode 100644
index 0000000..961d9a1
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.outline.expect
@@ -0,0 +1,45 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:1: Error: Expected a declaration, but got '('.
+// () async => a b < c $? >
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:2: Error: Expected a declaration, but got ')'.
+// () async => a b < c $? >
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:4: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// () async => a b < c $? >
+//    ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:19: Error: Expected '>' after this.
+// () async => a b < c $? >
+//                   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected an identifier, but got ''.
+// () async => a b < c $? >
+//                         ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected ';' after this.
+// () async => a b < c $? >
+//                         ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:19: Error: Type 'c' not found.
+// () async => a b < c $? >
+//                   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Type 'b' not found.
+// () async => a b < c $? >
+//               ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Expected 0 type arguments.
+// () async => a b < c $? >
+//               ^
+//
+import self as self;
+
+static method async() → dynamic
+  ;
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
new file mode 100644
index 0000000..4ad3dc2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.expect
@@ -0,0 +1,59 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:1: Error: Expected a declaration, but got '('.
+// () async => a b < c $? >
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:2: Error: Expected a declaration, but got ')'.
+// () async => a b < c $? >
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:4: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// () async => a b < c $? >
+//    ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:19: Error: Expected '>' after this.
+// () async => a b < c $? >
+//                   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected an identifier, but got ''.
+// () async => a b < c $? >
+//                         ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected ';' after this.
+// () async => a b < c $? >
+//                         ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:19: Error: Type 'c' not found.
+// () async => a b < c $? >
+//                   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Type 'b' not found.
+// () async => a b < c $? >
+//               ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Expected 0 type arguments.
+// () async => a b < c $? >
+//               ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:13: Error: Expected ';' after this.
+// () async => a b < c $? >
+//             ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:13: Error: Getter not found: 'a'.
+// () async => a b < c $? >
+//             ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Unexpected token 'b'.
+// () async => a b < c $? >
+//               ^
+//
+import self as self;
+
+static method async() → dynamic
+  return invalid-expression "pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:13: Error: Getter not found: 'a'.
+() 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
new file mode 100644
index 0000000..4ad3dc2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.transformed.expect
@@ -0,0 +1,59 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:1: Error: Expected a declaration, but got '('.
+// () async => a b < c $? >
+// ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:2: Error: Expected a declaration, but got ')'.
+// () async => a b < c $? >
+//  ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:4: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// () async => a b < c $? >
+//    ^^^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:19: Error: Expected '>' after this.
+// () async => a b < c $? >
+//                   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected an identifier, but got ''.
+// () async => a b < c $? >
+//                         ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected ';' after this.
+// () async => a b < c $? >
+//                         ^...
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:19: Error: Type 'c' not found.
+// () async => a b < c $? >
+//                   ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Type 'b' not found.
+// () async => a b < c $? >
+//               ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Expected 0 type arguments.
+// () async => a b < c $? >
+//               ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:13: Error: Expected ';' after this.
+// () async => a b < c $? >
+//             ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:13: Error: Getter not found: 'a'.
+// () async => a b < c $? >
+//             ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:15: Error: Unexpected token 'b'.
+// () async => a b < c $? >
+//               ^
+//
+import self as self;
+
+static method async() → dynamic
+  return invalid-expression "pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:13: Error: Getter not found: 'a'.
+() async => a b < c \$? >
+            ^";
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart
new file mode 100644
index 0000000..b3588d2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart
@@ -0,0 +1,5 @@
+class C {
+  C()
+    /
+    : super();
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.outline.expect
new file mode 100644
index 0000000..46d7222
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.outline.expect
@@ -0,0 +1,35 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Expected '{' before this.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: The name of a constructor must match the name of the enclosing class.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Operator '/' should have exactly one parameter.
+//     /
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C*
+    ;
+  constructor /() → self::C*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.strong.expect
new file mode 100644
index 0000000..3af922c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Expected '{' before this.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: The name of a constructor must match the name of the enclosing class.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Operator '/' should have exactly one parameter.
+//     /
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C*
+    : super core::Object::•() {}
+  constructor /() → self::C*
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..3af922c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Expected '{' before this.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Operator declarations must be preceded by the keyword 'operator'.
+// Try adding the keyword 'operator'.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: A method declaration needs an explicit list of parameters.
+// Try adding a parameter list to the method declaration.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: The name of a constructor must match the name of the enclosing class.
+//     /
+//     ^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39230.crash_dart:3:5: Error: Operator '/' should have exactly one parameter.
+//     /
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  constructor •() → self::C*
+    : super core::Object::•() {}
+  constructor /() → self::C*
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart
new file mode 100644
index 0000000..8bde84a
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart
@@ -0,0 +1 @@
+void<int> f() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.outline.expect
new file mode 100644
index 0000000..0698786
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.outline.expect
@@ -0,0 +1,13 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart:1:5: Error: Type 'void' can't have type arguments.
+// Try removing the type arguments.
+// void<int> f() {}
+//     ^
+//
+import self as self;
+
+static method f() → void
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.strong.expect
new file mode 100644
index 0000000..6945be8
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.strong.expect
@@ -0,0 +1,12 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart:1:5: Error: Type 'void' can't have type arguments.
+// Try removing the type arguments.
+// void<int> f() {}
+//     ^
+//
+import self as self;
+
+static method f() → void {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.strong.transformed.expect
new file mode 100644
index 0000000..6945be8
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_01.dart:1:5: Error: Type 'void' can't have type arguments.
+// Try removing the type arguments.
+// void<int> f() {}
+//     ^
+//
+import self as self;
+
+static method f() → void {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart
new file mode 100644
index 0000000..58b5740
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart
@@ -0,0 +1 @@
+dynamic<int> f() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.outline.expect
new file mode 100644
index 0000000..ba0fe79b
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.outline.expect
@@ -0,0 +1,12 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart:1:1: Error: Expected 0 type arguments.
+// dynamic<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.strong.expect
new file mode 100644
index 0000000..e7fc2a2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart:1:1: Error: Expected 0 type arguments.
+// dynamic<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.strong.transformed.expect
new file mode 100644
index 0000000..e7fc2a2
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_02.dart:1:1: Error: Expected 0 type arguments.
+// dynamic<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart
new file mode 100644
index 0000000..1a13723
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart
@@ -0,0 +1 @@
+int<int> f() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.outline.expect
new file mode 100644
index 0000000..5118ad3
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.outline.expect
@@ -0,0 +1,12 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart:1:1: Error: Expected 0 type arguments.
+// int<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.strong.expect
new file mode 100644
index 0000000..6782f5b
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart:1:1: Error: Expected 0 type arguments.
+// int<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.strong.transformed.expect
new file mode 100644
index 0000000..6782f5b
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_03.dart:1:1: Error: Expected 0 type arguments.
+// int<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart
new file mode 100644
index 0000000..1a373f5
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart
@@ -0,0 +1 @@
+Foo<int> f() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.outline.expect
new file mode 100644
index 0000000..7cf8e23
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.outline.expect
@@ -0,0 +1,16 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart:1:1: Error: Type 'Foo' not found.
+// Foo<int> f() {}
+// ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart:1:1: Error: Expected 0 type arguments.
+// Foo<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.strong.expect
new file mode 100644
index 0000000..03024b9
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.strong.expect
@@ -0,0 +1,15 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart:1:1: Error: Type 'Foo' not found.
+// Foo<int> f() {}
+// ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart:1:1: Error: Expected 0 type arguments.
+// Foo<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.strong.transformed.expect
new file mode 100644
index 0000000..03024b9
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart:1:1: Error: Type 'Foo' not found.
+// Foo<int> f() {}
+// ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_39958_04.dart:1:1: Error: Expected 0 type arguments.
+// Foo<int> f() {}
+// ^
+//
+import self as self;
+
+static method f() → invalid-type {}
diff --git a/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart
new file mode 100644
index 0000000..ad56555
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart
@@ -0,0 +1,5 @@
+Future<int> f() => Future.value(7);
+
+List<int> g() {
+  yield f();
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.outline.expect
new file mode 100644
index 0000000..3000fe7
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.outline.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method f() → asy::Future<core::int*>*
+  ;
+static method g() → core::List<core::int*>*
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.strong.expect
new file mode 100644
index 0000000..962b6f1
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.strong.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart:4:3: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+//   yield f();
+//   ^^^^^
+//
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method f() → asy::Future<core::int*>*
+  return asy::Future::value<core::int*>(7);
+static method g() → core::List<core::int*>* {
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart:4:3: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+  yield f();
+  ^";
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.strong.transformed.expect
new file mode 100644
index 0000000..962b6f1
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart:4:3: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+//   yield f();
+//   ^^^^^
+//
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method f() → asy::Future<core::int*>*
+  return asy::Future::value<core::int*>(7);
+static method g() → core::List<core::int*>* {
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/yield_not_in_generator.dart:4:3: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
+  yield f();
+  ^";
+}
diff --git a/pkg/front_end/testcases/general/for_in_scope.dart.strong.transformed.expect b/pkg/front_end/testcases/general/for_in_scope.dart.strong.transformed.expect
index cb9a540..ae6b6e7 100644
--- a/pkg/front_end/testcases/general/for_in_scope.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/for_in_scope.dart.strong.transformed.expect
@@ -1,11 +1,10 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method main(core::List<core::String*>* arguments) → dynamic {
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(arguments).{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = arguments.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* arguments = :sync-for-iterator.{core::Iterator::current};
       {
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 e6b4f0c..6065d16 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
@@ -66,7 +66,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Super extends core::Object {
   field core::int* superInstanceField = null;
@@ -87,7 +86,7 @@
     core::String* local;
     dynamic untypedLocal;
     {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String*>[]).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = <core::String*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -96,7 +95,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -105,7 +104,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -114,7 +113,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -123,7 +122,7 @@
       }
     }
     {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(<core::double*>[]).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = <core::double*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::double* #t5 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -132,7 +131,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -141,7 +140,7 @@
       }
     }
     {
-      core::Iterator<core::bool*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::bool*>*>(<core::bool*>[]).{core::Iterable::iterator};
+      core::Iterator<core::bool*>* :sync-for-iterator = <core::bool*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::bool* #t7 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -150,7 +149,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -159,7 +158,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t9 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -168,7 +167,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t10 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -178,7 +177,7 @@
     }
     self::C* c = new self::C::•();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -187,7 +186,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t12 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -196,7 +195,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t13 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -209,7 +208,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -222,7 +221,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t15 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -239,7 +238,7 @@
     for (main() in []) {}
          ^^^^";
       {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t16 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -256,7 +255,7 @@
     for (var x, y in <int>[]) {
          ^^^";
       {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t17 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -272,7 +271,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t18 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect
index 1d1c466..206c905 100644
--- a/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect
@@ -21,8 +21,8 @@
     final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -35,13 +35,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -54,8 +54,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -68,13 +68,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
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 4b93926..9281410 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
@@ -213,11 +213,11 @@
   field core::int* field1;
   field invalid-type field2;
   field core::int* field3 = 0;
-  field invalid-type field4 = 0 as{TypeError} invalid-type;
+  field invalid-type field4 = 0;
   field core::int* field5;
   field invalid-type field6;
   field core::int* field7 = 0;
-  field invalid-type field8 = 0 as{TypeError} invalid-type;
+  field invalid-type field8 = 0;
   field dynamic field9;
   generic-covariant-impl field core::int* field10;
   generic-covariant-impl field invalid-type field11;
@@ -236,11 +236,11 @@
   field core::int* field1;
   field invalid-type field2;
   field core::int* field3 = 0;
-  field invalid-type field4 = 0 as{TypeError} invalid-type;
+  field invalid-type field4 = 0;
   field core::int* field5;
   field invalid-type field6;
   field core::int* field7 = 0;
-  field invalid-type field8 = 0 as{TypeError} invalid-type;
+  field invalid-type field8 = 0;
   field dynamic field9;
   generic-covariant-impl field self::D::T* field10;
   generic-covariant-impl field self::D::T* field11;
diff --git a/pkg/front_end/testcases/general/invalid_operator2.dart.strong.expect b/pkg/front_end/testcases/general/invalid_operator2.dart.strong.expect
index ada9780..26fc9ec 100644
--- a/pkg/front_end/testcases/general/invalid_operator2.dart.strong.expect
+++ b/pkg/front_end/testcases/general/invalid_operator2.dart.strong.expect
@@ -33,6 +33,6 @@
     ;
   operator <<() → dynamic {}
   operator >(dynamic a) → invalid-type
-    return true as{TypeError} invalid-type;
+    return true;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/invalid_operator2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/invalid_operator2.dart.strong.transformed.expect
index ada9780..26fc9ec 100644
--- a/pkg/front_end/testcases/general/invalid_operator2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/invalid_operator2.dart.strong.transformed.expect
@@ -33,6 +33,6 @@
     ;
   operator <<() → dynamic {}
   operator >(dynamic a) → invalid-type
-    return true as{TypeError} invalid-type;
+    return true;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue37027.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue37027.dart.strong.transformed.expect
index 606d3a0..342575d 100644
--- a/pkg/front_end/testcases/general/issue37027.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue37027.dart.strong.transformed.expect
@@ -2,7 +2,6 @@
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
-import "dart:_internal" as _in;
 
 class C extends core::Object {
   final field core::Set<core::int*>* s;
@@ -10,7 +9,7 @@
     : self::C::s = block {
       final core::Set<core::int*>* #t1 = col::LinkedHashSet::•<core::int*>();
       {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(ell).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = ell.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           core::int* e = :sync-for-iterator.{core::Iterator::current};
           if(e.{core::int::isOdd})
diff --git a/pkg/front_end/testcases/general/issue39421.dart.outline.expect b/pkg/front_end/testcases/general/issue39421.dart.outline.expect
index 1987156..1ca93fb 100644
--- a/pkg/front_end/testcases/general/issue39421.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue39421.dart.outline.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general/issue39421.dart:16:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general/issue39421.dart:12:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/issue39421.dart.strong.expect b/pkg/front_end/testcases/general/issue39421.dart.strong.expect
index 6103be6..5bdde44 100644
--- a/pkg/front_end/testcases/general/issue39421.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue39421.dart.strong.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general/issue39421.dart:16:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general/issue39421.dart:12:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 // pkg/front_end/testcases/general/issue39421.dart:16:12: Error: Can't use 'A' because it is declared more than once.
 //   foo(List<A> a) {}
 //            ^
diff --git a/pkg/front_end/testcases/general/issue39421.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue39421.dart.strong.transformed.expect
index 6103be6..5bdde44 100644
--- a/pkg/front_end/testcases/general/issue39421.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue39421.dart.strong.transformed.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general/issue39421.dart:16:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general/issue39421.dart:12:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 // pkg/front_end/testcases/general/issue39421.dart:16:12: Error: Can't use 'A' because it is declared more than once.
 //   foo(List<A> a) {}
 //            ^
diff --git a/pkg/front_end/testcases/general/issue39817.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue39817.dart.strong.transformed.expect
index 896e8eb..da4a799 100644
--- a/pkg/front_end/testcases/general/issue39817.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue39817.dart.strong.transformed.expect
@@ -1,12 +1,11 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method foo() → dynamic {
   core::Null? _null;
   {
-    core::Iterator<core::Null?>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Null?>*>(_null).{core::Iterable::iterator};
+    core::Iterator<core::Null?>* :sync-for-iterator = _null.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic i = :sync-for-iterator.{core::Iterator::current};
       {}
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 52fd146..b69d96b 100644
--- a/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
@@ -12,8 +12,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -41,21 +41,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → void /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -70,13 +70,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.transformed.expect b/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.transformed.expect
index eb4e616..10d831b 100644
--- a/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Class extends core::Object {
   synthetic constructor •() → self::Class*
@@ -12,7 +11,7 @@
   dynamic o;
   if(false) {
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((let final dynamic #t1 = o in #t1.{core::Object::==}(null) ?{dynamic} null : #t1.iterable) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((let final dynamic #t1 = o in #t1.{core::Object::==}(null) ?{dynamic} null : #t1.iterable) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect b/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect
index e746568..c75c586 100644
--- a/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method nullAwareListSpread(core::List<core::String*>* list) → dynamic {
@@ -10,7 +9,7 @@
     #t1.{core::List::add}("foo");
     final core::Iterable<core::String*>* #t2 = list;
     if(!#t2.{core::Object::==}(null)) {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t2).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = #t2.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t3 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t3);
@@ -24,7 +23,7 @@
     #t4.{core::Set::add}("foo");
     final core::Iterable<core::String*>* #t5 = set;
     if(!#t5.{core::Object::==}(null)) {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t5).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = #t5.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t4.{core::Set::add}(#t6);
@@ -38,7 +37,7 @@
     #t7.{core::Map::[]=}(0, "foo");
     final core::Map<core::int*, core::String*>* #t8 = map;
     if(!#t8.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::int*, core::String*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::String*>*>*>(#t8.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::String*>*>* :sync-for-iterator = #t8.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::String*>* #t9 = :sync-for-iterator.{core::Iterator::current};
         #t7.{core::Map::[]=}(#t9.{core::MapEntry::key}, #t9.{core::MapEntry::value});
diff --git a/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect
index 0b31b37..19e0ff1 100644
--- a/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect
@@ -9,7 +9,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method main() → dynamic {
@@ -17,7 +16,7 @@
     final core::List<core::int*>* #t1 = <core::int*>[];
     #t1.{core::List::add}(1);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[2]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[2].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t2 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t2);
@@ -25,7 +24,7 @@
     }
     final core::Iterable<core::int*>* #t3 = <core::int*>[3];
     if(!#t3.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t3).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t3.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t4 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t4);
@@ -36,7 +35,7 @@
     final core::Map<core::int*, core::int*>* #t5 = <core::int*, core::int*>{};
     #t5.{core::Map::[]=}(1, 1);
     {
-      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(<core::int*, core::int*>{2: 2}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = <core::int*, core::int*>{2: 2}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::int*>* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
@@ -44,7 +43,7 @@
     }
     final core::Map<core::int*, core::int*>* #t7 = <core::int*, core::int*>{3: 3};
     if(!#t7.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(#t7.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = #t7.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::int*>* #t8 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
@@ -55,7 +54,7 @@
     final core::Set<core::int*>* #t9 = col::LinkedHashSet::•<core::int*>();
     #t9.{core::Set::add}(1);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[2]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[2].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t10 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::Set::add}(#t10);
@@ -63,7 +62,7 @@
     }
     final core::Iterable<core::int*>* #t11 = <core::int*>[3];
     if(!#t11.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t11).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t11.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t12 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::Set::add}(#t12);
diff --git a/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect
index 22a6806..3215846 100644
--- a/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect
@@ -98,7 +98,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method bar<K extends core::Object* = dynamic, V extends core::Object* = dynamic>() → core::Map<self::bar::K*, self::bar::V*>*
@@ -113,7 +112,7 @@
   core::List<dynamic>* lhs10 = block {
     final core::List<dynamic>* #t1 = <dynamic>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t2);
@@ -123,7 +122,7 @@
   core::Set<dynamic>* set10 = block {
     final core::Set<dynamic>* #t3 = col::LinkedHashSet::•<dynamic>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Set::add}(#t4);
@@ -133,7 +132,7 @@
   core::Map<dynamic, dynamic>* map10 = block {
     final core::Map<dynamic, dynamic>* #t5 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(<dynamic, dynamic>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = <dynamic, dynamic>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
@@ -143,7 +142,7 @@
   core::Map<dynamic, dynamic>* map10ambiguous = block {
     final core::Map<dynamic, dynamic>* #t7 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(<dynamic, dynamic>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = <dynamic, dynamic>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t8 = :sync-for-iterator.{core::Iterator::current};
         #t7.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
@@ -153,7 +152,7 @@
   core::List<core::int*>* lhs20 = block {
     final core::List<core::int*>* #t9 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t10 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::List::add}(#t10);
@@ -163,7 +162,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t11 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t12 = :sync-for-iterator.{core::Iterator::current};
         #t11.{core::Set::add}(#t12);
@@ -174,7 +173,7 @@
   core::Set<core::int*>* set20ambiguous = block {
     final core::Set<core::int*>* #t13 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -187,7 +186,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t16 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t17 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::Map::[]=}(#t17.{core::MapEntry::key}, #t17.{core::MapEntry::value});
@@ -198,7 +197,7 @@
   core::Map<core::String*, core::int*>* map20ambiguous = block {
     final core::Map<core::String*, core::int*>* #t18 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t19 = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::Map::[]=}(#t19.{core::MapEntry::key}, #t19.{core::MapEntry::value});
@@ -208,7 +207,7 @@
   core::List<dynamic>* lhs21 = block {
     final core::List<dynamic>* #t20 = <dynamic>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::List::add}(#t21);
@@ -218,7 +217,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t22 = col::LinkedHashSet::•<dynamic>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t23 = :sync-for-iterator.{core::Iterator::current};
         #t22.{core::Set::add}(#t23);
@@ -229,7 +228,7 @@
   core::Map<dynamic, dynamic>* map21 = block {
     final core::Map<dynamic, dynamic>* #t24 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(((mapSpread as dynamic) as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = ((mapSpread as dynamic) as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t25 = :sync-for-iterator.{core::Iterator::current};
         #t24.{core::Map::[]=}(#t25.{core::MapEntry::key}, #t25.{core::MapEntry::value});
@@ -244,7 +243,7 @@
   core::List<core::int*>* lhs22 = block {
     final core::List<core::int*>* #t26 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t27 = :sync-for-iterator.{core::Iterator::current};
         #t26.{core::List::add}(#t27);
@@ -254,7 +253,7 @@
   core::Set<core::int*>* set22 = block {
     final core::Set<core::int*>* #t28 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t29 = :sync-for-iterator.{core::Iterator::current};
         #t28.{core::Set::add}(#t29);
@@ -265,7 +264,7 @@
   core::Set<core::int*>* set22ambiguous = block {
     final core::Set<core::int*>* #t30 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t31 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -278,7 +277,7 @@
   core::Map<core::String*, core::int*>* map22 = block {
     final core::Map<core::String*, core::int*>* #t33 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t34 = :sync-for-iterator.{core::Iterator::current};
         #t33.{core::Map::[]=}(#t34.{core::MapEntry::key}, #t34.{core::MapEntry::value});
@@ -288,7 +287,7 @@
   core::List<core::List<core::int*>*>* lhs23 = block {
     final core::List<core::List<core::int*>*>* #t35 = <core::List<core::int*>*>[];
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t36 = :sync-for-iterator.{core::Iterator::current};
         #t35.{core::List::add}(#t36);
@@ -298,7 +297,7 @@
   core::Set<core::List<core::int*>*>* set23 = block {
     final core::Set<core::List<core::int*>*>* #t37 = col::LinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t38 = :sync-for-iterator.{core::Iterator::current};
         #t37.{core::Set::add}(#t38);
@@ -309,7 +308,7 @@
   core::Set<core::List<core::int*>*>* set23ambiguous = block {
     final core::Set<core::List<core::int*>*>* #t39 = col::LinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t40 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -322,7 +321,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map23 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t42 = <core::String*, core::List<core::int*>*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t43 = :sync-for-iterator.{core::Iterator::current};
         #t42.{core::Map::[]=}(#t43.{core::MapEntry::key}, #t43.{core::MapEntry::value});
@@ -338,7 +337,7 @@
                                    ^" in ( block {
     final core::List<core::int*>* #t45 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t46 = :sync-for-iterator.{core::Iterator::current};
         #t45.{core::List::add}(#t46);
@@ -351,7 +350,7 @@
                                    ^" in ( block {
     final core::Set<core::int*>* #t48 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t49 = :sync-for-iterator.{core::Iterator::current};
         #t48.{core::Set::add}(#t49);
@@ -365,7 +364,7 @@
       ^" in ( block {
     final core::Set<core::int*>* #t51 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t52 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -381,7 +380,7 @@
       ^" in ( block {
     final core::Map<core::String*, core::int*>* #t55 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t56 = :sync-for-iterator.{core::Iterator::current};
         #t55.{core::Map::[]=}(#t56.{core::MapEntry::key}, #t56.{core::MapEntry::value});
@@ -395,7 +394,7 @@
       ^" in ( block {
     final core::Map<core::String*, core::int*>* #t58 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t59 = :sync-for-iterator.{core::Iterator::current};
         #t58.{core::Map::[]=}(#t59.{core::MapEntry::key}, #t59.{core::MapEntry::value});
@@ -444,7 +443,7 @@
     ...null,
        ^");
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t69 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -461,7 +460,7 @@
     final core::List<core::int*>* #t71 = <core::int*>[];
     final core::Iterable<core::int*>* #t72 = null;
     if(!#t72.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t72).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t72.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t73 = :sync-for-iterator.{core::Iterator::current};
         #t71.{core::List::add}(#t73);
@@ -472,7 +471,7 @@
     final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>();
     final core::Iterable<core::int*>* #t75 = null;
     if(!#t75.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t75).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t75.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t76 = :sync-for-iterator.{core::Iterator::current};
         #t74.{core::Set::add}(#t76);
@@ -483,7 +482,7 @@
     final core::Set<dynamic>* #t77 = col::LinkedHashSet::•<dynamic>();
     final core::Iterable<dynamic>* #t78 = null;
     if(!#t78.{core::Object::==}(null)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(#t78).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = #t78.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t79 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -493,7 +492,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t81 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -507,7 +506,7 @@
     final core::Map<core::String*, core::int*>* #t83 = <core::String*, core::int*>{};
     final core::Map<core::String*, core::int*>* #t84 = null;
     if(!#t84.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(#t84.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = #t84.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t85 = :sync-for-iterator.{core::Iterator::current};
         #t83.{core::Map::[]=}(#t85.{core::MapEntry::key}, #t85.{core::MapEntry::value});
@@ -517,7 +516,7 @@
   core::Map<core::String*, core::int*>* map90 = block {
     final core::Map<core::String*, core::int*>* #t86 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(self::bar<core::String*, core::int*>().{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = self::bar<core::String*, core::int*>().{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t87 = :sync-for-iterator.{core::Iterator::current};
         #t86.{core::Map::[]=}(#t87.{core::MapEntry::key}, #t87.{core::MapEntry::value});
@@ -527,7 +526,7 @@
   core::List<core::int*>* list100 = block {
     final core::List<core::int*>* #t88 = <core::int*>[];
     {
-      core::Iterator<core::num*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::num*>*>(listNum).{core::Iterable::iterator};
+      core::Iterator<core::num*>* :sync-for-iterator = listNum.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t89 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -540,7 +539,7 @@
   core::Map<core::num*, core::int*>* map100 = block {
     final core::Map<core::num*, core::int*>* #t91 = <core::num*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::int*, core::num*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::num*>*>*>(mapIntNum.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::num*>*>* :sync-for-iterator = mapIntNum.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t92 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -554,7 +553,7 @@
   core::List<core::int*>* list110 = block {
     final core::List<core::int*>* #t95 = <core::int*>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t96 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -567,7 +566,7 @@
   core::Map<core::num*, core::int*>* map110 = block {
     final core::Map<core::num*, core::int*>* #t98 = <core::num*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t99 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.expect b/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.expect
index 3a5b1a7..8056cc0 100644
--- a/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.expect
@@ -16,9 +16,9 @@
     : super core::Object::•()
     ;
   method method() → invalid-type
-    return "Hello, World!" as{TypeError} invalid-type;
+    return "Hello, World!";
 }
 static method main() → dynamic {
-  core::String* s = new self::C::•<dynamic>().{self::C::method}() as{TypeError} core::String*;
+  core::String* s = new self::C::•<dynamic>().{self::C::method}();
   core::print(s);
 }
diff --git a/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.transformed.expect
index 3a5b1a7..8056cc0 100644
--- a/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_variable_prefix.dart.strong.transformed.expect
@@ -16,9 +16,9 @@
     : super core::Object::•()
     ;
   method method() → invalid-type
-    return "Hello, World!" as{TypeError} invalid-type;
+    return "Hello, World!";
 }
 static method main() → dynamic {
-  core::String* s = new self::C::•<dynamic>().{self::C::method}() as{TypeError} core::String*;
+  core::String* s = new self::C::•<dynamic>().{self::C::method}();
   core::print(s);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.strong.transformed.expect
index a4a39f8..c86613d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.strong.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -25,21 +25,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method asyncString2() → asy::Future<core::String*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -52,13 +52,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method syncStarString() → core::Iterable<core::String*>* /* originally sync* */ {
@@ -101,8 +101,8 @@
   asy::_AsyncStarStreamController<core::String*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -128,7 +128,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -145,8 +145,8 @@
   asy::_AsyncStarStreamController<core::String*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -163,7 +163,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -180,8 +180,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -195,12 +195,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect
index a4a39f8..c86613d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -25,21 +25,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method asyncString2() → asy::Future<core::String*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -52,13 +52,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method syncStarString() → core::Iterable<core::String*>* /* originally sync* */ {
@@ -101,8 +101,8 @@
   asy::_AsyncStarStreamController<core::String*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -128,7 +128,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -145,8 +145,8 @@
   asy::_AsyncStarStreamController<core::String*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -163,7 +163,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -180,8 +180,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -195,12 +195,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.strong.transformed.expect
index 2d6ae21..bdf5176 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.strong.transformed.expect
@@ -22,8 +22,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -56,13 +56,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect
index 2d6ae21..bdf5176 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect
@@ -22,8 +22,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -56,13 +56,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.strong.transformed.expect
index a4fa440..8c66908 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.strong.transformed.expect
@@ -8,8 +8,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -23,12 +23,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.weak.transformed.expect
index a4fa440..8c66908 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await.dart.weak.transformed.expect
@@ -8,8 +8,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -23,12 +23,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.strong.transformed.expect
index 8a2da7f..dfafacd 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.strong.transformed.expect
@@ -50,8 +50,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -93,21 +93,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method topLevelMembers() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -144,21 +144,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method instanceMembers() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -196,21 +196,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method others() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -248,21 +248,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method conditionals() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -320,21 +320,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method asserts() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -344,7 +344,7 @@
       #L6:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Function*>*>(<core::Function*>[#C1, #C2]).{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t26 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -393,21 +393,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method controlFlow() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -423,7 +423,7 @@
       #L7:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Function*>*>(<core::Function*>[#C1, #C2]).{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t33 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -539,8 +539,8 @@
                 final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
                 asy::FutureOr<dynamic>* :return_value;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -555,13 +555,13 @@
                     asy::_completeOnAsyncReturn(:async_completer, :return_value);
                     return;
                   }
-                  on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                  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.start(:async_op);
+                :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
                 return :async_completer.{asy::Completer::future};
               }).call(), :async_op_then, :async_op_error, :async_op) in null;
               self::expect(42, :result);
@@ -569,8 +569,8 @@
                 final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
                 asy::FutureOr<dynamic>* :return_value;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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 
@@ -583,13 +583,13 @@
                     asy::_completeOnAsyncReturn(:async_completer, :return_value);
                     return;
                   }
-                  on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                  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.start(:async_op);
+                :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
                 return :async_completer.{asy::Completer::future};
               }).call(), :async_op_then, :async_op_error, :async_op) in null;
               self::expect(42, :result);
@@ -597,8 +597,8 @@
                 asy::_AsyncStarStreamController<core::int*>* :controller;
                 dynamic :controller_stream;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -616,7 +616,7 @@
                       }
                       return;
                     }
-                    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                    on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                       :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
                     }
                   finally {
@@ -636,8 +636,8 @@
                 asy::_AsyncStarStreamController<core::int*>* :controller;
                 dynamic :controller_stream;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -655,7 +655,7 @@
                       }
                       return;
                     }
-                    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                    on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                       :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
                     }
                   finally {
@@ -678,21 +678,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method future<T extends core::Object* = dynamic>(self::future::T* value) → asy::FutureOr<self::future::T*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<self::future::T*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::future::T*>();
   asy::FutureOr<self::future::T*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -705,13 +705,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method id<T extends core::Object* = dynamic>(self::id::T* value) → asy::FutureOr<self::id::T*>*
@@ -720,8 +720,8 @@
   asy::_AsyncStarStreamController<core::int*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -738,7 +738,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -755,8 +755,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -784,13 +784,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect
index 8a2da7f..dfafacd 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect
@@ -50,8 +50,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -93,21 +93,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method topLevelMembers() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -144,21 +144,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method instanceMembers() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -196,21 +196,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method others() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -248,21 +248,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method conditionals() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -320,21 +320,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method asserts() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -344,7 +344,7 @@
       #L6:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Function*>*>(<core::Function*>[#C1, #C2]).{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t26 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -393,21 +393,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method controlFlow() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -423,7 +423,7 @@
       #L7:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Function*>*>(<core::Function*>[#C1, #C2]).{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t33 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -539,8 +539,8 @@
                 final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
                 asy::FutureOr<dynamic>* :return_value;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -555,13 +555,13 @@
                     asy::_completeOnAsyncReturn(:async_completer, :return_value);
                     return;
                   }
-                  on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                  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.start(:async_op);
+                :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
                 return :async_completer.{asy::Completer::future};
               }).call(), :async_op_then, :async_op_error, :async_op) in null;
               self::expect(42, :result);
@@ -569,8 +569,8 @@
                 final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
                 asy::FutureOr<dynamic>* :return_value;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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 
@@ -583,13 +583,13 @@
                     asy::_completeOnAsyncReturn(:async_completer, :return_value);
                     return;
                   }
-                  on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                  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.start(:async_op);
+                :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
                 return :async_completer.{asy::Completer::future};
               }).call(), :async_op_then, :async_op_error, :async_op) in null;
               self::expect(42, :result);
@@ -597,8 +597,8 @@
                 asy::_AsyncStarStreamController<core::int*>* :controller;
                 dynamic :controller_stream;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -616,7 +616,7 @@
                       }
                       return;
                     }
-                    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                    on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                       :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
                     }
                   finally {
@@ -636,8 +636,8 @@
                 asy::_AsyncStarStreamController<core::int*>* :controller;
                 dynamic :controller_stream;
                 dynamic :async_stack_trace;
-                dynamic :async_op_then;
-                dynamic :async_op_error;
+                (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;
@@ -655,7 +655,7 @@
                       }
                       return;
                     }
-                    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                    on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                       :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
                     }
                   finally {
@@ -678,21 +678,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method future<T extends core::Object* = dynamic>(self::future::T* value) → asy::FutureOr<self::future::T*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<self::future::T*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::future::T*>();
   asy::FutureOr<self::future::T*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -705,13 +705,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method id<T extends core::Object* = dynamic>(self::id::T* value) → asy::FutureOr<self::id::T*>*
@@ -720,8 +720,8 @@
   asy::_AsyncStarStreamController<core::int*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -738,7 +738,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -755,8 +755,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -784,13 +784,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.strong.transformed.expect
index be2d683..72c6420 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.strong.transformed.expect
@@ -14,8 +14,8 @@
     final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
     asy::FutureOr<core::List<core::int*>*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -31,21 +31,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   method _m() → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -58,13 +58,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -72,8 +72,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -87,13 +87,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect
index be2d683..72c6420 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect
@@ -14,8 +14,8 @@
     final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
     asy::FutureOr<core::List<core::int*>*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -31,21 +31,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   method _m() → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -58,13 +58,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -72,8 +72,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -87,13 +87,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.strong.transformed.expect
index ca4c8a8..895484d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.strong.transformed.expect
@@ -13,8 +13,8 @@
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -27,12 +27,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.weak.transformed.expect
index ca4c8a8..895484d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33196.dart.weak.transformed.expect
@@ -13,8 +13,8 @@
   final asy::_AsyncAwaitCompleter<core::String*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::String*>();
   asy::FutureOr<core::String*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -27,12 +27,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.strong.transformed.expect
index 052b974..fa92a38 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.strong.transformed.expect
@@ -25,8 +25,8 @@
   final asy::_AsyncAwaitCompleter<core::List<core::Object*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::Object*>*>();
   asy::FutureOr<core::List<core::Object*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -39,13 +39,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method f2() → core::List<core::Object*>*
@@ -54,8 +54,8 @@
   final asy::_AsyncAwaitCompleter<core::Object*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Object*>();
   asy::FutureOr<core::Object*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -68,21 +68,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method foo() → asy::Future<self::X*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<self::X*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::X*>();
   asy::FutureOr<self::X*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -101,21 +101,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → asy::Future<void>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<void>* :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
   asy::FutureOr<void>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -129,12 +129,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect
index 052b974..fa92a38 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect
@@ -25,8 +25,8 @@
   final asy::_AsyncAwaitCompleter<core::List<core::Object*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::Object*>*>();
   asy::FutureOr<core::List<core::Object*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -39,13 +39,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method f2() → core::List<core::Object*>*
@@ -54,8 +54,8 @@
   final asy::_AsyncAwaitCompleter<core::Object*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Object*>();
   asy::FutureOr<core::Object*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -68,21 +68,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method foo() → asy::Future<self::X*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<self::X*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::X*>();
   asy::FutureOr<self::X*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -101,21 +101,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → asy::Future<void>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<void>* :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
   asy::FutureOr<void>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -129,12 +129,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.strong.transformed.expect
index d20f094..1164433 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.strong.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -27,13 +27,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.weak.transformed.expect
index d20f094..1164433 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_before_args2.dart.weak.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -27,13 +27,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.strong.transformed.expect
index 7bd3d63..9cdff84 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method main() → dynamic {
@@ -18,14 +17,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t1.{core::List::add}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -48,14 +47,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t2.{core::Set::add}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t2.{core::Set::add}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -78,14 +77,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t3.{core::Map::[]=}(4, 4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Map::[]=}(i, i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
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 7bd3d63..9cdff84 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
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method main() → dynamic {
@@ -18,14 +17,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t1.{core::List::add}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -48,14 +47,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t2.{core::Set::add}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t2.{core::Set::add}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -78,14 +77,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t3.{core::Map::[]=}(4, 4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[5, 6, 7]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Map::[]=}(i, i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[8, 9, 10]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.strong.transformed.expect
index 4dce82d..5964136 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.strong.transformed.expect
@@ -424,8 +424,8 @@
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
-import "dart:_internal" as _in;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 class A extends core::Object {
   synthetic constructor •() → self::A*
@@ -496,7 +496,7 @@
   core::List<core::int*>* list20 = block {
     final core::List<core::int*>* #t10 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         #t10.{core::List::add}(#t11);
@@ -506,7 +506,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t12 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t13 = :sync-for-iterator.{core::Iterator::current};
         #t12.{core::Set::add}(#t13);
@@ -517,7 +517,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t14 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t15 = :sync-for-iterator.{core::Iterator::current};
         #t14.{core::Map::[]=}(#t15.{core::MapEntry::key}, #t15.{core::MapEntry::value});
@@ -528,7 +528,7 @@
   core::List<dynamic>* list21 = block {
     final core::List<dynamic>* #t16 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t17 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::List::add}(#t17);
@@ -538,7 +538,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t18 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t19 = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::Set::add}(#t19);
@@ -549,7 +549,7 @@
   core::Map<core::String*, dynamic>* map21 = block {
     final core::Map<core::String*, dynamic>* #t20 = <core::String*, dynamic>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, dynamic>* #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
@@ -560,7 +560,7 @@
   core::List<core::List<core::int*>*>* list22 = block {
     final core::List<core::List<core::int*>*>* #t22 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t23 = :sync-for-iterator.{core::Iterator::current};
         #t22.{core::List::add}(#t23);
@@ -570,7 +570,7 @@
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t24 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t25 = :sync-for-iterator.{core::Iterator::current};
         #t24.{core::Set::add}(#t25);
@@ -581,7 +581,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t26 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t27 = :sync-for-iterator.{core::Iterator::current};
         #t26.{core::Map::[]=}(#t27.{core::MapEntry::key}, #t27.{core::MapEntry::value});
@@ -593,7 +593,7 @@
     final core::List<core::int*>* #t28 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t29 = :sync-for-iterator.{core::Iterator::current};
           #t28.{core::List::add}(#t29);
@@ -604,7 +604,7 @@
     final core::Set<core::int*>* #t30 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t31 = :sync-for-iterator.{core::Iterator::current};
           #t30.{core::Set::add}(#t31);
@@ -616,7 +616,7 @@
     final core::Map<core::String*, core::int*>* #t32 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t33 = :sync-for-iterator.{core::Iterator::current};
           #t32.{core::Map::[]=}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
@@ -628,7 +628,7 @@
     final core::List<dynamic>* #t34 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t35 = :sync-for-iterator.{core::Iterator::current};
           #t34.{core::List::add}(#t35);
@@ -639,7 +639,7 @@
     final core::Set<dynamic>* #t36 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t37 = :sync-for-iterator.{core::Iterator::current};
           #t36.{core::Set::add}(#t37);
@@ -651,7 +651,7 @@
     final core::Map<core::String*, dynamic>* #t38 = <core::String*, dynamic>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, dynamic>* #t39 = :sync-for-iterator.{core::Iterator::current};
           #t38.{core::Map::[]=}(#t39.{core::MapEntry::key}, #t39.{core::MapEntry::value});
@@ -663,7 +663,7 @@
     final core::List<core::List<core::int*>*>* #t40 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t41 = :sync-for-iterator.{core::Iterator::current};
           #t40.{core::List::add}(#t41);
@@ -674,7 +674,7 @@
     final core::Set<core::List<core::int*>*>* #t42 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t43 = :sync-for-iterator.{core::Iterator::current};
           #t42.{core::Set::add}(#t43);
@@ -686,7 +686,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t44 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t45 = :sync-for-iterator.{core::Iterator::current};
           #t44.{core::Map::[]=}(#t45.{core::MapEntry::key}, #t45.{core::MapEntry::value});
@@ -697,7 +697,7 @@
   core::List<core::List<core::int*>*>* list40 = block {
     final core::List<core::List<core::int*>*>* #t46 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t47 = :sync-for-iterator.{core::Iterator::current};
         #t46.{core::List::add}(#t47);
@@ -707,7 +707,7 @@
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t48 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t49 = :sync-for-iterator.{core::Iterator::current};
         #t48.{core::Set::add}(#t49);
@@ -721,7 +721,7 @@
   core::List<core::List<core::int*>*>* list41 = block {
     final core::List<core::List<core::int*>*>* #t50 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t51 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t52 = #t51.{core::Set::add}(<core::int*>[]) in #t51).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t51 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t52 = #t51.{core::Set::add}(<core::int*>[]) in #t51).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t53 = :sync-for-iterator.{core::Iterator::current};
         #t50.{core::List::add}(#t53);
@@ -731,7 +731,7 @@
   core::Set<core::List<core::int*>*>* set41 = block {
     final core::Set<core::List<core::int*>*>* #t54 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t55 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t56 = #t55.{core::Set::add}(<core::int*>[]) in #t55).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t55 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t56 = #t55.{core::Set::add}(<core::int*>[]) in #t55).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t57 = :sync-for-iterator.{core::Iterator::current};
         #t54.{core::Set::add}(#t57);
@@ -743,7 +743,7 @@
     final core::List<core::List<core::int*>*>* #t58 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t59 = :sync-for-iterator.{core::Iterator::current};
           #t58.{core::List::add}(#t59);
@@ -754,7 +754,7 @@
     final core::Set<core::List<core::int*>*>* #t60 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t61 = :sync-for-iterator.{core::Iterator::current};
           #t60.{core::Set::add}(#t61);
@@ -766,7 +766,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t62 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t63 = :sync-for-iterator.{core::Iterator::current};
           #t62.{core::Map::[]=}(#t63.{core::MapEntry::key}, #t63.{core::MapEntry::value});
@@ -777,7 +777,7 @@
   core::List<core::int*>* list50 = block {
     final core::List<core::int*>* #t64 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t65 = :sync-for-iterator.{core::Iterator::current};
         #t64.{core::List::add}(#t65);
@@ -787,7 +787,7 @@
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t66 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t67 = :sync-for-iterator.{core::Iterator::current};
         #t66.{core::Set::add}(#t67);
@@ -798,7 +798,7 @@
   core::Map<core::String*, core::int*>* map50 = block {
     final core::Map<core::String*, core::int*>* #t68 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t69 = :sync-for-iterator.{core::Iterator::current};
         #t68.{core::Map::[]=}(#t69.{core::MapEntry::key}, #t69.{core::MapEntry::value});
@@ -809,7 +809,7 @@
   core::List<core::int*>* list51 = block {
     final core::List<core::int*>* #t70 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t71 = col::LinkedHashSet::•<core::int*>() in #t71).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t71 = col::LinkedHashSet::•<core::int*>() in #t71).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t72 = :sync-for-iterator.{core::Iterator::current};
         #t70.{core::List::add}(#t72);
@@ -819,7 +819,7 @@
   core::Set<core::int*>* set51 = block {
     final core::Set<core::int*>* #t73 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>() in #t74).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>() in #t74).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t75 = :sync-for-iterator.{core::Iterator::current};
         #t73.{core::Set::add}(#t75);
@@ -831,7 +831,7 @@
     final core::List<core::int*>* #t76 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t77 = :sync-for-iterator.{core::Iterator::current};
           #t76.{core::List::add}(#t77);
@@ -842,7 +842,7 @@
     final core::Set<core::int*>* #t78 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t79 = :sync-for-iterator.{core::Iterator::current};
           #t78.{core::Set::add}(#t79);
@@ -854,7 +854,7 @@
     final core::Map<core::String*, core::int*>* #t80 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t81 = :sync-for-iterator.{core::Iterator::current};
           #t80.{core::Map::[]=}(#t81.{core::MapEntry::key}, #t81.{core::MapEntry::value});
@@ -865,7 +865,7 @@
   core::List<core::List<core::int*>*>* list60 = block {
     final core::List<core::List<core::int*>*>* #t82 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t83 = :sync-for-iterator.{core::Iterator::current};
         #t82.{core::List::add}(#t83);
@@ -875,7 +875,7 @@
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t84 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t85 = :sync-for-iterator.{core::Iterator::current};
         #t84.{core::Set::add}(#t85);
@@ -886,7 +886,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t86 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t87 = :sync-for-iterator.{core::Iterator::current};
         #t86.{core::Map::[]=}(#t87.{core::MapEntry::key}, #t87.{core::MapEntry::value});
@@ -898,7 +898,7 @@
     final core::List<core::List<core::int*>*>* #t88 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t89 = :sync-for-iterator.{core::Iterator::current};
           #t88.{core::List::add}(#t89);
@@ -909,7 +909,7 @@
     final core::Set<core::List<core::int*>*>* #t90 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t91 = :sync-for-iterator.{core::Iterator::current};
           #t90.{core::Set::add}(#t91);
@@ -921,7 +921,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t92 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t93 = :sync-for-iterator.{core::Iterator::current};
           #t92.{core::Map::[]=}(#t93.{core::MapEntry::key}, #t93.{core::MapEntry::value});
@@ -979,14 +979,14 @@
   core::List<core::num*>* list81 = block {
     final core::List<core::num*>* #t101 = <core::num*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t102 = :sync-for-iterator.{core::Iterator::current};
         #t101.{core::List::add}(#t102);
       }
     }
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t103 = :sync-for-iterator.{core::Iterator::current};
         #t101.{core::List::add}(#t103);
@@ -996,14 +996,14 @@
   core::Set<core::num*>* set81 = block {
     final core::Set<core::num*>* #t104 = col::LinkedHashSet::•<core::num*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t105 = :sync-for-iterator.{core::Iterator::current};
         #t104.{core::Set::add}(#t105);
       }
     }
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t106 = :sync-for-iterator.{core::Iterator::current};
         #t104.{core::Set::add}(#t106);
@@ -1014,14 +1014,14 @@
   core::Map<core::String*, core::num*>* map81 = block {
     final core::Map<core::String*, core::num*>* #t107 = <core::String*, core::num*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapToInt.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapToInt.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t108 = :sync-for-iterator.{core::Iterator::current};
         #t107.{core::Map::[]=}(#t108.{core::MapEntry::key}, #t108.{core::MapEntry::value});
       }
     }
     else {
-      core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::double*>*>*>(mapToDouble.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = mapToDouble.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t109 = :sync-for-iterator.{core::Iterator::current};
         #t107.{core::Map::[]=}(#t109.{core::MapEntry::key}, #t109.{core::MapEntry::value});
@@ -1032,14 +1032,14 @@
   core::List<dynamic>* list82 = block {
     final core::List<dynamic>* #t110 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t111 = :sync-for-iterator.{core::Iterator::current};
         #t110.{core::List::add}(#t111);
       }
     }
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t112 = :sync-for-iterator.{core::Iterator::current};
         #t110.{core::List::add}(#t112);
@@ -1049,14 +1049,14 @@
   core::Set<dynamic>* set82 = block {
     final core::Set<dynamic>* #t113 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t114 = :sync-for-iterator.{core::Iterator::current};
         #t113.{core::Set::add}(#t114);
       }
     }
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t115 = :sync-for-iterator.{core::Iterator::current};
         #t113.{core::Set::add}(#t115);
@@ -1072,7 +1072,7 @@
   var map82 = {if (oracle(\"foo\")) ...mapToInt else ...dynVar, null};
                                      ^");
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t117 = :sync-for-iterator.{core::Iterator::current};
         #t116.{core::Set::add}(#t117);
@@ -1085,7 +1085,7 @@
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t118.{core::List::add}(42);
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t119 = :sync-for-iterator.{core::Iterator::current};
         #t118.{core::List::add}(#t119);
@@ -1095,7 +1095,7 @@
   core::Set<core::num*>* set83 = block {
     final core::Set<core::num*>* #t120 = col::LinkedHashSet::•<core::num*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t121 = :sync-for-iterator.{core::Iterator::current};
         #t120.{core::Set::add}(#t121);
@@ -1108,7 +1108,7 @@
   core::Map<core::String*, core::num*>* map83 = block {
     final core::Map<core::String*, core::num*>* #t122 = <core::String*, core::num*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapToInt.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapToInt.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t123 = :sync-for-iterator.{core::Iterator::current};
         #t122.{core::Map::[]=}(#t123.{core::MapEntry::key}, #t123.{core::MapEntry::value});
@@ -1138,7 +1138,7 @@
   core::List<core::int*>* list91 = block {
     final core::List<core::int*>* #t127 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t128 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1151,7 +1151,7 @@
   core::Set<core::int*>* set91 = block {
     final core::Set<core::int*>* #t130 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t131 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1165,7 +1165,7 @@
   core::Map<core::String*, core::int*>* map91 = block {
     final core::Map<core::String*, core::int*>* #t133 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t134 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1220,9 +1220,9 @@
   block {
     final core::List<core::int*>* #t146 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t147 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:92:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t147 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:92:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[if (oracle(\"foo\")) ...[\"bar\"]];
-                               ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                               ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t148 = :sync-for-iterator.{core::Iterator::current};
         #t146.{core::List::add}(#t148);
@@ -1232,9 +1232,9 @@
   block {
     final core::Set<core::int*>* #t149 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t150 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:93:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t150 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:93:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{if (oracle(\"foo\")) ...[\"bar\"], null};
-                               ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                               ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t151 = :sync-for-iterator.{core::Iterator::current};
         #t149.{core::Set::add}(#t151);
@@ -1245,9 +1245,9 @@
   block {
     final core::Map<core::String*, core::int*>* #t152 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": let final<BottomType> #t153 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:94:47: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": let final<BottomType> #t153 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:94:47: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <String, int>{if (oracle(\"foo\")) ...{\"bar\": \"bar\"}, \"baz\": null};
-                                              ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}).{core::Iterable::iterator};
+                                              ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t154 = :sync-for-iterator.{core::Iterator::current};
         #t152.{core::Map::[]=}(#t154.{core::MapEntry::key}, #t154.{core::MapEntry::value});
@@ -1509,7 +1509,7 @@
   core::List<core::int*>* list20 = block {
     final core::List<core::int*>* #t197 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t198 = :sync-for-iterator.{core::Iterator::current};
         #t197.{core::List::add}(#t198);
@@ -1519,7 +1519,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t199 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t200 = :sync-for-iterator.{core::Iterator::current};
         #t199.{core::Set::add}(#t200);
@@ -1530,7 +1530,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t201 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t202 = :sync-for-iterator.{core::Iterator::current};
         #t201.{core::Map::[]=}(#t202.{core::MapEntry::key}, #t202.{core::MapEntry::value});
@@ -1541,7 +1541,7 @@
   core::List<dynamic>* list21 = block {
     final core::List<dynamic>* #t203 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t204 = :sync-for-iterator.{core::Iterator::current};
         #t203.{core::List::add}(#t204);
@@ -1551,7 +1551,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t205 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t206 = :sync-for-iterator.{core::Iterator::current};
         #t205.{core::Set::add}(#t206);
@@ -1562,7 +1562,7 @@
   core::Map<core::String*, dynamic>* map21 = block {
     final core::Map<core::String*, dynamic>* #t207 = <core::String*, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, dynamic>* #t208 = :sync-for-iterator.{core::Iterator::current};
         #t207.{core::Map::[]=}(#t208.{core::MapEntry::key}, #t208.{core::MapEntry::value});
@@ -1573,7 +1573,7 @@
   core::List<core::List<core::int*>*>* list22 = block {
     final core::List<core::List<core::int*>*>* #t209 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t210 = :sync-for-iterator.{core::Iterator::current};
         #t209.{core::List::add}(#t210);
@@ -1583,7 +1583,7 @@
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t211 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t212 = :sync-for-iterator.{core::Iterator::current};
         #t211.{core::Set::add}(#t212);
@@ -1594,7 +1594,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t213 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t214 = :sync-for-iterator.{core::Iterator::current};
         #t213.{core::Map::[]=}(#t214.{core::MapEntry::key}, #t214.{core::MapEntry::value});
@@ -1606,7 +1606,7 @@
     final core::List<core::int*>* #t215 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t216 = :sync-for-iterator.{core::Iterator::current};
           #t215.{core::List::add}(#t216);
@@ -1617,7 +1617,7 @@
     final core::Set<core::int*>* #t217 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t218 = :sync-for-iterator.{core::Iterator::current};
           #t217.{core::Set::add}(#t218);
@@ -1629,7 +1629,7 @@
     final core::Map<core::String*, core::int*>* #t219 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t220 = :sync-for-iterator.{core::Iterator::current};
           #t219.{core::Map::[]=}(#t220.{core::MapEntry::key}, #t220.{core::MapEntry::value});
@@ -1641,7 +1641,7 @@
     final core::List<dynamic>* #t221 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t222 = :sync-for-iterator.{core::Iterator::current};
           #t221.{core::List::add}(#t222);
@@ -1652,7 +1652,7 @@
     final core::Set<dynamic>* #t223 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t224 = :sync-for-iterator.{core::Iterator::current};
           #t223.{core::Set::add}(#t224);
@@ -1664,7 +1664,7 @@
     final core::Map<core::String*, dynamic>* #t225 = <core::String*, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, dynamic>* #t226 = :sync-for-iterator.{core::Iterator::current};
           #t225.{core::Map::[]=}(#t226.{core::MapEntry::key}, #t226.{core::MapEntry::value});
@@ -1676,7 +1676,7 @@
     final core::List<core::List<core::int*>*>* #t227 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t228 = :sync-for-iterator.{core::Iterator::current};
           #t227.{core::List::add}(#t228);
@@ -1687,7 +1687,7 @@
     final core::Set<core::List<core::int*>*>* #t229 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t230 = :sync-for-iterator.{core::Iterator::current};
           #t229.{core::Set::add}(#t230);
@@ -1699,7 +1699,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t231 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t232 = :sync-for-iterator.{core::Iterator::current};
           #t231.{core::Map::[]=}(#t232.{core::MapEntry::key}, #t232.{core::MapEntry::value});
@@ -1710,7 +1710,7 @@
   core::List<core::List<core::int*>*>* list40 = block {
     final core::List<core::List<core::int*>*>* #t233 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t234 = :sync-for-iterator.{core::Iterator::current};
         #t233.{core::List::add}(#t234);
@@ -1720,7 +1720,7 @@
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t235 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t236 = :sync-for-iterator.{core::Iterator::current};
         #t235.{core::Set::add}(#t236);
@@ -1731,7 +1731,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map40 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t237 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t238 = :sync-for-iterator.{core::Iterator::current};
         #t237.{core::Map::[]=}(#t238.{core::MapEntry::key}, #t238.{core::MapEntry::value});
@@ -1742,7 +1742,7 @@
   core::List<core::List<core::int*>*>* list41 = block {
     final core::List<core::List<core::int*>*>* #t239 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t240 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t241 = #t240.{core::Set::add}(<core::int*>[]) in #t240).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t240 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t241 = #t240.{core::Set::add}(<core::int*>[]) in #t240).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t242 = :sync-for-iterator.{core::Iterator::current};
         #t239.{core::List::add}(#t242);
@@ -1752,7 +1752,7 @@
   core::Set<core::List<core::int*>*>* set41 = block {
     final core::Set<core::List<core::int*>*>* #t243 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t244 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t245 = #t244.{core::Set::add}(<core::int*>[]) in #t244).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t244 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t245 = #t244.{core::Set::add}(<core::int*>[]) in #t244).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t246 = :sync-for-iterator.{core::Iterator::current};
         #t243.{core::Set::add}(#t246);
@@ -1764,7 +1764,7 @@
     final core::List<core::List<core::int*>*>* #t247 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t248 = :sync-for-iterator.{core::Iterator::current};
           #t247.{core::List::add}(#t248);
@@ -1775,7 +1775,7 @@
     final core::Set<core::List<core::int*>*>* #t249 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t250 = :sync-for-iterator.{core::Iterator::current};
           #t249.{core::Set::add}(#t250);
@@ -1787,7 +1787,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t251 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t252 = :sync-for-iterator.{core::Iterator::current};
           #t251.{core::Map::[]=}(#t252.{core::MapEntry::key}, #t252.{core::MapEntry::value});
@@ -1798,7 +1798,7 @@
   core::List<core::int*>* list50 = block {
     final core::List<core::int*>* #t253 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t254 = :sync-for-iterator.{core::Iterator::current};
         #t253.{core::List::add}(#t254);
@@ -1808,7 +1808,7 @@
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t255 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t256 = :sync-for-iterator.{core::Iterator::current};
         #t255.{core::Set::add}(#t256);
@@ -1819,7 +1819,7 @@
   core::Map<core::String*, core::int*>* map50 = block {
     final core::Map<core::String*, core::int*>* #t257 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t258 = :sync-for-iterator.{core::Iterator::current};
         #t257.{core::Map::[]=}(#t258.{core::MapEntry::key}, #t258.{core::MapEntry::value});
@@ -1830,7 +1830,7 @@
   core::List<core::int*>* list51 = block {
     final core::List<core::int*>* #t259 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t260 = col::LinkedHashSet::•<core::int*>() in #t260).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t260 = col::LinkedHashSet::•<core::int*>() in #t260).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t261 = :sync-for-iterator.{core::Iterator::current};
         #t259.{core::List::add}(#t261);
@@ -1840,7 +1840,7 @@
   core::Set<core::int*>* set51 = block {
     final core::Set<core::int*>* #t262 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t263 = col::LinkedHashSet::•<core::int*>() in #t263).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t263 = col::LinkedHashSet::•<core::int*>() in #t263).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t264 = :sync-for-iterator.{core::Iterator::current};
         #t262.{core::Set::add}(#t264);
@@ -1852,7 +1852,7 @@
     final core::List<core::int*>* #t265 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t266 = :sync-for-iterator.{core::Iterator::current};
           #t265.{core::List::add}(#t266);
@@ -1863,7 +1863,7 @@
     final core::Set<core::int*>* #t267 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t268 = :sync-for-iterator.{core::Iterator::current};
           #t267.{core::Set::add}(#t268);
@@ -1874,7 +1874,7 @@
   core::List<core::List<core::int*>*>* list60 = block {
     final core::List<core::List<core::int*>*>* #t269 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t270 = :sync-for-iterator.{core::Iterator::current};
         #t269.{core::List::add}(#t270);
@@ -1884,7 +1884,7 @@
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t271 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t272 = :sync-for-iterator.{core::Iterator::current};
         #t271.{core::Set::add}(#t272);
@@ -1895,7 +1895,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t273 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t274 = :sync-for-iterator.{core::Iterator::current};
         #t273.{core::Map::[]=}(#t274.{core::MapEntry::key}, #t274.{core::MapEntry::value});
@@ -1907,7 +1907,7 @@
     final core::List<core::List<core::int*>*>* #t275 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t276 = :sync-for-iterator.{core::Iterator::current};
           #t275.{core::List::add}(#t276);
@@ -1918,7 +1918,7 @@
     final core::Set<core::List<core::int*>*>* #t277 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t278 = :sync-for-iterator.{core::Iterator::current};
           #t277.{core::Set::add}(#t278);
@@ -1930,7 +1930,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t279 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t280 = :sync-for-iterator.{core::Iterator::current};
           #t279.{core::Map::[]=}(#t280.{core::MapEntry::key}, #t280.{core::MapEntry::value});
@@ -2005,14 +2005,14 @@
     final core::List<core::num*>* #t290 = <core::num*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t291 = :sync-for-iterator.{core::Iterator::current};
           #t290.{core::List::add}(#t291);
         }
       }
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t292 = :sync-for-iterator.{core::Iterator::current};
           #t290.{core::List::add}(#t292);
@@ -2023,14 +2023,14 @@
     final core::Set<core::num*>* #t293 = col::LinkedHashSet::•<core::num*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t294 = :sync-for-iterator.{core::Iterator::current};
           #t293.{core::Set::add}(#t294);
         }
       }
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t295 = :sync-for-iterator.{core::Iterator::current};
           #t293.{core::Set::add}(#t295);
@@ -2042,14 +2042,14 @@
     final core::Map<core::String*, core::num*>* #t296 = <core::String*, core::num*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t297 = :sync-for-iterator.{core::Iterator::current};
           #t296.{core::Map::[]=}(#t297.{core::MapEntry::key}, #t297.{core::MapEntry::value});
         }
       }
       else {
-        core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::double*>*>*>(mapStringDouble.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = mapStringDouble.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t298 = :sync-for-iterator.{core::Iterator::current};
           #t296.{core::Map::[]=}(#t298.{core::MapEntry::key}, #t298.{core::MapEntry::value});
@@ -2061,14 +2061,14 @@
     final core::List<dynamic>* #t299 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t300 = :sync-for-iterator.{core::Iterator::current};
           #t299.{core::List::add}(#t300);
         }
       }
       else {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t301 = :sync-for-iterator.{core::Iterator::current};
           #t299.{core::List::add}(#t301);
@@ -2079,14 +2079,14 @@
     final core::Set<dynamic>* #t302 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t303 = :sync-for-iterator.{core::Iterator::current};
           #t302.{core::Set::add}(#t303);
         }
       }
       else {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t304 = :sync-for-iterator.{core::Iterator::current};
           #t302.{core::Set::add}(#t304);
@@ -2098,14 +2098,14 @@
     final core::Map<dynamic, dynamic>* #t305 = <dynamic, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, dynamic>* #t306 = :sync-for-iterator.{core::Iterator::current};
           #t305.{core::Map::[]=}(#t306.{core::MapEntry::key}, #t306.{core::MapEntry::value});
         }
       }
       else {
-        core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, dynamic>* #t307 = :sync-for-iterator.{core::Iterator::current};
           #t305.{core::Map::[]=}(#t307.{core::MapEntry::key}, #t307.{core::MapEntry::value});
@@ -2119,7 +2119,7 @@
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t308.{core::List::add}(42);
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t309 = :sync-for-iterator.{core::Iterator::current};
           #t308.{core::List::add}(#t309);
@@ -2130,7 +2130,7 @@
     final core::Set<core::num*>* #t310 = col::LinkedHashSet::•<core::num*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t311 = :sync-for-iterator.{core::Iterator::current};
           #t310.{core::Set::add}(#t311);
@@ -2144,7 +2144,7 @@
     final core::Map<core::String*, core::num*>* #t312 = <core::String*, core::num*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t313 = :sync-for-iterator.{core::Iterator::current};
           #t312.{core::Map::[]=}(#t313.{core::MapEntry::key}, #t313.{core::MapEntry::value});
@@ -2174,7 +2174,7 @@
   core::List<core::int*>* list91 = block {
     final core::List<core::int*>* #t317 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t318 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2187,7 +2187,7 @@
   core::Set<core::int*>* set91 = block {
     final core::Set<core::int*>* #t320 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t321 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2201,7 +2201,7 @@
   core::Map<core::String*, core::int*>* map91 = block {
     final core::Map<core::String*, core::int*>* #t323 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t324 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2231,7 +2231,7 @@
   core::List<core::int*>* list110 = block {
     final core::List<core::int*>* #t333 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t333.{core::List::add}(i);
@@ -2241,7 +2241,7 @@
   core::Set<core::int*>* set110 = block {
     final core::Set<core::int*>* #t334 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t334.{core::Set::add}(i);
@@ -2252,7 +2252,7 @@
   core::Map<core::String*, core::int*>* map110 = block {
     final core::Map<core::String*, core::int*>* #t335 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t335.{core::Map::[]=}("bar", i);
@@ -2263,7 +2263,7 @@
   core::List<core::int*>* list120 = block {
     final core::List<core::int*>* #t336 = <core::int*>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t336.{core::List::add}(i as{TypeError,ForDynamic} core::int*);
@@ -2273,7 +2273,7 @@
   core::Set<core::int*>* set120 = block {
     final core::Set<core::int*>* #t337 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t337.{core::Set::add}(i as{TypeError,ForDynamic} core::int*);
@@ -2284,7 +2284,7 @@
   core::Map<core::String*, core::int*>* map120 = block {
     final core::Map<core::String*, core::int*>* #t338 = <core::String*, core::int*>{};
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t338.{core::Map::[]=}("bar", i as{TypeError,ForDynamic} core::int*);
@@ -2312,8 +2312,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -2354,9 +2354,9 @@
         block {
           final core::List<core::int*>* #t350 = <core::int*>[];
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t351 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:215:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t351 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:215:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"]];
-                                                ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                                ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t352 = :sync-for-iterator.{core::Iterator::current};
               #t350.{core::List::add}(#t352);
@@ -2366,9 +2366,9 @@
         block {
           final core::Set<core::int*>* #t353 = col::LinkedHashSet::•<core::int*>();
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t354 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:216:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t354 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:216:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"], null};
-                                                ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                                ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t355 = :sync-for-iterator.{core::Iterator::current};
               #t353.{core::Set::add}(#t355);
@@ -2379,11 +2379,11 @@
         block {
           final core::Map<core::int*, core::int*>* #t356 = <core::int*, core::int*>{};
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(<core::int*, core::int*>{let final<BottomType> #t357 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:217:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = <core::int*, core::int*>{let final<BottomType> #t357 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:217:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...{\"bar\": \"bar\"}, \"baz\": null};
                                                      ^" in "bar" as{TypeError} core::int*: let final<BottomType> #t358 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:217:61: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...{\"bar\": \"bar\"}, \"baz\": null};
-                                                            ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}).{core::Iterable::iterator};
+                                                            ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}.{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::MapEntry<core::int*, core::int*>* #t359 = :sync-for-iterator.{core::Iterator::current};
               #t356.{core::Map::[]=}(#t359.{core::MapEntry::key}, #t359.{core::MapEntry::value});
@@ -2519,7 +2519,7 @@
         block {
           final core::List<core::int*>* #t376 = <core::int*>[];
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t377 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2534,7 +2534,7 @@
         block {
           final core::Set<core::int*>* #t378 = col::LinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t379 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2550,7 +2550,7 @@
         block {
           final core::Map<core::String*, core::int*>* #t380 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t381 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2566,7 +2566,7 @@
         core::List<dynamic>* list10 = block {
           final core::List<dynamic>* #t382 = <dynamic>[];
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t383 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:236:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t383 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:236:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var list10 = [for (var i in \"not iterable\") i];
                               ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2579,7 +2579,7 @@
         core::Set<dynamic>* set10 = block {
           final core::Set<dynamic>* #t384 = col::LinkedHashSet::•<dynamic>();
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t385 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:237:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t385 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:237:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var set10 = {for (var i in \"not iterable\") i, null};
                              ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2593,7 +2593,7 @@
         core::Map<core::String*, dynamic>* map10 = block {
           final core::Map<core::String*, dynamic>* #t386 = <core::String*, dynamic>{};
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t387 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:238:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t387 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:238:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var map10 = {for (var i in \"not iterable\") \"bar\": i, \"baz\": null};
                              ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2607,11 +2607,11 @@
         core::List<core::int*>* list20 = block {
           final core::List<core::int*>* #t388 = <core::int*>[];
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t389 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t389 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
                                ^" in "not" as{TypeError} core::int*, let final<BottomType> #t390 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:39: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
-                                      ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                      ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t388.{core::List::add}(i);
@@ -2621,11 +2621,11 @@
         core::Set<core::int*>* set20 = block {
           final core::Set<core::int*>* #t391 = col::LinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t392 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t392 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t393 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
-                                     ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t391.{core::Set::add}(i);
@@ -2636,11 +2636,11 @@
         core::Map<core::String*, core::int*>* map20 = block {
           final core::Map<core::String*, core::int*>* #t394 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t395 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t395 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t396 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
-                                     ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t394.{core::Map::[]=}("bar", i);
@@ -2650,7 +2650,7 @@
         } =>#t394;
         final core::List<dynamic>* #t397 = <dynamic>[];
         {
-          dynamic :stream = let final<BottomType> #t398 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:242:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t398 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:242:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var list30 = [await for (var i in \"not stream\") i];
                                     ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2677,7 +2677,7 @@
         core::List<dynamic>* list30 = block {} =>#t397;
         final core::Set<dynamic>* #t402 = col::LinkedHashSet::•<dynamic>();
         {
-          dynamic :stream = let final<BottomType> #t403 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:243:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t403 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:243:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var set30 = {await for (var i in \"not stream\") i, null};
                                    ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2706,7 +2706,7 @@
         } =>#t402;
         final core::Map<core::String*, dynamic>* #t407 = <core::String*, dynamic>{};
         {
-          dynamic :stream = let final<BottomType> #t408 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:244:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t408 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:244:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var map30 = {await for (var i in \"not stream\") \"bar\": i, \"baz\": null};
                                    ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2735,7 +2735,7 @@
         } =>#t407;
         final core::List<core::int*>* #t412 = <core::int*>[];
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t413 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t413 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
                                                          ^" in "not" as{TypeError} core::int*, let final<BottomType> #t414 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:65: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
@@ -2763,7 +2763,7 @@
         core::List<core::int*>* list40 = block {} =>#t412;
         final core::Set<core::int*>* #t418 = col::LinkedHashSet::•<core::int*>();
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t419 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t419 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t420 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
@@ -2793,7 +2793,7 @@
         } =>#t418;
         final core::Map<core::String*, core::int*>* #t424 = <core::String*, core::int*>{};
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t425 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t425 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t426 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
@@ -2865,13 +2865,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method testForElementErrorsNotAsync(asy::Stream<core::int*>* stream) → dynamic {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect
index 4dce82d..5964136 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect
@@ -424,8 +424,8 @@
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
-import "dart:_internal" as _in;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 class A extends core::Object {
   synthetic constructor •() → self::A*
@@ -496,7 +496,7 @@
   core::List<core::int*>* list20 = block {
     final core::List<core::int*>* #t10 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         #t10.{core::List::add}(#t11);
@@ -506,7 +506,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t12 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t13 = :sync-for-iterator.{core::Iterator::current};
         #t12.{core::Set::add}(#t13);
@@ -517,7 +517,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t14 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t15 = :sync-for-iterator.{core::Iterator::current};
         #t14.{core::Map::[]=}(#t15.{core::MapEntry::key}, #t15.{core::MapEntry::value});
@@ -528,7 +528,7 @@
   core::List<dynamic>* list21 = block {
     final core::List<dynamic>* #t16 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t17 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::List::add}(#t17);
@@ -538,7 +538,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t18 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t19 = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::Set::add}(#t19);
@@ -549,7 +549,7 @@
   core::Map<core::String*, dynamic>* map21 = block {
     final core::Map<core::String*, dynamic>* #t20 = <core::String*, dynamic>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, dynamic>* #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
@@ -560,7 +560,7 @@
   core::List<core::List<core::int*>*>* list22 = block {
     final core::List<core::List<core::int*>*>* #t22 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t23 = :sync-for-iterator.{core::Iterator::current};
         #t22.{core::List::add}(#t23);
@@ -570,7 +570,7 @@
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t24 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t25 = :sync-for-iterator.{core::Iterator::current};
         #t24.{core::Set::add}(#t25);
@@ -581,7 +581,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t26 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t27 = :sync-for-iterator.{core::Iterator::current};
         #t26.{core::Map::[]=}(#t27.{core::MapEntry::key}, #t27.{core::MapEntry::value});
@@ -593,7 +593,7 @@
     final core::List<core::int*>* #t28 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t29 = :sync-for-iterator.{core::Iterator::current};
           #t28.{core::List::add}(#t29);
@@ -604,7 +604,7 @@
     final core::Set<core::int*>* #t30 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t31 = :sync-for-iterator.{core::Iterator::current};
           #t30.{core::Set::add}(#t31);
@@ -616,7 +616,7 @@
     final core::Map<core::String*, core::int*>* #t32 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t33 = :sync-for-iterator.{core::Iterator::current};
           #t32.{core::Map::[]=}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
@@ -628,7 +628,7 @@
     final core::List<dynamic>* #t34 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t35 = :sync-for-iterator.{core::Iterator::current};
           #t34.{core::List::add}(#t35);
@@ -639,7 +639,7 @@
     final core::Set<dynamic>* #t36 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t37 = :sync-for-iterator.{core::Iterator::current};
           #t36.{core::Set::add}(#t37);
@@ -651,7 +651,7 @@
     final core::Map<core::String*, dynamic>* #t38 = <core::String*, dynamic>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, dynamic>* #t39 = :sync-for-iterator.{core::Iterator::current};
           #t38.{core::Map::[]=}(#t39.{core::MapEntry::key}, #t39.{core::MapEntry::value});
@@ -663,7 +663,7 @@
     final core::List<core::List<core::int*>*>* #t40 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t41 = :sync-for-iterator.{core::Iterator::current};
           #t40.{core::List::add}(#t41);
@@ -674,7 +674,7 @@
     final core::Set<core::List<core::int*>*>* #t42 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t43 = :sync-for-iterator.{core::Iterator::current};
           #t42.{core::Set::add}(#t43);
@@ -686,7 +686,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t44 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t45 = :sync-for-iterator.{core::Iterator::current};
           #t44.{core::Map::[]=}(#t45.{core::MapEntry::key}, #t45.{core::MapEntry::value});
@@ -697,7 +697,7 @@
   core::List<core::List<core::int*>*>* list40 = block {
     final core::List<core::List<core::int*>*>* #t46 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t47 = :sync-for-iterator.{core::Iterator::current};
         #t46.{core::List::add}(#t47);
@@ -707,7 +707,7 @@
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t48 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t49 = :sync-for-iterator.{core::Iterator::current};
         #t48.{core::Set::add}(#t49);
@@ -721,7 +721,7 @@
   core::List<core::List<core::int*>*>* list41 = block {
     final core::List<core::List<core::int*>*>* #t50 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t51 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t52 = #t51.{core::Set::add}(<core::int*>[]) in #t51).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t51 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t52 = #t51.{core::Set::add}(<core::int*>[]) in #t51).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t53 = :sync-for-iterator.{core::Iterator::current};
         #t50.{core::List::add}(#t53);
@@ -731,7 +731,7 @@
   core::Set<core::List<core::int*>*>* set41 = block {
     final core::Set<core::List<core::int*>*>* #t54 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t55 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t56 = #t55.{core::Set::add}(<core::int*>[]) in #t55).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t55 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t56 = #t55.{core::Set::add}(<core::int*>[]) in #t55).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t57 = :sync-for-iterator.{core::Iterator::current};
         #t54.{core::Set::add}(#t57);
@@ -743,7 +743,7 @@
     final core::List<core::List<core::int*>*>* #t58 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t59 = :sync-for-iterator.{core::Iterator::current};
           #t58.{core::List::add}(#t59);
@@ -754,7 +754,7 @@
     final core::Set<core::List<core::int*>*>* #t60 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t61 = :sync-for-iterator.{core::Iterator::current};
           #t60.{core::Set::add}(#t61);
@@ -766,7 +766,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t62 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t63 = :sync-for-iterator.{core::Iterator::current};
           #t62.{core::Map::[]=}(#t63.{core::MapEntry::key}, #t63.{core::MapEntry::value});
@@ -777,7 +777,7 @@
   core::List<core::int*>* list50 = block {
     final core::List<core::int*>* #t64 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t65 = :sync-for-iterator.{core::Iterator::current};
         #t64.{core::List::add}(#t65);
@@ -787,7 +787,7 @@
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t66 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t67 = :sync-for-iterator.{core::Iterator::current};
         #t66.{core::Set::add}(#t67);
@@ -798,7 +798,7 @@
   core::Map<core::String*, core::int*>* map50 = block {
     final core::Map<core::String*, core::int*>* #t68 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t69 = :sync-for-iterator.{core::Iterator::current};
         #t68.{core::Map::[]=}(#t69.{core::MapEntry::key}, #t69.{core::MapEntry::value});
@@ -809,7 +809,7 @@
   core::List<core::int*>* list51 = block {
     final core::List<core::int*>* #t70 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t71 = col::LinkedHashSet::•<core::int*>() in #t71).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t71 = col::LinkedHashSet::•<core::int*>() in #t71).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t72 = :sync-for-iterator.{core::Iterator::current};
         #t70.{core::List::add}(#t72);
@@ -819,7 +819,7 @@
   core::Set<core::int*>* set51 = block {
     final core::Set<core::int*>* #t73 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>() in #t74).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>() in #t74).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t75 = :sync-for-iterator.{core::Iterator::current};
         #t73.{core::Set::add}(#t75);
@@ -831,7 +831,7 @@
     final core::List<core::int*>* #t76 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t77 = :sync-for-iterator.{core::Iterator::current};
           #t76.{core::List::add}(#t77);
@@ -842,7 +842,7 @@
     final core::Set<core::int*>* #t78 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t79 = :sync-for-iterator.{core::Iterator::current};
           #t78.{core::Set::add}(#t79);
@@ -854,7 +854,7 @@
     final core::Map<core::String*, core::int*>* #t80 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t81 = :sync-for-iterator.{core::Iterator::current};
           #t80.{core::Map::[]=}(#t81.{core::MapEntry::key}, #t81.{core::MapEntry::value});
@@ -865,7 +865,7 @@
   core::List<core::List<core::int*>*>* list60 = block {
     final core::List<core::List<core::int*>*>* #t82 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t83 = :sync-for-iterator.{core::Iterator::current};
         #t82.{core::List::add}(#t83);
@@ -875,7 +875,7 @@
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t84 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t85 = :sync-for-iterator.{core::Iterator::current};
         #t84.{core::Set::add}(#t85);
@@ -886,7 +886,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t86 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t87 = :sync-for-iterator.{core::Iterator::current};
         #t86.{core::Map::[]=}(#t87.{core::MapEntry::key}, #t87.{core::MapEntry::value});
@@ -898,7 +898,7 @@
     final core::List<core::List<core::int*>*>* #t88 = <core::List<core::int*>*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t89 = :sync-for-iterator.{core::Iterator::current};
           #t88.{core::List::add}(#t89);
@@ -909,7 +909,7 @@
     final core::Set<core::List<core::int*>*>* #t90 = col::LinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t91 = :sync-for-iterator.{core::Iterator::current};
           #t90.{core::Set::add}(#t91);
@@ -921,7 +921,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t92 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t93 = :sync-for-iterator.{core::Iterator::current};
           #t92.{core::Map::[]=}(#t93.{core::MapEntry::key}, #t93.{core::MapEntry::value});
@@ -979,14 +979,14 @@
   core::List<core::num*>* list81 = block {
     final core::List<core::num*>* #t101 = <core::num*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t102 = :sync-for-iterator.{core::Iterator::current};
         #t101.{core::List::add}(#t102);
       }
     }
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t103 = :sync-for-iterator.{core::Iterator::current};
         #t101.{core::List::add}(#t103);
@@ -996,14 +996,14 @@
   core::Set<core::num*>* set81 = block {
     final core::Set<core::num*>* #t104 = col::LinkedHashSet::•<core::num*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t105 = :sync-for-iterator.{core::Iterator::current};
         #t104.{core::Set::add}(#t105);
       }
     }
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t106 = :sync-for-iterator.{core::Iterator::current};
         #t104.{core::Set::add}(#t106);
@@ -1014,14 +1014,14 @@
   core::Map<core::String*, core::num*>* map81 = block {
     final core::Map<core::String*, core::num*>* #t107 = <core::String*, core::num*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapToInt.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapToInt.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t108 = :sync-for-iterator.{core::Iterator::current};
         #t107.{core::Map::[]=}(#t108.{core::MapEntry::key}, #t108.{core::MapEntry::value});
       }
     }
     else {
-      core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::double*>*>*>(mapToDouble.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = mapToDouble.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t109 = :sync-for-iterator.{core::Iterator::current};
         #t107.{core::Map::[]=}(#t109.{core::MapEntry::key}, #t109.{core::MapEntry::value});
@@ -1032,14 +1032,14 @@
   core::List<dynamic>* list82 = block {
     final core::List<dynamic>* #t110 = <dynamic>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t111 = :sync-for-iterator.{core::Iterator::current};
         #t110.{core::List::add}(#t111);
       }
     }
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t112 = :sync-for-iterator.{core::Iterator::current};
         #t110.{core::List::add}(#t112);
@@ -1049,14 +1049,14 @@
   core::Set<dynamic>* set82 = block {
     final core::Set<dynamic>* #t113 = col::LinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t114 = :sync-for-iterator.{core::Iterator::current};
         #t113.{core::Set::add}(#t114);
       }
     }
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t115 = :sync-for-iterator.{core::Iterator::current};
         #t113.{core::Set::add}(#t115);
@@ -1072,7 +1072,7 @@
   var map82 = {if (oracle(\"foo\")) ...mapToInt else ...dynVar, null};
                                      ^");
     else {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t117 = :sync-for-iterator.{core::Iterator::current};
         #t116.{core::Set::add}(#t117);
@@ -1085,7 +1085,7 @@
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t118.{core::List::add}(42);
     else {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t119 = :sync-for-iterator.{core::Iterator::current};
         #t118.{core::List::add}(#t119);
@@ -1095,7 +1095,7 @@
   core::Set<core::num*>* set83 = block {
     final core::Set<core::num*>* #t120 = col::LinkedHashSet::•<core::num*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::num* #t121 = :sync-for-iterator.{core::Iterator::current};
         #t120.{core::Set::add}(#t121);
@@ -1108,7 +1108,7 @@
   core::Map<core::String*, core::num*>* map83 = block {
     final core::Map<core::String*, core::num*>* #t122 = <core::String*, core::num*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapToInt.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapToInt.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::num*>* #t123 = :sync-for-iterator.{core::Iterator::current};
         #t122.{core::Map::[]=}(#t123.{core::MapEntry::key}, #t123.{core::MapEntry::value});
@@ -1138,7 +1138,7 @@
   core::List<core::int*>* list91 = block {
     final core::List<core::int*>* #t127 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t128 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1151,7 +1151,7 @@
   core::Set<core::int*>* set91 = block {
     final core::Set<core::int*>* #t130 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t131 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1165,7 +1165,7 @@
   core::Map<core::String*, core::int*>* map91 = block {
     final core::Map<core::String*, core::int*>* #t133 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t134 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -1220,9 +1220,9 @@
   block {
     final core::List<core::int*>* #t146 = <core::int*>[];
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t147 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:92:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t147 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:92:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[if (oracle(\"foo\")) ...[\"bar\"]];
-                               ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                               ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t148 = :sync-for-iterator.{core::Iterator::current};
         #t146.{core::List::add}(#t148);
@@ -1232,9 +1232,9 @@
   block {
     final core::Set<core::int*>* #t149 = col::LinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t150 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:93:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t150 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:93:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{if (oracle(\"foo\")) ...[\"bar\"], null};
-                               ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                               ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t151 = :sync-for-iterator.{core::Iterator::current};
         #t149.{core::Set::add}(#t151);
@@ -1245,9 +1245,9 @@
   block {
     final core::Map<core::String*, core::int*>* #t152 = <core::String*, core::int*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": let final<BottomType> #t153 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:94:47: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": let final<BottomType> #t153 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:94:47: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <String, int>{if (oracle(\"foo\")) ...{\"bar\": \"bar\"}, \"baz\": null};
-                                              ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}).{core::Iterable::iterator};
+                                              ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t154 = :sync-for-iterator.{core::Iterator::current};
         #t152.{core::Map::[]=}(#t154.{core::MapEntry::key}, #t154.{core::MapEntry::value});
@@ -1509,7 +1509,7 @@
   core::List<core::int*>* list20 = block {
     final core::List<core::int*>* #t197 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t198 = :sync-for-iterator.{core::Iterator::current};
         #t197.{core::List::add}(#t198);
@@ -1519,7 +1519,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t199 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t200 = :sync-for-iterator.{core::Iterator::current};
         #t199.{core::Set::add}(#t200);
@@ -1530,7 +1530,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t201 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t202 = :sync-for-iterator.{core::Iterator::current};
         #t201.{core::Map::[]=}(#t202.{core::MapEntry::key}, #t202.{core::MapEntry::value});
@@ -1541,7 +1541,7 @@
   core::List<dynamic>* list21 = block {
     final core::List<dynamic>* #t203 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t204 = :sync-for-iterator.{core::Iterator::current};
         #t203.{core::List::add}(#t204);
@@ -1551,7 +1551,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t205 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t206 = :sync-for-iterator.{core::Iterator::current};
         #t205.{core::Set::add}(#t206);
@@ -1562,7 +1562,7 @@
   core::Map<core::String*, dynamic>* map21 = block {
     final core::Map<core::String*, dynamic>* #t207 = <core::String*, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, dynamic>* #t208 = :sync-for-iterator.{core::Iterator::current};
         #t207.{core::Map::[]=}(#t208.{core::MapEntry::key}, #t208.{core::MapEntry::value});
@@ -1573,7 +1573,7 @@
   core::List<core::List<core::int*>*>* list22 = block {
     final core::List<core::List<core::int*>*>* #t209 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t210 = :sync-for-iterator.{core::Iterator::current};
         #t209.{core::List::add}(#t210);
@@ -1583,7 +1583,7 @@
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t211 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t212 = :sync-for-iterator.{core::Iterator::current};
         #t211.{core::Set::add}(#t212);
@@ -1594,7 +1594,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t213 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t214 = :sync-for-iterator.{core::Iterator::current};
         #t213.{core::Map::[]=}(#t214.{core::MapEntry::key}, #t214.{core::MapEntry::value});
@@ -1606,7 +1606,7 @@
     final core::List<core::int*>* #t215 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t216 = :sync-for-iterator.{core::Iterator::current};
           #t215.{core::List::add}(#t216);
@@ -1617,7 +1617,7 @@
     final core::Set<core::int*>* #t217 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[42]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[42].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t218 = :sync-for-iterator.{core::Iterator::current};
           #t217.{core::Set::add}(#t218);
@@ -1629,7 +1629,7 @@
     final core::Map<core::String*, core::int*>* #t219 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{"bar": 42}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{"bar": 42}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::int*>* #t220 = :sync-for-iterator.{core::Iterator::current};
           #t219.{core::Map::[]=}(#t220.{core::MapEntry::key}, #t220.{core::MapEntry::value});
@@ -1641,7 +1641,7 @@
     final core::List<dynamic>* #t221 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t222 = :sync-for-iterator.{core::Iterator::current};
           #t221.{core::List::add}(#t222);
@@ -1652,7 +1652,7 @@
     final core::Set<dynamic>* #t223 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[dynVar]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[dynVar].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t224 = :sync-for-iterator.{core::Iterator::current};
           #t223.{core::Set::add}(#t224);
@@ -1664,7 +1664,7 @@
     final core::Map<core::String*, dynamic>* #t225 = <core::String*, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, dynamic>*>*>(<core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, dynamic>*>* :sync-for-iterator = <core::String*, dynamic>{"bar": dynVar}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, dynamic>* #t226 = :sync-for-iterator.{core::Iterator::current};
           #t225.{core::Map::[]=}(#t226.{core::MapEntry::key}, #t226.{core::MapEntry::value});
@@ -1676,7 +1676,7 @@
     final core::List<core::List<core::int*>*>* #t227 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t228 = :sync-for-iterator.{core::Iterator::current};
           #t227.{core::List::add}(#t228);
@@ -1687,7 +1687,7 @@
     final core::Set<core::List<core::int*>*>* #t229 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[42]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[42]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t230 = :sync-for-iterator.{core::Iterator::current};
           #t229.{core::Set::add}(#t230);
@@ -1699,7 +1699,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t231 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t232 = :sync-for-iterator.{core::Iterator::current};
           #t231.{core::Map::[]=}(#t232.{core::MapEntry::key}, #t232.{core::MapEntry::value});
@@ -1710,7 +1710,7 @@
   core::List<core::List<core::int*>*>* list40 = block {
     final core::List<core::List<core::int*>*>* #t233 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t234 = :sync-for-iterator.{core::Iterator::current};
         #t233.{core::List::add}(#t234);
@@ -1720,7 +1720,7 @@
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t235 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t236 = :sync-for-iterator.{core::Iterator::current};
         #t235.{core::Set::add}(#t236);
@@ -1731,7 +1731,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map40 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t237 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t238 = :sync-for-iterator.{core::Iterator::current};
         #t237.{core::Map::[]=}(#t238.{core::MapEntry::key}, #t238.{core::MapEntry::value});
@@ -1742,7 +1742,7 @@
   core::List<core::List<core::int*>*>* list41 = block {
     final core::List<core::List<core::int*>*>* #t239 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t240 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t241 = #t240.{core::Set::add}(<core::int*>[]) in #t240).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t240 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t241 = #t240.{core::Set::add}(<core::int*>[]) in #t240).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t242 = :sync-for-iterator.{core::Iterator::current};
         #t239.{core::List::add}(#t242);
@@ -1752,7 +1752,7 @@
   core::Set<core::List<core::int*>*>* set41 = block {
     final core::Set<core::List<core::int*>*>* #t243 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(let final core::Set<core::List<core::int*>*>* #t244 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t245 = #t244.{core::Set::add}(<core::int*>[]) in #t244).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = (let final core::Set<core::List<core::int*>*>* #t244 = col::LinkedHashSet::•<core::List<core::int*>*>() in let final core::bool* #t245 = #t244.{core::Set::add}(<core::int*>[]) in #t244).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t246 = :sync-for-iterator.{core::Iterator::current};
         #t243.{core::Set::add}(#t246);
@@ -1764,7 +1764,7 @@
     final core::List<core::List<core::int*>*>* #t247 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t248 = :sync-for-iterator.{core::Iterator::current};
           #t247.{core::List::add}(#t248);
@@ -1775,7 +1775,7 @@
     final core::Set<core::List<core::int*>*>* #t249 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t250 = :sync-for-iterator.{core::Iterator::current};
           #t249.{core::Set::add}(#t250);
@@ -1787,7 +1787,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t251 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t252 = :sync-for-iterator.{core::Iterator::current};
           #t251.{core::Map::[]=}(#t252.{core::MapEntry::key}, #t252.{core::MapEntry::value});
@@ -1798,7 +1798,7 @@
   core::List<core::int*>* list50 = block {
     final core::List<core::int*>* #t253 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t254 = :sync-for-iterator.{core::Iterator::current};
         #t253.{core::List::add}(#t254);
@@ -1808,7 +1808,7 @@
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t255 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t256 = :sync-for-iterator.{core::Iterator::current};
         #t255.{core::Set::add}(#t256);
@@ -1819,7 +1819,7 @@
   core::Map<core::String*, core::int*>* map50 = block {
     final core::Map<core::String*, core::int*>* #t257 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t258 = :sync-for-iterator.{core::Iterator::current};
         #t257.{core::Map::[]=}(#t258.{core::MapEntry::key}, #t258.{core::MapEntry::value});
@@ -1830,7 +1830,7 @@
   core::List<core::int*>* list51 = block {
     final core::List<core::int*>* #t259 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t260 = col::LinkedHashSet::•<core::int*>() in #t260).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t260 = col::LinkedHashSet::•<core::int*>() in #t260).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t261 = :sync-for-iterator.{core::Iterator::current};
         #t259.{core::List::add}(#t261);
@@ -1840,7 +1840,7 @@
   core::Set<core::int*>* set51 = block {
     final core::Set<core::int*>* #t262 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(let final core::Set<core::int*>* #t263 = col::LinkedHashSet::•<core::int*>() in #t263).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = (let final core::Set<core::int*>* #t263 = col::LinkedHashSet::•<core::int*>() in #t263).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t264 = :sync-for-iterator.{core::Iterator::current};
         #t262.{core::Set::add}(#t264);
@@ -1852,7 +1852,7 @@
     final core::List<core::int*>* #t265 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t266 = :sync-for-iterator.{core::Iterator::current};
           #t265.{core::List::add}(#t266);
@@ -1863,7 +1863,7 @@
     final core::Set<core::int*>* #t267 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t268 = :sync-for-iterator.{core::Iterator::current};
           #t267.{core::Set::add}(#t268);
@@ -1874,7 +1874,7 @@
   core::List<core::List<core::int*>*>* list60 = block {
     final core::List<core::List<core::int*>*>* #t269 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t270 = :sync-for-iterator.{core::Iterator::current};
         #t269.{core::List::add}(#t270);
@@ -1884,7 +1884,7 @@
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t271 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t272 = :sync-for-iterator.{core::Iterator::current};
         #t271.{core::Set::add}(#t272);
@@ -1895,7 +1895,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t273 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t274 = :sync-for-iterator.{core::Iterator::current};
         #t273.{core::Map::[]=}(#t274.{core::MapEntry::key}, #t274.{core::MapEntry::value});
@@ -1907,7 +1907,7 @@
     final core::List<core::List<core::int*>*>* #t275 = <core::List<core::int*>*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t276 = :sync-for-iterator.{core::Iterator::current};
           #t275.{core::List::add}(#t276);
@@ -1918,7 +1918,7 @@
     final core::Set<core::List<core::int*>*>* #t277 = col::LinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+        core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::List<core::int*>* #t278 = :sync-for-iterator.{core::Iterator::current};
           #t277.{core::Set::add}(#t278);
@@ -1930,7 +1930,7 @@
     final core::Map<core::String*, core::List<core::int*>*>* #t279 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t280 = :sync-for-iterator.{core::Iterator::current};
           #t279.{core::Map::[]=}(#t280.{core::MapEntry::key}, #t280.{core::MapEntry::value});
@@ -2005,14 +2005,14 @@
     final core::List<core::num*>* #t290 = <core::num*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t291 = :sync-for-iterator.{core::Iterator::current};
           #t290.{core::List::add}(#t291);
         }
       }
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t292 = :sync-for-iterator.{core::Iterator::current};
           #t290.{core::List::add}(#t292);
@@ -2023,14 +2023,14 @@
     final core::Set<core::num*>* #t293 = col::LinkedHashSet::•<core::num*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t294 = :sync-for-iterator.{core::Iterator::current};
           #t293.{core::Set::add}(#t294);
         }
       }
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t295 = :sync-for-iterator.{core::Iterator::current};
           #t293.{core::Set::add}(#t295);
@@ -2042,14 +2042,14 @@
     final core::Map<core::String*, core::num*>* #t296 = <core::String*, core::num*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t297 = :sync-for-iterator.{core::Iterator::current};
           #t296.{core::Map::[]=}(#t297.{core::MapEntry::key}, #t297.{core::MapEntry::value});
         }
       }
       else {
-        core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::double*>*>*>(mapStringDouble.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::double*>*>* :sync-for-iterator = mapStringDouble.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t298 = :sync-for-iterator.{core::Iterator::current};
           #t296.{core::Map::[]=}(#t298.{core::MapEntry::key}, #t298.{core::MapEntry::value});
@@ -2061,14 +2061,14 @@
     final core::List<dynamic>* #t299 = <dynamic>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t300 = :sync-for-iterator.{core::Iterator::current};
           #t299.{core::List::add}(#t300);
         }
       }
       else {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t301 = :sync-for-iterator.{core::Iterator::current};
           #t299.{core::List::add}(#t301);
@@ -2079,14 +2079,14 @@
     final core::Set<dynamic>* #t302 = col::LinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t303 = :sync-for-iterator.{core::Iterator::current};
           #t302.{core::Set::add}(#t303);
         }
       }
       else {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t304 = :sync-for-iterator.{core::Iterator::current};
           #t302.{core::Set::add}(#t304);
@@ -2098,14 +2098,14 @@
     final core::Map<dynamic, dynamic>* #t305 = <dynamic, dynamic>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, dynamic>* #t306 = :sync-for-iterator.{core::Iterator::current};
           #t305.{core::Map::[]=}(#t306.{core::MapEntry::key}, #t306.{core::MapEntry::value});
         }
       }
       else {
-        core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, dynamic>* #t307 = :sync-for-iterator.{core::Iterator::current};
           #t305.{core::Map::[]=}(#t307.{core::MapEntry::key}, #t307.{core::MapEntry::value});
@@ -2119,7 +2119,7 @@
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t308.{core::List::add}(42);
       else {
-        core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(listDouble).{core::Iterable::iterator};
+        core::Iterator<core::double*>* :sync-for-iterator = listDouble.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t309 = :sync-for-iterator.{core::Iterator::current};
           #t308.{core::List::add}(#t309);
@@ -2130,7 +2130,7 @@
     final core::Set<core::num*>* #t310 = col::LinkedHashSet::•<core::num*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(listInt).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = listInt.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::num* #t311 = :sync-for-iterator.{core::Iterator::current};
           #t310.{core::Set::add}(#t311);
@@ -2144,7 +2144,7 @@
     final core::Map<core::String*, core::num*>* #t312 = <core::String*, core::num*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapStringInt.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapStringInt.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::num*>* #t313 = :sync-for-iterator.{core::Iterator::current};
           #t312.{core::Map::[]=}(#t313.{core::MapEntry::key}, #t313.{core::MapEntry::value});
@@ -2174,7 +2174,7 @@
   core::List<core::int*>* list91 = block {
     final core::List<core::int*>* #t317 = <core::int*>[];
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t318 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2187,7 +2187,7 @@
   core::Set<core::int*>* set91 = block {
     final core::Set<core::int*>* #t320 = col::LinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t321 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2201,7 +2201,7 @@
   core::Map<core::String*, core::int*>* map91 = block {
     final core::Map<core::String*, core::int*>* #t323 = <core::String*, core::int*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t324 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -2231,7 +2231,7 @@
   core::List<core::int*>* list110 = block {
     final core::List<core::int*>* #t333 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t333.{core::List::add}(i);
@@ -2241,7 +2241,7 @@
   core::Set<core::int*>* set110 = block {
     final core::Set<core::int*>* #t334 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t334.{core::Set::add}(i);
@@ -2252,7 +2252,7 @@
   core::Map<core::String*, core::int*>* map110 = block {
     final core::Map<core::String*, core::int*>* #t335 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t335.{core::Map::[]=}("bar", i);
@@ -2263,7 +2263,7 @@
   core::List<core::int*>* list120 = block {
     final core::List<core::int*>* #t336 = <core::int*>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t336.{core::List::add}(i as{TypeError,ForDynamic} core::int*);
@@ -2273,7 +2273,7 @@
   core::Set<core::int*>* set120 = block {
     final core::Set<core::int*>* #t337 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t337.{core::Set::add}(i as{TypeError,ForDynamic} core::int*);
@@ -2284,7 +2284,7 @@
   core::Map<core::String*, core::int*>* map120 = block {
     final core::Map<core::String*, core::int*>* #t338 = <core::String*, core::int*>{};
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         dynamic i = :sync-for-iterator.{core::Iterator::current};
         #t338.{core::Map::[]=}("bar", i as{TypeError,ForDynamic} core::int*);
@@ -2312,8 +2312,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -2354,9 +2354,9 @@
         block {
           final core::List<core::int*>* #t350 = <core::int*>[];
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t351 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:215:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t351 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:215:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"]];
-                                                ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                                ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t352 = :sync-for-iterator.{core::Iterator::current};
               #t350.{core::List::add}(#t352);
@@ -2366,9 +2366,9 @@
         block {
           final core::Set<core::int*>* #t353 = col::LinkedHashSet::•<core::int*>();
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t354 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:216:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t354 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:216:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"], null};
-                                                ^" in "bar" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                                ^" in "bar" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t355 = :sync-for-iterator.{core::Iterator::current};
               #t353.{core::Set::add}(#t355);
@@ -2379,11 +2379,11 @@
         block {
           final core::Map<core::int*, core::int*>* #t356 = <core::int*, core::int*>{};
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-            core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(<core::int*, core::int*>{let final<BottomType> #t357 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:217:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = <core::int*, core::int*>{let final<BottomType> #t357 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:217:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...{\"bar\": \"bar\"}, \"baz\": null};
                                                      ^" in "bar" as{TypeError} core::int*: let final<BottomType> #t358 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:217:61: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...{\"bar\": \"bar\"}, \"baz\": null};
-                                                            ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}).{core::Iterable::iterator};
+                                                            ^" in "bar" as{TypeError} core::int*}.{core::Map::entries}.{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::MapEntry<core::int*, core::int*>* #t359 = :sync-for-iterator.{core::Iterator::current};
               #t356.{core::Map::[]=}(#t359.{core::MapEntry::key}, #t359.{core::MapEntry::value});
@@ -2519,7 +2519,7 @@
         block {
           final core::List<core::int*>* #t376 = <core::int*>[];
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t377 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2534,7 +2534,7 @@
         block {
           final core::Set<core::int*>* #t378 = col::LinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t379 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2550,7 +2550,7 @@
         block {
           final core::Map<core::String*, core::int*>* #t380 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1]).{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t381 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2566,7 +2566,7 @@
         core::List<dynamic>* list10 = block {
           final core::List<dynamic>* #t382 = <dynamic>[];
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t383 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:236:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t383 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:236:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var list10 = [for (var i in \"not iterable\") i];
                               ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2579,7 +2579,7 @@
         core::Set<dynamic>* set10 = block {
           final core::Set<dynamic>* #t384 = col::LinkedHashSet::•<dynamic>();
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t385 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:237:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t385 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:237:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var set10 = {for (var i in \"not iterable\") i, null};
                              ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2593,7 +2593,7 @@
         core::Map<core::String*, dynamic>* map10 = block {
           final core::Map<core::String*, dynamic>* #t386 = <core::String*, dynamic>{};
           {
-            core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t387 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:238:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+            core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t387 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:238:30: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   var map10 = {for (var i in \"not iterable\") \"bar\": i, \"baz\": null};
                              ^" in "not iterable" as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -2607,11 +2607,11 @@
         core::List<core::int*>* list20 = block {
           final core::List<core::int*>* #t388 = <core::int*>[];
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t389 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t389 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
                                ^" in "not" as{TypeError} core::int*, let final<BottomType> #t390 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:39: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
-                                      ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                      ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t388.{core::List::add}(i);
@@ -2621,11 +2621,11 @@
         core::Set<core::int*>* set20 = block {
           final core::Set<core::int*>* #t391 = col::LinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t392 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t392 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t393 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
-                                     ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t391.{core::Set::add}(i);
@@ -2636,11 +2636,11 @@
         core::Map<core::String*, core::int*>* map20 = block {
           final core::Map<core::String*, core::int*>* #t394 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[let final<BottomType> #t395 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t395 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t396 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
-                                     ^" in "int" as{TypeError} core::int*]).{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t394.{core::Map::[]=}("bar", i);
@@ -2650,7 +2650,7 @@
         } =>#t394;
         final core::List<dynamic>* #t397 = <dynamic>[];
         {
-          dynamic :stream = let final<BottomType> #t398 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:242:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t398 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:242:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var list30 = [await for (var i in \"not stream\") i];
                                     ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2677,7 +2677,7 @@
         core::List<dynamic>* list30 = block {} =>#t397;
         final core::Set<dynamic>* #t402 = col::LinkedHashSet::•<dynamic>();
         {
-          dynamic :stream = let final<BottomType> #t403 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:243:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t403 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:243:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var set30 = {await for (var i in \"not stream\") i, null};
                                    ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2706,7 +2706,7 @@
         } =>#t402;
         final core::Map<core::String*, dynamic>* #t407 = <core::String*, dynamic>{};
         {
-          dynamic :stream = let final<BottomType> #t408 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:244:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t408 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:244:36: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   var map30 = {await for (var i in \"not stream\") \"bar\": i, \"baz\": null};
                                    ^" in "not stream" as{TypeError} asy::Stream<dynamic>*;
@@ -2735,7 +2735,7 @@
         } =>#t407;
         final core::List<core::int*>* #t412 = <core::int*>[];
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t413 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t413 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
                                                          ^" in "not" as{TypeError} core::int*, let final<BottomType> #t414 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:65: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
@@ -2763,7 +2763,7 @@
         core::List<core::int*>* list40 = block {} =>#t412;
         final core::Set<core::int*>* #t418 = col::LinkedHashSet::•<core::int*>();
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t419 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t419 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t420 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
@@ -2793,7 +2793,7 @@
         } =>#t418;
         final core::Map<core::String*, core::int*>* #t424 = <core::String*, core::int*>{};
         {
-          dynamic :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t425 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*>* :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t425 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t426 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
@@ -2865,13 +2865,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method testForElementErrorsNotAsync(asy::Stream<core::int*>* stream) → dynamic {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart
new file mode 100644
index 0000000..4ac4d16
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.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.
+
+// @dart=2.6
+
+class A {
+  bool operator ==(covariant A other) => true;
+}
+
+class B extends A {
+  bool operator ==(other) => true;
+}
+
+class C<T> {
+  bool operator ==(covariant C<T> other) => true;
+}
+
+class D extends C<int> {}
+
+main() {}
+
+test(A a, B b, C c_dynamic, C<int> c_int, C<String> c_string, D d) {
+  a == a; // ok
+  a == b; // ok
+  a == c_dynamic; // error
+  a == c_int; // error
+  a == c_string; // error
+  a == d; // error
+
+  b == a; // ok
+  b == b; // ok
+  b == c_dynamic; // error
+  b == c_int; // error
+  b == c_string; // error
+  b == d; // error
+
+  c_dynamic == a; // error
+  c_dynamic == b; // error
+  c_dynamic == c_dynamic; // ok
+  c_dynamic == c_int; // ok
+  c_dynamic == c_string; // ok
+  c_dynamic == d; // ok
+
+  c_int == a; // error
+  c_int == b; // error
+  c_int == c_dynamic; // ok
+  c_int == c_int; // ok
+  c_int == c_string; // error
+  c_int == d; // ok}
+
+  c_string == a; // error
+  c_string == b; // error
+  c_string == c_dynamic; // ok
+  c_string == c_int; // error
+  c_string == c_string; // ok
+  c_string == d; // error
+
+  d == a; // error
+  d == b; // error
+  d == c_dynamic; // ok
+  d == c_int; // ok
+  d == c_string; // error
+  d == d; // ok
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.outline.expect
new file mode 100644
index 0000000..d521bc4
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    ;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    ;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    ;
+}
+static method main() → dynamic
+  ;
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.strong.expect
new file mode 100644
index 0000000..f58c540
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.strong.expect
@@ -0,0 +1,266 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError} self::A*);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError} self::A*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_dynamic as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError} self::C<core::String*>*);
+  d.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(d);
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.strong.transformed.expect
new file mode 100644
index 0000000..f58c540
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.strong.transformed.expect
@@ -0,0 +1,266 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError} self::A*);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError} self::A*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_dynamic as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError} self::C<core::String*>*);
+  d.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(d);
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.weak.expect
new file mode 100644
index 0000000..f58c540
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.weak.expect
@@ -0,0 +1,266 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError} self::A*);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError} self::A*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_dynamic as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError} self::C<core::String*>*);
+  d.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(d);
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.weak.transformed.expect
new file mode 100644
index 0000000..f58c540
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart.weak.transformed.expect
@@ -0,0 +1,266 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+//  - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+//  - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method test(self::A* a, self::B* b, self::C<dynamic>* c_dynamic, self::C<core::int*>* c_int, self::C<core::String*>* c_string, self::D* d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:26:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:27:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:28:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:29:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError} self::A*);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:33:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:34:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:35:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError} self::A*);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:36:8: Error: The argument type 'D' can't be assigned to the parameter type 'A'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError} self::A*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:38:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:39:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError} self::C<dynamic>*);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:45:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:46:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:49:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError} self::C<core::int*>*);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:52:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:53:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_dynamic as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:55:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError} self::C<core::String*>*);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:57:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>'.
+ - 'D' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError} self::C<core::String*>*);
+  d.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:59:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>'.
+ - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:60:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>'.
+ - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_dynamic as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart:63:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>'.
+ - 'C' is from 'pkg/front_end/testcases/general_nnbd_opt_out/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError} self::C<core::int*>*);
+  d.{self::C::==}(d);
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.expect
index 0e3241e..87aef8c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.expect
@@ -11,6 +11,6 @@
 import "dart:core";
 
 static method testDynamic() → invalid-type
-  return 0 as{TypeError} invalid-type;
+  return 0;
 static method testVoid() → void {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.transformed.expect
index 0e3241e..87aef8c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.strong.transformed.expect
@@ -11,6 +11,6 @@
 import "dart:core";
 
 static method testDynamic() → invalid-type
-  return 0 as{TypeError} invalid-type;
+  return 0;
 static method testVoid() → void {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.expect
index 0e3241e..87aef8c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.expect
@@ -11,6 +11,6 @@
 import "dart:core";
 
 static method testDynamic() → invalid-type
-  return 0 as{TypeError} invalid-type;
+  return 0;
 static method testVoid() → void {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.transformed.expect
index 0e3241e..87aef8c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/dynamic_and_void.dart.weak.transformed.expect
@@ -11,6 +11,6 @@
 import "dart:core";
 
 static method testDynamic() → invalid-type
-  return 0 as{TypeError} invalid-type;
+  return 0;
 static method testVoid() → void {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.strong.transformed.expect
index cb9a540..ae6b6e7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.strong.transformed.expect
@@ -1,11 +1,10 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method main(core::List<core::String*>* arguments) → dynamic {
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(arguments).{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = arguments.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* arguments = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.weak.transformed.expect
index cb9a540..ae6b6e7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_scope.dart.weak.transformed.expect
@@ -1,11 +1,10 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method main(core::List<core::String*>* arguments) → dynamic {
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(arguments).{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = arguments.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* arguments = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.strong.transformed.expect
index 220fbaa..99eaa37 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.strong.transformed.expect
@@ -66,7 +66,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Super extends core::Object {
   field core::int* superInstanceField = null;
@@ -87,7 +86,7 @@
     core::String* local;
     dynamic untypedLocal;
     {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String*>[]).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = <core::String*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -96,7 +95,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -105,7 +104,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -114,7 +113,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -123,7 +122,7 @@
       }
     }
     {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(<core::double*>[]).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = <core::double*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::double* #t5 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -132,7 +131,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -141,7 +140,7 @@
       }
     }
     {
-      core::Iterator<core::bool*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::bool*>*>(<core::bool*>[]).{core::Iterable::iterator};
+      core::Iterator<core::bool*>* :sync-for-iterator = <core::bool*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::bool* #t7 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -150,7 +149,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -159,7 +158,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t9 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -168,7 +167,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t10 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -178,7 +177,7 @@
     }
     self::C* c = new self::C::•();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -187,7 +186,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t12 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -196,7 +195,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t13 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -209,7 +208,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -222,7 +221,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t15 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -239,7 +238,7 @@
     for (main() in []) {}
          ^^^^";
       {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t16 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -256,7 +255,7 @@
     for (var x, y in <int>[]) {
          ^^^";
       {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t17 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -272,7 +271,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t18 = :sync-for-iterator.{core::Iterator::current};
         {
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 220fbaa..99eaa37 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
@@ -66,7 +66,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Super extends core::Object {
   field core::int* superInstanceField = null;
@@ -87,7 +86,7 @@
     core::String* local;
     dynamic untypedLocal;
     {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String*>[]).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = <core::String*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -96,7 +95,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -105,7 +104,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -114,7 +113,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -123,7 +122,7 @@
       }
     }
     {
-      core::Iterator<core::double*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::double*>*>(<core::double*>[]).{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = <core::double*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::double* #t5 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -132,7 +131,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -141,7 +140,7 @@
       }
     }
     {
-      core::Iterator<core::bool*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::bool*>*>(<core::bool*>[]).{core::Iterable::iterator};
+      core::Iterator<core::bool*>* :sync-for-iterator = <core::bool*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::bool* #t7 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -150,7 +149,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -159,7 +158,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t9 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -168,7 +167,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t10 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -178,7 +177,7 @@
     }
     self::C* c = new self::C::•();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -187,7 +186,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t12 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -196,7 +195,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t13 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -209,7 +208,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -222,7 +221,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t15 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -239,7 +238,7 @@
     for (main() in []) {}
          ^^^^";
       {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t16 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -256,7 +255,7 @@
     for (var x, y in <int>[]) {
          ^^^";
       {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t17 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -272,7 +271,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t18 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.strong.transformed.expect
index 1d1c466..206c905 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.strong.transformed.expect
@@ -21,8 +21,8 @@
     final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -35,13 +35,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -54,8 +54,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -68,13 +68,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.weak.transformed.expect
index 1d1c466..206c905 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/future_or_test.dart.weak.transformed.expect
@@ -21,8 +21,8 @@
     final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -35,13 +35,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -54,8 +54,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -68,13 +68,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.strong.transformed.expect
index 606d3a0..342575d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.strong.transformed.expect
@@ -2,7 +2,6 @@
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
-import "dart:_internal" as _in;
 
 class C extends core::Object {
   final field core::Set<core::int*>* s;
@@ -10,7 +9,7 @@
     : self::C::s = block {
       final core::Set<core::int*>* #t1 = col::LinkedHashSet::•<core::int*>();
       {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(ell).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = ell.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           core::int* e = :sync-for-iterator.{core::Iterator::current};
           if(e.{core::int::isOdd})
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.weak.transformed.expect
index 606d3a0..342575d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue37027.dart.weak.transformed.expect
@@ -2,7 +2,6 @@
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
-import "dart:_internal" as _in;
 
 class C extends core::Object {
   final field core::Set<core::int*>* s;
@@ -10,7 +9,7 @@
     : self::C::s = block {
       final core::Set<core::int*>* #t1 = col::LinkedHashSet::•<core::int*>();
       {
-        core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(ell).{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = ell.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           core::int* e = :sync-for-iterator.{core::Iterator::current};
           if(e.{core::int::isOdd})
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.outline.expect
index 26f9451..4a7ea21 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.outline.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:14:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.expect
index af49ff8..687b222 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:14:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:12: Error: Can't use 'A' because it is declared more than once.
 //   foo(List<A> a) {}
 //            ^
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.transformed.expect
index af49ff8..687b222 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.strong.transformed.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:14:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:12: Error: Can't use 'A' because it is declared more than once.
 //   foo(List<A> a) {}
 //            ^
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.expect
index af49ff8..687b222 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:14:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:12: Error: Can't use 'A' because it is declared more than once.
 //   foo(List<A> a) {}
 //            ^
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.transformed.expect
index af49ff8..687b222 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart.weak.transformed.expect
@@ -16,15 +16,6 @@
 //   foo(List<A> a) {}
 //            ^
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
-//  - 'List' is from 'dart:core'.
-// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
-//   foo(List<A> a) {}
-//               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:14:3: Context: This is the overridden method ('foo').
-//   foo(List<Null> a) {}
-//   ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/issue39421.dart:18:12: Error: Can't use 'A' because it is declared more than once.
 //   foo(List<A> a) {}
 //            ^
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.strong.transformed.expect
index 896e8eb..da4a799 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.strong.transformed.expect
@@ -1,12 +1,11 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method foo() → dynamic {
   core::Null? _null;
   {
-    core::Iterator<core::Null?>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Null?>*>(_null).{core::Iterable::iterator};
+    core::Iterator<core::Null?>* :sync-for-iterator = _null.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic i = :sync-for-iterator.{core::Iterator::current};
       {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.weak.transformed.expect
index 896e8eb..da4a799 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39817.dart.weak.transformed.expect
@@ -1,12 +1,11 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method foo() → dynamic {
   core::Null? _null;
   {
-    core::Iterator<core::Null?>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Null?>*>(_null).{core::Iterable::iterator};
+    core::Iterator<core::Null?>* :sync-for-iterator = _null.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic i = :sync-for-iterator.{core::Iterator::current};
       {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.strong.transformed.expect
index eb4e616..10d831b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Class extends core::Object {
   synthetic constructor •() → self::Class*
@@ -12,7 +11,7 @@
   dynamic o;
   if(false) {
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((let final dynamic #t1 = o in #t1.{core::Object::==}(null) ?{dynamic} null : #t1.iterable) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((let final dynamic #t1 = o in #t1.{core::Object::==}(null) ?{dynamic} null : #t1.iterable) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.weak.transformed.expect
index eb4e616..10d831b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_for_in.dart.weak.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Class extends core::Object {
   synthetic constructor •() → self::Class*
@@ -12,7 +11,7 @@
   dynamic o;
   if(false) {
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((let final dynamic #t1 = o in #t1.{core::Object::==}(null) ?{dynamic} null : #t1.iterable) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((let final dynamic #t1 = o in #t1.{core::Object::==}(null) ?{dynamic} null : #t1.iterable) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.strong.transformed.expect
index e746568..c75c586 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method nullAwareListSpread(core::List<core::String*>* list) → dynamic {
@@ -10,7 +9,7 @@
     #t1.{core::List::add}("foo");
     final core::Iterable<core::String*>* #t2 = list;
     if(!#t2.{core::Object::==}(null)) {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t2).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = #t2.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t3 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t3);
@@ -24,7 +23,7 @@
     #t4.{core::Set::add}("foo");
     final core::Iterable<core::String*>* #t5 = set;
     if(!#t5.{core::Object::==}(null)) {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t5).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = #t5.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t4.{core::Set::add}(#t6);
@@ -38,7 +37,7 @@
     #t7.{core::Map::[]=}(0, "foo");
     final core::Map<core::int*, core::String*>* #t8 = map;
     if(!#t8.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::int*, core::String*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::String*>*>*>(#t8.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::String*>*>* :sync-for-iterator = #t8.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::String*>* #t9 = :sync-for-iterator.{core::Iterator::current};
         #t7.{core::Map::[]=}(#t9.{core::MapEntry::key}, #t9.{core::MapEntry::value});
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect
index e746568..c75c586 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method nullAwareListSpread(core::List<core::String*>* list) → dynamic {
@@ -10,7 +9,7 @@
     #t1.{core::List::add}("foo");
     final core::Iterable<core::String*>* #t2 = list;
     if(!#t2.{core::Object::==}(null)) {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t2).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = #t2.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t3 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t3);
@@ -24,7 +23,7 @@
     #t4.{core::Set::add}("foo");
     final core::Iterable<core::String*>* #t5 = set;
     if(!#t5.{core::Object::==}(null)) {
-      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t5).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = #t5.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t4.{core::Set::add}(#t6);
@@ -38,7 +37,7 @@
     #t7.{core::Map::[]=}(0, "foo");
     final core::Map<core::int*, core::String*>* #t8 = map;
     if(!#t8.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::int*, core::String*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::String*>*>*>(#t8.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::String*>*>* :sync-for-iterator = #t8.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::String*>* #t9 = :sync-for-iterator.{core::Iterator::current};
         #t7.{core::Map::[]=}(#t9.{core::MapEntry::key}, #t9.{core::MapEntry::value});
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.strong.transformed.expect
index 935dc38..ab00273 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.strong.transformed.expect
@@ -9,7 +9,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method main() → dynamic {
@@ -17,7 +16,7 @@
     final core::List<core::int*>* #t1 = <core::int*>[];
     #t1.{core::List::add}(1);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[2]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[2].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t2 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t2);
@@ -25,7 +24,7 @@
     }
     final core::Iterable<core::int*>* #t3 = <core::int*>[3];
     if(!#t3.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t3).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t3.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t4 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t4);
@@ -36,7 +35,7 @@
     final core::Map<core::int*, core::int*>* #t5 = <core::int*, core::int*>{};
     #t5.{core::Map::[]=}(1, 1);
     {
-      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(<core::int*, core::int*>{2: 2}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = <core::int*, core::int*>{2: 2}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::int*>* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
@@ -44,7 +43,7 @@
     }
     final core::Map<core::int*, core::int*>* #t7 = <core::int*, core::int*>{3: 3};
     if(!#t7.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(#t7.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = #t7.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::int*>* #t8 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
@@ -55,7 +54,7 @@
     final core::Set<core::int*>* #t9 = col::LinkedHashSet::•<core::int*>();
     #t9.{core::Set::add}(1);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[2]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[2].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t10 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::Set::add}(#t10);
@@ -63,7 +62,7 @@
     }
     final core::Iterable<core::int*>* #t11 = <core::int*>[3];
     if(!#t11.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t11).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t11.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t12 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::Set::add}(#t12);
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect
index 935dc38..ab00273 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect
@@ -9,7 +9,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method main() → dynamic {
@@ -17,7 +16,7 @@
     final core::List<core::int*>* #t1 = <core::int*>[];
     #t1.{core::List::add}(1);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[2]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[2].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t2 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t2);
@@ -25,7 +24,7 @@
     }
     final core::Iterable<core::int*>* #t3 = <core::int*>[3];
     if(!#t3.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t3).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t3.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t4 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t4);
@@ -36,7 +35,7 @@
     final core::Map<core::int*, core::int*>* #t5 = <core::int*, core::int*>{};
     #t5.{core::Map::[]=}(1, 1);
     {
-      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(<core::int*, core::int*>{2: 2}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = <core::int*, core::int*>{2: 2}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::int*>* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
@@ -44,7 +43,7 @@
     }
     final core::Map<core::int*, core::int*>* #t7 = <core::int*, core::int*>{3: 3};
     if(!#t7.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(#t7.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = #t7.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::int*>* #t8 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
@@ -55,7 +54,7 @@
     final core::Set<core::int*>* #t9 = col::LinkedHashSet::•<core::int*>();
     #t9.{core::Set::add}(1);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[2]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[2].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t10 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::Set::add}(#t10);
@@ -63,7 +62,7 @@
     }
     final core::Iterable<core::int*>* #t11 = <core::int*>[3];
     if(!#t11.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t11).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t11.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t12 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::Set::add}(#t12);
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.strong.transformed.expect
index db8baa1..8eb50fc 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.strong.transformed.expect
@@ -98,7 +98,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method bar<K extends core::Object* = dynamic, V extends core::Object* = dynamic>() → core::Map<self::bar::K*, self::bar::V*>*
@@ -113,7 +112,7 @@
   core::List<dynamic>* lhs10 = block {
     final core::List<dynamic>* #t1 = <dynamic>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t2);
@@ -123,7 +122,7 @@
   core::Set<dynamic>* set10 = block {
     final core::Set<dynamic>* #t3 = col::LinkedHashSet::•<dynamic>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Set::add}(#t4);
@@ -133,7 +132,7 @@
   core::Map<dynamic, dynamic>* map10 = block {
     final core::Map<dynamic, dynamic>* #t5 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(<dynamic, dynamic>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = <dynamic, dynamic>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
@@ -143,7 +142,7 @@
   core::Map<dynamic, dynamic>* map10ambiguous = block {
     final core::Map<dynamic, dynamic>* #t7 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(<dynamic, dynamic>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = <dynamic, dynamic>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t8 = :sync-for-iterator.{core::Iterator::current};
         #t7.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
@@ -153,7 +152,7 @@
   core::List<core::int*>* lhs20 = block {
     final core::List<core::int*>* #t9 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t10 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::List::add}(#t10);
@@ -163,7 +162,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t11 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t12 = :sync-for-iterator.{core::Iterator::current};
         #t11.{core::Set::add}(#t12);
@@ -174,7 +173,7 @@
   core::Set<core::int*>* set20ambiguous = block {
     final core::Set<core::int*>* #t13 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -187,7 +186,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t16 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t17 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::Map::[]=}(#t17.{core::MapEntry::key}, #t17.{core::MapEntry::value});
@@ -198,7 +197,7 @@
   core::Map<core::String*, core::int*>* map20ambiguous = block {
     final core::Map<core::String*, core::int*>* #t18 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t19 = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::Map::[]=}(#t19.{core::MapEntry::key}, #t19.{core::MapEntry::value});
@@ -208,7 +207,7 @@
   core::List<dynamic>* lhs21 = block {
     final core::List<dynamic>* #t20 = <dynamic>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::List::add}(#t21);
@@ -218,7 +217,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t22 = col::LinkedHashSet::•<dynamic>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t23 = :sync-for-iterator.{core::Iterator::current};
         #t22.{core::Set::add}(#t23);
@@ -229,7 +228,7 @@
   core::Map<dynamic, dynamic>* map21 = block {
     final core::Map<dynamic, dynamic>* #t24 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(((mapSpread as dynamic) as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = ((mapSpread as dynamic) as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t25 = :sync-for-iterator.{core::Iterator::current};
         #t24.{core::Map::[]=}(#t25.{core::MapEntry::key}, #t25.{core::MapEntry::value});
@@ -244,7 +243,7 @@
   core::List<core::int*>* lhs22 = block {
     final core::List<core::int*>* #t26 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t27 = :sync-for-iterator.{core::Iterator::current};
         #t26.{core::List::add}(#t27);
@@ -254,7 +253,7 @@
   core::Set<core::int*>* set22 = block {
     final core::Set<core::int*>* #t28 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t29 = :sync-for-iterator.{core::Iterator::current};
         #t28.{core::Set::add}(#t29);
@@ -265,7 +264,7 @@
   core::Set<core::int*>* set22ambiguous = block {
     final core::Set<core::int*>* #t30 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t31 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -278,7 +277,7 @@
   core::Map<core::String*, core::int*>* map22 = block {
     final core::Map<core::String*, core::int*>* #t33 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t34 = :sync-for-iterator.{core::Iterator::current};
         #t33.{core::Map::[]=}(#t34.{core::MapEntry::key}, #t34.{core::MapEntry::value});
@@ -288,7 +287,7 @@
   core::List<core::List<core::int*>*>* lhs23 = block {
     final core::List<core::List<core::int*>*>* #t35 = <core::List<core::int*>*>[];
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t36 = :sync-for-iterator.{core::Iterator::current};
         #t35.{core::List::add}(#t36);
@@ -298,7 +297,7 @@
   core::Set<core::List<core::int*>*>* set23 = block {
     final core::Set<core::List<core::int*>*>* #t37 = col::LinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t38 = :sync-for-iterator.{core::Iterator::current};
         #t37.{core::Set::add}(#t38);
@@ -309,7 +308,7 @@
   core::Set<core::List<core::int*>*>* set23ambiguous = block {
     final core::Set<core::List<core::int*>*>* #t39 = col::LinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t40 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -322,7 +321,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map23 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t42 = <core::String*, core::List<core::int*>*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t43 = :sync-for-iterator.{core::Iterator::current};
         #t42.{core::Map::[]=}(#t43.{core::MapEntry::key}, #t43.{core::MapEntry::value});
@@ -338,7 +337,7 @@
                                    ^" in ( block {
     final core::List<core::int*>* #t45 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t46 = :sync-for-iterator.{core::Iterator::current};
         #t45.{core::List::add}(#t46);
@@ -351,7 +350,7 @@
                                    ^" in ( block {
     final core::Set<core::int*>* #t48 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t49 = :sync-for-iterator.{core::Iterator::current};
         #t48.{core::Set::add}(#t49);
@@ -365,7 +364,7 @@
       ^" in ( block {
     final core::Set<core::int*>* #t51 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t52 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -381,7 +380,7 @@
       ^" in ( block {
     final core::Map<core::String*, core::int*>* #t55 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t56 = :sync-for-iterator.{core::Iterator::current};
         #t55.{core::Map::[]=}(#t56.{core::MapEntry::key}, #t56.{core::MapEntry::value});
@@ -395,7 +394,7 @@
       ^" in ( block {
     final core::Map<core::String*, core::int*>* #t58 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t59 = :sync-for-iterator.{core::Iterator::current};
         #t58.{core::Map::[]=}(#t59.{core::MapEntry::key}, #t59.{core::MapEntry::value});
@@ -444,7 +443,7 @@
     ...null,
        ^");
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t69 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -461,7 +460,7 @@
     final core::List<core::int*>* #t71 = <core::int*>[];
     final core::Iterable<core::int*>* #t72 = null;
     if(!#t72.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t72).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t72.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t73 = :sync-for-iterator.{core::Iterator::current};
         #t71.{core::List::add}(#t73);
@@ -472,7 +471,7 @@
     final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>();
     final core::Iterable<core::int*>* #t75 = null;
     if(!#t75.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t75).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t75.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t76 = :sync-for-iterator.{core::Iterator::current};
         #t74.{core::Set::add}(#t76);
@@ -483,7 +482,7 @@
     final core::Set<dynamic>* #t77 = col::LinkedHashSet::•<dynamic>();
     final core::Iterable<dynamic>* #t78 = null;
     if(!#t78.{core::Object::==}(null)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(#t78).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = #t78.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t79 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -493,7 +492,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t81 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -507,7 +506,7 @@
     final core::Map<core::String*, core::int*>* #t83 = <core::String*, core::int*>{};
     final core::Map<core::String*, core::int*>* #t84 = null;
     if(!#t84.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(#t84.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = #t84.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t85 = :sync-for-iterator.{core::Iterator::current};
         #t83.{core::Map::[]=}(#t85.{core::MapEntry::key}, #t85.{core::MapEntry::value});
@@ -517,7 +516,7 @@
   core::Map<core::String*, core::int*>* map90 = block {
     final core::Map<core::String*, core::int*>* #t86 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(self::bar<core::String*, core::int*>().{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = self::bar<core::String*, core::int*>().{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t87 = :sync-for-iterator.{core::Iterator::current};
         #t86.{core::Map::[]=}(#t87.{core::MapEntry::key}, #t87.{core::MapEntry::value});
@@ -527,7 +526,7 @@
   core::List<core::int*>* list100 = block {
     final core::List<core::int*>* #t88 = <core::int*>[];
     {
-      core::Iterator<core::num*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::num*>*>(listNum).{core::Iterable::iterator};
+      core::Iterator<core::num*>* :sync-for-iterator = listNum.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t89 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -540,7 +539,7 @@
   core::Map<core::num*, core::int*>* map100 = block {
     final core::Map<core::num*, core::int*>* #t91 = <core::num*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::int*, core::num*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::num*>*>*>(mapIntNum.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::num*>*>* :sync-for-iterator = mapIntNum.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t92 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -554,7 +553,7 @@
   core::List<core::int*>* list110 = block {
     final core::List<core::int*>* #t95 = <core::int*>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t96 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -567,7 +566,7 @@
   core::Map<core::num*, core::int*>* map110 = block {
     final core::Map<core::num*, core::int*>* #t98 = <core::num*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t99 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect
index db8baa1..8eb50fc 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect
@@ -98,7 +98,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method bar<K extends core::Object* = dynamic, V extends core::Object* = dynamic>() → core::Map<self::bar::K*, self::bar::V*>*
@@ -113,7 +112,7 @@
   core::List<dynamic>* lhs10 = block {
     final core::List<dynamic>* #t1 = <dynamic>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}(#t2);
@@ -123,7 +122,7 @@
   core::Set<dynamic>* set10 = block {
     final core::Set<dynamic>* #t3 = col::LinkedHashSet::•<dynamic>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Set::add}(#t4);
@@ -133,7 +132,7 @@
   core::Map<dynamic, dynamic>* map10 = block {
     final core::Map<dynamic, dynamic>* #t5 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(<dynamic, dynamic>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = <dynamic, dynamic>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t6 = :sync-for-iterator.{core::Iterator::current};
         #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
@@ -143,7 +142,7 @@
   core::Map<dynamic, dynamic>* map10ambiguous = block {
     final core::Map<dynamic, dynamic>* #t7 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(<dynamic, dynamic>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = <dynamic, dynamic>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t8 = :sync-for-iterator.{core::Iterator::current};
         #t7.{core::Map::[]=}(#t8.{core::MapEntry::key}, #t8.{core::MapEntry::value});
@@ -153,7 +152,7 @@
   core::List<core::int*>* lhs20 = block {
     final core::List<core::int*>* #t9 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t10 = :sync-for-iterator.{core::Iterator::current};
         #t9.{core::List::add}(#t10);
@@ -163,7 +162,7 @@
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t11 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t12 = :sync-for-iterator.{core::Iterator::current};
         #t11.{core::Set::add}(#t12);
@@ -174,7 +173,7 @@
   core::Set<core::int*>* set20ambiguous = block {
     final core::Set<core::int*>* #t13 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -187,7 +186,7 @@
   core::Map<core::String*, core::int*>* map20 = block {
     final core::Map<core::String*, core::int*>* #t16 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t17 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::Map::[]=}(#t17.{core::MapEntry::key}, #t17.{core::MapEntry::value});
@@ -198,7 +197,7 @@
   core::Map<core::String*, core::int*>* map20ambiguous = block {
     final core::Map<core::String*, core::int*>* #t18 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t19 = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::Map::[]=}(#t19.{core::MapEntry::key}, #t19.{core::MapEntry::value});
@@ -208,7 +207,7 @@
   core::List<dynamic>* lhs21 = block {
     final core::List<dynamic>* #t20 = <dynamic>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::List::add}(#t21);
@@ -218,7 +217,7 @@
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t22 = col::LinkedHashSet::•<dynamic>();
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = ((spread as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t23 = :sync-for-iterator.{core::Iterator::current};
         #t22.{core::Set::add}(#t23);
@@ -229,7 +228,7 @@
   core::Map<dynamic, dynamic>* map21 = block {
     final core::Map<dynamic, dynamic>* #t24 = <dynamic, dynamic>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(((mapSpread as dynamic) as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = ((mapSpread as dynamic) as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t25 = :sync-for-iterator.{core::Iterator::current};
         #t24.{core::Map::[]=}(#t25.{core::MapEntry::key}, #t25.{core::MapEntry::value});
@@ -244,7 +243,7 @@
   core::List<core::int*>* lhs22 = block {
     final core::List<core::int*>* #t26 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t27 = :sync-for-iterator.{core::Iterator::current};
         #t26.{core::List::add}(#t27);
@@ -254,7 +253,7 @@
   core::Set<core::int*>* set22 = block {
     final core::Set<core::int*>* #t28 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t29 = :sync-for-iterator.{core::Iterator::current};
         #t28.{core::Set::add}(#t29);
@@ -265,7 +264,7 @@
   core::Set<core::int*>* set22ambiguous = block {
     final core::Set<core::int*>* #t30 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[]).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t31 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -278,7 +277,7 @@
   core::Map<core::String*, core::int*>* map22 = block {
     final core::Map<core::String*, core::int*>* #t33 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(<core::String*, core::int*>{}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = <core::String*, core::int*>{}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t34 = :sync-for-iterator.{core::Iterator::current};
         #t33.{core::Map::[]=}(#t34.{core::MapEntry::key}, #t34.{core::MapEntry::value});
@@ -288,7 +287,7 @@
   core::List<core::List<core::int*>*>* lhs23 = block {
     final core::List<core::List<core::int*>*>* #t35 = <core::List<core::int*>*>[];
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t36 = :sync-for-iterator.{core::Iterator::current};
         #t35.{core::List::add}(#t36);
@@ -298,7 +297,7 @@
   core::Set<core::List<core::int*>*>* set23 = block {
     final core::Set<core::List<core::int*>*>* #t37 = col::LinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::List<core::int*>* #t38 = :sync-for-iterator.{core::Iterator::current};
         #t37.{core::Set::add}(#t38);
@@ -309,7 +308,7 @@
   core::Set<core::List<core::int*>*>* set23ambiguous = block {
     final core::Set<core::List<core::int*>*>* #t39 = col::LinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::List<core::int*>*>*>(<core::List<core::int*>*>[<core::int*>[]]).{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t40 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -322,7 +321,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map23 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t42 = <core::String*, core::List<core::int*>*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::List<core::int*>*>*>*>(<core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>*>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t43 = :sync-for-iterator.{core::Iterator::current};
         #t42.{core::Map::[]=}(#t43.{core::MapEntry::key}, #t43.{core::MapEntry::value});
@@ -338,7 +337,7 @@
                                    ^" in ( block {
     final core::List<core::int*>* #t45 = <core::int*>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t46 = :sync-for-iterator.{core::Iterator::current};
         #t45.{core::List::add}(#t46);
@@ -351,7 +350,7 @@
                                    ^" in ( block {
     final core::Set<core::int*>* #t48 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t49 = :sync-for-iterator.{core::Iterator::current};
         #t48.{core::Set::add}(#t49);
@@ -365,7 +364,7 @@
       ^" in ( block {
     final core::Set<core::int*>* #t51 = col::LinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(spread).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = spread.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t52 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -381,7 +380,7 @@
       ^" in ( block {
     final core::Map<core::String*, core::int*>* #t55 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t56 = :sync-for-iterator.{core::Iterator::current};
         #t55.{core::Map::[]=}(#t56.{core::MapEntry::key}, #t56.{core::MapEntry::value});
@@ -395,7 +394,7 @@
       ^" in ( block {
     final core::Map<core::String*, core::int*>* #t58 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(mapSpread.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = mapSpread.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t59 = :sync-for-iterator.{core::Iterator::current};
         #t58.{core::Map::[]=}(#t59.{core::MapEntry::key}, #t59.{core::MapEntry::value});
@@ -444,7 +443,7 @@
     ...null,
        ^");
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t69 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -461,7 +460,7 @@
     final core::List<core::int*>* #t71 = <core::int*>[];
     final core::Iterable<core::int*>* #t72 = null;
     if(!#t72.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t72).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t72.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t73 = :sync-for-iterator.{core::Iterator::current};
         #t71.{core::List::add}(#t73);
@@ -472,7 +471,7 @@
     final core::Set<core::int*>* #t74 = col::LinkedHashSet::•<core::int*>();
     final core::Iterable<core::int*>* #t75 = null;
     if(!#t75.{core::Object::==}(null)) {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(#t75).{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = #t75.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t76 = :sync-for-iterator.{core::Iterator::current};
         #t74.{core::Set::add}(#t76);
@@ -483,7 +482,7 @@
     final core::Set<dynamic>* #t77 = col::LinkedHashSet::•<dynamic>();
     final core::Iterable<dynamic>* #t78 = null;
     if(!#t78.{core::Object::==}(null)) {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(#t78).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = #t78.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t79 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -493,7 +492,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t81 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -507,7 +506,7 @@
     final core::Map<core::String*, core::int*>* #t83 = <core::String*, core::int*>{};
     final core::Map<core::String*, core::int*>* #t84 = null;
     if(!#t84.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(#t84.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = #t84.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t85 = :sync-for-iterator.{core::Iterator::current};
         #t83.{core::Map::[]=}(#t85.{core::MapEntry::key}, #t85.{core::MapEntry::value});
@@ -517,7 +516,7 @@
   core::Map<core::String*, core::int*>* map90 = block {
     final core::Map<core::String*, core::int*>* #t86 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(self::bar<core::String*, core::int*>().{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = self::bar<core::String*, core::int*>().{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::int*>* #t87 = :sync-for-iterator.{core::Iterator::current};
         #t86.{core::Map::[]=}(#t87.{core::MapEntry::key}, #t87.{core::MapEntry::value});
@@ -527,7 +526,7 @@
   core::List<core::int*>* list100 = block {
     final core::List<core::int*>* #t88 = <core::int*>[];
     {
-      core::Iterator<core::num*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::num*>*>(listNum).{core::Iterable::iterator};
+      core::Iterator<core::num*>* :sync-for-iterator = listNum.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t89 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -540,7 +539,7 @@
   core::Map<core::num*, core::int*>* map100 = block {
     final core::Map<core::num*, core::int*>* #t91 = <core::num*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<core::int*, core::num*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::num*>*>*>(mapIntNum.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::num*>*>* :sync-for-iterator = mapIntNum.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t92 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -554,7 +553,7 @@
   core::List<core::int*>* list110 = block {
     final core::List<core::int*>* #t95 = <core::int*>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t96 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -567,7 +566,7 @@
   core::Map<core::num*, core::int*>* map110 = block {
     final core::Map<core::num*, core::int*>* #t98 = <core::num*, core::int*>{};
     {
-      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>((dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Map<dynamic, dynamic>*).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, dynamic>* #t99 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.expect
index 299c8ab..62bc2c5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.expect
@@ -16,9 +16,9 @@
     : super core::Object::•()
     ;
   method method() → invalid-type
-    return "Hello, World!" as{TypeError} invalid-type;
+    return "Hello, World!";
 }
 static method main() → dynamic {
-  core::String* s = new self::C::•<dynamic>().{self::C::method}() as{TypeError} core::String*;
+  core::String* s = new self::C::•<dynamic>().{self::C::method}();
   core::print(s);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.transformed.expect
index 299c8ab..62bc2c5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.strong.transformed.expect
@@ -16,9 +16,9 @@
     : super core::Object::•()
     ;
   method method() → invalid-type
-    return "Hello, World!" as{TypeError} invalid-type;
+    return "Hello, World!";
 }
 static method main() → dynamic {
-  core::String* s = new self::C::•<dynamic>().{self::C::method}() as{TypeError} core::String*;
+  core::String* s = new self::C::•<dynamic>().{self::C::method}();
   core::print(s);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.expect
index 299c8ab..62bc2c5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.expect
@@ -16,9 +16,9 @@
     : super core::Object::•()
     ;
   method method() → invalid-type
-    return "Hello, World!" as{TypeError} invalid-type;
+    return "Hello, World!";
 }
 static method main() → dynamic {
-  core::String* s = new self::C::•<dynamic>().{self::C::method}() as{TypeError} core::String*;
+  core::String* s = new self::C::•<dynamic>().{self::C::method}();
   core::print(s);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.transformed.expect
index 299c8ab..62bc2c5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_prefix.dart.weak.transformed.expect
@@ -16,9 +16,9 @@
     : super core::Object::•()
     ;
   method method() → invalid-type
-    return "Hello, World!" as{TypeError} invalid-type;
+    return "Hello, World!";
 }
 static method main() → dynamic {
-  core::String* s = new self::C::•<dynamic>().{self::C::method}() as{TypeError} core::String*;
+  core::String* s = new self::C::•<dynamic>().{self::C::method}();
   core::print(s);
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
index 4a9ec12..4da97d9 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
@@ -212,7 +212,7 @@
     method /* from org-dartlang-sdk:///sdk/lib/collection/list.dart */ addAll(generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void {
       dart.core::int* i = this.{dart.core::List::length};
       {
-        dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(iterable).{dart.core::Iterable::iterator};
+        dart.core::Iterator<dart.core::int*>* :sync-for-iterator = iterable.{dart.core::Iterable::iterator};
         for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
           dart.core::int* element = :sync-for-iterator.{dart.core::Iterator::current};
           {
@@ -458,7 +458,7 @@
       }
       else {
         {
-          dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(iterable).{dart.core::Iterable::iterator};
+          dart.core::Iterator<dart.core::int*>* :sync-for-iterator = iterable.{dart.core::Iterable::iterator};
           for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
             dart.core::int* element = :sync-for-iterator.{dart.core::Iterator::current};
             {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
index 4a9ec12..4da97d9 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
@@ -212,7 +212,7 @@
     method /* from org-dartlang-sdk:///sdk/lib/collection/list.dart */ addAll(generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void {
       dart.core::int* i = this.{dart.core::List::length};
       {
-        dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(iterable).{dart.core::Iterable::iterator};
+        dart.core::Iterator<dart.core::int*>* :sync-for-iterator = iterable.{dart.core::Iterable::iterator};
         for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
           dart.core::int* element = :sync-for-iterator.{dart.core::Iterator::current};
           {
@@ -458,7 +458,7 @@
       }
       else {
         {
-          dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(iterable).{dart.core::Iterable::iterator};
+          dart.core::Iterator<dart.core::int*>* :sync-for-iterator = iterable.{dart.core::Iterable::iterator};
           for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
             dart.core::int* element = :sync-for-iterator.{dart.core::Iterator::current};
             {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
index b765c13..c3e26f0 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
@@ -5,8 +5,8 @@
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -22,13 +22,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
 }
@@ -48,8 +48,8 @@
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -64,13 +64,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
index c5de17c..e864fa8 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
@@ -5,8 +5,8 @@
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -22,13 +22,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
 }
@@ -48,8 +48,8 @@
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -65,13 +65,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.1.expect
index 42d7120..373b5c9 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.1.expect
@@ -14,8 +14,8 @@
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -30,21 +30,21 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -60,13 +60,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.2.expect
index 418248d..b65715d 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.2.expect
@@ -14,8 +14,8 @@
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -30,21 +30,21 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -60,13 +60,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.3.expect
index 13582f4..306cc91 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.3.expect
@@ -14,8 +14,8 @@
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -31,21 +31,21 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
     dart.async::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -61,13 +61,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
 }
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 ecb9078..cd1110d 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
@@ -15,8 +15,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -38,8 +38,8 @@
           final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
           asy::FutureOr<core::int*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -52,21 +52,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test1() → asy::Future<core::int*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
           asy::FutureOr<core::int*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -79,21 +79,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test2() → asy::Future<asy::Future<core::int*>*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<asy::Future<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<asy::Future<core::int*>*>();
           asy::FutureOr<asy::Future<core::int*>*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -106,21 +106,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test3() → asy::Future<asy::FutureOr<core::int*>*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<asy::FutureOr<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<asy::FutureOr<core::int*>*>();
           asy::FutureOr<asy::FutureOr<core::int*>*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -133,21 +133,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test4() → asy::Future<self::MyFuture*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<self::MyFuture*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::MyFuture*>();
           asy::FutureOr<self::MyFuture*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -160,21 +160,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test5() → asy::Future<core::int*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
           asy::FutureOr<core::int*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -187,21 +187,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test6() → asy::Future<asy::Future<core::int*>*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<asy::Future<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<asy::Future<core::int*>*>();
           asy::FutureOr<asy::Future<core::int*>*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -214,21 +214,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test7() → asy::Future<asy::FutureOr<core::int*>*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<asy::FutureOr<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<asy::FutureOr<core::int*>*>();
           asy::FutureOr<asy::FutureOr<core::int*>*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -241,21 +241,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test8() → asy::Future<self::MyFuture*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<self::MyFuture*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::MyFuture*>();
           asy::FutureOr<self::MyFuture*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -268,21 +268,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         function test9() → asy::Future<core::int*>* /* originally async */ {
           final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
           asy::FutureOr<core::int*>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -295,13 +295,13 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         [yield] let dynamic #t1 = asy::_awaitHelper(x0, :async_op_then, :async_op_error, :async_op) in null;
@@ -328,13 +328,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect
index c587b4b..b9580fb 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -25,13 +25,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 };
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect
index 69a4666..bd3ef80 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect
@@ -7,8 +7,8 @@
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -21,13 +21,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 };
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect
index 13ab2d2..913d676 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect
@@ -11,8 +11,8 @@
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -25,13 +25,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 };
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect
index 461478b..d0e8788 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect
@@ -12,8 +12,8 @@
     final asy::_AsyncAwaitCompleter<core::num*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::num*>();
     asy::FutureOr<core::num*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -32,13 +32,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   asy::Future<core::num*>* g = f.call();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect
index 6675875..30eabe7 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect
@@ -12,8 +12,8 @@
     final asy::_AsyncAwaitCompleter<core::num*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::num*>();
     asy::FutureOr<core::num*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -32,13 +32,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   asy::Future<core::num*>* g = f.call();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect
index 83d4912..cddac4a 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect
@@ -12,8 +12,8 @@
     final asy::_AsyncAwaitCompleter<core::num*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::num*>();
     asy::FutureOr<core::num*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -32,13 +32,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   asy::Future<core::num*>* g = f.call();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect
index c640de2..a0abb09 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
     asy::_AsyncStarStreamController<core::num*>* :controller;
     dynamic :controller_stream;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -33,7 +33,7 @@
           }
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
           :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
         }
       finally {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
index 72c0762..b6a939d 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -23,8 +23,8 @@
           final asy::_AsyncAwaitCompleter<core::Null?>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Null?>();
           asy::FutureOr<core::Null?>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -37,13 +37,13 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
         asy::Future<dynamic>* y = f.call();
@@ -54,12 +54,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
index c810580..cd7251f 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -23,8 +23,8 @@
           asy::_AsyncStarStreamController<core::Null?>* :controller;
           dynamic :controller_stream;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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;
@@ -41,7 +41,7 @@
                 }
                 return;
               }
-              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+              on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                 :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
               }
             finally {
@@ -62,12 +62,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.expect
index d1e47f9..189aa8d 100644
--- a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.expect
@@ -9,6 +9,6 @@
 //
 import self as self;
 
-static field invalid-type x = (() → () →* invalid-type => self::y) as{TypeError} invalid-type;
+static field invalid-type x = () → () →* invalid-type => self::y;
 static field () →* invalid-type y = () → invalid-type => self::x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.transformed.expect
index d1e47f9..189aa8d 100644
--- a/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/circular_reference_via_closures.dart.strong.transformed.expect
@@ -9,6 +9,6 @@
 //
 import self as self;
 
-static field invalid-type x = (() → () →* invalid-type => self::y) as{TypeError} invalid-type;
+static field invalid-type x = () → () →* invalid-type => self::y;
 static field () →* invalid-type y = () → invalid-type => self::x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.expect
index 758e00e..2439199 100644
--- a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.expect
@@ -9,6 +9,6 @@
 //
 import self as self;
 
-static field invalid-type x = (() → () →* invalid-type => self::y) as{TypeError} invalid-type;
+static field invalid-type x = () → () →* invalid-type => self::y;
 static field () →* invalid-type y = () → invalid-type => self::x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.transformed.expect
index 758e00e..2439199 100644
--- a/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/circular_reference_via_closures_initializer_types.dart.strong.transformed.expect
@@ -9,6 +9,6 @@
 //
 import self as self;
 
-static field invalid-type x = (() → () →* invalid-type => self::y) as{TypeError} invalid-type;
+static field invalid-type x = () → () →* invalid-type => self::y;
 static field () →* invalid-type y = () → invalid-type => self::x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
index 41a115e..c81fe3a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library test;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
@@ -12,7 +11,7 @@
   for (@#C1 core::int* i = 0; i.{core::num::<}(1); i = i.{core::num::+}(1)) {
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[0]).{core::Iterable::iterator};
+    core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[0].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       @#C1 core::int* i = :sync-for-iterator.{core::Iterator::current};
       {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
index 92361c9..1ab4c3c 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -28,12 +28,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
index f95b190..99eb58d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
@@ -16,8 +16,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -31,28 +31,28 @@
         dynamic d;
         core::Object* o;
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(self::F<core::Iterable<dynamic>*>()).{core::Iterable::iterator};
+          core::Iterator<dynamic>* :sync-for-iterator = self::F<core::Iterable<dynamic>*>().{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             dynamic x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(self::F<core::Iterable<dynamic>*>()).{core::Iterable::iterator};
+          core::Iterator<dynamic>* :sync-for-iterator = self::F<core::Iterable<dynamic>*>().{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             dynamic x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          core::Iterator<core::Object*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Object*>*>(self::F<core::Iterable<core::Object*>*>()).{core::Iterable::iterator};
+          core::Iterator<core::Object*>* :sync-for-iterator = self::F<core::Iterable<core::Object*>*>().{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             core::Object* x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(self::F<core::Iterable<dynamic>*>()).{core::Iterable::iterator};
+          core::Iterator<dynamic>* :sync-for-iterator = self::F<core::Iterable<dynamic>*>().{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -61,7 +61,7 @@
           }
         }
         {
-          core::Iterator<core::Object*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::Object*>*>(self::F<core::Iterable<core::Object*>*>()).{core::Iterable::iterator};
+          core::Iterator<core::Object*>* :sync-for-iterator = self::F<core::Iterable<core::Object*>*>().{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Object* #t2 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -70,7 +70,7 @@
           }
         }
         {
-          dynamic :stream = self::F<asy::Stream<dynamic>*>();
+          asy::Stream<dynamic>* :stream = self::F<asy::Stream<dynamic>*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -92,7 +92,7 @@
             }
         }
         {
-          dynamic :stream = self::F<asy::Stream<dynamic>*>();
+          asy::Stream<dynamic>* :stream = self::F<asy::Stream<dynamic>*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -114,7 +114,7 @@
             }
         }
         {
-          dynamic :stream = self::F<asy::Stream<core::Object*>*>();
+          asy::Stream<core::Object*>* :stream = self::F<asy::Stream<core::Object*>*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::Object*>* :for-iterator = new asy::_StreamIterator::•<core::Object*>(:stream);
           try
@@ -136,7 +136,7 @@
             }
         }
         {
-          dynamic :stream = self::F<asy::Stream<dynamic>*>();
+          asy::Stream<dynamic>* :stream = self::F<asy::Stream<dynamic>*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -160,7 +160,7 @@
             }
         }
         {
-          dynamic :stream = self::F<asy::Stream<core::Object*>*>();
+          asy::Stream<core::Object*>* :stream = self::F<asy::Stream<core::Object*>*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::Object*>* :for-iterator = new asy::_StreamIterator::•<core::Object*>(:stream);
           try
@@ -187,21 +187,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → asy::Future<dynamic>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -213,28 +213,28 @@
       #L7:
       {
         {
-          core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+          core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             core::int* x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          core::Iterator<core::num*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::num*>*>(<core::num*>[1, 2, 3]).{core::Iterable::iterator};
+          core::Iterator<core::num*>* :sync-for-iterator = <core::num*>[1, 2, 3].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             core::num* x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3]).{core::Iterable::iterator};
+          core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             core::int* x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          dynamic :stream = self::MyStream::•<core::int*>();
+          self::MyStream<core::int*>* :stream = self::MyStream::•<core::int*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
@@ -256,7 +256,7 @@
             }
         }
         {
-          dynamic :stream = self::MyStream::•<core::int*>();
+          self::MyStream<core::int*>* :stream = self::MyStream::•<core::int*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
@@ -281,12 +281,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
index b784630..1dc5905 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
@@ -40,8 +40,8 @@
   asy::_AsyncStarStreamController<core::List<core::int*>*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -78,7 +78,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
diff --git a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect
index 2bc7b4c..525b2c0 100644
--- a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect
@@ -8,8 +8,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -22,14 +22,14 @@
       {
         core::Object* o;
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(o as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
+          core::Iterator<dynamic>* :sync-for-iterator = (o as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             dynamic x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          dynamic :stream = o as{TypeError} asy::Stream<dynamic>*;
+          asy::Stream<dynamic>* :stream = o as{TypeError} asy::Stream<dynamic>*;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -52,7 +52,7 @@
         }
         core::int* y;
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(o as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
+          core::Iterator<dynamic>* :sync-for-iterator = (o as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -61,7 +61,7 @@
           }
         }
         {
-          dynamic :stream = o as{TypeError} asy::Stream<dynamic>*;
+          asy::Stream<dynamic>* :stream = o as{TypeError} asy::Stream<dynamic>*;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -88,13 +88,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.strong.transformed.expect
index a5c5985..bda8d12 100644
--- a/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/for_in_loop_promotion.dart.strong.transformed.expect
@@ -1,11 +1,10 @@
 library test;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method test(core::List<core::num*>* nums) → void {
   {
-    core::Iterator<core::num*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::num*>*>(nums).{core::Iterable::iterator};
+    core::Iterator<core::num*>* :sync-for-iterator = nums.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::num* x = :sync-for-iterator.{core::Iterator::current};
       {
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 48ef203..1c08fc3 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -46,21 +46,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -75,21 +75,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -102,21 +102,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -129,13 +129,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* => asy::Future::value<core::int*>(3));
@@ -146,8 +146,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -160,21 +160,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t8 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -187,13 +187,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
 }
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 a340d04..b4d284b 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -46,21 +46,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -75,21 +75,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -102,21 +102,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -129,13 +129,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((dynamic _) → self::MyFuture<core::int*>* => new self::MyFuture::value<core::int*>(3));
@@ -146,8 +146,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -160,21 +160,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t8 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -187,13 +187,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
 }
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 61dc898..d3bd398 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -46,21 +46,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -75,21 +75,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -102,21 +102,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -129,13 +129,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* => asy::Future::value<core::int*>(3));
@@ -146,8 +146,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -160,21 +160,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t8 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -187,13 +187,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
 }
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 36e80aa..24a4359 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -46,21 +46,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -75,21 +75,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -102,21 +102,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -129,13 +129,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((dynamic _) → self::MyFuture<core::int*>* => new self::MyFuture::value<core::int*>(3));
@@ -146,8 +146,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -160,21 +160,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t8 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -187,13 +187,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
 }
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 9d8eb63..282f036 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -46,21 +46,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -75,21 +75,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -102,21 +102,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -129,13 +129,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((dynamic _) → self::MyFuture<core::int*>* => new self::MyFuture::value<core::int*>(3));
@@ -146,8 +146,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -160,21 +160,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t8 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -187,13 +187,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
 }
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 9efbea1..fd93688 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -46,21 +46,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -75,21 +75,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -102,21 +102,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -129,13 +129,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* => asy::Future::value<core::int*>(3));
@@ -146,8 +146,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -160,21 +160,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t8 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -187,13 +187,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
 }
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 c53bad4..0ec550c 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -53,21 +53,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -82,13 +82,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::FutureOr<core::int*>* => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*);
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 20f8e91..e3e191c 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -53,21 +53,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -82,13 +82,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::FutureOr<core::int*>* => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*);
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 2be73df..aaf989c 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -53,21 +53,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -82,13 +82,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::FutureOr<core::int*>* => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*);
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 ab579f5..d767998 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -53,21 +53,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -82,13 +82,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   self::MyFuture<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::FutureOr<core::int*>* => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*);
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 f68b46e..0702c99 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -53,21 +53,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :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) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -82,13 +82,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :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) → asy::FutureOr<core::int*>* => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*);
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 a7f2f7a..7a8790e 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -53,21 +53,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :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) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -82,13 +82,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :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) → asy::FutureOr<core::int*>* => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*);
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 9d9e7dc..8f10629 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,8 +30,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -54,21 +54,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -83,13 +83,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t5 = x in #t5.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t5) as{TypeError} asy::FutureOr<core::int*>*);
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 0c1809a..e8d3a2b 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
@@ -27,8 +27,8 @@
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -41,21 +41,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g2(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -68,21 +68,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g3(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -96,13 +96,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
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 1812257..d51f046 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
@@ -27,8 +27,8 @@
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -41,21 +41,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g2(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -68,21 +68,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g3(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
   asy::FutureOr<core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -96,13 +96,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
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 829fcb3..c45e377 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
@@ -41,8 +41,8 @@
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -55,21 +55,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g3() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -82,13 +82,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
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 a99851d..90cc080 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
@@ -30,8 +30,8 @@
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -44,21 +44,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g3() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -71,13 +71,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
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 585b9a59..4e9ddea 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
@@ -41,8 +41,8 @@
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -55,21 +55,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g3() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -82,13 +82,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
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 7448b01..b54c92f 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
@@ -30,8 +30,8 @@
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -44,21 +44,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method g3() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
   asy::FutureOr<core::List<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -71,13 +71,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
index 69f42e3..fad67c5 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
@@ -15,8 +15,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -32,13 +32,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect
index ce99844..fce1d5c 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect
@@ -12,8 +12,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -28,13 +28,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
index c71cd17..6e13ec4 100644
--- a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
@@ -25,8 +25,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -47,12 +47,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect
index fc34967..6c34434 100644
--- a/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect
@@ -11,8 +11,8 @@
     asy::_AsyncStarStreamController<core::int*>* :controller;
     dynamic :controller_stream;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -33,7 +33,7 @@
           }
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
           :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
         }
       finally {
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
index 1e35606..a0717bb 100644
--- a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
@@ -39,8 +39,8 @@
     return x;
 }
 static method main() → dynamic {
-  core::int* y = (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:18:74: Error: Expected 0 type arguments.
+  core::int* y = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:18:74: Error: Expected 0 type arguments.
       . /*error:WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD*/ /*@target=D::m*/ m<int>(
-                                                                         ^" in new self::D::•().{self::D::m}<core::int*>(42)) as{TypeError} core::int*;
+                                                                         ^" in new self::D::•().{self::D::m}<core::int*>(42);
   core::print(y);
 }
diff --git a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect
index e6b1e38..8446ce803 100644
--- a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -24,13 +24,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function f2() → core::int* {
@@ -40,8 +40,8 @@
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     asy::FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -54,13 +54,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function f4() → core::Iterable<core::int*>* /* originally sync* */ {
@@ -81,8 +81,8 @@
     asy::_AsyncStarStreamController<core::int*>* :controller;
     dynamic :controller_stream;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -99,7 +99,7 @@
           }
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
           :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
         }
       finally {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
index 8b874fc..c15b9d3 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
@@ -30,7 +30,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Foo extends core::Object {
   field core::int* bar = 42;
@@ -44,7 +43,7 @@
     ;
   method foo(generic-covariant-impl self::Bar::T* t) → void {
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(t).{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = t.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::String* i = :sync-for-iterator.{core::Iterator::current};
         {
@@ -62,7 +61,7 @@
     ;
   method foo(generic-covariant-impl self::Baz::S* t) → void {
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(t).{core::Iterable::iterator};
+      core::Iterator<self::Baz::T*>* :sync-for-iterator = t.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         self::Baz::T* i = :sync-for-iterator.{core::Iterator::current};
         {
@@ -78,7 +77,7 @@
 static method test() → dynamic {
   core::List<self::Foo*>* list = <self::Foo*>[];
   {
-    core::Iterator<self::Foo*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::Foo*>*>(list).{core::Iterable::iterator};
+    core::Iterator<self::Foo*>* :sync-for-iterator = list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       self::Foo* x = :sync-for-iterator.{core::Iterator::current};
       {
@@ -90,7 +89,7 @@
     }
   }
   {
-    core::Iterator<self::Foo*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::Foo*>*>(list).{core::Iterable::iterator};
+    core::Iterator<self::Foo*>* :sync-for-iterator = list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic x = :sync-for-iterator.{core::Iterator::current};
       {
@@ -99,7 +98,7 @@
     }
   }
   {
-    core::Iterator<self::Foo*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::Foo*>*>(list).{core::Iterable::iterator};
+    core::Iterator<self::Foo*>* :sync-for-iterator = list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final self::Foo* #t4 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -114,7 +113,7 @@
   }
   dynamic z;
   {
-    core::Iterator<self::Foo*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::Foo*>*>(list).{core::Iterable::iterator};
+    core::Iterator<self::Foo*>* :sync-for-iterator = list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final self::Foo* #t6 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -125,7 +124,7 @@
   }
   core::Iterable<dynamic>* iter = list;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(iter).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = iter.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t7 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -136,7 +135,7 @@
   }
   dynamic iter2 = list;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(iter2 as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = (iter2 as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -147,7 +146,7 @@
   }
   core::Map<core::String*, self::Foo*>* map = <core::String*, self::Foo*>{};
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:60:70: Error: The type 'Map<String, Foo>' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:60:70: Error: The type 'Map<String, Foo>' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Map' is from 'dart:core'.
  - 'Foo' is from 'pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart'.
  - 'Iterable' is from 'dart:core'.
@@ -161,7 +160,7 @@
     }
   }
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(map.{core::Map::keys}).{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = map.{core::Map::keys}.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* x = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
index 7f3335c..7959a66 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
@@ -49,8 +49,8 @@
     final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -62,7 +62,7 @@
         #L1:
         {
           {
-            dynamic :stream = t;
+            self::Bar::T* :stream = t;
             asy::_asyncStarListenHelper(:stream, :async_op);
             asy::_StreamIterator<core::String*>* :for-iterator = new asy::_StreamIterator::•<core::String*>(:stream);
             try
@@ -91,13 +91,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -109,8 +109,8 @@
     final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -122,7 +122,7 @@
         #L3:
         {
           {
-            dynamic :stream = t;
+            self::Baz::S* :stream = t;
             asy::_asyncStarListenHelper(:stream, :async_op);
             asy::_StreamIterator<self::Baz::T*>* :for-iterator = new asy::_StreamIterator::•<self::Baz::T*>(:stream);
             try
@@ -152,13 +152,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
 }
@@ -170,8 +170,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -184,7 +184,7 @@
       {
         self::MyStream<self::Foo*>* myStream = self::MyStream::•<self::Foo*>();
         {
-          dynamic :stream = myStream;
+          self::MyStream<self::Foo*>* :stream = myStream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<self::Foo*>* :for-iterator = new asy::_StreamIterator::•<self::Foo*>(:stream);
           try
@@ -211,7 +211,7 @@
             }
         }
         {
-          dynamic :stream = myStream;
+          self::MyStream<self::Foo*>* :stream = myStream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -235,7 +235,7 @@
             }
         }
         {
-          dynamic :stream = myStream;
+          self::MyStream<self::Foo*>* :stream = myStream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<self::Foo*>* :for-iterator = new asy::_StreamIterator::•<self::Foo*>(:stream);
           try
@@ -265,7 +265,7 @@
         }
         dynamic z;
         {
-          dynamic :stream = myStream;
+          self::MyStream<self::Foo*>* :stream = myStream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<self::Foo*>* :for-iterator = new asy::_StreamIterator::•<self::Foo*>(:stream);
           try
@@ -291,7 +291,7 @@
         }
         asy::Stream<dynamic>* stream = myStream;
         {
-          dynamic :stream = stream;
+          asy::Stream<dynamic>* :stream = stream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -317,7 +317,7 @@
         }
         dynamic stream2 = myStream;
         {
-          dynamic :stream = stream2 as{TypeError,ForDynamic} asy::Stream<dynamic>*;
+          asy::Stream<dynamic>* :stream = stream2 as{TypeError,ForDynamic} asy::Stream<dynamic>*;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -343,7 +343,7 @@
         }
         core::Map<core::String*, self::Foo*>* map = <core::String*, self::Foo*>{};
         {
-          dynamic :stream = let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:66:76: Error: The type 'Map<String, Foo>' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:66:76: Error: The type 'Map<String, Foo>' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Map' is from 'dart:core'.
  - 'Foo' is from 'pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart'.
  - 'Stream' is from 'dart:async'.
@@ -375,13 +375,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
index d796649..b2ac7ae 100644
--- a/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
@@ -22,8 +22,8 @@
     final asy::_AsyncAwaitCompleter<(core::int*) →* core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<(core::int*) →* core::int*>();
     asy::FutureOr<(core::int*) →* core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -39,13 +39,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function c() → core::Iterable<(core::int*) →* core::int*>* /* originally sync* */ {
@@ -80,8 +80,8 @@
     asy::_AsyncStarStreamController<(core::int*) →* core::int*>* :controller;
     dynamic :controller_stream;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -98,7 +98,7 @@
           }
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
           :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
         }
       finally {
@@ -115,8 +115,8 @@
     asy::_AsyncStarStreamController<(core::int*) →* core::int*>* :controller;
     dynamic :controller_stream;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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;
@@ -133,7 +133,7 @@
           }
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
           :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
         }
       finally {
diff --git a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
index f6ea666..135c992 100644
--- a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
@@ -21,8 +21,8 @@
   final asy::_AsyncAwaitCompleter<(core::int*) →* core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<(core::int*) →* core::int*>();
   asy::FutureOr<(core::int*) →* core::int*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -38,13 +38,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method c() → core::Iterable<(core::int*) →* core::int*>* /* originally sync* */ {
@@ -79,8 +79,8 @@
   asy::_AsyncStarStreamController<(core::int*) →* core::int*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -97,7 +97,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -114,8 +114,8 @@
   asy::_AsyncStarStreamController<(core::int*) →* core::int*>* :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -132,7 +132,7 @@
         }
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.expect
index 3b1a187..e89c7cf 100644
--- a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.expect
@@ -20,7 +20,7 @@
     return 0;
 }
 static field self::A* a = new self::A::•();
-static field invalid-type b = (() → () →* invalid-type => self::a.{self::A::f}<() →* invalid-type>(self::c)) as{TypeError} invalid-type;
+static field invalid-type b = () → () →* invalid-type => self::a.{self::A::f}<() →* invalid-type>(self::c);
 static field () →* invalid-type c = () → invalid-type => self::a.{self::A::f}<invalid-type>(self::b);
 static field () →* () →* core::int* d = () → () →* core::int* => self::a.{self::A::f}<() →* core::int*>(self::e);
 static field () →* core::int* e = () → core::int* => self::a.{self::A::g}(self::d);
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.transformed.expect
index 3b1a187..e89c7cf 100644
--- a/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     return 0;
 }
 static field self::A* a = new self::A::•();
-static field invalid-type b = (() → () →* invalid-type => self::a.{self::A::f}<() →* invalid-type>(self::c)) as{TypeError} invalid-type;
+static field invalid-type b = () → () →* invalid-type => self::a.{self::A::f}<() →* invalid-type>(self::c);
 static field () →* invalid-type c = () → invalid-type => self::a.{self::A::f}<invalid-type>(self::b);
 static field () →* () →* core::int* d = () → () →* core::int* => self::a.{self::A::f}<() →* core::int*>(self::e);
 static field () →* core::int* e = () → core::int* => self::a.{self::A::g}(self::d);
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
index 2620e6d..f3dce3c 100644
--- a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
@@ -13,7 +13,7 @@
 static field core::int* intValue = 0;
 static field core::num* numValue = 0;
 static field core::double* doubleValue = 0.0;
-static field invalid-type a = (() → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num*)) as{TypeError} invalid-type;
+static field invalid-type a = () → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num*);
 static field dynamic b = self::a.call();
 static field () →* core::num* c = () → core::num* => self::numValue.{core::num::+}(self::d);
 static field core::num* d = self::c.call();
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect
index 2620e6d..f3dce3c 100644
--- a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
 static field core::int* intValue = 0;
 static field core::num* numValue = 0;
 static field core::double* doubleValue = 0.0;
-static field invalid-type a = (() → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num*)) as{TypeError} invalid-type;
+static field invalid-type a = () → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num*);
 static field dynamic b = self::a.call();
 static field () →* core::num* c = () → core::num* => self::numValue.{core::num::+}(self::d);
 static field core::num* d = self::c.call();
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.expect b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.expect
index 3de0169..5367e37 100644
--- a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.expect
@@ -11,7 +11,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  field invalid-type x = (() → invalid-type => new self::B::•().{self::B::x}) as{TypeError} invalid-type;
+  field invalid-type x = () → invalid-type => new self::B::•().{self::B::x};
   field () →* invalid-type y = () → invalid-type => new self::B::•().{self::B::x};
   synthetic constructor •() → self::A*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.transformed.expect
index 3de0169..5367e37 100644
--- a/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/field_inference_circularity.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  field invalid-type x = (() → invalid-type => new self::B::•().{self::B::x}) as{TypeError} invalid-type;
+  field invalid-type x = () → invalid-type => new self::B::•().{self::B::x};
   field () →* invalid-type y = () → invalid-type => new self::B::•().{self::B::x};
   synthetic constructor •() → self::A*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.strong.transformed.expect
index 6bbfddf..3b7b28d 100644
--- a/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library test;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class A extends core::Object {
   synthetic constructor •() → self::A*
@@ -17,7 +16,7 @@
   method test() → void {
     self::A* aLocal;
     {
-      core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(self::f<core::Iterable<self::A*>*>()).{core::Iterable::iterator};
+      core::Iterator<self::A*>* :sync-for-iterator = self::f<core::Iterable<self::A*>*>().{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final self::A* #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -26,7 +25,7 @@
       }
     }
     {
-      core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(self::f<core::Iterable<self::A*>*>()).{core::Iterable::iterator};
+      core::Iterator<self::A*>* :sync-for-iterator = self::f<core::Iterable<self::A*>*>().{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final self::A* #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -35,7 +34,7 @@
       }
     }
     {
-      core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(self::f<core::Iterable<self::A*>*>()).{core::Iterable::iterator};
+      core::Iterator<self::A*>* :sync-for-iterator = self::f<core::Iterable<self::A*>*>().{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final self::A* #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -44,7 +43,7 @@
       }
     }
     {
-      core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(self::f<core::Iterable<self::A*>*>()).{core::Iterable::iterator};
+      core::Iterator<self::A*>* :sync-for-iterator = self::f<core::Iterable<self::A*>*>().{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final self::A* #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -53,7 +52,7 @@
       }
     }
     {
-      core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(self::f<core::Iterable<self::A*>*>()).{core::Iterable::iterator};
+      core::Iterator<self::A*>* :sync-for-iterator = self::f<core::Iterable<self::A*>*>().{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final self::A* #t5 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
index 796c34d..4cab266 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
@@ -31,8 +31,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -45,7 +45,7 @@
       {
         core::String* s;
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:10:17: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+          core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:10:17: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   for (int x in s) {}
                 ^" in s as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -57,7 +57,7 @@
           }
         }
         {
-          dynamic :stream = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:11:23: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:11:23: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   await for (int x in s) {}
                       ^" in s as{TypeError} asy::Stream<dynamic>*;
@@ -85,7 +85,7 @@
         }
         core::int* y;
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:13:13: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
+          core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:13:13: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   for (y in s) {}
             ^" in s as{TypeError} core::Iterable<dynamic>*).{core::Iterable::iterator};
@@ -97,7 +97,7 @@
           }
         }
         {
-          dynamic :stream = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:14:19: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
+          asy::Stream<dynamic>* :stream = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:14:19: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
   await for (y in s) {}
                   ^" in s as{TypeError} asy::Stream<dynamic>*;
@@ -127,13 +127,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
index 480adea..eac8b7c 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
@@ -37,8 +37,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -55,7 +55,7 @@
         self::B* b;
         core::int* i;
         {
-          core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(iterable).{core::Iterable::iterator};
+          core::Iterator<self::A*>* :sync-for-iterator = iterable.{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final self::A* #t1 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -64,7 +64,7 @@
           }
         }
         {
-          dynamic :stream = stream;
+          asy::Stream<self::A*>* :stream = stream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<self::A*>* :for-iterator = new asy::_StreamIterator::•<self::A*>(:stream);
           try
@@ -88,7 +88,7 @@
             }
         }
         {
-          core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(iterable).{core::Iterable::iterator};
+          core::Iterator<self::A*>* :sync-for-iterator = iterable.{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final self::A* #t6 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -97,7 +97,7 @@
           }
         }
         {
-          dynamic :stream = stream;
+          asy::Stream<self::A*>* :stream = stream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<self::A*>* :for-iterator = new asy::_StreamIterator::•<self::A*>(:stream);
           try
@@ -121,7 +121,7 @@
             }
         }
         {
-          core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(iterable).{core::Iterable::iterator};
+          core::Iterator<self::A*>* :sync-for-iterator = iterable.{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final self::A* #t11 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -134,7 +134,7 @@
           }
         }
         {
-          dynamic :stream = stream;
+          asy::Stream<self::A*>* :stream = stream;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<self::A*>* :for-iterator = new asy::_StreamIterator::•<self::A*>(:stream);
           try
@@ -162,7 +162,7 @@
             }
         }
         {
-          core::Iterator<self::A*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::A*>*>(self::f<core::Iterable<self::A*>*>()).{core::Iterable::iterator};
+          core::Iterator<self::A*>* :sync-for-iterator = self::f<core::Iterable<self::A*>*>().{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final self::A* #t18 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -171,7 +171,7 @@
           }
         }
         {
-          dynamic :stream = self::f<asy::Stream<self::A*>*>();
+          asy::Stream<self::A*>* :stream = self::f<asy::Stream<self::A*>*>();
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<self::A*>* :for-iterator = new asy::_StreamIterator::•<self::A*>(:stream);
           try
@@ -198,13 +198,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.expect
index e6998d8..0f7cb20 100644
--- a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.expect
@@ -11,7 +11,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  field invalid-type b = (() → () →* invalid-type => self::x) as{TypeError} invalid-type;
+  field invalid-type b = () → () →* invalid-type => self::x;
   field () →* () →* invalid-type c = () → () →* invalid-type => self::x;
   synthetic constructor •() → self::A*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.transformed.expect
index e6998d8..0f7cb20 100644
--- a/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref_circular.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  field invalid-type b = (() → () →* invalid-type => self::x) as{TypeError} invalid-type;
+  field invalid-type b = () → () →* invalid-type => self::x;
   field () →* () →* invalid-type c = () → () →* invalid-type => self::x;
   synthetic constructor •() → self::A*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.expect b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.expect
index d5891bf..276a1c2 100644
--- a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.expect
@@ -10,7 +10,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field invalid-type x = (() → () →* invalid-type => self::f() ?{() →* invalid-type} self::y : self::z) as{TypeError} invalid-type;
+static field invalid-type x = () → () →* invalid-type => self::f() ?{() →* invalid-type} self::y : self::z;
 static field () →* invalid-type y = () → invalid-type => self::x;
 static field () →* invalid-type z = () → invalid-type => self::x;
 static method f() → core::bool*
diff --git a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.transformed.expect
index d5891bf..276a1c2 100644
--- a/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/strongly_connected_component.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field invalid-type x = (() → () →* invalid-type => self::f() ?{() →* invalid-type} self::y : self::z) as{TypeError} invalid-type;
+static field invalid-type x = () → () →* invalid-type => self::f() ?{() →* invalid-type} self::y : self::z;
 static field () →* invalid-type y = () → invalid-type => self::x;
 static field () →* invalid-type z = () → invalid-type => self::x;
 static method f() → core::bool*
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect
index 3259378..38ca669 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect
@@ -21,7 +21,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(self::Class::_#nullableStaticField#isSet)
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
       self::Class::_#nullableStaticField#isSet = true;
@@ -33,7 +33,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(this.{self::Class::_#Class#nullableInstanceField#isSet})
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
       this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
@@ -51,7 +51,7 @@
   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 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::num::hashCode} : 0;
+    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;
     if(self::_#nullableTopLevelField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
     self::_#nullableTopLevelField#isSet = true;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect
index 3259378..38ca669 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(self::Class::_#nullableStaticField#isSet)
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
       self::Class::_#nullableStaticField#isSet = true;
@@ -33,7 +33,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(this.{self::Class::_#Class#nullableInstanceField#isSet})
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
       this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
@@ -51,7 +51,7 @@
   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 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::num::hashCode} : 0;
+    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;
     if(self::_#nullableTopLevelField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
     self::_#nullableTopLevelField#isSet = true;
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 3259378..38ca669 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
@@ -21,7 +21,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(self::Class::_#nullableStaticField#isSet)
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
       self::Class::_#nullableStaticField#isSet = true;
@@ -33,7 +33,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(this.{self::Class::_#Class#nullableInstanceField#isSet})
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
       this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
@@ -51,7 +51,7 @@
   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 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::num::hashCode} : 0;
+    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;
     if(self::_#nullableTopLevelField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
     self::_#nullableTopLevelField#isSet = true;
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 3259378..38ca669 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
@@ -21,7 +21,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(self::Class::_#nullableStaticField#isSet)
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
       self::Class::_#nullableStaticField#isSet = true;
@@ -33,7 +33,7 @@
     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 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::num::hashCode} : 0;
+      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;
       if(this.{self::Class::_#Class#nullableInstanceField#isSet})
         throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
       this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
@@ -51,7 +51,7 @@
   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 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::num::hashCode} : 0;
+    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;
     if(self::_#nullableTopLevelField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
     self::_#nullableTopLevelField#isSet = true;
diff --git a/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect
index 1f469d7..2787548 100644
--- a/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect
@@ -14,14 +14,13 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method error() → dynamic {
   for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
     core::print(i);
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int>[]).{core::Iterable::iterator};
+    core::Iterator<core::int*> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect
index 1f469d7..2787548 100644
--- a/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect
@@ -14,14 +14,13 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method error() → dynamic {
   for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
     core::print(i);
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int>[]).{core::Iterable::iterator};
+    core::Iterator<core::int*> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart
new file mode 100644
index 0000000..5ec6fd4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.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.
+
+import 'dart:test';
+
+main() {
+  A a;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.outline.expect
new file mode 100644
index 0000000..6c7f4d3
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.outline.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x;
+  synthetic constructor •() → self2::A
+    ;
+  get x() → core::int;
+  set x(core::int #t1) → void;
+}
+class _B extends core::Object implements self2::A {
+  field core::int x;
+  synthetic constructor •() → self2::_B
+    ;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.expect
new file mode 100644
index 0000000..139a488
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::A a;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{test::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements test::A {
+  field core::int x = 3;
+  synthetic constructor •() → test::_B
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.transformed.expect
new file mode 100644
index 0000000..139a488
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::A a;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{test::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements test::A {
+  field core::int x = 3;
+  synthetic constructor •() → test::_B
+    : super core::Object::•()
+    ;
+}
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
new file mode 100644
index 0000000..139a488
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::A a;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{test::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements test::A {
+  field core::int x = 3;
+  synthetic constructor •() → test::_B
+    : super core::Object::•()
+    ;
+}
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
new file mode 100644
index 0000000..139a488
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::A a;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{test::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements test::A {
+  field core::int x = 3;
+  synthetic constructor •() → test::_B
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/libraries.json b/pkg/front_end/testcases/late_lowering/issue41436/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/libraries.json
@@ -0,0 +1,12 @@
+{
+  "none": {
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/origin_lib.dart b/pkg/front_end/testcases/late_lowering/issue41436/origin_lib.dart
new file mode 100644
index 0000000..f223fd12
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/origin_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.
+
+abstract class A {
+  late int x;
+}
+
+class _B implements A {
+  int x = 3;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/patch_lib.dart b/pkg/front_end/testcases/late_lowering/issue41436/patch_lib.dart
new file mode 100644
index 0000000..a08c72e
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436/patch_lib.dart
@@ -0,0 +1,3 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart b/pkg/front_end/testcases/late_lowering/issue41436b.dart
new file mode 100644
index 0000000..2371d6c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.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.
+
+abstract class A {
+  late int x;
+}
+
+class _B implements A {
+  int x = 3;
+}
+
+main() {
+  A a;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.outline.expect
new file mode 100644
index 0000000..bdf7500
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.outline.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x;
+  synthetic constructor •() → self::A
+    ;
+  get x() → core::int;
+  set x(core::int #t1) → void;
+}
+class _B extends core::Object implements self::A {
+  field core::int x;
+  synthetic constructor •() → self::_B
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.expect
new file mode 100644
index 0000000..61c5d86
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{self::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements self::A {
+  field core::int x = 3;
+  synthetic constructor •() → self::_B
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::A a;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.transformed.expect
new file mode 100644
index 0000000..61c5d86
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{self::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements self::A {
+  field core::int x = 3;
+  synthetic constructor •() → self::_B
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::A a;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
new file mode 100644
index 0000000..61c5d86
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{self::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements self::A {
+  field core::int x = 3;
+  synthetic constructor •() → self::_B
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::A a;
+}
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
new file mode 100644
index 0000000..61c5d86
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{self::A::_#A#x} = #t2;
+}
+class _B extends core::Object implements self::A {
+  field core::int x = 3;
+  synthetic constructor •() → self::_B
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::A a;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart
new file mode 100644
index 0000000..ec85c08
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.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 'issue41436c_lib.dart';
+
+class C extends B {}
+
+main() {
+  new C();
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart
new file mode 100644
index 0000000..d7adb14
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_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.
+
+abstract class A {
+  late int x;
+}
+
+class B implements A {
+  int x = 3;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.outline.expect
new file mode 100644
index 0000000..de879f1
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.outline.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41436c_lib.dart" as iss;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue41436c_lib.dart";
+
+class C extends iss::B {
+  synthetic constructor •() → self::C
+    ;
+  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(#_#A#x, 1, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
+  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(#_#A#x=, 2, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
+}
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x;
+  synthetic constructor •() → iss::A
+    ;
+  get x() → core::int;
+  set x(core::int #t1) → void;
+}
+class B extends core::Object implements iss::A {
+  field core::int x;
+  synthetic constructor •() → iss::B
+    ;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.strong.expect
new file mode 100644
index 0000000..05bf5e3
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.strong.expect
@@ -0,0 +1,49 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41436c_lib.dart" as iss;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue41436c_lib.dart";
+
+class C extends iss::B {
+  synthetic constructor •() → self::C
+    : super iss::B::•()
+    ;
+  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?;
+  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)));
+}
+static method main() → dynamic {
+  new self::C::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{iss::A::_#A#x} = #t2;
+}
+class B extends core::Object implements iss::A {
+  field core::int x = 3;
+  synthetic constructor •() → iss::B
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
+  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.strong.transformed.expect
new file mode 100644
index 0000000..05bf5e3
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.strong.transformed.expect
@@ -0,0 +1,49 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41436c_lib.dart" as iss;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue41436c_lib.dart";
+
+class C extends iss::B {
+  synthetic constructor •() → self::C
+    : super iss::B::•()
+    ;
+  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?;
+  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)));
+}
+static method main() → dynamic {
+  new self::C::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{iss::A::_#A#x} = #t2;
+}
+class B extends core::Object implements iss::A {
+  field core::int x = 3;
+  synthetic constructor •() → iss::B
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
+  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.weak.expect
new file mode 100644
index 0000000..05bf5e3
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.weak.expect
@@ -0,0 +1,49 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41436c_lib.dart" as iss;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue41436c_lib.dart";
+
+class C extends iss::B {
+  synthetic constructor •() → self::C
+    : super iss::B::•()
+    ;
+  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?;
+  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)));
+}
+static method main() → dynamic {
+  new self::C::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{iss::A::_#A#x} = #t2;
+}
+class B extends core::Object implements iss::A {
+  field core::int x = 3;
+  synthetic constructor •() → iss::B
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
+  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.weak.transformed.expect
new file mode 100644
index 0000000..05bf5e3
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c_lib.dart.weak.transformed.expect
@@ -0,0 +1,49 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41436c_lib.dart" as iss;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue41436c_lib.dart";
+
+class C extends iss::B {
+  synthetic constructor •() → self::C
+    : super iss::B::•()
+    ;
+  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?;
+  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)));
+}
+static method main() → dynamic {
+  new self::C::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as iss;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#x = null;
+  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
+    this.{iss::A::_#A#x} = #t2;
+}
+class B extends core::Object implements iss::A {
+  field core::int x = 3;
+  synthetic constructor •() → iss::B
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
+  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/link.options b/pkg/front_end/testcases/late_lowering/issue41436c/link.options
new file mode 100644
index 0000000..8503704
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/link.options
@@ -0,0 +1 @@
+issue41436c_lib.dart
\ No newline at end of file
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 a0a1523..66413d4 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
@@ -122,7 +122,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String>["baz"]).{core::Iterable::iterator};
+    core::Iterator<core::String*> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -140,8 +140,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -153,7 +153,7 @@
       #L1:
       {
         {
-          dynamic :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String*>* :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
@@ -182,21 +182,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method fisk() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -223,8 +223,8 @@
             final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
             asy::FutureOr<dynamic>? :return_value;
             dynamic :async_stack_trace;
-            dynamic :async_op_then;
-            dynamic :async_op_error;
+            (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;
@@ -239,13 +239,13 @@
                 asy::_completeOnAsyncReturn(:async_completer, :return_value);
                 return;
               }
-              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+              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.start(: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
@@ -254,13 +254,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 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 a0a1523..66413d4 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
@@ -122,7 +122,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String>["baz"]).{core::Iterable::iterator};
+    core::Iterator<core::String*> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -140,8 +140,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -153,7 +153,7 @@
       #L1:
       {
         {
-          dynamic :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String*>* :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
@@ -182,21 +182,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method fisk() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -223,8 +223,8 @@
             final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
             asy::FutureOr<dynamic>? :return_value;
             dynamic :async_stack_trace;
-            dynamic :async_op_then;
-            dynamic :async_op_error;
+            (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;
@@ -239,13 +239,13 @@
                 asy::_completeOnAsyncReturn(:async_completer, :return_value);
                 return;
               }
-              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+              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.start(: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
@@ -254,13 +254,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart
new file mode 100644
index 0000000..54eb0eb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.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.
+
+// @dart=2.6
+
+import 'bounds_from_opt_in_lib.dart';
+
+class LegacyClass<T extends Null> extends Class<T> {
+  method<T extends Null>() {}
+}
+
+test() {
+  Class<Null> c = new Class<Null>();
+  c.method<Null>();
+  method<Null>();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.outline.expect
new file mode 100644
index 0000000..695900a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "bounds_from_opt_in_lib.dart" as bou;
+
+import "org-dartlang-testcase:///bounds_from_opt_in_lib.dart";
+
+class LegacyClass<T extends core::Null? = core::Null?> extends bou::Class<self::LegacyClass::T*> {
+  synthetic constructor •() → self::LegacyClass<self::LegacyClass::T*>*
+    ;
+  method method<T extends core::Null? = core::Null?>() → dynamic
+    ;
+}
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as bou;
+import "dart:core" as core;
+
+class Class<T extends Never = Never> extends core::Object {
+  synthetic constructor •() → bou::Class<bou::Class::T>
+    ;
+  method method<T extends Never = Never>() → dynamic
+    ;
+}
+static method method<T extends Never = Never>() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.strong.expect
new file mode 100644
index 0000000..45d24f4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.strong.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "bounds_from_opt_in_lib.dart" as bou;
+
+import "org-dartlang-testcase:///bounds_from_opt_in_lib.dart";
+
+class LegacyClass<T extends core::Null? = core::Null?> extends bou::Class<self::LegacyClass::T*> {
+  synthetic constructor •() → self::LegacyClass<self::LegacyClass::T*>*
+    : super bou::Class::•()
+    ;
+  method method<T extends core::Null? = core::Null?>() → dynamic {}
+}
+static method test() → dynamic {
+  bou::Class<core::Null?>* c = new bou::Class::•<core::Null?>();
+  c.{bou::Class::method}<core::Null?>();
+  bou::method<core::Null?>();
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as bou;
+import "dart:core" as core;
+
+class Class<T extends Never = Never> extends core::Object {
+  synthetic constructor •() → bou::Class<bou::Class::T>
+    : super core::Object::•()
+    ;
+  method method<T extends Never = Never>() → dynamic {}
+}
+static method method<T extends Never = Never>() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..45d24f4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "bounds_from_opt_in_lib.dart" as bou;
+
+import "org-dartlang-testcase:///bounds_from_opt_in_lib.dart";
+
+class LegacyClass<T extends core::Null? = core::Null?> extends bou::Class<self::LegacyClass::T*> {
+  synthetic constructor •() → self::LegacyClass<self::LegacyClass::T*>*
+    : super bou::Class::•()
+    ;
+  method method<T extends core::Null? = core::Null?>() → dynamic {}
+}
+static method test() → dynamic {
+  bou::Class<core::Null?>* c = new bou::Class::•<core::Null?>();
+  c.{bou::Class::method}<core::Null?>();
+  bou::method<core::Null?>();
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as bou;
+import "dart:core" as core;
+
+class Class<T extends Never = Never> extends core::Object {
+  synthetic constructor •() → bou::Class<bou::Class::T>
+    : super core::Object::•()
+    ;
+  method method<T extends Never = Never>() → dynamic {}
+}
+static method method<T extends Never = Never>() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..45d24f4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.weak.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "bounds_from_opt_in_lib.dart" as bou;
+
+import "org-dartlang-testcase:///bounds_from_opt_in_lib.dart";
+
+class LegacyClass<T extends core::Null? = core::Null?> extends bou::Class<self::LegacyClass::T*> {
+  synthetic constructor •() → self::LegacyClass<self::LegacyClass::T*>*
+    : super bou::Class::•()
+    ;
+  method method<T extends core::Null? = core::Null?>() → dynamic {}
+}
+static method test() → dynamic {
+  bou::Class<core::Null?>* c = new bou::Class::•<core::Null?>();
+  c.{bou::Class::method}<core::Null?>();
+  bou::method<core::Null?>();
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as bou;
+import "dart:core" as core;
+
+class Class<T extends Never = Never> extends core::Object {
+  synthetic constructor •() → bou::Class<bou::Class::T>
+    : super core::Object::•()
+    ;
+  method method<T extends Never = Never>() → dynamic {}
+}
+static method method<T extends Never = Never>() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..45d24f4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/bounds_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "bounds_from_opt_in_lib.dart" as bou;
+
+import "org-dartlang-testcase:///bounds_from_opt_in_lib.dart";
+
+class LegacyClass<T extends core::Null? = core::Null?> extends bou::Class<self::LegacyClass::T*> {
+  synthetic constructor •() → self::LegacyClass<self::LegacyClass::T*>*
+    : super bou::Class::•()
+    ;
+  method method<T extends core::Null? = core::Null?>() → dynamic {}
+}
+static method test() → dynamic {
+  bou::Class<core::Null?>* c = new bou::Class::•<core::Null?>();
+  c.{bou::Class::method}<core::Null?>();
+  bou::method<core::Null?>();
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as bou;
+import "dart:core" as core;
+
+class Class<T extends Never = Never> extends core::Object {
+  synthetic constructor •() → bou::Class<bou::Class::T>
+    : super core::Object::•()
+    ;
+  method method<T extends Never = Never>() → dynamic {}
+}
+static method method<T extends Never = Never>() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/bounds_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd/bounds_from_opt_in_lib.dart
new file mode 100644
index 0000000..cddbf37
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/bounds_from_opt_in_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 Class<T extends Never> {
+  method<T extends Never>() {}
+}
+
+method<T extends Never>() {}
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart b/pkg/front_end/testcases/nnbd/constant_null_is.dart
new file mode 100644
index 0000000..fa999f7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.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:async';
+import 'constant_null_is_lib.dart';
+
+const c0 = null is int?;
+const c1 = null is int;
+const c2 = null is Null;
+const c3 = null is Never?;
+const c4 = null is Never;
+const c5 = null is FutureOr<int?>;
+const c6 = null is FutureOr<int>;
+const c7 = null is FutureOr<int>?;
+const c8 = null is FutureOr<Null>;
+const c9 = null is FutureOr<Null>?;
+const c10 = null is FutureOr<Never>;
+const c11 = null is FutureOr<Never?>;
+const c12 = null is FutureOr<Never>?;
+
+main() {
+  expect(null is int?, c0, "null is int?");
+  expect(null is int, c1, "null is int");
+  expect(null is Null, c2, "null is Null");
+  expect(null is Never?, c3, "null is Never?");
+  expect(null is Never, c4, "null is Never");
+  expect(null is FutureOr<int?>, c5, "null is FutureOr<int?>");
+  expect(null is FutureOr<int>, c6, "null is FutureOr<int>");
+  expect(null is FutureOr<int>?, c7, "null is FutureOr<int>?");
+  expect(null is FutureOr<Null>, c8, "null is FutureOr<Null>");
+  expect(null is FutureOr<Null>?, c9, "null is FutureOr<Null>?");
+  expect(null is FutureOr<Never>, c10, "null is FutureOr<Never>");
+  expect(null is FutureOr<Never?>, c11, "null is FutureOr<Never?>");
+  expect(null is FutureOr<Never>?, c12, "null is FutureOr<Never>?");
+  test();
+}
+
+expect(expected, actual, String message) {
+  if (expected != actual)
+    throw 'Expected $expected, actual $actual for $message';
+}
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
new file mode 100644
index 0000000..9a984f8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is_lib.dart";
+
+static const field core::bool c0 = null is{ForNonNullableByDefault} core::int?;
+static const field core::bool c1 = null is{ForNonNullableByDefault} core::int;
+static const field core::bool c2 = null is{ForNonNullableByDefault} core::Null?;
+static const field core::bool c3 = null is{ForNonNullableByDefault} Never?;
+static const field core::bool c4 = null is{ForNonNullableByDefault} Never;
+static const field core::bool c5 = null is{ForNonNullableByDefault} asy::FutureOr<core::int?>;
+static const field core::bool c6 = null is{ForNonNullableByDefault} asy::FutureOr<core::int>;
+static const field core::bool c7 = null is{ForNonNullableByDefault} asy::FutureOr<core::int>?;
+static const field core::bool c8 = null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>;
+static const field core::bool c9 = null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>?;
+static const field core::bool c10 = null is{ForNonNullableByDefault} asy::FutureOr<Never>;
+static const field core::bool c11 = null is{ForNonNullableByDefault} asy::FutureOr<Never?>;
+static const field core::bool c12 = null is{ForNonNullableByDefault} asy::FutureOr<Never>?;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual, core::String message) → dynamic
+  ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is.dart";
+
+static const field core::bool* d0 = null is core::int*;
+static const field core::bool* d1 = null is core::Null?;
+static method test() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.expect
new file mode 100644
index 0000000..6490709
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "constant_null_is_lib.dart" as con;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is_lib.dart";
+
+static const field core::bool c0 = #C1;
+static const field core::bool c1 = #C2;
+static const field core::bool c2 = #C1;
+static const field core::bool c3 = #C1;
+static const field core::bool c4 = #C2;
+static const field core::bool c5 = #C1;
+static const field core::bool c6 = #C2;
+static const field core::bool c7 = #C1;
+static const field core::bool c8 = #C1;
+static const field core::bool c9 = #C1;
+static const field core::bool c10 = #C2;
+static const field core::bool c11 = #C1;
+static const field core::bool c12 = #C1;
+static method main() → dynamic {
+  self::expect(null is{ForNonNullableByDefault} core::int?, #C1, "null is int?");
+  self::expect(null is{ForNonNullableByDefault} core::int, #C2, "null is int");
+  self::expect(null is{ForNonNullableByDefault} core::Null?, #C1, "null is Null");
+  self::expect(null is{ForNonNullableByDefault} Never?, #C1, "null is Never?");
+  self::expect(null is{ForNonNullableByDefault} Never, #C2, "null is Never");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int?>, #C1, "null is FutureOr<int?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>, #C2, "null is FutureOr<int>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>?, #C1, "null is FutureOr<int>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>, #C1, "null is FutureOr<Null>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>?, #C1, "null is FutureOr<Null>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>, #C2, "null is FutureOr<Never>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never?>, #C1, "null is FutureOr<Never?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>?, #C1, "null is FutureOr<Never>?");
+  con::test();
+}
+static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual} for ${message}";
+}
+
+library;
+import self as con;
+import "constant_null_is.dart" as self;
+import "dart:core" as core;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is.dart";
+
+static const field core::bool* d0 = #C2;
+static const field core::bool* d1 = #C1;
+static method test() → dynamic {
+  self::expect(null is core::int*, #C2, "null is int (opt-out)");
+  self::expect(null is core::Null?, #C1, "null is Null");
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+}
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
new file mode 100644
index 0000000..6490709
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "constant_null_is_lib.dart" as con;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is_lib.dart";
+
+static const field core::bool c0 = #C1;
+static const field core::bool c1 = #C2;
+static const field core::bool c2 = #C1;
+static const field core::bool c3 = #C1;
+static const field core::bool c4 = #C2;
+static const field core::bool c5 = #C1;
+static const field core::bool c6 = #C2;
+static const field core::bool c7 = #C1;
+static const field core::bool c8 = #C1;
+static const field core::bool c9 = #C1;
+static const field core::bool c10 = #C2;
+static const field core::bool c11 = #C1;
+static const field core::bool c12 = #C1;
+static method main() → dynamic {
+  self::expect(null is{ForNonNullableByDefault} core::int?, #C1, "null is int?");
+  self::expect(null is{ForNonNullableByDefault} core::int, #C2, "null is int");
+  self::expect(null is{ForNonNullableByDefault} core::Null?, #C1, "null is Null");
+  self::expect(null is{ForNonNullableByDefault} Never?, #C1, "null is Never?");
+  self::expect(null is{ForNonNullableByDefault} Never, #C2, "null is Never");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int?>, #C1, "null is FutureOr<int?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>, #C2, "null is FutureOr<int>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>?, #C1, "null is FutureOr<int>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>, #C1, "null is FutureOr<Null>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>?, #C1, "null is FutureOr<Null>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>, #C2, "null is FutureOr<Never>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never?>, #C1, "null is FutureOr<Never?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>?, #C1, "null is FutureOr<Never>?");
+  con::test();
+}
+static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual} for ${message}";
+}
+
+library;
+import self as con;
+import "constant_null_is.dart" as self;
+import "dart:core" as core;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is.dart";
+
+static const field core::bool* d0 = #C2;
+static const field core::bool* d1 = #C1;
+static method test() → dynamic {
+  self::expect(null is core::int*, #C2, "null is int (opt-out)");
+  self::expect(null is core::Null?, #C1, "null is Null");
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+}
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.expect
new file mode 100644
index 0000000..6490709
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "constant_null_is_lib.dart" as con;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is_lib.dart";
+
+static const field core::bool c0 = #C1;
+static const field core::bool c1 = #C2;
+static const field core::bool c2 = #C1;
+static const field core::bool c3 = #C1;
+static const field core::bool c4 = #C2;
+static const field core::bool c5 = #C1;
+static const field core::bool c6 = #C2;
+static const field core::bool c7 = #C1;
+static const field core::bool c8 = #C1;
+static const field core::bool c9 = #C1;
+static const field core::bool c10 = #C2;
+static const field core::bool c11 = #C1;
+static const field core::bool c12 = #C1;
+static method main() → dynamic {
+  self::expect(null is{ForNonNullableByDefault} core::int?, #C1, "null is int?");
+  self::expect(null is{ForNonNullableByDefault} core::int, #C2, "null is int");
+  self::expect(null is{ForNonNullableByDefault} core::Null?, #C1, "null is Null");
+  self::expect(null is{ForNonNullableByDefault} Never?, #C1, "null is Never?");
+  self::expect(null is{ForNonNullableByDefault} Never, #C2, "null is Never");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int?>, #C1, "null is FutureOr<int?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>, #C2, "null is FutureOr<int>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>?, #C1, "null is FutureOr<int>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>, #C1, "null is FutureOr<Null>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>?, #C1, "null is FutureOr<Null>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>, #C2, "null is FutureOr<Never>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never?>, #C1, "null is FutureOr<Never?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>?, #C1, "null is FutureOr<Never>?");
+  con::test();
+}
+static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual} for ${message}";
+}
+
+library;
+import self as con;
+import "constant_null_is.dart" as self;
+import "dart:core" as core;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is.dart";
+
+static const field core::bool* d0 = #C2;
+static const field core::bool* d1 = #C1;
+static method test() → dynamic {
+  self::expect(null is core::int*, #C2, "null is int (opt-out)");
+  self::expect(null is core::Null?, #C1, "null is Null");
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+}
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
new file mode 100644
index 0000000..6490709
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "constant_null_is_lib.dart" as con;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is_lib.dart";
+
+static const field core::bool c0 = #C1;
+static const field core::bool c1 = #C2;
+static const field core::bool c2 = #C1;
+static const field core::bool c3 = #C1;
+static const field core::bool c4 = #C2;
+static const field core::bool c5 = #C1;
+static const field core::bool c6 = #C2;
+static const field core::bool c7 = #C1;
+static const field core::bool c8 = #C1;
+static const field core::bool c9 = #C1;
+static const field core::bool c10 = #C2;
+static const field core::bool c11 = #C1;
+static const field core::bool c12 = #C1;
+static method main() → dynamic {
+  self::expect(null is{ForNonNullableByDefault} core::int?, #C1, "null is int?");
+  self::expect(null is{ForNonNullableByDefault} core::int, #C2, "null is int");
+  self::expect(null is{ForNonNullableByDefault} core::Null?, #C1, "null is Null");
+  self::expect(null is{ForNonNullableByDefault} Never?, #C1, "null is Never?");
+  self::expect(null is{ForNonNullableByDefault} Never, #C2, "null is Never");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int?>, #C1, "null is FutureOr<int?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>, #C2, "null is FutureOr<int>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::int>?, #C1, "null is FutureOr<int>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>, #C1, "null is FutureOr<Null>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<core::Null?>?, #C1, "null is FutureOr<Null>?");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>, #C2, "null is FutureOr<Never>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never?>, #C1, "null is FutureOr<Never?>");
+  self::expect(null is{ForNonNullableByDefault} asy::FutureOr<Never>?, #C1, "null is FutureOr<Never>?");
+  con::test();
+}
+static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual} for ${message}";
+}
+
+library;
+import self as con;
+import "constant_null_is.dart" as self;
+import "dart:core" as core;
+
+import "dart:async";
+import "org-dartlang-testcase:///constant_null_is.dart";
+
+static const field core::bool* d0 = #C2;
+static const field core::bool* d1 = #C1;
+static method test() → dynamic {
+  self::expect(null is core::int*, #C2, "null is int (opt-out)");
+  self::expect(null is core::Null?, #C1, "null is Null");
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+}
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is_lib.dart b/pkg/front_end/testcases/nnbd/constant_null_is_lib.dart
new file mode 100644
index 0000000..16b98a5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/constant_null_is_lib.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.6
+
+import 'dart:async';
+import 'constant_null_is.dart';
+
+const d0 = null is int;
+const d1 = null is Null;
+//const d2 = null is FutureOr<Null>;
+//const d3 = null is Never;
+
+test() {
+  expect(null is int, d0, "null is int (opt-out)");
+  expect(null is Null, d1, "null is Null");
+  //expect(null is FutureOr<Null>, d2, "null is FutureOr<Null> (opt-out)");
+  //expect(null is Never, d3, "null is Never (opt-out)");
+}
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart b/pkg/front_end/testcases/nnbd/covariant_equals.dart
new file mode 100644
index 0000000..bcb77b7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.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.
+
+class A {
+  bool operator ==(covariant A other) => true;
+}
+
+class B extends A {
+  bool operator ==(other) => true;
+}
+
+class C<T> {
+  bool operator ==(covariant C<T> other) => true;
+}
+
+class D extends C<int> {}
+
+main() {}
+
+testNonNullable(A a, B b, C c_dynamic, C<int> c_int, C<String> c_string, D d) {
+  a == a; // ok
+  a == b; // ok
+  a == c_dynamic; // error
+  a == c_int; // error
+  a == c_string; // error
+  a == d; // error
+
+  b == a; // ok
+  b == b; // ok
+  b == c_dynamic; // error
+  b == c_int; // error
+  b == c_string; // error
+  b == d; // error
+
+  c_dynamic == a; // error
+  c_dynamic == b; // error
+  c_dynamic == c_dynamic; // ok
+  c_dynamic == c_int; // ok
+  c_dynamic == c_string; // ok
+  c_dynamic == d; // ok
+
+  c_int == a; // error
+  c_int == b; // error
+  c_int == c_dynamic; // error
+  c_int == c_int; // ok
+  c_int == c_string; // error
+  c_int == d; // ok}
+
+  c_string == a; // error
+  c_string == b; // error
+  c_string == c_dynamic; // error
+  c_string == c_int; // error
+  c_string == c_string; // ok
+  c_string == d; // error
+
+  d == a; // error
+  d == b; // error
+  d == c_dynamic; // error
+  d == c_int; // ok
+  d == c_string; // error
+  d == d; // ok
+}
+
+testNullable(
+    A? a, B? b, C? c_dynamic, C<int>? c_int, C<String>? c_string, D? d) {
+  // Since the receiver type is nullable, the calls are checked against the
+  // Object member.
+
+  a == a; // ok
+  a == b; // ok
+  a == c_dynamic; // ok
+  a == c_int; // ok
+  a == c_string; // ok
+  a == d; // ok
+
+  b == a; // ok
+  b == b; // ok
+  b == c_dynamic; // ok
+  b == c_int; // ok
+  b == c_string; // ok
+  b == d; // ok
+
+  c_dynamic == a; // ok
+  c_dynamic == b; // ok
+  c_dynamic == c_dynamic; // ok
+  c_dynamic == c_int; // ok
+  c_dynamic == c_string; // ok
+  c_dynamic == d; // ok
+
+  c_int == a; // ok
+  c_int == b; // ok
+  c_int == c_dynamic; // ok
+  c_int == c_int; // ok
+  c_int == c_string; // ok
+  c_int == d; // ok}
+
+  c_string == a; // ok
+  c_string == b; // ok
+  c_string == c_dynamic; // ok
+  c_string == c_int; // ok
+  c_string == c_string; // ok
+  c_string == d; // ok
+
+  d == a; // ok
+  d == b; // ok
+  d == c_dynamic; // ok
+  d == c_int; // ok
+  d == c_string; // ok
+  d == d; // ok
+}
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.outline.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.outline.expect
new file mode 100644
index 0000000..7ead045
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.outline.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  operator ==(covariant self::A other) → core::bool
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    ;
+  operator ==(covariant self::A other) → core::bool
+    ;
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T%> other) → core::bool
+    ;
+}
+class D extends self::C<core::int> {
+  synthetic constructor •() → self::D
+    ;
+}
+static method main() → dynamic
+  ;
+static method testNonNullable(self::A a, self::B b, self::C<dynamic> c_dynamic, self::C<core::int> c_int, self::C<core::String> c_string, self::D d) → dynamic
+  ;
+static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.expect
new file mode 100644
index 0000000..93ef34b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.expect
@@ -0,0 +1,328 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T%> other) → core::bool
+    return true;
+}
+class D extends self::C<core::int> {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method testNonNullable(self::A a, self::B b, self::C<dynamic> c_dynamic, self::C<core::int> c_int, self::C<core::String> c_string, self::D d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // error
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // error
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
+}
+static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
+  a.{core::Object::==}(a);
+  a.{core::Object::==}(b);
+  a.{core::Object::==}(c_dynamic);
+  a.{core::Object::==}(c_int);
+  a.{core::Object::==}(c_string);
+  a.{core::Object::==}(d);
+  b.{core::Object::==}(a);
+  b.{core::Object::==}(b);
+  b.{core::Object::==}(c_dynamic);
+  b.{core::Object::==}(c_int);
+  b.{core::Object::==}(c_string);
+  b.{core::Object::==}(d);
+  c_dynamic.{core::Object::==}(a);
+  c_dynamic.{core::Object::==}(b);
+  c_dynamic.{core::Object::==}(c_dynamic);
+  c_dynamic.{core::Object::==}(c_int);
+  c_dynamic.{core::Object::==}(c_string);
+  c_dynamic.{core::Object::==}(d);
+  c_int.{core::Object::==}(a);
+  c_int.{core::Object::==}(b);
+  c_int.{core::Object::==}(c_dynamic);
+  c_int.{core::Object::==}(c_int);
+  c_int.{core::Object::==}(c_string);
+  c_int.{core::Object::==}(d);
+  c_string.{core::Object::==}(a);
+  c_string.{core::Object::==}(b);
+  c_string.{core::Object::==}(c_dynamic);
+  c_string.{core::Object::==}(c_int);
+  c_string.{core::Object::==}(c_string);
+  c_string.{core::Object::==}(d);
+  d.{core::Object::==}(a);
+  d.{core::Object::==}(b);
+  d.{core::Object::==}(c_dynamic);
+  d.{core::Object::==}(c_int);
+  d.{core::Object::==}(c_string);
+  d.{core::Object::==}(d);
+}
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.transformed.expect
new file mode 100644
index 0000000..93ef34b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.transformed.expect
@@ -0,0 +1,328 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T%> other) → core::bool
+    return true;
+}
+class D extends self::C<core::int> {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method testNonNullable(self::A a, self::B b, self::C<dynamic> c_dynamic, self::C<core::int> c_int, self::C<core::String> c_string, self::D d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // error
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // error
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
+}
+static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
+  a.{core::Object::==}(a);
+  a.{core::Object::==}(b);
+  a.{core::Object::==}(c_dynamic);
+  a.{core::Object::==}(c_int);
+  a.{core::Object::==}(c_string);
+  a.{core::Object::==}(d);
+  b.{core::Object::==}(a);
+  b.{core::Object::==}(b);
+  b.{core::Object::==}(c_dynamic);
+  b.{core::Object::==}(c_int);
+  b.{core::Object::==}(c_string);
+  b.{core::Object::==}(d);
+  c_dynamic.{core::Object::==}(a);
+  c_dynamic.{core::Object::==}(b);
+  c_dynamic.{core::Object::==}(c_dynamic);
+  c_dynamic.{core::Object::==}(c_int);
+  c_dynamic.{core::Object::==}(c_string);
+  c_dynamic.{core::Object::==}(d);
+  c_int.{core::Object::==}(a);
+  c_int.{core::Object::==}(b);
+  c_int.{core::Object::==}(c_dynamic);
+  c_int.{core::Object::==}(c_int);
+  c_int.{core::Object::==}(c_string);
+  c_int.{core::Object::==}(d);
+  c_string.{core::Object::==}(a);
+  c_string.{core::Object::==}(b);
+  c_string.{core::Object::==}(c_dynamic);
+  c_string.{core::Object::==}(c_int);
+  c_string.{core::Object::==}(c_string);
+  c_string.{core::Object::==}(d);
+  d.{core::Object::==}(a);
+  d.{core::Object::==}(b);
+  d.{core::Object::==}(c_dynamic);
+  d.{core::Object::==}(c_int);
+  d.{core::Object::==}(c_string);
+  d.{core::Object::==}(d);
+}
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.expect
new file mode 100644
index 0000000..93ef34b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.expect
@@ -0,0 +1,328 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T%> other) → core::bool
+    return true;
+}
+class D extends self::C<core::int> {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method testNonNullable(self::A a, self::B b, self::C<dynamic> c_dynamic, self::C<core::int> c_int, self::C<core::String> c_string, self::D d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // error
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // error
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
+}
+static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
+  a.{core::Object::==}(a);
+  a.{core::Object::==}(b);
+  a.{core::Object::==}(c_dynamic);
+  a.{core::Object::==}(c_int);
+  a.{core::Object::==}(c_string);
+  a.{core::Object::==}(d);
+  b.{core::Object::==}(a);
+  b.{core::Object::==}(b);
+  b.{core::Object::==}(c_dynamic);
+  b.{core::Object::==}(c_int);
+  b.{core::Object::==}(c_string);
+  b.{core::Object::==}(d);
+  c_dynamic.{core::Object::==}(a);
+  c_dynamic.{core::Object::==}(b);
+  c_dynamic.{core::Object::==}(c_dynamic);
+  c_dynamic.{core::Object::==}(c_int);
+  c_dynamic.{core::Object::==}(c_string);
+  c_dynamic.{core::Object::==}(d);
+  c_int.{core::Object::==}(a);
+  c_int.{core::Object::==}(b);
+  c_int.{core::Object::==}(c_dynamic);
+  c_int.{core::Object::==}(c_int);
+  c_int.{core::Object::==}(c_string);
+  c_int.{core::Object::==}(d);
+  c_string.{core::Object::==}(a);
+  c_string.{core::Object::==}(b);
+  c_string.{core::Object::==}(c_dynamic);
+  c_string.{core::Object::==}(c_int);
+  c_string.{core::Object::==}(c_string);
+  c_string.{core::Object::==}(d);
+  d.{core::Object::==}(a);
+  d.{core::Object::==}(b);
+  d.{core::Object::==}(c_dynamic);
+  d.{core::Object::==}(c_int);
+  d.{core::Object::==}(c_string);
+  d.{core::Object::==}(d);
+}
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.transformed.expect
new file mode 100644
index 0000000..93ef34b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.transformed.expect
@@ -0,0 +1,328 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // error
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // error
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // error
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // error
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A other) → core::bool
+    return true;
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T%> other) → core::bool
+    return true;
+}
+class D extends self::C<core::int> {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
+static method testNonNullable(self::A a, self::B b, self::C<dynamic> c_dynamic, self::C<core::int> c_int, self::C<core::String> c_string, self::D d) → dynamic {
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:24:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:25:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:26:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:27:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:31:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:32:8: Error: The argument type 'C<int>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // error
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:33:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:34:8: Error: The argument type 'D' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // error
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:36:16: Error: The argument type 'A' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // error
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:37:16: Error: The argument type 'B' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // error
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:43:12: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // error
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:44:12: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // error
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:45:12: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // error
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:47:12: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // error
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:50:15: Error: The argument type 'A' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // error
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:51:15: Error: The argument type 'B' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // error
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:52:15: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // error
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:53:15: Error: The argument type 'C<int>' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // error
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:55:15: Error: The argument type 'D' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // error
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:57:8: Error: The argument type 'A' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // error
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:58:8: Error: The argument type 'B' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // error
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:59:8: Error: The argument type 'C<dynamic>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // error
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:61:8: Error: The argument type 'C<String>' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // error
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
+}
+static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
+  a.{core::Object::==}(a);
+  a.{core::Object::==}(b);
+  a.{core::Object::==}(c_dynamic);
+  a.{core::Object::==}(c_int);
+  a.{core::Object::==}(c_string);
+  a.{core::Object::==}(d);
+  b.{core::Object::==}(a);
+  b.{core::Object::==}(b);
+  b.{core::Object::==}(c_dynamic);
+  b.{core::Object::==}(c_int);
+  b.{core::Object::==}(c_string);
+  b.{core::Object::==}(d);
+  c_dynamic.{core::Object::==}(a);
+  c_dynamic.{core::Object::==}(b);
+  c_dynamic.{core::Object::==}(c_dynamic);
+  c_dynamic.{core::Object::==}(c_int);
+  c_dynamic.{core::Object::==}(c_string);
+  c_dynamic.{core::Object::==}(d);
+  c_int.{core::Object::==}(a);
+  c_int.{core::Object::==}(b);
+  c_int.{core::Object::==}(c_dynamic);
+  c_int.{core::Object::==}(c_int);
+  c_int.{core::Object::==}(c_string);
+  c_int.{core::Object::==}(d);
+  c_string.{core::Object::==}(a);
+  c_string.{core::Object::==}(b);
+  c_string.{core::Object::==}(c_dynamic);
+  c_string.{core::Object::==}(c_int);
+  c_string.{core::Object::==}(c_string);
+  c_string.{core::Object::==}(d);
+  d.{core::Object::==}(a);
+  d.{core::Object::==}(b);
+  d.{core::Object::==}(c_dynamic);
+  d.{core::Object::==}(c_int);
+  d.{core::Object::==}(c_string);
+  d.{core::Object::==}(d);
+}
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
index b65a75c..0b1f6c0 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
@@ -50,11 +50,10 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method error(core::Iterable<core::int>? i2, core::List<core::int>? l2, core::Object o1, core::Object? o2) → dynamic {
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   for (int x in i2) x;
                 ^" in i2 as{TypeError,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
@@ -66,7 +65,7 @@
   block {
     final core::List<core::int> #t2 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in i2) x];
                  ^" in i2 as{TypeError,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
@@ -77,7 +76,7 @@
     }
   } =>#t2;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'List' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   for (int x in l2) x;
@@ -90,7 +89,7 @@
   block {
     final core::List<core::int> #t5 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'List' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in l2) x];
@@ -102,7 +101,7 @@
     }
   } =>#t5;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   for (int x in o1) x;
@@ -118,7 +117,7 @@
   block {
     final core::List<core::int> #t9 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in o1) x];
@@ -133,7 +132,7 @@
     }
   } =>#t9;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   for (int x in o2) x;
@@ -149,7 +148,7 @@
   block {
     final core::List<core::int> #t14 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in o2) x];
@@ -166,7 +165,7 @@
 }
 static method ok(core::Iterable<core::int> i1, core::List<core::int> l1, dynamic d) → dynamic {
   {
-    core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+    core::Iterator<core::int> :sync-for-iterator = i1.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int x = :sync-for-iterator.{core::Iterator::current};
       x;
@@ -175,7 +174,7 @@
   block {
     final core::List<core::int> #t17 = <core::int>[];
     {
-      core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+      core::Iterator<core::int> :sync-for-iterator = i1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int x = :sync-for-iterator.{core::Iterator::current};
         #t17.{core::List::add}(x);
@@ -183,7 +182,7 @@
     }
   } =>#t17;
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+    core::Iterator<core::int*> :sync-for-iterator = l1.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int x = :sync-for-iterator.{core::Iterator::current};
       x;
@@ -192,7 +191,7 @@
   block {
     final core::List<core::int> #t18 = <core::int>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+      core::Iterator<core::int*> :sync-for-iterator = l1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int x = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::List::add}(x);
@@ -200,7 +199,7 @@
     }
   } =>#t18;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
+    core::Iterator<dynamic> :sync-for-iterator = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t19 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -212,7 +211,7 @@
   block {
     final core::List<core::int> #t20 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
+      core::Iterator<dynamic> :sync-for-iterator = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t21 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
index b65a75c..0b1f6c0 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
@@ -50,11 +50,10 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method error(core::Iterable<core::int>? i2, core::List<core::int>? l2, core::Object o1, core::Object? o2) → dynamic {
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   for (int x in i2) x;
                 ^" in i2 as{TypeError,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
@@ -66,7 +65,7 @@
   block {
     final core::List<core::int> #t2 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in i2) x];
                  ^" in i2 as{TypeError,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
@@ -77,7 +76,7 @@
     }
   } =>#t2;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'List' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   for (int x in l2) x;
@@ -90,7 +89,7 @@
   block {
     final core::List<core::int> #t5 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'List' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in l2) x];
@@ -102,7 +101,7 @@
     }
   } =>#t5;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   for (int x in o1) x;
@@ -118,7 +117,7 @@
   block {
     final core::List<core::int> #t9 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in o1) x];
@@ -133,7 +132,7 @@
     }
   } =>#t9;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+    core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   for (int x in o2) x;
@@ -149,7 +148,7 @@
   block {
     final core::List<core::int> #t14 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+      core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
  - 'Iterable' is from 'dart:core'.
   [for (int x in o2) x];
@@ -166,7 +165,7 @@
 }
 static method ok(core::Iterable<core::int> i1, core::List<core::int> l1, dynamic d) → dynamic {
   {
-    core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+    core::Iterator<core::int> :sync-for-iterator = i1.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int x = :sync-for-iterator.{core::Iterator::current};
       x;
@@ -175,7 +174,7 @@
   block {
     final core::List<core::int> #t17 = <core::int>[];
     {
-      core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+      core::Iterator<core::int> :sync-for-iterator = i1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int x = :sync-for-iterator.{core::Iterator::current};
         #t17.{core::List::add}(x);
@@ -183,7 +182,7 @@
     }
   } =>#t17;
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+    core::Iterator<core::int*> :sync-for-iterator = l1.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int x = :sync-for-iterator.{core::Iterator::current};
       x;
@@ -192,7 +191,7 @@
   block {
     final core::List<core::int> #t18 = <core::int>[];
     {
-      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+      core::Iterator<core::int*> :sync-for-iterator = l1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int x = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::List::add}(x);
@@ -200,7 +199,7 @@
     }
   } =>#t18;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
+    core::Iterator<dynamic> :sync-for-iterator = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t19 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -212,7 +211,7 @@
   block {
     final core::List<core::int> #t20 = <core::int>[];
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
+      core::Iterator<dynamic> :sync-for-iterator = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t21 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
index 83177be..d1038a3 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
@@ -14,14 +14,13 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method error() → dynamic {
   for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
     core::print(i);
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int>[]).{core::Iterable::iterator};
+    core::Iterator<core::int*> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
index 83177be..d1038a3 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
@@ -14,14 +14,13 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method error() → dynamic {
   for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
     core::print(i);
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int>[]).{core::Iterable::iterator};
+    core::Iterator<core::int*> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart b/pkg/front_end/testcases/nnbd/issue41114.dart
new file mode 100644
index 0000000..7db889f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41114.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.
+
+main() async {
+  List<String>? a = <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.outline.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.outline.expect
new file mode 100644
index 0000000..e2cba6b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.outline.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
new file mode 100644
index 0000000..0354e2d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic async {
+  core::List<core::String>? a = <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.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
new file mode 100644
index 0000000..22f3911
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::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:
+      {
+        core::List<core::String>? a = <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);
+      }
+      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/nnbd/issue41114.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
new file mode 100644
index 0000000..0354e2d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic async {
+  core::List<core::String>? a = <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.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
new file mode 100644
index 0000000..22f3911
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::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:
+      {
+        core::List<core::String>? a = <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);
+      }
+      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/nnbd/issue41156.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
index b79d082..873c7eb 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
@@ -59,8 +59,8 @@
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -73,21 +73,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -99,21 +99,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -126,21 +126,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -153,21 +153,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -179,21 +179,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -206,13 +206,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
 }
@@ -220,8 +220,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -272,8 +272,8 @@
           final asy::_AsyncAwaitCompleter<core::String> :async_completer = new asy::_AsyncAwaitCompleter::•<core::String>();
           asy::FutureOr<core::String>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -293,21 +293,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
         (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> /* originally async */ {
           final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
           asy::FutureOr<Never>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -328,21 +328,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
         (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<core::String> /* originally async */ {
           final asy::_AsyncAwaitCompleter<core::String> :async_completer = new asy::_AsyncAwaitCompleter::•<core::String>();
           asy::FutureOr<core::String>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -362,21 +362,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
         (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> /* originally async */ {
           final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
           asy::FutureOr<Never>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -397,25 +397,25 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
       }
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
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 b79d082..873c7eb 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
@@ -59,8 +59,8 @@
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -73,21 +73,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -99,21 +99,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -126,21 +126,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -153,21 +153,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -179,21 +179,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
     asy::FutureOr<Never>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -206,13 +206,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   };
 }
@@ -220,8 +220,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -272,8 +272,8 @@
           final asy::_AsyncAwaitCompleter<core::String> :async_completer = new asy::_AsyncAwaitCompleter::•<core::String>();
           asy::FutureOr<core::String>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -293,21 +293,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
         (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> /* originally async */ {
           final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
           asy::FutureOr<Never>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -328,21 +328,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
         (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<core::String> /* originally async */ {
           final asy::_AsyncAwaitCompleter<core::String> :async_completer = new asy::_AsyncAwaitCompleter::•<core::String>();
           asy::FutureOr<core::String>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -362,21 +362,21 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
         (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> /* originally async */ {
           final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
           asy::FutureOr<Never>? :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -397,25 +397,25 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         };
       }
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/nnbd/issue41210a/issue41210_lib1.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41210a/issue41210_lib1.dart.strong.transformed.expect
new file mode 100644
index 0000000..a170b13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41210a/issue41210_lib1.dart.strong.transformed.expect
@@ -0,0 +1,63 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue41210_lib1.dart" as iss;
+
+import "org-dartlang-testcase:///issue41210_lib1.dart";
+
+abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A*
+    : super core::Object::•()
+    ;
+  method /* from org-dartlang-testcase:///issue41210_lib1.dart */ method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A&B*
+    : super self::_C&Object&A::•()
+    ;
+  abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
+}
+class C extends self::_C&Object&A&B {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&A&B::•()
+    ;
+  abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{self::C::method}());
+}
+
+library;
+import self as iss;
+import "dart:core" as core;
+import "issue41210_lib2.dart" as iss2;
+
+import "org-dartlang-testcase:///issue41210_lib2.dart";
+
+abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/  {
+  method method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class B extends core::Object implements iss2::Interface {
+  synthetic constructor •() → iss::B*
+    : super core::Object::•()
+    ;
+  abstract member-signature method method() → core::String*;
+}
+static method main() → void {}
+
+library /*isNonNullableByDefault*/;
+import self as iss2;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → iss2::Interface
+    : super core::Object::•()
+    ;
+  abstract method method() → core::String;
+}
+
+constants  {
+  #C1 = "hello"
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41210a/issue41210_lib1.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41210a/issue41210_lib1.dart.weak.transformed.expect
new file mode 100644
index 0000000..a170b13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41210a/issue41210_lib1.dart.weak.transformed.expect
@@ -0,0 +1,63 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue41210_lib1.dart" as iss;
+
+import "org-dartlang-testcase:///issue41210_lib1.dart";
+
+abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A*
+    : super core::Object::•()
+    ;
+  method /* from org-dartlang-testcase:///issue41210_lib1.dart */ method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A&B*
+    : super self::_C&Object&A::•()
+    ;
+  abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
+}
+class C extends self::_C&Object&A&B {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&A&B::•()
+    ;
+  abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{self::C::method}());
+}
+
+library;
+import self as iss;
+import "dart:core" as core;
+import "issue41210_lib2.dart" as iss2;
+
+import "org-dartlang-testcase:///issue41210_lib2.dart";
+
+abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/  {
+  method method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class B extends core::Object implements iss2::Interface {
+  synthetic constructor •() → iss::B*
+    : super core::Object::•()
+    ;
+  abstract member-signature method method() → core::String*;
+}
+static method main() → void {}
+
+library /*isNonNullableByDefault*/;
+import self as iss2;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → iss2::Interface
+    : super core::Object::•()
+    ;
+  abstract method method() → core::String;
+}
+
+constants  {
+  #C1 = "hello"
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41210b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41210b.dart.strong.transformed.expect
new file mode 100644
index 0000000..8f2efe4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41210b.dart.strong.transformed.expect
@@ -0,0 +1,62 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue41210b_lib1.dart" as iss;
+
+import "org-dartlang-testcase:///issue41210b_lib1.dart";
+
+abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A*
+    : super core::Object::•()
+    ;
+  method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A&B*
+    : super self::_C&Object&A::•()
+    ;
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method() → core::String*;
+}
+class C extends self::_C&Object&A&B {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&A&B::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{iss::A::method}());
+}
+
+library;
+import self as iss;
+import "dart:core" as core;
+import "issue41210b_lib2.dart" as iss2;
+
+import "org-dartlang-testcase:///issue41210b_lib2.dart";
+
+abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/  {
+  method method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class B extends core::Object implements iss2::Interface {
+  synthetic constructor •() → iss::B*
+    : super core::Object::•()
+    ;
+  abstract member-signature method method() → core::String*;
+}
+static method main() → void {}
+
+library /*isNonNullableByDefault*/;
+import self as iss2;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → iss2::Interface
+    : super core::Object::•()
+    ;
+  abstract method method() → core::String;
+}
+
+constants  {
+  #C1 = "hello"
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41210b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41210b.dart.weak.transformed.expect
new file mode 100644
index 0000000..8f2efe4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41210b.dart.weak.transformed.expect
@@ -0,0 +1,62 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "issue41210b_lib1.dart" as iss;
+
+import "org-dartlang-testcase:///issue41210b_lib1.dart";
+
+abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A*
+    : super core::Object::•()
+    ;
+  method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A&B*
+    : super self::_C&Object&A::•()
+    ;
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method() → core::String*;
+}
+class C extends self::_C&Object&A&B {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&A&B::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{iss::A::method}());
+}
+
+library;
+import self as iss;
+import "dart:core" as core;
+import "issue41210b_lib2.dart" as iss2;
+
+import "org-dartlang-testcase:///issue41210b_lib2.dart";
+
+abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/  {
+  method method({core::String* s = #C1}) → core::String*
+    return s;
+}
+abstract class B extends core::Object implements iss2::Interface {
+  synthetic constructor •() → iss::B*
+    : super core::Object::•()
+    ;
+  abstract member-signature method method() → core::String*;
+}
+static method main() → void {}
+
+library /*isNonNullableByDefault*/;
+import self as iss2;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → iss2::Interface
+    : super core::Object::•()
+    ;
+  abstract method method() → core::String;
+}
+
+constants  {
+  #C1 = "hello"
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart b/pkg/front_end/testcases/nnbd/issue41273.dart
new file mode 100644
index 0000000..f490918
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41273.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.
+
+void test(var x) {
+  if (x is Never) {
+    Never n1 = x.toString();
+    Never n2 = x.runtimeType;
+    Never n3 = x.someGetter;
+    Never n4 = x.someMethod();
+    Never n5 = x + x;
+    Never n6 = x[x];
+    Never n7 = x();
+    Never n8 = x.runtimeType();
+    Never n9 = x.toString;
+    x.runtimeType = Object;
+    x.toString = () => '';
+    var v1 = x.toString();
+    var v2 = x.runtimeType;
+    var v3 = x.someGetter;
+    var v4 = x.someMethod();
+    var v5 = x + x;
+    var v6 = x[x];
+    var v7 = x();
+    var v8 = x.runtimeType();
+    var v9 = x.toString;
+  }
+}
+
+main() {
+  test(null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.outline.expect
new file mode 100644
index 0000000..a79e819
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method test(dynamic x) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.expect
new file mode 100644
index 0000000..eff260bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+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;
+  }
+}
+static method main() → dynamic {
+  self::test(null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
new file mode 100644
index 0000000..eff260bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+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;
+  }
+}
+static method main() → dynamic {
+  self::test(null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
new file mode 100644
index 0000000..eff260bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+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;
+  }
+}
+static method main() → dynamic {
+  self::test(null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
new file mode 100644
index 0000000..eff260bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+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;
+  }
+}
+static method main() → dynamic {
+  self::test(null);
+}
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 37628df..13a5cc4 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -64,8 +64,8 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 class A extends core::Object {
   field core::int a = 42;
@@ -109,7 +109,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String>["baz"]).{core::Iterable::iterator};
+    core::Iterator<core::String*> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -127,8 +127,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -140,7 +140,7 @@
       #L1:
       {
         {
-          dynamic :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String*>* :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
@@ -169,21 +169,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method fisk() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -205,8 +205,8 @@
             final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
             asy::FutureOr<dynamic>? :return_value;
             dynamic :async_stack_trace;
-            dynamic :async_op_then;
-            dynamic :async_op_error;
+            (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;
@@ -221,13 +221,13 @@
                 asy::_completeOnAsyncReturn(:async_completer, :return_value);
                 return;
               }
-              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+              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.start(:async_op);
+            :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
             return :async_completer.{asy::Completer::future};
           };
         late core::Function f = #f#initializer.call();
@@ -235,13 +235,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
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 37628df..13a5cc4 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -64,8 +64,8 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 class A extends core::Object {
   field core::int a = 42;
@@ -109,7 +109,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String>["baz"]).{core::Iterable::iterator};
+    core::Iterator<core::String*> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -127,8 +127,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -140,7 +140,7 @@
       #L1:
       {
         {
-          dynamic :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String*>* :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
@@ -169,21 +169,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method fisk() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -205,8 +205,8 @@
             final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
             asy::FutureOr<dynamic>? :return_value;
             dynamic :async_stack_trace;
-            dynamic :async_op_then;
-            dynamic :async_op_error;
+            (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;
@@ -221,13 +221,13 @@
                 asy::_completeOnAsyncReturn(:async_completer, :return_value);
                 return;
               }
-              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+              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.start(:async_op);
+            :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
             return :async_completer.{asy::Completer::future};
           };
         late core::Function f = #f#initializer.call();
@@ -235,13 +235,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart
new file mode 100644
index 0000000..dc5f062
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.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.
+
+// Declarations taken from
+//    language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_test
+
+import 'mixin_from_opt_in_out_in_lib1.dart';
+import 'mixin_from_opt_in_out_in_lib2.dart';
+
+// Member signatures: B.
+class DiB0 extends C0 implements B {}
+
+// Member signatures: Bq.
+class DiBq0 extends C0 implements Bq {}
+
+// Member signatures: B.
+class DwB0 extends C0 with B {}
+
+// Member signatures: Bq.
+class DwBq0 extends C0 with Bq {}
+
+// Member signatures: legacy.
+class DiB3 extends C3 implements B {}
+
+// Member signatures: legacy.
+class DiBq3 extends C3 implements Bq {}
+
+// Member signatures: B.
+class DwB3 extends C3 with B {}
+
+// Member signatures: Bq.
+class DwBq3 extends C3 with Bq {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.outline.expect
new file mode 100644
index 0000000..8aa3ee5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.outline.expect
@@ -0,0 +1,122 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "mixin_from_opt_in_out_in_lib1.dart" as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib1.dart";
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class DiB0 extends mix::C0 implements mix2::B {
+  synthetic constructor •() → self::DiB0
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq0 extends mix::C0 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq0
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB0&C0&B = mix::C0 with mix2::B /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwB0&C0&B
+    : super mix::C0::•()
+    ;
+}
+class DwB0 extends self::_DwB0&C0&B {
+  synthetic constructor •() → self::DwB0
+    ;
+}
+abstract class _DwBq0&C0&Bq = mix::C0 with mix2::Bq /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwBq0&C0&Bq
+    : super mix::C0::•()
+    ;
+}
+class DwBq0 extends self::_DwBq0&C0&Bq {
+  synthetic constructor •() → self::DwBq0
+    ;
+}
+class DiB3 extends mix::C3 implements mix2::B {
+  synthetic constructor •() → self::DiB3
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq3 extends mix::C3 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq3
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB3&C3&B = mix::C3 with mix2::B /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwB3&C3&B
+    : super mix::C3::•()
+    ;
+}
+class DwB3 extends self::_DwB3&C3&B {
+  synthetic constructor •() → self::DwB3
+    ;
+}
+abstract class _DwBq3&C3&Bq = mix::C3 with mix2::Bq /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwBq3&C3&Bq
+    : super mix::C3::•()
+    ;
+}
+class DwBq3 extends self::_DwBq3&C3&Bq {
+  synthetic constructor •() → self::DwBq3
+    ;
+}
+static method main() → dynamic
+  ;
+
+library;
+import self as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class C0 extends mix2::B {
+  synthetic constructor •() → mix::C0*
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+class C3 extends mix2::Bq {
+  synthetic constructor •() → mix::C3*
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix2;
+import "dart:core" as core;
+
+class B extends core::Object {
+  synthetic constructor •() → mix2::B
+    ;
+  get a() → core::List<(core::int) → core::int>
+    ;
+  set a(core::List<(core::int) → core::int> _) → void
+    ;
+  method m((core::int) → core::int x) → (core::int) → core::int
+    ;
+}
+class Bq extends core::Object {
+  synthetic constructor •() → mix2::Bq
+    ;
+  get a() → core::List<(core::int?) → core::int?>
+    ;
+  set a(core::List<(core::int?) → core::int?> _) → void
+    ;
+  method m((core::int?) → core::int? x) → (core::int?) → core::int?
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.strong.expect
new file mode 100644
index 0000000..fe1d001
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.strong.expect
@@ -0,0 +1,131 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "mixin_from_opt_in_out_in_lib1.dart" as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib1.dart";
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class DiB0 extends mix::C0 implements mix2::B {
+  synthetic constructor •() → self::DiB0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq0 extends mix::C0 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB0&C0&B = mix::C0 with mix2::B /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwB0&C0&B
+    : super mix::C0::•()
+    ;
+}
+class DwB0 extends self::_DwB0&C0&B {
+  synthetic constructor •() → self::DwB0
+    : super self::_DwB0&C0&B::•()
+    ;
+}
+abstract class _DwBq0&C0&Bq = mix::C0 with mix2::Bq /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwBq0&C0&Bq
+    : super mix::C0::•()
+    ;
+}
+class DwBq0 extends self::_DwBq0&C0&Bq {
+  synthetic constructor •() → self::DwBq0
+    : super self::_DwBq0&C0&Bq::•()
+    ;
+}
+class DiB3 extends mix::C3 implements mix2::B {
+  synthetic constructor •() → self::DiB3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq3 extends mix::C3 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB3&C3&B = mix::C3 with mix2::B /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwB3&C3&B
+    : super mix::C3::•()
+    ;
+}
+class DwB3 extends self::_DwB3&C3&B {
+  synthetic constructor •() → self::DwB3
+    : super self::_DwB3&C3&B::•()
+    ;
+}
+abstract class _DwBq3&C3&Bq = mix::C3 with mix2::Bq /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwBq3&C3&Bq
+    : super mix::C3::•()
+    ;
+}
+class DwBq3 extends self::_DwBq3&C3&Bq {
+  synthetic constructor •() → self::DwBq3
+    : super self::_DwBq3&C3&Bq::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class C0 extends mix2::B {
+  synthetic constructor •() → mix::C0*
+    : super mix2::B::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+class C3 extends mix2::Bq {
+  synthetic constructor •() → mix::C3*
+    : super mix2::Bq::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix2;
+import "dart:core" as core;
+
+class B extends core::Object {
+  synthetic constructor •() → mix2::B
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set a(core::List<(core::int) → core::int> _) → void {}
+  method m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class Bq extends core::Object {
+  synthetic constructor •() → mix2::Bq
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set a(core::List<(core::int?) → core::int?> _) → void {}
+  method m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..53ac2ec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.strong.transformed.expect
@@ -0,0 +1,151 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "mixin_from_opt_in_out_in_lib1.dart" as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib1.dart";
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class DiB0 extends mix::C0 implements mix2::B {
+  synthetic constructor •() → self::DiB0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq0 extends mix::C0 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB0&C0&B extends mix::C0 implements mix2::B /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwB0&C0&B
+    : super mix::C0::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class DwB0 extends self::_DwB0&C0&B {
+  synthetic constructor •() → self::DwB0
+    : super self::_DwB0&C0&B::•()
+    ;
+}
+abstract class _DwBq0&C0&Bq extends mix::C0 implements mix2::Bq /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwBq0&C0&Bq
+    : super mix::C0::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
+class DwBq0 extends self::_DwBq0&C0&Bq {
+  synthetic constructor •() → self::DwBq0
+    : super self::_DwBq0&C0&Bq::•()
+    ;
+}
+class DiB3 extends mix::C3 implements mix2::B {
+  synthetic constructor •() → self::DiB3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq3 extends mix::C3 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB3&C3&B extends mix::C3 implements mix2::B /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwB3&C3&B
+    : super mix::C3::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class DwB3 extends self::_DwB3&C3&B {
+  synthetic constructor •() → self::DwB3
+    : super self::_DwB3&C3&B::•()
+    ;
+}
+abstract class _DwBq3&C3&Bq extends mix::C3 implements mix2::Bq /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwBq3&C3&Bq
+    : super mix::C3::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
+class DwBq3 extends self::_DwBq3&C3&Bq {
+  synthetic constructor •() → self::DwBq3
+    : super self::_DwBq3&C3&Bq::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class C0 extends mix2::B {
+  synthetic constructor •() → mix::C0*
+    : super mix2::B::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+class C3 extends mix2::Bq {
+  synthetic constructor •() → mix::C3*
+    : super mix2::Bq::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix2;
+import "dart:core" as core;
+
+class B extends core::Object {
+  synthetic constructor •() → mix2::B
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set a(core::List<(core::int) → core::int> _) → void {}
+  method m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class Bq extends core::Object {
+  synthetic constructor •() → mix2::Bq
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set a(core::List<(core::int?) → core::int?> _) → void {}
+  method m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.weak.expect
new file mode 100644
index 0000000..fe1d001
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.weak.expect
@@ -0,0 +1,131 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "mixin_from_opt_in_out_in_lib1.dart" as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib1.dart";
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class DiB0 extends mix::C0 implements mix2::B {
+  synthetic constructor •() → self::DiB0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq0 extends mix::C0 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB0&C0&B = mix::C0 with mix2::B /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwB0&C0&B
+    : super mix::C0::•()
+    ;
+}
+class DwB0 extends self::_DwB0&C0&B {
+  synthetic constructor •() → self::DwB0
+    : super self::_DwB0&C0&B::•()
+    ;
+}
+abstract class _DwBq0&C0&Bq = mix::C0 with mix2::Bq /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwBq0&C0&Bq
+    : super mix::C0::•()
+    ;
+}
+class DwBq0 extends self::_DwBq0&C0&Bq {
+  synthetic constructor •() → self::DwBq0
+    : super self::_DwBq0&C0&Bq::•()
+    ;
+}
+class DiB3 extends mix::C3 implements mix2::B {
+  synthetic constructor •() → self::DiB3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq3 extends mix::C3 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB3&C3&B = mix::C3 with mix2::B /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwB3&C3&B
+    : super mix::C3::•()
+    ;
+}
+class DwB3 extends self::_DwB3&C3&B {
+  synthetic constructor •() → self::DwB3
+    : super self::_DwB3&C3&B::•()
+    ;
+}
+abstract class _DwBq3&C3&Bq = mix::C3 with mix2::Bq /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DwBq3&C3&Bq
+    : super mix::C3::•()
+    ;
+}
+class DwBq3 extends self::_DwBq3&C3&Bq {
+  synthetic constructor •() → self::DwBq3
+    : super self::_DwBq3&C3&Bq::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class C0 extends mix2::B {
+  synthetic constructor •() → mix::C0*
+    : super mix2::B::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+class C3 extends mix2::Bq {
+  synthetic constructor •() → mix::C3*
+    : super mix2::Bq::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix2;
+import "dart:core" as core;
+
+class B extends core::Object {
+  synthetic constructor •() → mix2::B
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set a(core::List<(core::int) → core::int> _) → void {}
+  method m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class Bq extends core::Object {
+  synthetic constructor •() → mix2::Bq
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set a(core::List<(core::int?) → core::int?> _) → void {}
+  method m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..53ac2ec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in.dart.weak.transformed.expect
@@ -0,0 +1,151 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "mixin_from_opt_in_out_in_lib1.dart" as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib1.dart";
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class DiB0 extends mix::C0 implements mix2::B {
+  synthetic constructor •() → self::DiB0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq0 extends mix::C0 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq0
+    : super mix::C0::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB0&C0&B extends mix::C0 implements mix2::B /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwB0&C0&B
+    : super mix::C0::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class DwB0 extends self::_DwB0&C0&B {
+  synthetic constructor •() → self::DwB0
+    : super self::_DwB0&C0&B::•()
+    ;
+}
+abstract class _DwBq0&C0&Bq extends mix::C0 implements mix2::Bq /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwBq0&C0&Bq
+    : super mix::C0::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
+class DwBq0 extends self::_DwBq0&C0&Bq {
+  synthetic constructor •() → self::DwBq0
+    : super self::_DwBq0&C0&Bq::•()
+    ;
+}
+class DiB3 extends mix::C3 implements mix2::B {
+  synthetic constructor •() → self::DiB3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int) → core::int>;
+  abstract member-signature set a(core::List<(core::int) → core::int> _) → void;
+  abstract member-signature method m((core::int) → core::int x) → (core::int) → core::int;
+}
+class DiBq3 extends mix::C3 implements mix2::Bq {
+  synthetic constructor •() → self::DiBq3
+    : super mix::C3::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>;
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void;
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?;
+}
+abstract class _DwB3&C3&B extends mix::C3 implements mix2::B /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwB3&C3&B
+    : super mix::C3::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class DwB3 extends self::_DwB3&C3&B {
+  synthetic constructor •() → self::DwB3
+    : super self::_DwB3&C3&B::•()
+    ;
+}
+abstract class _DwBq3&C3&Bq extends mix::C3 implements mix2::Bq /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_DwBq3&C3&Bq
+    : super mix::C3::•()
+    ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
+class DwBq3 extends self::_DwBq3&C3&Bq {
+  synthetic constructor •() → self::DwBq3
+    : super self::_DwBq3&C3&Bq::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as mix;
+import "mixin_from_opt_in_out_in_lib2.dart" as mix2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart";
+
+class C0 extends mix2::B {
+  synthetic constructor •() → mix::C0*
+    : super mix2::B::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+class C3 extends mix2::Bq {
+  synthetic constructor •() → mix::C3*
+    : super mix2::Bq::•()
+    ;
+  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*;
+  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void;
+  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*;
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix2;
+import "dart:core" as core;
+
+class B extends core::Object {
+  synthetic constructor •() → mix2::B
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int) → core::int>
+    return <(core::int) → core::int>[];
+  set a(core::List<(core::int) → core::int> _) → void {}
+  method m((core::int) → core::int x) → (core::int) → core::int
+    return x;
+}
+class Bq extends core::Object {
+  synthetic constructor •() → mix2::Bq
+    : super core::Object::•()
+    ;
+  get a() → core::List<(core::int?) → core::int?>
+    return <(core::int?) → core::int?>[];
+  set a(core::List<(core::int?) → core::int?> _) → void {}
+  method m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in_lib1.dart b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in_lib1.dart
new file mode 100644
index 0000000..e08646b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in_lib1.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.
+
+// @dart=2.6
+
+import 'mixin_from_opt_in_out_in_lib2.dart';
+
+class C0 extends B {}
+
+class C3 extends Bq {}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in_lib2.dart b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in_lib2.dart
new file mode 100644
index 0000000..55a1a29
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_out_in_lib2.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 B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart b/pkg/front_end/testcases/nnbd/never_receiver.dart
index 61af20a..caf301bf 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart
@@ -21,6 +21,12 @@
   y?.[42]; // Not an error.
   y?.[42] = 42; // Not an error.
 
+  x?.foo(); // Warning.
+  x?.bar; // Warning.
+  x?.baz = 42; // Warning.
+  x?.[42]; // Warning.
+  x?.[42] = 42; // Warning.
+
   y.foo(); // Error.
   y.bar; // Error.
   y.baz = 42; // Error.
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
index 06d0203..5ef8175 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
@@ -2,69 +2,89 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:24:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.foo(); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:25:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.bar; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:26:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.baz = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42]; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:28:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42] = 42; // Warning.
+//   ^
+//
+// 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.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
 //   y[42] = 42; // Error.
 //    ^
 //
@@ -82,55 +102,60 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
+  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) ?{dynamic} null : #t4{Never}.call();
+  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);
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+  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);
+  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.
     ^^^";
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
     ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
   y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
   y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // Error.
    ^";
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect
index 06d0203..5ef8175 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect
@@ -2,69 +2,89 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:24:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.foo(); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:25:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.bar; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:26:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.baz = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42]; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:28:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42] = 42; // Warning.
+//   ^
+//
+// 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.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
 //   y[42] = 42; // Error.
 //    ^
 //
@@ -82,55 +102,60 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
+  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) ?{dynamic} null : #t4{Never}.call();
+  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);
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+  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);
+  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.
     ^^^";
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
     ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
   y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
   y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // Error.
    ^";
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 06d0203..5ef8175 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
@@ -2,69 +2,89 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:24:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.foo(); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:25:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.bar; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:26:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.baz = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42]; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:28:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42] = 42; // Warning.
+//   ^
+//
+// 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.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
 //   y[42] = 42; // Error.
 //    ^
 //
@@ -82,55 +102,60 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
+  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) ?{dynamic} null : #t4{Never}.call();
+  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);
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+  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);
+  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.
     ^^^";
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
     ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
   y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
   y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // 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 06d0203..5ef8175 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
@@ -2,69 +2,89 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:24:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.foo(); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:25:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.bar; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:26:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.baz = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42]; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/never_receiver.dart:28:3: Warning: Operand of null-aware operation '?.' has type 'Never' which excludes null.
+//   x?.[42] = 42; // Warning.
+//   ^
+//
+// 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.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 // Try accessing using ?. instead.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
 //   y[42] = 42; // Error.
 //    ^
 //
@@ -82,55 +102,60 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
+  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) ?{dynamic} null : #t4{Never}.call();
+  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);
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:24:5: Error: The method 'foo' isn't defined for the class 'Never'.
+  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);
+  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.
     ^^^";
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:25:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
 Try accessing using ?. instead.
   y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:26:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
-  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:27:4: Error: The method 'call' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:28:4: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
+  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
   y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:29:5: Error: The operator '+' isn't defined for the class 'Never'.
+    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
     ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
   y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:4: Error: The operator '[]' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
   y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // Error.
    ^";
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart b/pkg/front_end/testcases/nnbd/nullable_object_access.dart
new file mode 100644
index 0000000..bf88ca3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.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.
+
+abstract class CustomType extends Type {
+  void call() {}
+}
+
+abstract class CustomInvocation implements Invocation {}
+
+abstract class Class {
+  CustomType get runtimeType;
+  String noSuchMethod(covariant CustomInvocation invocation);
+  bool operator ==(covariant Class o);
+  String toString({Object o});
+}
+
+main() {}
+
+void test(Class c1, Class? c2, Invocation invocation,
+    CustomInvocation customInvocation) {
+  CustomType runtimeType1 = c1.runtimeType; // ok
+  var runtimeTypeVariable1 = c1.runtimeType;
+  c1.runtimeType(); // ok
+
+  String Function(CustomInvocation) noSuchMethodTearOff1 =
+      c1.noSuchMethod; // ok
+  var noSuchMethodTearOffVariable1 = c1.noSuchMethod;
+
+  String noSuchMethod1a = c1.noSuchMethod(customInvocation); // ok
+  String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+  var noSuchMethodVariable1 = c1.noSuchMethod(customInvocation);
+
+  c1 == ''; // error
+  c1 == c2; // ok
+
+  String Function({Object o}) toStringTearOff1 = c1.toString; // ok
+  var toStringTearOffVariable1 = c1.toString;
+
+  c1.toString(o: c1); // ok
+
+  CustomType runtimeType2 = c2.runtimeType; // error
+  var runtimeTypeVariable2 = c2.runtimeType;
+  c2.runtimeType(); // error
+
+  String Function(CustomInvocation) noSuchMethodTearOff2 =
+      c2.noSuchMethod; // error
+  var noSuchMethodTearOffVariable2 = c2.noSuchMethod;
+
+  int noSuchMethod2 = c2.noSuchMethod(invocation); // ok
+  var noSuchMethodVariable2 = c2.noSuchMethod(invocation);
+
+  c2 == ''; // ok
+  c2 == c1; // ok
+
+  String Function({Object o}) toStringTearOff2 = c2.toString; // error
+  var toStringTearOffVariable2 = c2.toString;
+
+  c2.toString(o: c1); // error
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.outline.expect
new file mode 100644
index 0000000..f472974
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.outline.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class CustomType extends core::Type {
+  synthetic constructor •() → self::CustomType
+    ;
+  method call() → void
+    ;
+}
+abstract class CustomInvocation extends core::Object implements core::Invocation {
+  synthetic constructor •() → self::CustomInvocation
+    ;
+}
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    ;
+  abstract get runtimeType() → self::CustomType;
+  forwarding-stub forwarding-semi-stub method noSuchMethod(covariant self::CustomInvocation invocation) → core::String
+    return super.{core::Object::noSuchMethod}(invocation);
+  forwarding-stub forwarding-semi-stub operator ==(covariant self::Class o) → core::bool
+    return super.{core::Object::==}(o);
+  abstract method toString({core::Object o}) → core::String;
+}
+static method main() → dynamic
+  ;
+static method test(self::Class c1, self::Class? c2, core::Invocation invocation, self::CustomInvocation customInvocation) → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.expect
new file mode 100644
index 0000000..81b9a41
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.expect
@@ -0,0 +1,123 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   c1 == ''; // error
+//         ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+//  - 'Type' is from 'dart:core'.
+//  - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   CustomType runtimeType2 = c2.runtimeType; // error
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+//   c2.runtimeType(); // error
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//       c2.noSuchMethod; // error
+//          ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+//  - 'Object' is from 'dart:core'.
+//   String Function({Object o}) toStringTearOff2 = c2.toString; // error
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+// Try calling using ?. instead.
+//   c2.toString(o: c1); // error
+//      ^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class CustomType extends core::Type {
+  synthetic constructor •() → self::CustomType
+    : super core::Type::•()
+    ;
+  method call() → void {}
+}
+abstract class CustomInvocation extends core::Object implements core::Invocation {
+  synthetic constructor •() → self::CustomInvocation
+    : super core::Object::•()
+    ;
+}
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract get runtimeType() → self::CustomType;
+  forwarding-stub forwarding-semi-stub method noSuchMethod(covariant self::CustomInvocation invocation) → core::String
+    return super.{core::Object::noSuchMethod}(invocation);
+  forwarding-stub forwarding-semi-stub operator ==(covariant self::Class o) → core::bool
+    return super.{core::Object::==}(o);
+  abstract method toString({core::Object o = #C1}) → core::String;
+}
+static method main() → dynamic {}
+static method test(self::Class c1, self::Class? c2, core::Invocation invocation, self::CustomInvocation customInvocation) → void {
+  self::CustomType runtimeType1 = c1.{self::Class::runtimeType};
+  self::CustomType runtimeTypeVariable1 = c1.{self::Class::runtimeType};
+  c1.{self::Class::runtimeType}.{self::CustomType::call}();
+  (self::CustomInvocation) → core::String noSuchMethodTearOff1 = c1.{self::Class::noSuchMethod};
+  (self::CustomInvocation) → core::String noSuchMethodTearOffVariable1 = c1.{self::Class::noSuchMethod};
+  core::String noSuchMethod1a = c1.{self::Class::noSuchMethod}(customInvocation);
+  core::String noSuchMethod1b = c1.{self::Class::noSuchMethod}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+                                          ^" in invocation as{TypeError,ForNonNullableByDefault} self::CustomInvocation);
+  core::String noSuchMethodVariable1 = c1.{self::Class::noSuchMethod}(customInvocation);
+  c1.{self::Class::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  c1 == ''; // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} self::Class?);
+  c1.{self::Class::==}(c2);
+  ({o: core::Object}) → core::String toStringTearOff1 = c1.{self::Class::toString};
+  ({o: core::Object}) → core::String toStringTearOffVariable1 = c1.{self::Class::toString};
+  c1.{self::Class::toString}(o: c1);
+  self::CustomType runtimeType2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+ - 'Type' is from 'dart:core'.
+ - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  CustomType runtimeType2 = c2.runtimeType; // error
+                               ^" in c2.{core::Object::runtimeType} as{TypeError,ForNonNullableByDefault} self::CustomType;
+  core::Type runtimeTypeVariable2 = c2.{core::Object::runtimeType};
+  invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+  c2.runtimeType(); // error
+                ^^^^^^^^^^^";
+  (self::CustomInvocation) → core::String noSuchMethodTearOff2 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+      c2.noSuchMethod; // error
+         ^" in c2.{core::Object::noSuchMethod} as{TypeError,ForNonNullableByDefault} (self::CustomInvocation) → core::String;
+  (core::Invocation) → dynamic noSuchMethodTearOffVariable2 = c2.{core::Object::noSuchMethod};
+  core::int noSuchMethod2 = c2.{core::Object::noSuchMethod}(invocation) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  dynamic noSuchMethodVariable2 = c2.{core::Object::noSuchMethod}(invocation);
+  c2.{core::Object::==}("");
+  c2.{core::Object::==}(c1);
+  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+ - 'Object' is from 'dart:core'.
+  String Function({Object o}) toStringTearOff2 = c2.toString; // error
+                                                    ^" in c2.{core::Object::toString} as{TypeError,ForNonNullableByDefault} ({o: core::Object}) → core::String;
+  () → core::String toStringTearOffVariable2 = c2.{core::Object::toString};
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+Try calling using ?. instead.
+  c2.toString(o: c1); // error
+     ^^^^^^^^" in c2.{self::Class::toString}(o: c1);
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.transformed.expect
new file mode 100644
index 0000000..81b9a41
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.transformed.expect
@@ -0,0 +1,123 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   c1 == ''; // error
+//         ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+//  - 'Type' is from 'dart:core'.
+//  - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   CustomType runtimeType2 = c2.runtimeType; // error
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+//   c2.runtimeType(); // error
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//       c2.noSuchMethod; // error
+//          ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+//  - 'Object' is from 'dart:core'.
+//   String Function({Object o}) toStringTearOff2 = c2.toString; // error
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+// Try calling using ?. instead.
+//   c2.toString(o: c1); // error
+//      ^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class CustomType extends core::Type {
+  synthetic constructor •() → self::CustomType
+    : super core::Type::•()
+    ;
+  method call() → void {}
+}
+abstract class CustomInvocation extends core::Object implements core::Invocation {
+  synthetic constructor •() → self::CustomInvocation
+    : super core::Object::•()
+    ;
+}
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract get runtimeType() → self::CustomType;
+  forwarding-stub forwarding-semi-stub method noSuchMethod(covariant self::CustomInvocation invocation) → core::String
+    return super.{core::Object::noSuchMethod}(invocation);
+  forwarding-stub forwarding-semi-stub operator ==(covariant self::Class o) → core::bool
+    return super.{core::Object::==}(o);
+  abstract method toString({core::Object o = #C1}) → core::String;
+}
+static method main() → dynamic {}
+static method test(self::Class c1, self::Class? c2, core::Invocation invocation, self::CustomInvocation customInvocation) → void {
+  self::CustomType runtimeType1 = c1.{self::Class::runtimeType};
+  self::CustomType runtimeTypeVariable1 = c1.{self::Class::runtimeType};
+  c1.{self::Class::runtimeType}.{self::CustomType::call}();
+  (self::CustomInvocation) → core::String noSuchMethodTearOff1 = c1.{self::Class::noSuchMethod};
+  (self::CustomInvocation) → core::String noSuchMethodTearOffVariable1 = c1.{self::Class::noSuchMethod};
+  core::String noSuchMethod1a = c1.{self::Class::noSuchMethod}(customInvocation);
+  core::String noSuchMethod1b = c1.{self::Class::noSuchMethod}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+                                          ^" in invocation as{TypeError,ForNonNullableByDefault} self::CustomInvocation);
+  core::String noSuchMethodVariable1 = c1.{self::Class::noSuchMethod}(customInvocation);
+  c1.{self::Class::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  c1 == ''; // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} self::Class?);
+  c1.{self::Class::==}(c2);
+  ({o: core::Object}) → core::String toStringTearOff1 = c1.{self::Class::toString};
+  ({o: core::Object}) → core::String toStringTearOffVariable1 = c1.{self::Class::toString};
+  c1.{self::Class::toString}(o: c1);
+  self::CustomType runtimeType2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+ - 'Type' is from 'dart:core'.
+ - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  CustomType runtimeType2 = c2.runtimeType; // error
+                               ^" in c2.{core::Object::runtimeType} as{TypeError,ForNonNullableByDefault} self::CustomType;
+  core::Type runtimeTypeVariable2 = c2.{core::Object::runtimeType};
+  invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+  c2.runtimeType(); // error
+                ^^^^^^^^^^^";
+  (self::CustomInvocation) → core::String noSuchMethodTearOff2 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+      c2.noSuchMethod; // error
+         ^" in c2.{core::Object::noSuchMethod} as{TypeError,ForNonNullableByDefault} (self::CustomInvocation) → core::String;
+  (core::Invocation) → dynamic noSuchMethodTearOffVariable2 = c2.{core::Object::noSuchMethod};
+  core::int noSuchMethod2 = c2.{core::Object::noSuchMethod}(invocation) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  dynamic noSuchMethodVariable2 = c2.{core::Object::noSuchMethod}(invocation);
+  c2.{core::Object::==}("");
+  c2.{core::Object::==}(c1);
+  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+ - 'Object' is from 'dart:core'.
+  String Function({Object o}) toStringTearOff2 = c2.toString; // error
+                                                    ^" in c2.{core::Object::toString} as{TypeError,ForNonNullableByDefault} ({o: core::Object}) → core::String;
+  () → core::String toStringTearOffVariable2 = c2.{core::Object::toString};
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+Try calling using ?. instead.
+  c2.toString(o: c1); // error
+     ^^^^^^^^" in c2.{self::Class::toString}(o: c1);
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.expect
new file mode 100644
index 0000000..81b9a41
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.expect
@@ -0,0 +1,123 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   c1 == ''; // error
+//         ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+//  - 'Type' is from 'dart:core'.
+//  - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   CustomType runtimeType2 = c2.runtimeType; // error
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+//   c2.runtimeType(); // error
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//       c2.noSuchMethod; // error
+//          ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+//  - 'Object' is from 'dart:core'.
+//   String Function({Object o}) toStringTearOff2 = c2.toString; // error
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+// Try calling using ?. instead.
+//   c2.toString(o: c1); // error
+//      ^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class CustomType extends core::Type {
+  synthetic constructor •() → self::CustomType
+    : super core::Type::•()
+    ;
+  method call() → void {}
+}
+abstract class CustomInvocation extends core::Object implements core::Invocation {
+  synthetic constructor •() → self::CustomInvocation
+    : super core::Object::•()
+    ;
+}
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract get runtimeType() → self::CustomType;
+  forwarding-stub forwarding-semi-stub method noSuchMethod(covariant self::CustomInvocation invocation) → core::String
+    return super.{core::Object::noSuchMethod}(invocation);
+  forwarding-stub forwarding-semi-stub operator ==(covariant self::Class o) → core::bool
+    return super.{core::Object::==}(o);
+  abstract method toString({core::Object o = #C1}) → core::String;
+}
+static method main() → dynamic {}
+static method test(self::Class c1, self::Class? c2, core::Invocation invocation, self::CustomInvocation customInvocation) → void {
+  self::CustomType runtimeType1 = c1.{self::Class::runtimeType};
+  self::CustomType runtimeTypeVariable1 = c1.{self::Class::runtimeType};
+  c1.{self::Class::runtimeType}.{self::CustomType::call}();
+  (self::CustomInvocation) → core::String noSuchMethodTearOff1 = c1.{self::Class::noSuchMethod};
+  (self::CustomInvocation) → core::String noSuchMethodTearOffVariable1 = c1.{self::Class::noSuchMethod};
+  core::String noSuchMethod1a = c1.{self::Class::noSuchMethod}(customInvocation);
+  core::String noSuchMethod1b = c1.{self::Class::noSuchMethod}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+                                          ^" in invocation as{TypeError,ForNonNullableByDefault} self::CustomInvocation);
+  core::String noSuchMethodVariable1 = c1.{self::Class::noSuchMethod}(customInvocation);
+  c1.{self::Class::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  c1 == ''; // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} self::Class?);
+  c1.{self::Class::==}(c2);
+  ({o: core::Object}) → core::String toStringTearOff1 = c1.{self::Class::toString};
+  ({o: core::Object}) → core::String toStringTearOffVariable1 = c1.{self::Class::toString};
+  c1.{self::Class::toString}(o: c1);
+  self::CustomType runtimeType2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+ - 'Type' is from 'dart:core'.
+ - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  CustomType runtimeType2 = c2.runtimeType; // error
+                               ^" in c2.{core::Object::runtimeType} as{TypeError,ForNonNullableByDefault} self::CustomType;
+  core::Type runtimeTypeVariable2 = c2.{core::Object::runtimeType};
+  invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+  c2.runtimeType(); // error
+                ^^^^^^^^^^^";
+  (self::CustomInvocation) → core::String noSuchMethodTearOff2 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+      c2.noSuchMethod; // error
+         ^" in c2.{core::Object::noSuchMethod} as{TypeError,ForNonNullableByDefault} (self::CustomInvocation) → core::String;
+  (core::Invocation) → dynamic noSuchMethodTearOffVariable2 = c2.{core::Object::noSuchMethod};
+  core::int noSuchMethod2 = c2.{core::Object::noSuchMethod}(invocation) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  dynamic noSuchMethodVariable2 = c2.{core::Object::noSuchMethod}(invocation);
+  c2.{core::Object::==}("");
+  c2.{core::Object::==}(c1);
+  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+ - 'Object' is from 'dart:core'.
+  String Function({Object o}) toStringTearOff2 = c2.toString; // error
+                                                    ^" in c2.{core::Object::toString} as{TypeError,ForNonNullableByDefault} ({o: core::Object}) → core::String;
+  () → core::String toStringTearOffVariable2 = c2.{core::Object::toString};
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+Try calling using ?. instead.
+  c2.toString(o: c1); // error
+     ^^^^^^^^" in c2.{self::Class::toString}(o: c1);
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.transformed.expect
new file mode 100644
index 0000000..81b9a41
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.transformed.expect
@@ -0,0 +1,123 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   c1 == ''; // error
+//         ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+//  - 'Type' is from 'dart:core'.
+//  - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   CustomType runtimeType2 = c2.runtimeType; // error
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+//   c2.runtimeType(); // error
+//                 ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+//  - 'Invocation' is from 'dart:core'.
+//  - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//       c2.noSuchMethod; // error
+//          ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+//  - 'Object' is from 'dart:core'.
+//   String Function({Object o}) toStringTearOff2 = c2.toString; // error
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+// Try calling using ?. instead.
+//   c2.toString(o: c1); // error
+//      ^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class CustomType extends core::Type {
+  synthetic constructor •() → self::CustomType
+    : super core::Type::•()
+    ;
+  method call() → void {}
+}
+abstract class CustomInvocation extends core::Object implements core::Invocation {
+  synthetic constructor •() → self::CustomInvocation
+    : super core::Object::•()
+    ;
+}
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract get runtimeType() → self::CustomType;
+  forwarding-stub forwarding-semi-stub method noSuchMethod(covariant self::CustomInvocation invocation) → core::String
+    return super.{core::Object::noSuchMethod}(invocation);
+  forwarding-stub forwarding-semi-stub operator ==(covariant self::Class o) → core::bool
+    return super.{core::Object::==}(o);
+  abstract method toString({core::Object o = #C1}) → core::String;
+}
+static method main() → dynamic {}
+static method test(self::Class c1, self::Class? c2, core::Invocation invocation, self::CustomInvocation customInvocation) → void {
+  self::CustomType runtimeType1 = c1.{self::Class::runtimeType};
+  self::CustomType runtimeTypeVariable1 = c1.{self::Class::runtimeType};
+  c1.{self::Class::runtimeType}.{self::CustomType::call}();
+  (self::CustomInvocation) → core::String noSuchMethodTearOff1 = c1.{self::Class::noSuchMethod};
+  (self::CustomInvocation) → core::String noSuchMethodTearOffVariable1 = c1.{self::Class::noSuchMethod};
+  core::String noSuchMethod1a = c1.{self::Class::noSuchMethod}(customInvocation);
+  core::String noSuchMethod1b = c1.{self::Class::noSuchMethod}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:31:43: Error: The argument type 'Invocation' can't be assigned to the parameter type 'CustomInvocation'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  String noSuchMethod1b = c1.noSuchMethod(invocation); // error
+                                          ^" in invocation as{TypeError,ForNonNullableByDefault} self::CustomInvocation);
+  core::String noSuchMethodVariable1 = c1.{self::Class::noSuchMethod}(customInvocation);
+  c1.{self::Class::==}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:34:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  c1 == ''; // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} self::Class?);
+  c1.{self::Class::==}(c2);
+  ({o: core::Object}) → core::String toStringTearOff1 = c1.{self::Class::toString};
+  ({o: core::Object}) → core::String toStringTearOffVariable1 = c1.{self::Class::toString};
+  c1.{self::Class::toString}(o: c1);
+  self::CustomType runtimeType2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:42:32: Error: A value of type 'Type' can't be assigned to a variable of type 'CustomType'.
+ - 'Type' is from 'dart:core'.
+ - 'CustomType' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  CustomType runtimeType2 = c2.runtimeType; // error
+                               ^" in c2.{core::Object::runtimeType} as{TypeError,ForNonNullableByDefault} self::CustomType;
+  core::Type runtimeTypeVariable2 = c2.{core::Object::runtimeType};
+  invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:44:17: Error: 'runtimeType' isn't a function or method and can't be invoked.
+  c2.runtimeType(); // error
+                ^^^^^^^^^^^";
+  (self::CustomInvocation) → core::String noSuchMethodTearOff2 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:47:10: Error: A value of type 'dynamic Function(Invocation)' can't be assigned to a variable of type 'String Function(CustomInvocation)'.
+ - 'Invocation' is from 'dart:core'.
+ - 'CustomInvocation' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+      c2.noSuchMethod; // error
+         ^" in c2.{core::Object::noSuchMethod} as{TypeError,ForNonNullableByDefault} (self::CustomInvocation) → core::String;
+  (core::Invocation) → dynamic noSuchMethodTearOffVariable2 = c2.{core::Object::noSuchMethod};
+  core::int noSuchMethod2 = c2.{core::Object::noSuchMethod}(invocation) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  dynamic noSuchMethodVariable2 = c2.{core::Object::noSuchMethod}(invocation);
+  c2.{core::Object::==}("");
+  c2.{core::Object::==}(c1);
+  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+ - 'Object' is from 'dart:core'.
+  String Function({Object o}) toStringTearOff2 = c2.toString; // error
+                                                    ^" in c2.{core::Object::toString} as{TypeError,ForNonNullableByDefault} ({o: core::Object}) → core::String;
+  () → core::String toStringTearOffVariable2 = c2.{core::Object::toString};
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+Try calling using ?. instead.
+  c2.toString(o: c1); // error
+     ^^^^^^^^" in c2.{self::Class::toString}(o: c1);
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart b/pkg/front_end/testcases/nnbd/nullable_param.dart
index 75cc3db..ba646b8 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart
@@ -1,6 +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.
+
 class Foo {
   int? field;
   int? bar(int? x) {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
index 24d5f3d..380d689 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
@@ -119,18 +119,18 @@
                         ^" in a as{TypeError} () →? void;
 }
 static method ok<T extends core::Object? = core::Object?>(core::String? s, self::A? a, self::ok::T% t, self::B? b, core::Invocation i) → dynamic {
-  s.{core::String::==}(s);
+  s.{core::Object::==}(s);
   a.{core::Object::==}(a);
   t.{core::Object::==}(t);
   b.{core::Object::==}(b);
-  s.{core::String::hashCode};
+  s.{core::Object::hashCode};
   a.{core::Object::hashCode};
   t.{core::Object::hashCode};
   b.{core::Object::hashCode};
   s.{core::Object::toString}();
   a.{core::Object::toString}();
   t.{core::Object::toString}();
-  b.{self::B::toString}();
+  b.{core::Object::toString}();
   try {
     s.{core::Object::noSuchMethod}(i);
   }
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.transformed.expect
index 24d5f3d..380d689 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.transformed.expect
@@ -119,18 +119,18 @@
                         ^" in a as{TypeError} () →? void;
 }
 static method ok<T extends core::Object? = core::Object?>(core::String? s, self::A? a, self::ok::T% t, self::B? b, core::Invocation i) → dynamic {
-  s.{core::String::==}(s);
+  s.{core::Object::==}(s);
   a.{core::Object::==}(a);
   t.{core::Object::==}(t);
   b.{core::Object::==}(b);
-  s.{core::String::hashCode};
+  s.{core::Object::hashCode};
   a.{core::Object::hashCode};
   t.{core::Object::hashCode};
   b.{core::Object::hashCode};
   s.{core::Object::toString}();
   a.{core::Object::toString}();
   t.{core::Object::toString}();
-  b.{self::B::toString}();
+  b.{core::Object::toString}();
   try {
     s.{core::Object::noSuchMethod}(i);
   }
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
index 24d5f3d..380d689 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
@@ -119,18 +119,18 @@
                         ^" in a as{TypeError} () →? void;
 }
 static method ok<T extends core::Object? = core::Object?>(core::String? s, self::A? a, self::ok::T% t, self::B? b, core::Invocation i) → dynamic {
-  s.{core::String::==}(s);
+  s.{core::Object::==}(s);
   a.{core::Object::==}(a);
   t.{core::Object::==}(t);
   b.{core::Object::==}(b);
-  s.{core::String::hashCode};
+  s.{core::Object::hashCode};
   a.{core::Object::hashCode};
   t.{core::Object::hashCode};
   b.{core::Object::hashCode};
   s.{core::Object::toString}();
   a.{core::Object::toString}();
   t.{core::Object::toString}();
-  b.{self::B::toString}();
+  b.{core::Object::toString}();
   try {
     s.{core::Object::noSuchMethod}(i);
   }
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.transformed.expect
index 24d5f3d..380d689 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.transformed.expect
@@ -119,18 +119,18 @@
                         ^" in a as{TypeError} () →? void;
 }
 static method ok<T extends core::Object? = core::Object?>(core::String? s, self::A? a, self::ok::T% t, self::B? b, core::Invocation i) → dynamic {
-  s.{core::String::==}(s);
+  s.{core::Object::==}(s);
   a.{core::Object::==}(a);
   t.{core::Object::==}(t);
   b.{core::Object::==}(b);
-  s.{core::String::hashCode};
+  s.{core::Object::hashCode};
   a.{core::Object::hashCode};
   t.{core::Object::hashCode};
   b.{core::Object::hashCode};
   s.{core::Object::toString}();
   a.{core::Object::toString}();
   t.{core::Object::toString}();
-  b.{self::B::toString}();
+  b.{core::Object::toString}();
   try {
     s.{core::Object::noSuchMethod}(i);
   }
diff --git a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.expect
index 8c42147..dd56766 100644
--- a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.expect
@@ -10,9 +10,9 @@
 
 typedef F = invalid-type;
 static method foo(() → void x) → void {
-  self::bar(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::bar(x);
   self::bar(null);
-  self::baz(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::baz(x);
   self::baz(null);
 }
 static method bar(invalid-type x) → void {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.transformed.expect
index 8c42147..dd56766 100644
--- a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.strong.transformed.expect
@@ -10,9 +10,9 @@
 
 typedef F = invalid-type;
 static method foo(() → void x) → void {
-  self::bar(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::bar(x);
   self::bar(null);
-  self::baz(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::baz(x);
   self::baz(null);
 }
 static method bar(invalid-type x) → void {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.expect
index 8c42147..dd56766 100644
--- a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.expect
@@ -10,9 +10,9 @@
 
 typedef F = invalid-type;
 static method foo(() → void x) → void {
-  self::bar(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::bar(x);
   self::bar(null);
-  self::baz(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::baz(x);
   self::baz(null);
 }
 static method bar(invalid-type x) → void {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.transformed.expect
index 8c42147..dd56766 100644
--- a/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_rhs_of_typedef.dart.weak.transformed.expect
@@ -10,9 +10,9 @@
 
 typedef F = invalid-type;
 static method foo(() → void x) → void {
-  self::bar(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::bar(x);
   self::bar(null);
-  self::baz(x as{TypeError,ForNonNullableByDefault} invalid-type);
+  self::baz(x);
   self::baz(null);
 }
 static method bar(invalid-type x) → void {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart
new file mode 100644
index 0000000..d680fba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart
@@ -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 file.
+
+const num three = 3;
+dynamic dynamicFunction(dynamic d) => d;
+Object? objectFunction(Object? o) => o;
+int intFunction(int i) => i;
+T idFunction<T>(T t) => t;
+
+const int Function(int) idAsIntFunction = idFunction;
+
+class Class<T> {
+  final T field;
+
+  const Class(dynamic value) : field = value as T;
+}
+
+class ClassWithBound<T extends num> {
+  final T field;
+
+  const ClassWithBound() : field = three as T;
+
+  const ClassWithBound.withValue(dynamic value) : field = value as T;
+}
+
+class ClassWithList<T> {
+  final List<T> field;
+
+  const ClassWithList(dynamic value) : field = value as List<T>;
+}
+
+class ClassWithFunction<T> {
+  final T Function(T) field;
+
+  const ClassWithFunction(dynamic value) : field = value as T Function(T);
+}
+
+void main() {
+  const Class(0); // ok
+  const Class<num>(0); // ok
+  const Class<int>(0); // ok
+  const Class<String>(''); // ok
+  const ClassWithBound<int>(); // ok
+  const ClassWithBound<int>.withValue(0); // ok
+  const ClassWithBound<int>.withValue(three); // ok
+  const ClassWithBound<double>.withValue(0.5); // ok
+  const ClassWithList([]); // ok
+  const ClassWithList<num>(<int>[0]); // ok
+  const ClassWithList<int>(<int>[0]); // ok
+  const ClassWithList<String>(<String>['']); // ok
+  const ClassWithFunction(dynamicFunction); // ok
+  const ClassWithFunction<Object?>(dynamicFunction); // ok
+  const ClassWithFunction(objectFunction); // ok
+  const ClassWithFunction<void>(objectFunction); // ok
+  const ClassWithFunction<int>(intFunction); // ok
+  const ClassWithFunction<int>(idAsIntFunction); // ok
+}
+
+weakMode() {
+  const ClassWithFunction<Object>(objectFunction); // ok in weak mode
+}
+
+errors() {
+  const Class<num>(''); // error
+  const Class<int>(0.5); // error
+  const Class<String>(0); // error
+  const ClassWithBound<double>(); // error
+  const ClassWithBound<double>.withValue(0); // error
+  const ClassWithBound<double>.withValue(three); // error
+  const ClassWithBound<num>.withValue(''); // error
+  const ClassWithList(0); // error
+  const ClassWithList<num>(<String>['']); // error
+  const ClassWithList<int>(<num>[0]); // error
+  const ClassWithList<String>(<int>[0]); // error
+  const ClassWithFunction(0); // error
+  const ClassWithFunction(intFunction); // error
+  const ClassWithFunction<Object>(intFunction); // error
+  const ClassWithFunction<void>(intFunction); // error
+  const ClassWithFunction<num>(intFunction); // error
+  const ClassWithFunction<int>(idFunction); // error
+}
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
new file mode 100644
index 0000000..fa3b2cf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.outline.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field self::Class::T% field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value as{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field self::ClassWithBound::T field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = self::three as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::List<self::ClassWithList::T%> field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value as{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field (self::ClassWithFunction::T%) → self::ClassWithFunction::T% field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value as{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = 3;
+static const field (core::int) → core::int idAsIntFunction = self::idFunction<core::int>;
+static method dynamicFunction(dynamic d) → dynamic
+  ;
+static method objectFunction(core::Object? o) → core::Object?
+  ;
+static method intFunction(core::int i) → core::int
+  ;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  ;
+static method main() → void
+  ;
+static method weakMode() → dynamic
+  ;
+static method errors() → dynamic
+  ;
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
new file mode 100644
index 0000000..6ec69f6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
@@ -0,0 +1,256 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:61:9: Error: Constant evaluation error:
+//   const ClassWithFunction<Object>(objectFunction); // ok in weak mode
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'objectFunction' to be of type 'Object Function(Object)', but was of type 'Object? Function(Object?)'.
+//  - 'Object' is from 'dart:core'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:65:9: Error: Constant evaluation error:
+//   const Class<num>(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:66:9: Error: Constant evaluation error:
+//   const Class<int>(0.5); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0.5' to be of type 'int', but was of type 'double'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:67:9: Error: Constant evaluation error:
+//   const Class<String>(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0' to be of type 'String', but was of type 'int'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:68:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>(); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:22:42: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound() : field = three as T;
+//                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:69:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '0' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:70:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(three); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:71:9: Error: Constant evaluation error:
+//   const ClassWithBound<num>.withValue(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:72:9: Error: Constant evaluation error:
+//   const ClassWithList(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:73:9: Error: Constant evaluation error:
+//   const ClassWithList<num>(<String>['']); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<String>[""]' to be of type 'List<num>', but was of type 'List<String>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:74:9: Error: Constant evaluation error:
+//   const ClassWithList<int>(<num>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:75:9: Error: Constant evaluation error:
+//   const ClassWithList<String>(<int>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:76:9: Error: Constant evaluation error:
+//   const ClassWithFunction(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:77:9: Error: Constant evaluation error:
+//   const ClassWithFunction(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:78:9: Error: Constant evaluation error:
+//   const ClassWithFunction<Object>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+//  - 'Object' is from 'dart:core'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:79:9: Error: Constant evaluation error:
+//   const ClassWithFunction<void>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:80:9: Error: Constant evaluation error:
+//   const ClassWithFunction<num>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:81:9: Error: Constant evaluation error:
+//   const ClassWithFunction<int>(idFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field self::Class::T% field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value as{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field self::ClassWithBound::T field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::List<self::ClassWithList::T%> field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value as{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field (self::ClassWithFunction::T%) → self::ClassWithFunction::T% field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value as{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C9;
+  #C10;
+  #C11;
+  #C10;
+  #C13;
+  #C15;
+  #C17;
+  #C18;
+  #C20;
+  #C22;
+  #C23;
+  #C25;
+  #C26;
+  #C28;
+  #C29;
+}
+static method weakMode() → dynamic {
+  invalid-expression "Expected constant 'objectFunction' to be of type 'Object Function(Object)', but was of type 'Object? Function(Object?)'.
+ - 'Object' is from 'dart:core'.";
+}
+static method errors() → dynamic {
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0.5' to be of type 'int', but was of type 'double'.";
+  invalid-expression "Expected constant '0' to be of type 'String', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '0' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<String>[\"\"]' to be of type 'List<num>', but was of type 'List<String>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+ - 'Object' is from 'dart:core'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.";
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int>
+  #C4 = 0
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num> {field:#C4}
+  #C7 = self::Class<core::int> {field:#C4}
+  #C8 = ""
+  #C9 = self::Class<core::String> {field:#C8}
+  #C10 = self::ClassWithBound<core::int> {field:#C1}
+  #C11 = self::ClassWithBound<core::int> {field:#C4}
+  #C12 = 0.5
+  #C13 = self::ClassWithBound<core::double> {field:#C12}
+  #C14 = <dynamic>[]
+  #C15 = self::ClassWithList<dynamic> {field:#C14}
+  #C16 = <core::int>[#C4]
+  #C17 = self::ClassWithList<core::num> {field:#C16}
+  #C18 = self::ClassWithList<core::int> {field:#C16}
+  #C19 = <core::String>[#C8]
+  #C20 = self::ClassWithList<core::String> {field:#C19}
+  #C21 = tearoff self::dynamicFunction
+  #C22 = self::ClassWithFunction<dynamic> {field:#C21}
+  #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
+  #C24 = tearoff self::objectFunction
+  #C25 = self::ClassWithFunction<dynamic> {field:#C24}
+  #C26 = self::ClassWithFunction<void> {field:#C24}
+  #C27 = tearoff self::intFunction
+  #C28 = self::ClassWithFunction<core::int> {field:#C27}
+  #C29 = self::ClassWithFunction<core::int> {field:#C3}
+}
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
new file mode 100644
index 0000000..6ec69f6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
@@ -0,0 +1,256 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:61:9: Error: Constant evaluation error:
+//   const ClassWithFunction<Object>(objectFunction); // ok in weak mode
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'objectFunction' to be of type 'Object Function(Object)', but was of type 'Object? Function(Object?)'.
+//  - 'Object' is from 'dart:core'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:65:9: Error: Constant evaluation error:
+//   const Class<num>(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:66:9: Error: Constant evaluation error:
+//   const Class<int>(0.5); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0.5' to be of type 'int', but was of type 'double'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:67:9: Error: Constant evaluation error:
+//   const Class<String>(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0' to be of type 'String', but was of type 'int'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:68:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>(); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:22:42: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound() : field = three as T;
+//                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:69:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '0' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:70:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(three); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:71:9: Error: Constant evaluation error:
+//   const ClassWithBound<num>.withValue(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:72:9: Error: Constant evaluation error:
+//   const ClassWithList(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:73:9: Error: Constant evaluation error:
+//   const ClassWithList<num>(<String>['']); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<String>[""]' to be of type 'List<num>', but was of type 'List<String>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:74:9: Error: Constant evaluation error:
+//   const ClassWithList<int>(<num>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:75:9: Error: Constant evaluation error:
+//   const ClassWithList<String>(<int>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:76:9: Error: Constant evaluation error:
+//   const ClassWithFunction(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:77:9: Error: Constant evaluation error:
+//   const ClassWithFunction(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:78:9: Error: Constant evaluation error:
+//   const ClassWithFunction<Object>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+//  - 'Object' is from 'dart:core'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:79:9: Error: Constant evaluation error:
+//   const ClassWithFunction<void>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:80:9: Error: Constant evaluation error:
+//   const ClassWithFunction<num>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:81:9: Error: Constant evaluation error:
+//   const ClassWithFunction<int>(idFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field self::Class::T% field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value as{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field self::ClassWithBound::T field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::List<self::ClassWithList::T%> field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value as{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field (self::ClassWithFunction::T%) → self::ClassWithFunction::T% field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value as{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C9;
+  #C10;
+  #C11;
+  #C10;
+  #C13;
+  #C15;
+  #C17;
+  #C18;
+  #C20;
+  #C22;
+  #C23;
+  #C25;
+  #C26;
+  #C28;
+  #C29;
+}
+static method weakMode() → dynamic {
+  invalid-expression "Expected constant 'objectFunction' to be of type 'Object Function(Object)', but was of type 'Object? Function(Object?)'.
+ - 'Object' is from 'dart:core'.";
+}
+static method errors() → dynamic {
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0.5' to be of type 'int', but was of type 'double'.";
+  invalid-expression "Expected constant '0' to be of type 'String', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '0' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<String>[\"\"]' to be of type 'List<num>', but was of type 'List<String>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+ - 'Object' is from 'dart:core'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.";
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int>
+  #C4 = 0
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num> {field:#C4}
+  #C7 = self::Class<core::int> {field:#C4}
+  #C8 = ""
+  #C9 = self::Class<core::String> {field:#C8}
+  #C10 = self::ClassWithBound<core::int> {field:#C1}
+  #C11 = self::ClassWithBound<core::int> {field:#C4}
+  #C12 = 0.5
+  #C13 = self::ClassWithBound<core::double> {field:#C12}
+  #C14 = <dynamic>[]
+  #C15 = self::ClassWithList<dynamic> {field:#C14}
+  #C16 = <core::int>[#C4]
+  #C17 = self::ClassWithList<core::num> {field:#C16}
+  #C18 = self::ClassWithList<core::int> {field:#C16}
+  #C19 = <core::String>[#C8]
+  #C20 = self::ClassWithList<core::String> {field:#C19}
+  #C21 = tearoff self::dynamicFunction
+  #C22 = self::ClassWithFunction<dynamic> {field:#C21}
+  #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
+  #C24 = tearoff self::objectFunction
+  #C25 = self::ClassWithFunction<dynamic> {field:#C24}
+  #C26 = self::ClassWithFunction<void> {field:#C24}
+  #C27 = tearoff self::intFunction
+  #C28 = self::ClassWithFunction<core::int> {field:#C27}
+  #C29 = self::ClassWithFunction<core::int> {field:#C3}
+}
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
new file mode 100644
index 0000000..37e43f1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
@@ -0,0 +1,248 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:65:9: Error: Constant evaluation error:
+//   const Class<num>(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:66:9: Error: Constant evaluation error:
+//   const Class<int>(0.5); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0.5' to be of type 'int', but was of type 'double'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:67:9: Error: Constant evaluation error:
+//   const Class<String>(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0' to be of type 'String', but was of type 'int'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:68:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>(); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:22:42: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound() : field = three as T;
+//                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:69:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '0' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:70:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(three); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:71:9: Error: Constant evaluation error:
+//   const ClassWithBound<num>.withValue(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:72:9: Error: Constant evaluation error:
+//   const ClassWithList(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:73:9: Error: Constant evaluation error:
+//   const ClassWithList<num>(<String>['']); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<String>[""]' to be of type 'List<num>', but was of type 'List<String>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:74:9: Error: Constant evaluation error:
+//   const ClassWithList<int>(<num>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:75:9: Error: Constant evaluation error:
+//   const ClassWithList<String>(<int>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:76:9: Error: Constant evaluation error:
+//   const ClassWithFunction(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:77:9: Error: Constant evaluation error:
+//   const ClassWithFunction(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:78:9: Error: Constant evaluation error:
+//   const ClassWithFunction<Object>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+//  - 'Object' is from 'dart:core'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:79:9: Error: Constant evaluation error:
+//   const ClassWithFunction<void>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:80:9: Error: Constant evaluation error:
+//   const ClassWithFunction<num>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:81:9: Error: Constant evaluation error:
+//   const ClassWithFunction<int>(idFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field self::Class::T% field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value as{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field self::ClassWithBound::T field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::List<self::ClassWithList::T%> field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value as{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field (self::ClassWithFunction::T%) → self::ClassWithFunction::T% field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value as{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C9;
+  #C10;
+  #C11;
+  #C10;
+  #C13;
+  #C15;
+  #C17;
+  #C18;
+  #C20;
+  #C22;
+  #C23;
+  #C25;
+  #C26;
+  #C28;
+  #C29;
+}
+static method weakMode() → dynamic {
+  #C30;
+}
+static method errors() → dynamic {
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0.5' to be of type 'int', but was of type 'double'.";
+  invalid-expression "Expected constant '0' to be of type 'String', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '0' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<String>[\"\"]' to be of type 'List<num>', but was of type 'List<String>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+ - 'Object' is from 'dart:core'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.";
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C4 = 0
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num*> {field:#C4}
+  #C7 = self::Class<core::int*> {field:#C4}
+  #C8 = ""
+  #C9 = self::Class<core::String*> {field:#C8}
+  #C10 = self::ClassWithBound<core::int*> {field:#C1}
+  #C11 = self::ClassWithBound<core::int*> {field:#C4}
+  #C12 = 0.5
+  #C13 = self::ClassWithBound<core::double*> {field:#C12}
+  #C14 = <dynamic>[]
+  #C15 = self::ClassWithList<dynamic> {field:#C14}
+  #C16 = <core::int*>[#C4]
+  #C17 = self::ClassWithList<core::num*> {field:#C16}
+  #C18 = self::ClassWithList<core::int*> {field:#C16}
+  #C19 = <core::String*>[#C8]
+  #C20 = self::ClassWithList<core::String*> {field:#C19}
+  #C21 = tearoff self::dynamicFunction
+  #C22 = self::ClassWithFunction<dynamic> {field:#C21}
+  #C23 = self::ClassWithFunction<core::Object*> {field:#C21}
+  #C24 = tearoff self::objectFunction
+  #C25 = self::ClassWithFunction<dynamic> {field:#C24}
+  #C26 = self::ClassWithFunction<void> {field:#C24}
+  #C27 = tearoff self::intFunction
+  #C28 = self::ClassWithFunction<core::int*> {field:#C27}
+  #C29 = self::ClassWithFunction<core::int*> {field:#C3}
+  #C30 = self::ClassWithFunction<core::Object*> {field:#C24}
+}
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
new file mode 100644
index 0000000..37e43f1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
@@ -0,0 +1,248 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:65:9: Error: Constant evaluation error:
+//   const Class<num>(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:66:9: Error: Constant evaluation error:
+//   const Class<int>(0.5); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0.5' to be of type 'int', but was of type 'double'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:67:9: Error: Constant evaluation error:
+//   const Class<String>(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:16:46: Context: Expected constant '0' to be of type 'String', but was of type 'int'.
+//   const Class(dynamic value) : field = value as T;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:68:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>(); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:22:42: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound() : field = three as T;
+//                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:69:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '0' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:70:9: Error: Constant evaluation error:
+//   const ClassWithBound<double>.withValue(three); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '3' to be of type 'double', but was of type 'int'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:71:9: Error: Constant evaluation error:
+//   const ClassWithBound<num>.withValue(''); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:24:65: Context: Expected constant '""' to be of type 'num', but was of type 'String'.
+//   const ClassWithBound.withValue(dynamic value) : field = value as T;
+//                                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:72:9: Error: Constant evaluation error:
+//   const ClassWithList(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:73:9: Error: Constant evaluation error:
+//   const ClassWithList<num>(<String>['']); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<String>[""]' to be of type 'List<num>', but was of type 'List<String>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:74:9: Error: Constant evaluation error:
+//   const ClassWithList<int>(<num>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:75:9: Error: Constant evaluation error:
+//   const ClassWithList<String>(<int>[0]); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:30:54: Context: Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+//  - 'List' is from 'dart:core'.
+//   const ClassWithList(dynamic value) : field = value as List<T>;
+//                                                      ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:76:9: Error: Constant evaluation error:
+//   const ClassWithFunction(0); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:77:9: Error: Constant evaluation error:
+//   const ClassWithFunction(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:78:9: Error: Constant evaluation error:
+//   const ClassWithFunction<Object>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+//  - 'Object' is from 'dart:core'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:79:9: Error: Constant evaluation error:
+//   const ClassWithFunction<void>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:80:9: Error: Constant evaluation error:
+//   const ClassWithFunction<num>(intFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:81:9: Error: Constant evaluation error:
+//   const ClassWithFunction<int>(idFunction); // error
+//         ^
+// pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:36:58: Context: Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.
+//   const ClassWithFunction(dynamic value) : field = value as T Function(T);
+//                                                          ^
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field self::Class::T% field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value as{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field self::ClassWithBound::T field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value as{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::List<self::ClassWithList::T%> field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value as{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field (self::ClassWithFunction::T%) → self::ClassWithFunction::T% field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value as{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C9;
+  #C10;
+  #C11;
+  #C10;
+  #C13;
+  #C15;
+  #C17;
+  #C18;
+  #C20;
+  #C22;
+  #C23;
+  #C25;
+  #C26;
+  #C28;
+  #C29;
+}
+static method weakMode() → dynamic {
+  #C30;
+}
+static method errors() → dynamic {
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0.5' to be of type 'int', but was of type 'double'.";
+  invalid-expression "Expected constant '0' to be of type 'String', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '0' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '3' to be of type 'double', but was of type 'int'.";
+  invalid-expression "Expected constant '\"\"' to be of type 'num', but was of type 'String'.";
+  invalid-expression "Expected constant '0' to be of type 'List<dynamic>', but was of type 'int'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<String>[\"\"]' to be of type 'List<num>', but was of type 'List<String>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<num>[0]' to be of type 'List<int>', but was of type 'List<num>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '<int>[0]' to be of type 'List<String>', but was of type 'List<int>'.
+ - 'List' is from 'dart:core'.";
+  invalid-expression "Expected constant '0' to be of type 'dynamic Function(dynamic)', but was of type 'int'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'dynamic Function(dynamic)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'Object Function(Object)', but was of type 'int Function(int)'.
+ - 'Object' is from 'dart:core'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'void Function(void)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'intFunction' to be of type 'num Function(num)', but was of type 'int Function(int)'.";
+  invalid-expression "Expected constant 'idFunction' to be of type 'int Function(int)', but was of type 'T Function<T>(T)'.";
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C4 = 0
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num*> {field:#C4}
+  #C7 = self::Class<core::int*> {field:#C4}
+  #C8 = ""
+  #C9 = self::Class<core::String*> {field:#C8}
+  #C10 = self::ClassWithBound<core::int*> {field:#C1}
+  #C11 = self::ClassWithBound<core::int*> {field:#C4}
+  #C12 = 0.5
+  #C13 = self::ClassWithBound<core::double*> {field:#C12}
+  #C14 = <dynamic>[]
+  #C15 = self::ClassWithList<dynamic> {field:#C14}
+  #C16 = <core::int*>[#C4]
+  #C17 = self::ClassWithList<core::num*> {field:#C16}
+  #C18 = self::ClassWithList<core::int*> {field:#C16}
+  #C19 = <core::String*>[#C8]
+  #C20 = self::ClassWithList<core::String*> {field:#C19}
+  #C21 = tearoff self::dynamicFunction
+  #C22 = self::ClassWithFunction<dynamic> {field:#C21}
+  #C23 = self::ClassWithFunction<core::Object*> {field:#C21}
+  #C24 = tearoff self::objectFunction
+  #C25 = self::ClassWithFunction<dynamic> {field:#C24}
+  #C26 = self::ClassWithFunction<void> {field:#C24}
+  #C27 = tearoff self::intFunction
+  #C28 = self::ClassWithFunction<core::int*> {field:#C27}
+  #C29 = self::ClassWithFunction<core::int*> {field:#C3}
+  #C30 = self::ClassWithFunction<core::Object*> {field:#C24}
+}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart
new file mode 100644
index 0000000..e7793b7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 num three = 3;
+dynamic dynamicFunction(dynamic d) => d;
+Object? objectFunction(Object? o) => o;
+int intFunction(int i) => i;
+T idFunction<T>(T t) => t;
+
+const int Function(int) idAsIntFunction = idFunction;
+
+class Class<T> {
+  final bool field;
+
+  const Class(dynamic value) : field = value is T;
+}
+
+class ClassWithBound<T extends num> {
+  final bool field;
+
+  const ClassWithBound() : field = three is T;
+
+  const ClassWithBound.withValue(dynamic value) : field = value is T;
+}
+
+class ClassWithList<T> {
+  final bool field;
+
+  const ClassWithList(dynamic value) : field = value is List<T>;
+}
+
+class ClassWithFunction<T> {
+  final bool field;
+
+  const ClassWithFunction(dynamic value) : field = value is T Function(T);
+}
+
+void main() {
+  const Class(0);
+  const Class<num>(0);
+  const Class<int>(0);
+  const Class<String>('');
+  const ClassWithBound<int>();
+  const ClassWithBound<int>.withValue(0);
+  const ClassWithBound<int>.withValue(three);
+  const ClassWithBound<double>.withValue(0.5);
+  const ClassWithList([]);
+  const ClassWithList<num>(<int>[0]);
+  const ClassWithList<int>(<int>[0]);
+  const ClassWithList<String>(<String>['']);
+  const ClassWithFunction(dynamicFunction);
+  const ClassWithFunction<Object?>(dynamicFunction);
+  const ClassWithFunction(objectFunction);
+  const ClassWithFunction<void>(objectFunction);
+  const ClassWithFunction<int>(intFunction);
+  const ClassWithFunction<int>(idAsIntFunction);
+  const ClassWithFunction<Object>(objectFunction);
+  const Class<num>('');
+  const Class<int>(0.5);
+  const Class<String>(0);
+  const ClassWithBound<double>();
+  const ClassWithBound<double>.withValue(0);
+  const ClassWithBound<double>.withValue(three);
+  const ClassWithBound<num>.withValue('');
+  const ClassWithList(0);
+  const ClassWithList<num>(<String>['']);
+  const ClassWithList<int>(<num>[0]);
+  const ClassWithList<String>(<int>[0]);
+  const ClassWithFunction(0);
+  const ClassWithFunction(intFunction);
+  const ClassWithFunction<Object>(intFunction);
+  const ClassWithFunction<void>(intFunction);
+  const ClassWithFunction<num>(intFunction);
+  const ClassWithFunction<int>(idFunction);
+}
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
new file mode 100644
index 0000000..59b2a45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.outline.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value is{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = self::three is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value is{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value is{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = 3;
+static const field (core::int) → core::int idAsIntFunction = self::idFunction<core::int>;
+static method dynamicFunction(dynamic d) → dynamic
+  ;
+static method objectFunction(core::Object? o) → core::Object?
+  ;
+static method intFunction(core::int i) → core::int
+  ;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  ;
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
new file mode 100644
index 0000000..8ff2377
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
@@ -0,0 +1,115 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value is{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value is{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value is{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C8;
+  #C9;
+  #C9;
+  #C9;
+  #C10;
+  #C11;
+  #C12;
+  #C13;
+  #C14;
+  #C15;
+  #C16;
+  #C15;
+  #C17;
+  #C18;
+  #C18;
+  #C20;
+  #C21;
+  #C22;
+  #C23;
+  #C24;
+  #C24;
+  #C24;
+  #C25;
+  #C26;
+  #C27;
+  #C28;
+  #C29;
+  #C30;
+  #C30;
+  #C20;
+  #C31;
+  #C32;
+  #C33;
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int>
+  #C4 = true
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num> {field:#C4}
+  #C7 = self::Class<core::int> {field:#C4}
+  #C8 = self::Class<core::String> {field:#C4}
+  #C9 = self::ClassWithBound<core::int> {field:#C4}
+  #C10 = self::ClassWithBound<core::double> {field:#C4}
+  #C11 = self::ClassWithList<dynamic> {field:#C4}
+  #C12 = self::ClassWithList<core::num> {field:#C4}
+  #C13 = self::ClassWithList<core::int> {field:#C4}
+  #C14 = self::ClassWithList<core::String> {field:#C4}
+  #C15 = self::ClassWithFunction<dynamic> {field:#C4}
+  #C16 = self::ClassWithFunction<core::Object?> {field:#C4}
+  #C17 = self::ClassWithFunction<void> {field:#C4}
+  #C18 = self::ClassWithFunction<core::int> {field:#C4}
+  #C19 = false
+  #C20 = self::ClassWithFunction<core::Object> {field:#C19}
+  #C21 = self::Class<core::num> {field:#C19}
+  #C22 = self::Class<core::int> {field:#C19}
+  #C23 = self::Class<core::String> {field:#C19}
+  #C24 = self::ClassWithBound<core::double> {field:#C19}
+  #C25 = self::ClassWithBound<core::num> {field:#C19}
+  #C26 = self::ClassWithList<dynamic> {field:#C19}
+  #C27 = self::ClassWithList<core::num> {field:#C19}
+  #C28 = self::ClassWithList<core::int> {field:#C19}
+  #C29 = self::ClassWithList<core::String> {field:#C19}
+  #C30 = self::ClassWithFunction<dynamic> {field:#C19}
+  #C31 = self::ClassWithFunction<void> {field:#C19}
+  #C32 = self::ClassWithFunction<core::num> {field:#C19}
+  #C33 = self::ClassWithFunction<core::int> {field:#C19}
+}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
new file mode 100644
index 0000000..8ff2377
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
@@ -0,0 +1,115 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value is{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value is{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value is{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C8;
+  #C9;
+  #C9;
+  #C9;
+  #C10;
+  #C11;
+  #C12;
+  #C13;
+  #C14;
+  #C15;
+  #C16;
+  #C15;
+  #C17;
+  #C18;
+  #C18;
+  #C20;
+  #C21;
+  #C22;
+  #C23;
+  #C24;
+  #C24;
+  #C24;
+  #C25;
+  #C26;
+  #C27;
+  #C28;
+  #C29;
+  #C30;
+  #C30;
+  #C20;
+  #C31;
+  #C32;
+  #C33;
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int>
+  #C4 = true
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num> {field:#C4}
+  #C7 = self::Class<core::int> {field:#C4}
+  #C8 = self::Class<core::String> {field:#C4}
+  #C9 = self::ClassWithBound<core::int> {field:#C4}
+  #C10 = self::ClassWithBound<core::double> {field:#C4}
+  #C11 = self::ClassWithList<dynamic> {field:#C4}
+  #C12 = self::ClassWithList<core::num> {field:#C4}
+  #C13 = self::ClassWithList<core::int> {field:#C4}
+  #C14 = self::ClassWithList<core::String> {field:#C4}
+  #C15 = self::ClassWithFunction<dynamic> {field:#C4}
+  #C16 = self::ClassWithFunction<core::Object?> {field:#C4}
+  #C17 = self::ClassWithFunction<void> {field:#C4}
+  #C18 = self::ClassWithFunction<core::int> {field:#C4}
+  #C19 = false
+  #C20 = self::ClassWithFunction<core::Object> {field:#C19}
+  #C21 = self::Class<core::num> {field:#C19}
+  #C22 = self::Class<core::int> {field:#C19}
+  #C23 = self::Class<core::String> {field:#C19}
+  #C24 = self::ClassWithBound<core::double> {field:#C19}
+  #C25 = self::ClassWithBound<core::num> {field:#C19}
+  #C26 = self::ClassWithList<dynamic> {field:#C19}
+  #C27 = self::ClassWithList<core::num> {field:#C19}
+  #C28 = self::ClassWithList<core::int> {field:#C19}
+  #C29 = self::ClassWithList<core::String> {field:#C19}
+  #C30 = self::ClassWithFunction<dynamic> {field:#C19}
+  #C31 = self::ClassWithFunction<void> {field:#C19}
+  #C32 = self::ClassWithFunction<core::num> {field:#C19}
+  #C33 = self::ClassWithFunction<core::int> {field:#C19}
+}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
new file mode 100644
index 0000000..839df94
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
@@ -0,0 +1,115 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value is{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value is{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value is{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C8;
+  #C9;
+  #C9;
+  #C9;
+  #C10;
+  #C11;
+  #C12;
+  #C13;
+  #C14;
+  #C15;
+  #C16;
+  #C15;
+  #C17;
+  #C18;
+  #C18;
+  #C16;
+  #C20;
+  #C21;
+  #C22;
+  #C23;
+  #C23;
+  #C23;
+  #C24;
+  #C25;
+  #C26;
+  #C27;
+  #C28;
+  #C29;
+  #C29;
+  #C30;
+  #C31;
+  #C32;
+  #C33;
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C4 = true
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num*> {field:#C4}
+  #C7 = self::Class<core::int*> {field:#C4}
+  #C8 = self::Class<core::String*> {field:#C4}
+  #C9 = self::ClassWithBound<core::int*> {field:#C4}
+  #C10 = self::ClassWithBound<core::double*> {field:#C4}
+  #C11 = self::ClassWithList<dynamic> {field:#C4}
+  #C12 = self::ClassWithList<core::num*> {field:#C4}
+  #C13 = self::ClassWithList<core::int*> {field:#C4}
+  #C14 = self::ClassWithList<core::String*> {field:#C4}
+  #C15 = self::ClassWithFunction<dynamic> {field:#C4}
+  #C16 = self::ClassWithFunction<core::Object*> {field:#C4}
+  #C17 = self::ClassWithFunction<void> {field:#C4}
+  #C18 = self::ClassWithFunction<core::int*> {field:#C4}
+  #C19 = false
+  #C20 = self::Class<core::num*> {field:#C19}
+  #C21 = self::Class<core::int*> {field:#C19}
+  #C22 = self::Class<core::String*> {field:#C19}
+  #C23 = self::ClassWithBound<core::double*> {field:#C19}
+  #C24 = self::ClassWithBound<core::num*> {field:#C19}
+  #C25 = self::ClassWithList<dynamic> {field:#C19}
+  #C26 = self::ClassWithList<core::num*> {field:#C19}
+  #C27 = self::ClassWithList<core::int*> {field:#C19}
+  #C28 = self::ClassWithList<core::String*> {field:#C19}
+  #C29 = self::ClassWithFunction<dynamic> {field:#C19}
+  #C30 = self::ClassWithFunction<core::Object*> {field:#C19}
+  #C31 = self::ClassWithFunction<void> {field:#C19}
+  #C32 = self::ClassWithFunction<core::num*> {field:#C19}
+  #C33 = self::ClassWithFunction<core::int*> {field:#C19}
+}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
new file mode 100644
index 0000000..839df94
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
@@ -0,0 +1,115 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::Class<self::Class::T%>
+    : self::Class::field = value is{ForNonNullableByDefault} self::Class::T%, super core::Object::•()
+    ;
+}
+class ClassWithBound<T extends core::num = core::num> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •() → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = (#C1) is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+  const constructor withValue(dynamic value) → self::ClassWithBound<self::ClassWithBound::T>
+    : self::ClassWithBound::field = value is{ForNonNullableByDefault} self::ClassWithBound::T, super core::Object::•()
+    ;
+}
+class ClassWithList<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithList<self::ClassWithList::T%>
+    : self::ClassWithList::field = value is{ForNonNullableByDefault} core::List<self::ClassWithList::T%>, super core::Object::•()
+    ;
+}
+class ClassWithFunction<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool field;
+  const constructor •(dynamic value) → self::ClassWithFunction<self::ClassWithFunction::T%>
+    : self::ClassWithFunction::field = value is{ForNonNullableByDefault} (self::ClassWithFunction::T%) → self::ClassWithFunction::T%, super core::Object::•()
+    ;
+}
+static const field core::num three = #C1;
+static const field (core::int) → core::int idAsIntFunction = #C3;
+static method dynamicFunction(dynamic d) → dynamic
+  return d;
+static method objectFunction(core::Object? o) → core::Object?
+  return o;
+static method intFunction(core::int i) → core::int
+  return i;
+static method idFunction<T extends core::Object? = dynamic>(self::idFunction::T% t) → self::idFunction::T%
+  return t;
+static method main() → void {
+  #C5;
+  #C6;
+  #C7;
+  #C8;
+  #C9;
+  #C9;
+  #C9;
+  #C10;
+  #C11;
+  #C12;
+  #C13;
+  #C14;
+  #C15;
+  #C16;
+  #C15;
+  #C17;
+  #C18;
+  #C18;
+  #C16;
+  #C20;
+  #C21;
+  #C22;
+  #C23;
+  #C23;
+  #C23;
+  #C24;
+  #C25;
+  #C26;
+  #C27;
+  #C28;
+  #C29;
+  #C29;
+  #C30;
+  #C31;
+  #C32;
+  #C33;
+}
+
+constants  {
+  #C1 = 3
+  #C2 = tearoff self::idFunction
+  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C4 = true
+  #C5 = self::Class<dynamic> {field:#C4}
+  #C6 = self::Class<core::num*> {field:#C4}
+  #C7 = self::Class<core::int*> {field:#C4}
+  #C8 = self::Class<core::String*> {field:#C4}
+  #C9 = self::ClassWithBound<core::int*> {field:#C4}
+  #C10 = self::ClassWithBound<core::double*> {field:#C4}
+  #C11 = self::ClassWithList<dynamic> {field:#C4}
+  #C12 = self::ClassWithList<core::num*> {field:#C4}
+  #C13 = self::ClassWithList<core::int*> {field:#C4}
+  #C14 = self::ClassWithList<core::String*> {field:#C4}
+  #C15 = self::ClassWithFunction<dynamic> {field:#C4}
+  #C16 = self::ClassWithFunction<core::Object*> {field:#C4}
+  #C17 = self::ClassWithFunction<void> {field:#C4}
+  #C18 = self::ClassWithFunction<core::int*> {field:#C4}
+  #C19 = false
+  #C20 = self::Class<core::num*> {field:#C19}
+  #C21 = self::Class<core::int*> {field:#C19}
+  #C22 = self::Class<core::String*> {field:#C19}
+  #C23 = self::ClassWithBound<core::double*> {field:#C19}
+  #C24 = self::ClassWithBound<core::num*> {field:#C19}
+  #C25 = self::ClassWithList<dynamic> {field:#C19}
+  #C26 = self::ClassWithList<core::num*> {field:#C19}
+  #C27 = self::ClassWithList<core::int*> {field:#C19}
+  #C28 = self::ClassWithList<core::String*> {field:#C19}
+  #C29 = self::ClassWithFunction<dynamic> {field:#C19}
+  #C30 = self::ClassWithFunction<core::Object*> {field:#C19}
+  #C31 = self::ClassWithFunction<void> {field:#C19}
+  #C32 = self::ClassWithFunction<core::num*> {field:#C19}
+  #C33 = self::ClassWithFunction<core::int*> {field:#C19}
+}
diff --git a/pkg/front_end/testcases/nnbd/regress_null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/regress_null_aware.dart.strong.transformed.expect
index a7e6b48..14ff5aa 100644
--- a/pkg/front_end/testcases/nnbd/regress_null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/regress_null_aware.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 class Class extends core::Object {
@@ -15,7 +14,7 @@
       #t1.{core::List::add}(node);
       final core::Iterable<core::String*>* #t2 = let final core::Iterable<core::String*>* #t3 = let final core::Set<core::String*>* #t4 = this.{self::Class::map}.{core::Map::[]}(node) in #t4.{core::Object::==}(null) ?{core::Iterable<core::String*>*} null : #t4.{core::Iterable::expand}<core::String*>((core::String* node) → core::List<core::String*>* => this.{self::Class::method}(node, set)) in #t3.{core::Object::==}(null) ?{core::List<core::String*>*} null : #t3.{core::Iterable::toList}();
       if(!#t2.{core::Object::==}(null)) {
-        core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t2).{core::Iterable::iterator};
+        core::Iterator<core::String*>* :sync-for-iterator = #t2.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::String* #t5 = :sync-for-iterator.{core::Iterator::current};
           #t1.{core::List::add}(#t5);
diff --git a/pkg/front_end/testcases/nnbd/regress_null_aware.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/regress_null_aware.dart.weak.transformed.expect
index a7e6b48..14ff5aa 100644
--- a/pkg/front_end/testcases/nnbd/regress_null_aware.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/regress_null_aware.dart.weak.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 class Class extends core::Object {
@@ -15,7 +14,7 @@
       #t1.{core::List::add}(node);
       final core::Iterable<core::String*>* #t2 = let final core::Iterable<core::String*>* #t3 = let final core::Set<core::String*>* #t4 = this.{self::Class::map}.{core::Map::[]}(node) in #t4.{core::Object::==}(null) ?{core::Iterable<core::String*>*} null : #t4.{core::Iterable::expand}<core::String*>((core::String* node) → core::List<core::String*>* => this.{self::Class::method}(node, set)) in #t3.{core::Object::==}(null) ?{core::List<core::String*>*} null : #t3.{core::Iterable::toList}();
       if(!#t2.{core::Object::==}(null)) {
-        core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t2).{core::Iterable::iterator};
+        core::Iterator<core::String*>* :sync-for-iterator = #t2.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::String* #t5 = :sync-for-iterator.{core::Iterator::current};
           #t1.{core::List::add}(#t5);
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 7c0e736..bdf53ff 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
@@ -101,8 +101,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -112,21 +112,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync2() → asy::FutureOr<dynamic> /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -136,21 +136,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync3() → asy::FutureOr<core::int> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int>();
   asy::FutureOr<core::int>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -165,21 +165,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync4() → asy::FutureOr<core::int?> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
   asy::FutureOr<core::int?>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -189,21 +189,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync5() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -213,21 +213,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync6() → asy::Future<core::int?> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
   asy::FutureOr<core::int?>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -240,21 +240,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
   asy::FutureOr<core::int?>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -264,13 +264,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method yieldSync() → core::Iterable<dynamic> /* originally sync* */ {
@@ -286,8 +286,8 @@
   asy::_AsyncStarStreamController<dynamic>? :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -297,7 +297,7 @@
         {}
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -368,8 +368,8 @@
     final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -379,21 +379,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync2() → asy::FutureOr<dynamic> /* originally async */ {
     final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -403,21 +403,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync3() → asy::FutureOr<core::int> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int>();
     asy::FutureOr<core::int>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -432,21 +432,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync4() → asy::FutureOr<core::int?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
     asy::FutureOr<core::int?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -456,21 +456,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync5() → asy::Future<core::Null?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::Null?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Null?>();
     asy::FutureOr<core::Null?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -480,21 +480,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync6() → asy::Future<core::int?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
     asy::FutureOr<core::int?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -507,21 +507,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync7() → asy::Future<core::int?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
     asy::FutureOr<core::int?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -531,13 +531,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function yieldSync() → core::Iterable<dynamic> /* originally sync* */ {
@@ -553,8 +553,8 @@
     asy::_AsyncStarStreamController<dynamic>? :controller;
     dynamic :controller_stream;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -564,7 +564,7 @@
           {}
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, core::StackTrace :stack_trace) {
           :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
         }
       finally {
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 319833c..ce589a6 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
@@ -101,8 +101,8 @@
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -112,21 +112,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync2() → asy::FutureOr<dynamic> /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -136,21 +136,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync3() → asy::FutureOr<core::int> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int>();
   asy::FutureOr<core::int>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -165,21 +165,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync4() → asy::FutureOr<core::int?> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
   asy::FutureOr<core::int?>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -189,21 +189,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync5() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -213,21 +213,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync6() → asy::Future<core::int?> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
   asy::FutureOr<core::int?>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -240,21 +240,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
   asy::FutureOr<core::int?>? :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -264,13 +264,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method yieldSync() → core::Iterable<dynamic> /* originally sync* */ {
@@ -286,8 +286,8 @@
   asy::_AsyncStarStreamController<dynamic>? :controller;
   dynamic :controller_stream;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -297,7 +297,7 @@
         {}
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, core::StackTrace :stack_trace) {
         :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
       }
     finally {
@@ -368,8 +368,8 @@
     final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -379,21 +379,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync2() → asy::FutureOr<dynamic> /* originally async */ {
     final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
     asy::FutureOr<dynamic>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -403,21 +403,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync3() → asy::FutureOr<core::int> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int>();
     asy::FutureOr<core::int>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -432,21 +432,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync4() → asy::FutureOr<core::int?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
     asy::FutureOr<core::int?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -456,21 +456,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync5() → asy::Future<core::Null?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::Null?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Null?>();
     asy::FutureOr<core::Null?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -480,21 +480,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync6() → asy::Future<core::int?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
     asy::FutureOr<core::int?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -507,21 +507,21 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function returnAsync7() → asy::Future<core::int?> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::int?>();
     asy::FutureOr<core::int?>? :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -531,13 +531,13 @@
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      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.start(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   }
   function yieldSync() → core::Iterable<dynamic> /* originally sync* */ {
@@ -553,8 +553,8 @@
     asy::_AsyncStarStreamController<dynamic>? :controller;
     dynamic :controller_stream;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (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 
@@ -564,7 +564,7 @@
           {}
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, core::StackTrace :stack_trace) {
           :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
         }
       finally {
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 3d6a2f4..218772f 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
@@ -102,7 +102,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 class A extends core::Object {
@@ -140,7 +139,7 @@
     final core::List<core::String> #t6 = <core::String>[];
     final core::Iterable<core::String>? #t7 = l;
     if(!#t7.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t7{core::Iterable<core::String>}).{core::Iterable::iterator};
+      core::Iterator<core::String> :sync-for-iterator = #t7{core::Iterable<core::String>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String #t8 = :sync-for-iterator.{core::Iterator::current};
         #t6.{core::List::add}(#t8);
@@ -151,7 +150,7 @@
     final core::Set<core::String> #t9 = col::LinkedHashSet::•<core::String>();
     final core::Iterable<core::String>? #t10 = l;
     if(!#t10.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t10{core::Iterable<core::String>}).{core::Iterable::iterator};
+      core::Iterator<core::String> :sync-for-iterator = #t10{core::Iterable<core::String>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t11 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -165,7 +164,7 @@
     final core::Set<core::String> #t13 = col::LinkedHashSet::•<core::String>();
     final core::Iterable<core::String>? #t14 = l;
     if(!#t14.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t14{core::Iterable<core::String>}).{core::Iterable::iterator};
+      core::Iterator<core::String> :sync-for-iterator = #t14{core::Iterable<core::String>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String #t15 = :sync-for-iterator.{core::Iterator::current};
         #t13.{core::Set::add}(#t15);
@@ -176,7 +175,7 @@
     final core::Map<core::String, core::int> #t16 = <core::String, core::int>{};
     final core::Map<core::String, core::int>? #t17 = m;
     if(!#t17.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(#t17{core::Map<core::String, core::int>}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*> :sync-for-iterator = #t17{core::Map<core::String, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String, core::int> #t18 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
@@ -187,7 +186,7 @@
     final core::Map<core::String, core::int> #t19 = <core::String, core::int>{};
     final core::Map<core::String, core::int>? #t20 = m;
     if(!#t20.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(#t20{core::Map<core::String, core::int>}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*> :sync-for-iterator = #t20{core::Map<core::String, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String, core::int> #t21 = :sync-for-iterator.{core::Iterator::current};
         #t19.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
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 3d6a2f4..218772f 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
@@ -102,7 +102,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 class A extends core::Object {
@@ -140,7 +139,7 @@
     final core::List<core::String> #t6 = <core::String>[];
     final core::Iterable<core::String>? #t7 = l;
     if(!#t7.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t7{core::Iterable<core::String>}).{core::Iterable::iterator};
+      core::Iterator<core::String> :sync-for-iterator = #t7{core::Iterable<core::String>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String #t8 = :sync-for-iterator.{core::Iterator::current};
         #t6.{core::List::add}(#t8);
@@ -151,7 +150,7 @@
     final core::Set<core::String> #t9 = col::LinkedHashSet::•<core::String>();
     final core::Iterable<core::String>? #t10 = l;
     if(!#t10.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t10{core::Iterable<core::String>}).{core::Iterable::iterator};
+      core::Iterator<core::String> :sync-for-iterator = #t10{core::Iterable<core::String>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t11 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -165,7 +164,7 @@
     final core::Set<core::String> #t13 = col::LinkedHashSet::•<core::String>();
     final core::Iterable<core::String>? #t14 = l;
     if(!#t14.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t14{core::Iterable<core::String>}).{core::Iterable::iterator};
+      core::Iterator<core::String> :sync-for-iterator = #t14{core::Iterable<core::String>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String #t15 = :sync-for-iterator.{core::Iterator::current};
         #t13.{core::Set::add}(#t15);
@@ -176,7 +175,7 @@
     final core::Map<core::String, core::int> #t16 = <core::String, core::int>{};
     final core::Map<core::String, core::int>? #t17 = m;
     if(!#t17.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(#t17{core::Map<core::String, core::int>}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*> :sync-for-iterator = #t17{core::Map<core::String, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String, core::int> #t18 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
@@ -187,7 +186,7 @@
     final core::Map<core::String, core::int> #t19 = <core::String, core::int>{};
     final core::Map<core::String, core::int>? #t20 = m;
     if(!#t20.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<core::String*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::String*, core::int*>*>*>(#t20{core::Map<core::String, core::int>}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::int*>*> :sync-for-iterator = #t20{core::Map<core::String, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String, core::int> #t21 = :sync-for-iterator.{core::Iterator::current};
         #t19.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect
index c033f30..5600544 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class Base extends core::Object {
   synthetic constructor •() → self::Base*
@@ -31,7 +30,7 @@
 static method main() → dynamic {
   core::List<self::Base*>* list = <self::Base*>[new self::Me::•(), new self::You::•()];
   {
-    core::Iterator<self::Base*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<self::Base*>*>(list).{core::Iterable::iterator};
+    core::Iterator<self::Base*>* :sync-for-iterator = list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       self::Base* baba = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 6d3a0e2..ca35b47 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -2,26 +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.md file.
 
-general/abstract_members: TypeCheckError
-general/bug30695: TypeCheckError
-general/bug30695: TypeCheckError
-general/infer_field_from_multiple: TypeCheckError
-general/invalid_operator: TypeCheckError
-general/issue41210a: TypeCheckError
-general/issue41210b/issue41210: TypeCheckError
-
-general/mixin_application_override: TypeCheckError
-general/override_check_accessor_after_inference: TypeCheckError
-general/override_check_accessor_basic: TypeCheckError
-general/override_check_accessor_with_covariant_modifier: TypeCheckError
-general/override_check_after_inference: TypeCheckError
-general/override_check_basic: TypeCheckError
-general/override_check_with_covariant_modifier: TypeCheckError
-general/override_setter_with_field: TypeCheckError
-
 general_nnbd_opt_out/abstract_members: TypeCheckError
 general_nnbd_opt_out/bug30695: TypeCheckError
-general_nnbd_opt_out/bug30695: TypeCheckError
 general_nnbd_opt_out/mixin_application_override: TypeCheckError
 general_nnbd_opt_out/override_check_accessor_after_inference: TypeCheckError
 general_nnbd_opt_out/override_check_accessor_basic: TypeCheckError
@@ -30,13 +12,26 @@
 general_nnbd_opt_out/override_check_basic: TypeCheckError
 general_nnbd_opt_out/override_check_with_covariant_modifier: TypeCheckError
 general_nnbd_opt_out/override_setter_with_field: TypeCheckError
-
+general/abstract_members: TypeCheckError
+general/bug30695: TypeCheckError
+general/infer_field_from_multiple: TypeCheckError
+general/invalid_operator: TypeCheckError
+general/issue41210a: TypeCheckError
+general/issue41210b/issue41210: TypeCheckError
+general/mixin_application_override: TypeCheckError
+general/override_check_accessor_after_inference: TypeCheckError
+general/override_check_accessor_basic: TypeCheckError
+general/override_check_accessor_with_covariant_modifier: TypeCheckError
+general/override_check_after_inference: TypeCheckError
+general/override_check_basic: TypeCheckError
+general/override_check_with_covariant_modifier: TypeCheckError
+general/override_setter_with_field: TypeCheckError
 inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: Fail
 inference/generic_methods_do_not_infer_invalid_override_of_generic_method: Fail
 inference/generic_methods_handle_override_of_non_generic_with_generic: Fail
 inference/infer_assign_to_index: Fail
-inference/infer_assign_to_property: Fail
 inference/infer_assign_to_property_custom: Fail
+inference/infer_assign_to_property: Fail
 inference/infer_method_missing_params: TypeCheckError
 inference/infer_type_cast: Fail
 inference/infer_types_on_generic_instantiations_infer: TypeCheckError
@@ -44,15 +39,10 @@
 inference/mixin_inference_outwards_4: TypeCheckError
 inference/mixin_inference_unification_1: TypeCheckError
 inference/mixin_inference_unification_2: TypeCheckError
-
 nnbd/inheritance_from_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/never_opt_out: TypeCheckError
-nnbd/issue41210a/issue41210: TypeCheckError
-nnbd/issue41210b: TypeCheckError
-
 rasta/native_is_illegal: Pass # Issue 29763
-
 runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
 runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
index b962902..b17c1d1 100644
--- a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 import "package:expect/expect.dart" as exp;
 
 import "package:expect/expect.dart";
@@ -10,7 +9,7 @@
 static method fact4() → dynamic {
   core::int* f = 1;
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2, 3, 4]).{core::Iterable::iterator};
+    core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3, 4].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int* n = :sync-for-iterator.{core::Iterator::current};
       {
@@ -24,7 +23,7 @@
   core::int* f = 1;
   dynamic n;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[1, 2, 3, 4, 5]).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[1, 2, 3, 4, 5].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -38,7 +37,7 @@
 static method fact6() → dynamic {
   core::int* f = 1;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[1, 2, 3, 4, 5, 6]).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[1, 2, 3, 4, 5, 6].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
index e81f7fc..3e7ecfd 100644
--- a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
@@ -22,7 +22,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static method main() → dynamic {
   {
@@ -30,7 +29,7 @@
   for (var x, y in []) {}
        ^^^";
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
index 1673fff..b936679 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
@@ -85,7 +85,7 @@
 static method b(dynamic c) → invalid-type
   return invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:7:10: Error: Getter not found: 'd'.
 a b(c) = d;
-         ^" as{TypeError,ForDynamic} invalid-type;
+         ^";
 static method main() → dynamic {
   self::C* c = null;
   core::print(#C1);
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
index 211952a..efeabae 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
@@ -85,7 +85,7 @@
 static method b(dynamic c) → invalid-type
   return invalid-expression "pkg/front_end/testcases/rasta/issue_000044.dart:7:10: Error: Getter not found: 'd'.
 a b(c) = d;
-         ^" as{TypeError,ForDynamic} invalid-type;
+         ^";
 static method main() → dynamic {
   self::C* c = null;
   core::print(#C1);
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 48bbc83..cebfb0d 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
@@ -82,7 +82,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 import "dart:collection" as collection;
 
@@ -93,7 +92,7 @@
     ;
   method it1(dynamic x) → dynamic {
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -111,7 +110,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -123,7 +122,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -137,7 +136,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -153,7 +152,7 @@
     for (1 in x) {
          ^";
       {
-        core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = (x as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -175,7 +174,7 @@
 static method main(dynamic arguments) → dynamic {
   new self::Fisk::•();
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = (arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -189,7 +188,7 @@
     }
   }
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = (arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t7 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -201,7 +200,7 @@
     }
   }
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = (arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -215,7 +214,7 @@
     }
   }
   {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = (arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t9 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -231,7 +230,7 @@
   for (1 in arguments) {
        ^";
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = (arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t10 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
index 8a0e754..d20d13f 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
@@ -34,6 +34,6 @@
  - 'Type' is from 'dart:core'.
 Try correcting the operator to an existing operator, or defining a '<' operator.
 type T = Map<A, B>
-            ^" as{TypeError,ForDynamic} invalid-type;
+            ^";
 static field invalid-type B;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
index 8a0e754..d20d13f 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
@@ -34,6 +34,6 @@
  - 'Type' is from 'dart:core'.
 Try correcting the operator to an existing operator, or defining a '<' operator.
 type T = Map<A, B>
-            ^" as{TypeError,ForDynamic} invalid-type;
+            ^";
 static field invalid-type B;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_32200.dart.strong.expect b/pkg/front_end/testcases/regress/issue_32200.dart.strong.expect
index 99cd03a..4750f38 100644
--- a/pkg/front_end/testcases/regress/issue_32200.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_32200.dart.strong.expect
@@ -19,5 +19,5 @@
 }
 static method main() → dynamic {
   self::Foo* instance = new self::Foo::•();
-  instance.{self::Foo::self} = instance as{TypeError} invalid-type;
+  instance.{self::Foo::self} = instance;
 }
diff --git a/pkg/front_end/testcases/regress/issue_32200.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_32200.dart.strong.transformed.expect
index 99cd03a..4750f38 100644
--- a/pkg/front_end/testcases/regress/issue_32200.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_32200.dart.strong.transformed.expect
@@ -19,5 +19,5 @@
 }
 static method main() → dynamic {
   self::Foo* instance = new self::Foo::•();
-  instance.{self::Foo::self} = instance as{TypeError} invalid-type;
+  instance.{self::Foo::self} = instance;
 }
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
index 356eb8e..ad3a1ce 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.strong.expect
@@ -50,10 +50,6 @@
 // Future<List<>> f3() async {
 // ^
 //
-// pkg/front_end/testcases/regress/issue_34850.dart:14:16: Error: Functions marked 'async' must have a return type assignable to 'Future'.
-// Future<List<>> f3() async {
-//                ^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
index 1175daa..730777c 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
@@ -50,10 +50,6 @@
 // Future<List<>> f3() async {
 // ^
 //
-// pkg/front_end/testcases/regress/issue_34850.dart:14:16: Error: Functions marked 'async' must have a return type assignable to 'Future'.
-// Future<List<>> f3() async {
-//                ^^
-//
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
@@ -67,8 +63,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -81,21 +77,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method f3() → invalid-type /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -108,21 +104,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method main() → dynamic /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -139,12 +135,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect
index 79ba707..b47cf9c 100644
--- a/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect
@@ -23,8 +23,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -39,8 +39,8 @@
           final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
           asy::FutureOr<dynamic>* :return_value;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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 
@@ -53,13 +53,13 @@
               asy::_completeOnAsyncReturn(:async_completer, :return_value);
               return;
             }
-            on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+            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.start(:async_op);
+          :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
           return :async_completer.{asy::Completer::future};
         }
         [yield] let dynamic #t1 = asy::_awaitHelper(f_async.call(), :async_op_then, :async_op_error, :async_op) in null;
@@ -68,8 +68,8 @@
           asy::_AsyncStarStreamController<dynamic>* :controller;
           dynamic :controller_stream;
           dynamic :async_stack_trace;
-          dynamic :async_op_then;
-          dynamic :async_op_error;
+          (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;
@@ -86,7 +86,7 @@
                 }
                 return;
               }
-              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+              on dynamic catch(dynamic :exception, core::StackTrace* :stack_trace) {
                 :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
               }
             finally {
@@ -100,7 +100,7 @@
           return :controller_stream;
         }
         {
-          dynamic :stream = (f_async_star.call() as dynamic) as{TypeError,ForDynamic} asy::Stream<dynamic>*;
+          asy::Stream<dynamic>* :stream = (f_async_star.call() as dynamic) as{TypeError,ForDynamic} asy::Stream<dynamic>*;
           asy::_asyncStarListenHelper(:stream, :async_op);
           asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
           try
@@ -138,7 +138,7 @@
           return new core::_SyncIterable::•<dynamic>(:sync_op);
         }
         {
-          core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>((f_sync_star.call() as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
+          core::Iterator<dynamic>* :sync-for-iterator = ((f_sync_star.call() as dynamic) as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             dynamic x = :sync-for-iterator.{core::Iterator::current};
             {
@@ -150,12 +150,12 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
diff --git a/pkg/front_end/testcases/regress/issue_41265.crash_dart b/pkg/front_end/testcases/regress/issue_41265.crash_dart
new file mode 100644
index 0000000..b4deaff
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_41265.crash_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.md file.
+
+class A<T> {}
+
+mixin M<T> {}
+
+class DND1 extends Object with M<dynamic> Function()> {
+}
+
+class DND2 extends Object with M<dynamic> Function() {
+}
+
+class DND3 extends M<dynamic> Function() {
+}
+
+class DND4 implements M<dynamic> Function() {
+}
+
+main() {
+  // nothing.
+}
diff --git a/pkg/front_end/testcases/regress/issue_41265.crash_dart.outline.expect b/pkg/front_end/testcases/regress/issue_41265.crash_dart.outline.expect
new file mode 100644
index 0000000..a373059
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_41265.crash_dart.outline.expect
@@ -0,0 +1,67 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:53: Error: Unexpected token '>'.
+// class DND1 extends Object with M<dynamic> Function()> {
+//                                                     ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:7: Error: The type '() -> M<dynamic>' can't be mixed in.
+// class DND1 extends Object with M<dynamic> Function()> {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:12:7: Error: The type '() -> M<dynamic>' can't be mixed in.
+// class DND2 extends Object with M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:7: Error: Can't use a function type as supertype.
+// class DND1 extends Object with M<dynamic> Function()> {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:12:7: Error: Can't use a function type as supertype.
+// class DND2 extends Object with M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:15:7: Error: Can't use a function type as supertype.
+// class DND3 extends M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:18:7: Error: Can't use a function type as supertype.
+// class DND4 implements M<dynamic> Function() {
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    ;
+}
+abstract class M<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _DND1&Object extends core::Object /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DND1&Object*
+    ;
+}
+class DND1 extends self::_DND1&Object {
+  synthetic constructor •() → self::DND1*
+    ;
+}
+abstract class _DND2&Object extends core::Object /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DND2&Object*
+    ;
+}
+class DND2 extends self::_DND2&Object {
+  synthetic constructor •() → self::DND2*
+    ;
+}
+class DND3 extends core::Object {
+  synthetic constructor •() → self::DND3*
+    ;
+}
+class DND4 extends core::Object {
+  synthetic constructor •() → self::DND4*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_41265.crash_dart.strong.expect b/pkg/front_end/testcases/regress/issue_41265.crash_dart.strong.expect
new file mode 100644
index 0000000..a161395
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_41265.crash_dart.strong.expect
@@ -0,0 +1,73 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:53: Error: Unexpected token '>'.
+// class DND1 extends Object with M<dynamic> Function()> {
+//                                                     ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:7: Error: The type '() -> M<dynamic>' can't be mixed in.
+// class DND1 extends Object with M<dynamic> Function()> {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:12:7: Error: The type '() -> M<dynamic>' can't be mixed in.
+// class DND2 extends Object with M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:7: Error: Can't use a function type as supertype.
+// class DND1 extends Object with M<dynamic> Function()> {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:12:7: Error: Can't use a function type as supertype.
+// class DND2 extends Object with M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:15:7: Error: Can't use a function type as supertype.
+// class DND3 extends M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:18:7: Error: Can't use a function type as supertype.
+// class DND4 implements M<dynamic> Function() {
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    : super core::Object::•()
+    ;
+}
+abstract class M<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _DND1&Object extends core::Object /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DND1&Object*
+    : super core::Object::•()
+    ;
+}
+class DND1 extends self::_DND1&Object {
+  synthetic constructor •() → self::DND1*
+    : super self::_DND1&Object::•()
+    ;
+}
+abstract class _DND2&Object extends core::Object /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DND2&Object*
+    : super core::Object::•()
+    ;
+}
+class DND2 extends self::_DND2&Object {
+  synthetic constructor •() → self::DND2*
+    : super self::_DND2&Object::•()
+    ;
+}
+class DND3 extends core::Object {
+  synthetic constructor •() → self::DND3*
+    : super core::Object::•()
+    ;
+}
+class DND4 extends core::Object {
+  synthetic constructor •() → self::DND4*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_41265.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_41265.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..a161395
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_41265.crash_dart.strong.transformed.expect
@@ -0,0 +1,73 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:53: Error: Unexpected token '>'.
+// class DND1 extends Object with M<dynamic> Function()> {
+//                                                     ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:7: Error: The type '() -> M<dynamic>' can't be mixed in.
+// class DND1 extends Object with M<dynamic> Function()> {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:12:7: Error: The type '() -> M<dynamic>' can't be mixed in.
+// class DND2 extends Object with M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:9:7: Error: Can't use a function type as supertype.
+// class DND1 extends Object with M<dynamic> Function()> {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:12:7: Error: Can't use a function type as supertype.
+// class DND2 extends Object with M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:15:7: Error: Can't use a function type as supertype.
+// class DND3 extends M<dynamic> Function() {
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_41265.crash_dart:18:7: Error: Can't use a function type as supertype.
+// class DND4 implements M<dynamic> Function() {
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    : super core::Object::•()
+    ;
+}
+abstract class M<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _DND1&Object extends core::Object /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DND1&Object*
+    : super core::Object::•()
+    ;
+}
+class DND1 extends self::_DND1&Object {
+  synthetic constructor •() → self::DND1*
+    : super self::_DND1&Object::•()
+    ;
+}
+abstract class _DND2&Object extends core::Object /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_DND2&Object*
+    : super core::Object::•()
+    ;
+}
+class DND2 extends self::_DND2&Object {
+  synthetic constructor •() → self::DND2*
+    : super self::_DND2&Object::•()
+    ;
+}
+class DND3 extends core::Object {
+  synthetic constructor •() → self::DND3*
+    : super core::Object::•()
+    ;
+}
+class DND4 extends core::Object {
+  synthetic constructor •() → self::DND4*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect
index 5ae1f55..6a96046 100644
--- a/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect
@@ -1,7 +1,6 @@
 library test;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class C extends core::Object {
   static field dynamic staticField = null;
@@ -14,7 +13,7 @@
   method test() → void {
     dynamic localVar;
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -23,7 +22,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -32,7 +31,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -41,7 +40,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -50,7 +49,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -59,7 +58,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -68,7 +67,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(<dynamic>[]).{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t7 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/sdk.status b/pkg/front_end/testcases/sdk.status
index f795f08..9119938 100644
--- a/pkg/front_end/testcases/sdk.status
+++ b/pkg/front_end/testcases/sdk.status
@@ -13,6 +13,9 @@
 language_2/conditional_property_increment_decrement_test/16_generated: VerificationError
 language_2/conditional_property_increment_decrement_test/21_generated: VerificationError
 language_2/conditional_property_increment_decrement_test/27_generated: VerificationError
+language_2/constructor5_test: VerificationError
+language_2/constructor6_test: VerificationError
+language_2/extension_methods/static_extension_operators_test: VerificationError
 language_2/if_null_assignment_behavior_test/13_generated: Crash
 language_2/if_null_assignment_behavior_test/15_generated: Crash
 language_2/if_null_assignment_behavior_test/29_generated: Crash
@@ -34,6 +37,3 @@
 language_2/type_variable_scope_test/03_generated: VerificationError
 language_2/void/void_type_usage_test/final_local_use_in_conditional_assignment_left_generated: Crash
 language_2/void/void_type_usage_test/paren_use_in_conditional_assignment_left_generated: Crash
-language_2/constructor5_test: VerificationError
-language_2/constructor6_test: VerificationError
-language_2/extension_methods/static_extension_operators_test: VerificationError
\ No newline at end of file
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
index 3f7f9e6..7b742dc 100644
--- a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
@@ -57,8 +57,8 @@
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
   asy::FutureOr<dynamic>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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;
@@ -105,21 +105,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method mapfun() → asy::Future<core::Map<core::int*, core::bool*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::Map<core::int*, core::bool*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Map<core::int*, core::bool*>*>();
   asy::FutureOr<core::Map<core::int*, core::bool*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -132,21 +132,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method setfun() → asy::Future<core::Set<core::int*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::Set<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Set<core::int*>*>();
   asy::FutureOr<core::Set<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -159,21 +159,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method iterablefun() → asy::Future<core::Iterable<core::int*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<core::Iterable<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Iterable<core::int*>*>();
   asy::FutureOr<core::Iterable<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -186,21 +186,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method lhsfun() → asy::Future<col::LinkedHashSet<core::int*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<col::LinkedHashSet<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<col::LinkedHashSet<core::int*>*>();
   asy::FutureOr<col::LinkedHashSet<core::int*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -218,21 +218,21 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method lhmfun() → asy::Future<col::LinkedHashMap<core::int*, core::bool*>*>* /* originally async */ {
   final asy::_AsyncAwaitCompleter<col::LinkedHashMap<core::int*, core::bool*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<col::LinkedHashMap<core::int*, core::bool*>*>();
   asy::FutureOr<col::LinkedHashMap<core::int*, core::bool*>*>* :return_value;
   dynamic :async_stack_trace;
-  dynamic :async_op_then;
-  dynamic :async_op_error;
+  (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 
@@ -250,13 +250,13 @@
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
     }
-    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+    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.start(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
   return :async_completer.{asy::Completer::future};
 }
 static method mapfun2() → asy::FutureOr<core::Map<core::int*, core::bool*>*>*
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 61f29c9e..d6a567e 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -12,58 +12,6 @@
 extensions/invalid_explicit_access: RuntimeError
 extensions/issue40713: TypeCheckError
 extensions/static_access_of_instance: RuntimeError
-general/abstract_members: TypeCheckError
-general/accessors: RuntimeError
-general/ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
-general/await_in_non_async: RuntimeError # Expected.
-general/bug21938: TypeCheckError
-general/bug30695: TypeCheckError
-general/bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
-general/call: TypeCheckError
-general/candidate_found: TypeCheckError
-general/cascade: RuntimeError
-general/constructor_initializer_invalid: RuntimeError # Fails execution after recovery
-general/covariant_generic: RuntimeError
-general/duplicated_declarations: TypeCheckError
-general/duplicated_field_initializer: RuntimeError
-general/error_locations/error_location_01: RuntimeError
-general/error_locations/error_location_02: RuntimeError
-general/error_locations/error_location_03: RuntimeError
-general/error_locations/error_location_05: RuntimeError
-general/error_locations/error_location_06: RuntimeError
-general/expressions: RuntimeError
-general/external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
-general/incomplete_field_formal_parameter: RuntimeError
-general/infer_field_from_multiple: TypeCheckError
-general/invalid_operator: TypeCheckError
-general/invocations: RuntimeError
-general/issue37776: RuntimeError
-general/issue38938: RuntimeError # no main and compile time errors.
-general/issue38944: RuntimeError # no main and compile time errors.
-general/issue38961: RuntimeError # no main and compile time errors.
-general/issue41210a: TypeCheckError
-general/issue41210b/issue41210: TypeCheckError
-general/micro: RuntimeError
-general/mixin_application_override: ExpectationFileMismatch # Too many errors.
-general/mixin_application_override: TypeCheckError
-general/mixin_constructors_with_default_values: RuntimeError # Expected
-general/operator_method_not_found: RuntimeError # Expected
-general/optional: TypeCheckError
-general/override_check_accessor_after_inference: TypeCheckError # Issue #31620
-general/override_check_accessor_basic: TypeCheckError # Issue #31620
-general/override_check_accessor_with_covariant_modifier: TypeCheckError # Issue #31620
-general/override_check_after_inference: TypeCheckError # Issue #31620
-general/override_check_basic: TypeCheckError # Issue #31620
-general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
-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
-general/unsound_promotion: TypeCheckError
-general/void_methods: RuntimeError
 general_nnbd_opt_out/abstract_members: TypeCheckError
 general_nnbd_opt_out/accessors: RuntimeError
 general_nnbd_opt_out/ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
@@ -112,12 +60,95 @@
 general_nnbd_opt_out/type_variable_bound_access: TypeCheckError
 general_nnbd_opt_out/unsound_promotion: TypeCheckError
 general_nnbd_opt_out/void_methods: RuntimeError
+general/abstract_members: TypeCheckError
+general/accessors: RuntimeError
+general/ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
+general/await_in_non_async: RuntimeError # Expected.
+general/bug21938: TypeCheckError
+general/bug30695: TypeCheckError
+general/bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
+general/call: TypeCheckError
+general/candidate_found: TypeCheckError
+general/cascade: RuntimeError
+general/constructor_initializer_invalid: RuntimeError # Fails execution after recovery
+general/covariant_generic: RuntimeError
+general/duplicated_declarations: TypeCheckError
+general/duplicated_field_initializer: RuntimeError
+general/error_locations/error_location_01: RuntimeError
+general/error_locations/error_location_02: RuntimeError
+general/error_locations/error_location_03: RuntimeError
+general/error_locations/error_location_05: RuntimeError
+general/error_locations/error_location_06: RuntimeError
+general/error_recovery/await_not_in_async: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_general.crash: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_get.crash: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_return_type.crash: RuntimeError
+general/error_recovery/constructor_recovery_bad_name_set.crash: RuntimeError
+general/error_recovery/constructor_recovery_get: RuntimeError
+general/error_recovery/constructor_recovery_ok: RuntimeError
+general/error_recovery/constructor_recovery_operator.crash: RuntimeError
+general/error_recovery/constructor_recovery_return_type: RuntimeError
+general/error_recovery/constructor_recovery_set: RuntimeError
+general/error_recovery/empty_await_for: RuntimeError
+general/error_recovery/empty_for: RuntimeError
+general/error_recovery/issue_38415.crash: RuntimeError
+general/error_recovery/issue_39024.crash: RuntimeError
+general/error_recovery/issue_39026_prime.crash: RuntimeError
+general/error_recovery/issue_39026.crash: RuntimeError
+general/error_recovery/issue_39033.crash: RuntimeError
+general/error_recovery/issue_39058_prime.crash: RuntimeError
+general/error_recovery/issue_39058.crash: RuntimeError
+general/error_recovery/issue_39202.crash: RuntimeError
+general/error_recovery/issue_39230.crash: RuntimeError
+general/error_recovery/issue_39958_01: RuntimeError
+general/error_recovery/issue_39958_02: RuntimeError
+general/error_recovery/issue_39958_03: RuntimeError
+general/error_recovery/issue_39958_04: RuntimeError
+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/incomplete_field_formal_parameter: RuntimeError
+general/infer_field_from_multiple: TypeCheckError
+general/invalid_operator: TypeCheckError
+general/invocations: RuntimeError
+general/issue37776: RuntimeError
+general/issue38938: RuntimeError # no main and compile time errors.
+general/issue38944: RuntimeError # no main and compile time errors.
+general/issue38961: RuntimeError # no main and compile time errors.
+general/issue41210a: TypeCheckError
+general/issue41210b/issue41210: TypeCheckError
+general/micro: RuntimeError
+general/mixin_application_override: ExpectationFileMismatch # Too many errors.
+general/mixin_application_override: TypeCheckError
+general/mixin_constructors_with_default_values: RuntimeError # Expected
+general/operator_method_not_found: RuntimeError # Expected
+general/optional: TypeCheckError
+general/override_check_accessor_after_inference: TypeCheckError # Issue #31620
+general/override_check_accessor_basic: TypeCheckError # Issue #31620
+general/override_check_accessor_with_covariant_modifier: TypeCheckError # Issue #31620
+general/override_check_after_inference: TypeCheckError # Issue #31620
+general/override_check_basic: TypeCheckError # Issue #31620
+general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
+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
+general/unsound_promotion: TypeCheckError
+general/void_methods: RuntimeError
+inference_new/infer_assign_to_index_super_upwards: TypeCheckError
+inference_new/infer_assign_to_index_this_upwards: TypeCheckError
+inference_new/infer_assign_to_index_upwards: TypeCheckError
+inference_new/infer_assign_to_property_custom: TypeCheckError
+inference_new/invalid_assignment_during_toplevel_inference: TypeCheckError
 inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
 inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: TypeCheckError
 inference/downwards_inference_for_each: RuntimeError # Issue #36382
 inference/downwards_inference_on_list_literals_infer_downwards: RuntimeError
-inference/future_then_upwards: RuntimeError
 inference/future_then_upwards_2: RuntimeError
+inference/future_then_upwards: RuntimeError
 inference/generic_methods_correctly_recognize_generic_upper_bound: TypeCheckError
 inference/generic_methods_do_not_infer_invalid_override_of_generic_method: TypeCheckError
 inference/generic_methods_handle_override_of_non_generic_with_generic: TypeCheckError
@@ -132,17 +163,10 @@
 inference/mixin_inference_unification_1: TypeCheckError
 inference/mixin_inference_unification_2: TypeCheckError
 inference/override_equals: RuntimeError
-inference_new/infer_assign_to_index_super_upwards: TypeCheckError
-inference_new/infer_assign_to_index_this_upwards: TypeCheckError
-inference_new/infer_assign_to_index_upwards: TypeCheckError
-inference_new/infer_assign_to_property_custom: TypeCheckError
-inference_new/invalid_assignment_during_toplevel_inference: TypeCheckError
 instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: RuntimeError # Expected
 instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError # Expected
 nnbd/inheritance_from_opt_in: TypeCheckError
 nnbd/issue41180: RuntimeError # Strong mode runtime checking fails due to mixed strong mode.
-nnbd/issue41210a/issue41210: TypeCheckError
-nnbd/issue41210b: TypeCheckError
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/never_opt_out: TypeCheckError
@@ -181,16 +205,16 @@
 rasta/native_is_illegal: RuntimeError
 rasta/parser_error: RuntimeError
 rasta/static: RuntimeError
-rasta/super: TypeCheckError
 rasta/super_initializer: RuntimeError
 rasta/super_mixin: TypeCheckError
 rasta/super_operator: TypeCheckError
+rasta/super: TypeCheckError
 rasta/type_literals: RuntimeError
 rasta/typedef: RuntimeError
-rasta/unresolved: RuntimeError
 rasta/unresolved_constructor: RuntimeError
 rasta/unresolved_for_in: RuntimeError
 rasta/unresolved_recovery: TypeCheckError
+rasta/unresolved: RuntimeError
 regress/issue_29976: RuntimeError # Tests runtime behavior of error recovery.
 regress/issue_29982: RuntimeError # Tests runtime behavior of error recovery.
 regress/issue_30836: RuntimeError # Issue 30836.
@@ -205,8 +229,8 @@
 regress/issue_35260: RuntimeError # Expected
 regress/issue_35266: RuntimeError # Expected
 regress/issue_36400: RuntimeError
-regress/issue_36647: RuntimeError # Expected
 regress/issue_36647_2: RuntimeError # Expected
+regress/issue_36647: RuntimeError # Expected
 regress/issue_36669: RuntimeError
 regress/issue_37285: RuntimeError
 regress/issue_39035.crash: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 9e2e2bb..f800f49 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -35,8 +35,8 @@
 extensions/extension_constructor: TextSerializationFailure
 extensions/extension_field_with_type_parameter_usage: TextSerializationFailure
 extensions/extension_methods: TextSerializationFailure
-extensions/extension_setter: TextSerializationFailure
 extensions/extension_setter_error: TypeCheckError
+extensions/extension_setter: TextSerializationFailure
 extensions/generic_function_in_generic_extension: TextSerializationFailure
 extensions/getter_setter_conflict: TextSerializationFailure
 extensions/if_null: TextSerializationFailure
@@ -44,8 +44,8 @@
 extensions/implicit_this: TextSerializationFailure
 extensions/import_via_prefix: TextSerializationFailure
 extensions/index: TextSerializationFailure
-extensions/instance_access: TextSerializationFailure
 extensions/instance_access_of_static: TextSerializationFailure
+extensions/instance_access: TextSerializationFailure
 extensions/instance_members: TextSerializationFailure
 extensions/instance_tearoff: TextSerializationFailure
 extensions/internal_resolution: TextSerializationFailure
@@ -73,313 +73,12 @@
 extensions/operators: TextSerializationFailure
 extensions/other_kinds: TextSerializationFailure
 extensions/private_members: TextSerializationFailure
-extensions/static_access: TextSerializationFailure
 extensions/static_access_of_instance: TextSerializationFailure
+extensions/static_access: TextSerializationFailure
 extensions/tear_offs: TextSerializationFailure
 extensions/type_variables: TextSerializationFailure
 extensions/unnamed_extensions: TextSerializationFailure
 extensions/use_this: TextSerializationFailure
-general/DeltaBlue: TextSerializationFailure # Was: Pass
-general/abstract_members: TypeCheckError
-general/abstract_overrides_concrete_with_no_such_method: TextSerializationFailure
-general/accessors: TextSerializationFailure # Was: RuntimeError
-general/all_variances: TextSerializationFailure
-general/ambiguous_exports: TextSerializationFailure # Was: RuntimeError # Expected, this file exports two main methods.
-general/annotation_eof: TextSerializationFailure # Was: Pass
-general/annotation_on_enum_values: TextSerializationFailure # Was: Pass
-general/annotation_top: TextSerializationFailure # Was: Pass
-general/annotation_typedef_formals: TextSerializationFailure # Was: Pass
-general/annotation_typedef_formals_resolution: TextSerializationFailure # Was: Pass
-general/annotation_variable_declaration: TextSerializationFailure # Was: Pass
-general/argument: TextSerializationFailure # Was: Pass
-general/argument_mismatch: TextSerializationFailure
-general/arithmetic: TextSerializationFailure # Was: Pass
-general/arrow_function: TextSerializationFailure # Was: Pass
-general/assign_to_initializing_formal: TextSerializationFailure
-general/async_function: TextSerializationFailure # Was: Pass
-general/async_nested: TextSerializationFailure # Was: Pass
-general/await: TextSerializationFailure # Was: Pass
-general/await_complex: TextSerializationFailure
-general/await_in_cascade: TextSerializationFailure
-general/await_in_non_async: TextSerializationFailure
-general/bad_setter_abstract: TextSerializationFailure # Was: Pass
-general/bad_store: TextSerializationFailure # Was: Pass
-general/bad_type_variable_uses_in_supertypes: TextSerializationFailure
-general/bounds_check_depends_on_inference: TextSerializationFailure # Was: Pass
-general/bug21938: TypeCheckError
-general/bug30695: TypeCheckError
-general/bug31124: TextSerializationFailure # Was: RuntimeError # Test has no main method (and we shouldn't add one).
-general/bug32414a: TextSerializationFailure # Was: Pass
-general/bug32414b: TextSerializationFailure # Was: Pass
-general/bug32426: TextSerializationFailure # Was: Pass
-general/bug32629: TextSerializationFailure
-general/bug32866: TextSerializationFailure # Was: Pass
-general/bug33099: TextSerializationFailure # Was: Pass
-general/bug33196: TextSerializationFailure # Was: Pass
-general/bug33206: TextSerializationFailure # Was: Pass
-general/bug33298: TextSerializationFailure # Was: Pass
-general/bug34511: TextSerializationFailure # Was: Pass
-general/bug35470: TextSerializationFailure # Was: Pass
-general/bug37476: TextSerializationFailure
-general/call: TypeCheckError
-general/candidate_found: TypeCheckError
-general/cascade: TextSerializationFailure # Was: RuntimeError
-general/casts: TextSerializationFailure # Was: Pass
-general/check_deferred_allocation: TextSerializationFailure # Was: Pass
-general/check_deferred_as_check: TextSerializationFailure # Was: Pass
-general/check_deferred_before_args2: TextSerializationFailure # Was: Pass
-general/check_deferred_before_args: TextSerializationFailure # Was: Pass
-general/check_deferred_before_call: TextSerializationFailure # Was: Pass
-general/check_deferred_before_write: TextSerializationFailure # Was: Pass
-general/check_deferred_is_check: TextSerializationFailure # Was: Pass
-general/check_deferred_read: TextSerializationFailure # Was: Pass
-general/check_deferred_read_static_field: TextSerializationFailure # Was: Pass
-general/check_deferred_read_type: TextSerializationFailure # Was: Pass
-general/check_deferred_static_method_call: TextSerializationFailure # Was: Pass
-general/check_deferred_type_declaration: TextSerializationFailure # Was: Pass
-general/circularity-via-initializing-formal: TextSerializationFailure # Was: Pass
-general/classes: TextSerializationFailure # Was: Pass
-general/clone_function_type: TextSerializationFailure # Was: Pass
-general/closure: TextSerializationFailure # Was: Pass
-general/co19_language_metadata_syntax_t04: TextSerializationFailure # Was: Pass
-general/complex_class_hierarchy: TextSerializationFailure
-general/compound_binary_implicit_as: TextSerializationFailure
-general/const_redirect_to_nonconst: TextSerializationFailure
-general/constructor_const_inference: TextSerializationFailure # Was: Pass
-general/constructor_cycle: TextSerializationFailure # Was: Pass
-general/constructor_function_types: TextSerializationFailure # Was: Pass
-general/constructor_initializer_invalid: TextSerializationFailure # Was: RuntimeError # Fails execution after recovery
-general/continue_inference_after_error: TextSerializationFailure # Was: Pass
-general/continue_inference_after_error_lib: TextSerializationFailure # Was: Pass
-general/control_flow_collection: TextSerializationFailure
-general/control_flow_collection_inference: TextSerializationFailure
-general/covariant_generic: TextSerializationFailure # Was: RuntimeError
-general/covariant_parameter_in_superclass_of_mixin_application: TextSerializationFailure
-general/cycles: TextSerializationFailure # Was: Pass
-general/default_values: TextSerializationFailure # Was: Pass
-general/deferred_lib: TextSerializationFailure # Was: Pass
-general/deferred_type_annotation: TextSerializationFailure # Was: Pass
-general/demote_closure_types: TextSerializationFailure
-general/duplicated_bad_prefix: TextSerializationFailure # Was: Pass
-general/duplicated_bad_prefix_lib1: TextSerializationFailure # Was: Pass
-general/duplicated_bad_prefix_lib2: TextSerializationFailure # Was: Pass
-general/duplicated_declarations: TypeCheckError
-general/duplicated_declarations_lib: TextSerializationFailure # Was: Pass
-general/duplicated_declarations_part: TextSerializationFailure # Was: Pass
-general/duplicated_field_initializer: TextSerializationFailure # Was: RuntimeError
-general/duplicated_named_args_3: TextSerializationFailure # Was: Pass
-general/dynamic_and_void: TextSerializationFailure
-general/error_locations/error_location_01: TextSerializationFailure
-general/error_locations/error_location_02: TextSerializationFailure
-general/error_locations/error_location_03: TextSerializationFailure
-general/error_locations/error_location_04: TextSerializationFailure
-general/error_locations/error_location_05: TextSerializationFailure
-general/error_locations/error_location_06: TextSerializationFailure
-general/escape: TextSerializationFailure # Was: Pass
-general/export_main: TextSerializationFailure # Was: Pass
-general/export_test: TextSerializationFailure # Was: Pass
-general/expressions: TextSerializationFailure # Was: RuntimeError
-general/extend_with_type_variable: TextSerializationFailure
-general/external: TextSerializationFailure # Was: Pass
-general/external_import: TextSerializationFailure # Was: RuntimeError # The native extension to import doesn't exist. This is ok.
-general/fallthrough: TextSerializationFailure
-general/ffi_sample: TextSerializationFailure
-general/fibonacci: TextSerializationFailure # Was: Pass
-general/for_in_scope: TextSerializationFailure # Was: Pass
-general/for_in_without_declaration: TextSerializationFailure
-general/forwarding_stub_for_operator: TextSerializationFailure
-general/function_in_field: TextSerializationFailure # Was: Pass
-general/function_type_assignments: TextSerializationFailure # Was: Pass
-general/function_type_default_value: TextSerializationFailure
-general/function_type_is_check: TextSerializationFailure # Was: Pass
-general/function_type_recovery: TextSerializationFailure # Was: Pass
-general/functions: TextSerializationFailure # Was: Pass
-general/future_or_test: TextSerializationFailure # Was: Pass
-general/generic_function_type_in_message: TextSerializationFailure
-general/getter_call: TextSerializationFailure
-general/having_part_with_part_and_annotation: TextSerializationFailure
-general/having_part_with_parts_and_annotation: TextSerializationFailure
-general/hello: TextSerializationFailure # Was: Pass
-general/if_null_in_cascade: TextSerializationFailure
-general/if_null_in_list_literal: TextSerializationFailure
-general/if_null_in_set_literal: TextSerializationFailure
-general/ignore_function: TextSerializationFailure
-general/illegal_named_function_expression: TextSerializationFailure # Was: Pass
-general/illegal_named_function_expression_scope: TextSerializationFailure # Was: Pass
-general/implicit_const_with_static_fields: TextSerializationFailure # Was: Pass
-general/implicit_new: TextSerializationFailure # Was: Pass
-general/implicit_scope_test: TextSerializationFailure # Was: Pass
-general/implicit_this: TextSerializationFailure # Was: Pass
-general/import_conflicting_getters: TextSerializationFailure
-general/import_conflicting_setters: TextSerializationFailure
-general/import_conflicting_type_member: TextSerializationFailure
-general/import_conflicting_types: TextSerializationFailure
-general/incomplete_field_formal_parameter: TextSerializationFailure # Was: RuntimeError
-general/infer_field_from_multiple: TypeCheckError
-general/infer_field_type: TextSerializationFailure
-general/infer_fixed_generic_return_type: TextSerializationFailure
-general/infer_map_literal_with_closure: TextSerializationFailure
-general/inherit_function: TextSerializationFailure
-general/interface_conflict: TextSerializationFailure
-general/interface_contravariant_from_class: TextSerializationFailure
-general/interface_covariantImpl_from_class: TextSerializationFailure
-general/interface_covariantInterface_from_class: TextSerializationFailure
-general/invalid_assignment: TextSerializationFailure # Was: Pass
-general/invalid_cast: TextSerializationFailure # Was: Pass
-general/invalid_operator2: TextSerializationFailure
-general/invalid_operator: TypeCheckError
-general/invalid_type: TextSerializationFailure
-general/invocations: TextSerializationFailure # Was: RuntimeError
-general/issue129167943: TextSerializationFailure
-general/issue34515: TextSerializationFailure
-general/issue34899: TextSerializationFailure
-general/issue35875: TextSerializationFailure
-general/issue37027: TextSerializationFailure
-general/issue37381: TextSerializationFailure
-general/issue37776: TextSerializationFailure
-general/issue38812: TextSerializationFailure
-general/issue38938: TextSerializationFailure
-general/issue38943: TextSerializationFailure
-general/issue38944: TextSerializationFailure
-general/issue38961: TextSerializationFailure
-general/issue39344: TextSerializationFailure
-general/issue39421: TextSerializationFailure
-general/issue39817: TextSerializationFailure
-general/issue40242: TextSerializationFailure
-general/issue40428: TextSerializationFailure
-general/issue40662: TextSerializationFailure
-general/issue40744: TextSerializationFailure
-general/issue41070: TextSerializationFailure
-general/issue41210a: TypeCheckError
-general/issue41210b/issue41210: TypeCheckError
-general/literals: TextSerializationFailure # Was: Pass
-general/local_generic_function: TextSerializationFailure # Was: Pass
-general/long_chain_of_typedefs: TextSerializationFailure
-general/magic_const: TextSerializationFailure # Was: Pass
-general/many_errors: TextSerializationFailure
-general/map: TextSerializationFailure # Was: Pass
-general/metadata_enum: TextSerializationFailure # Was: Pass
-general/metadata_named_mixin_application: TextSerializationFailure # Was: Pass
-general/micro: TextSerializationFailure # Was: RuntimeError
-general/minimum_int: TextSerializationFailure # Was: Pass
-general/missing_constructor: TextSerializationFailure # Was: Pass
-general/missing_toplevel: TextSerializationFailure
-general/mixin: TextSerializationFailure # Was: Pass
-general/mixin_application_inferred_parameter_type: TextSerializationFailure
-general/mixin_application_override: ExpectationFileMismatch
-general/mixin_application_override: TypeCheckError
-general/mixin_conflicts: TextSerializationFailure
-general/mixin_constructors_with_default_values: TextSerializationFailure # Was: Pass
-general/mixin_covariant: TextSerializationFailure
-general/mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
-general/mixin_interface_conflict: TextSerializationFailure
-general/mixin_super_repeated: TextSerializationFailure # Was: Pass
-general/mixin_with_static_member: TextSerializationFailure
-general/named_function_scope: TextSerializationFailure # Was: Pass
-general/named_parameters: TextSerializationFailure # Was: Pass
-general/native_as_name: TextSerializationFailure # Was: Pass
-general/nested_implicit_const_with_env_var: TextSerializationFailure # Was: Pass
-general/nested_property_set: TextSerializationFailure
-general/nested_variable_set: TextSerializationFailure
-general/nested_variance: TextSerializationFailure
-general/no_such_method_private_setter: TextSerializationFailure # Was: Pass
-general/no_such_method_private_setter_lib: TextSerializationFailure # Was: Pass
-general/non_covariant_checks: TextSerializationFailure
-general/null_aware: TextSerializationFailure # Was: Pass
-general/null_aware_for_in: TextSerializationFailure
-general/null_aware_postfix: TextSerializationFailure
-general/null_aware_spread: TextSerializationFailure
-general/operator_method_not_found: TextSerializationFailure
-general/operators: TextSerializationFailure # Was: Pass
-general/optional: TypeCheckError
-general/override: TextSerializationFailure # Was: Pass
-general/override_check_accessor_after_inference: TypeCheckError # Issue #31620
-general/override_check_accessor_basic: TypeCheckError # Issue #31620
-general/override_check_accessor_with_covariant_modifier: TypeCheckError # Issue #31620
-general/override_check_after_inference: TypeCheckError # Issue #31620
-general/override_check_basic: TypeCheckError # Issue #31620
-general/override_check_generic_method_f_bounded: TextSerializationFailure # Was: Pass
-general/override_check_two_substitutions: TextSerializationFailure # Was: Pass
-general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
-general/override_inference_for_getters_and_setters: TextSerializationFailure
-general/override_inference_for_setters: TextSerializationFailure
-general/override_inference_named_parameters_ordering: TextSerializationFailure
-general/override_setter_with_field: TypeCheckError
-general/part_as_entry_point: TextSerializationFailure # Was: Pass
-general/part_as_entry_point_lib: TextSerializationFailure # Was: Pass
-general/part_not_part_of: TextSerializationFailure
-general/part_not_part_of_same_named_library: TextSerializationFailure
-general/part_part_of_different_unnamed_library: TextSerializationFailure
-general/part_part_of_differently_named_library: TextSerializationFailure
-general/platform: TextSerializationFailure
-general/platform_invalid_uris/main: TextSerializationFailure
-general/prefer_baseclass: TextSerializationFailure # Was: Pass
-general/private_method_tearoff: TextSerializationFailure # Was: Pass
-general/private_method_tearoff_lib: TextSerializationFailure # Was: Pass
-general/promoted_access: TextSerializationFailure
-general/promoted_null_aware_access: TextSerializationFailure
-general/public_method_tearoff: TextSerializationFailure # Was: Pass
-general/public_method_tearoff_lib: TextSerializationFailure # Was: Pass
-general/qualified: TextSerializationFailure # Was: Pass
-general/qualified_lib: TextSerializationFailure # Was: Pass
-general/qualified_part: TextSerializationFailure # Was: Pass
-general/redirecting_constructor: TextSerializationFailure # Was: Pass
-general/redirecting_factory: TextSerializationFailure # Was: Pass
-general/redirecting_factory_chain_test: TextSerializationFailure # Was: Pass
-general/redirecting_factory_const_inference: TextSerializationFailure # Was: Pass
-general/redirecting_factory_metadata: TextSerializationFailure # Was: Pass
-general/redirecting_factory_simple_test: TextSerializationFailure # Was: Pass
-general/redirecting_factory_typeargs_test: TextSerializationFailure # Was: Pass
-general/redirecting_factory_typeparam_test: TextSerializationFailure # Was: Pass
-general/redirecting_factory_typeparambounds_test: TextSerializationFailure # Was: Pass
-general/redirecting_initializer_arguments_assignable_test: TextSerializationFailure # Was: Pass
-general/redirecting_initializer_arguments_test: TextSerializationFailure # Was: Pass
-general/redirection_chain_type_arguments: TextSerializationFailure # Was: Pass
-general/redirection_chain_type_arguments_subst: TextSerializationFailure # Was: Pass
-general/redirection_type_arguments: TextSerializationFailure # Was: Pass
-general/reject_generic_function_types_in_bounds: TextSerializationFailure # Was: RuntimeError # Expected
-general/return_with_unknown_type_in_context: TextSerializationFailure # Was: Pass
-general/sdk_diagnostic: TextSerializationFailure
-general/spread_collection: TextSerializationFailure # Should be fixed as part of implementing spread collection support
-general/spread_collection_inference: TextSerializationFailure # Should be fixed as part of implementing spread collection support
-general/statements: Crash
-general/static_setter: TextSerializationFailure # Was: Pass
-general/store_load: TextSerializationFailure # Was: Pass
-general/stringliteral: TextSerializationFailure # Was: Pass
-general/super_call: TextSerializationFailure # Was: Pass
-general/super_nsm: TextSerializationFailure # Was: Pass
-general/tabs: TextSerializationFailure # Was: Pass
-general/this_field_call: TextSerializationFailure
-general/three_typedefs_loop: TextSerializationFailure
-general/top_level_accessors: TextSerializationFailure # Was: Pass
-general/top_level_accessors_part: TextSerializationFailure # Was: Pass
-general/top_level_library_method: TextSerializationFailure # Was: Pass
-general/type_literal_as_metadata: TextSerializationFailure
-general/type_of_null: TextSerializationFailure
-general/type_parameter_type_named_int: TextSerializationFailure
-general/type_parameter_usage_in_static_method_in_class: TextSerializationFailure
-general/type_parameter_usage_in_static_method_in_extension: TextSerializationFailure
-general/type_parameters_on_dynamic: TextSerializationFailure
-general/type_parameters_on_void: TextSerializationFailure
-general/type_variable_as_super: TextSerializationFailure # Was: RuntimeError
-general/type_variable_bound_access: TypeCheckError
-general/type_variable_prefix: TextSerializationFailure # Was: RuntimeError
-general/type_variable_uses: TextSerializationFailure # Was: Pass
-general/typedef: TextSerializationFailure # Was: Pass
-general/undefined: TextSerializationFailure # Was: Pass
-general/undefined_getter_in_compound_assignment: TextSerializationFailure # Was: Pass
-general/uninitialized_fields: TextSerializationFailure # Was: Pass
-general/unsound_promotion: TypeCheckError
-general/unused_methods: TextSerializationFailure # Was: Pass
-general/var_as_type_name: TextSerializationFailure # Was: Pass
-general/vm_type_ops: TextSerializationFailure
-general/void_methods: TextSerializationFailure
-general/warn_unresolved_sends: TextSerializationFailure
-general/well_boundness_checks_in_outline: TextSerializationFailure
-general/with_dependencies/abstract_members_from_dill/main: TextSerializationFailure
-general/with_dependencies/extension_from_dill/extension_from_dill: TextSerializationFailure
-general/with_dependencies/variance_from_dill/variance_from_dill: TextSerializationFailure
-general_nnbd_opt_out/DeltaBlue: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/abstract_members: TypeCheckError
 general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method: TextSerializationFailure
 general_nnbd_opt_out/accessors: TextSerializationFailure # Was: RuntimeError
@@ -388,20 +87,20 @@
 general_nnbd_opt_out/annotation_eof: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/annotation_on_enum_values: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/annotation_top: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/annotation_typedef_formals: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/annotation_typedef_formals_resolution: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/annotation_typedef_formals: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/annotation_variable_declaration: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/argument: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/argument_mismatch: TextSerializationFailure
+general_nnbd_opt_out/argument: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/arithmetic: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/arrow_function: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/assign_to_initializing_formal: TextSerializationFailure
 general_nnbd_opt_out/async_function: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/async_nested: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/await: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/await_complex: TextSerializationFailure
 general_nnbd_opt_out/await_in_cascade: TextSerializationFailure
 general_nnbd_opt_out/await_in_non_async: TextSerializationFailure
+general_nnbd_opt_out/await: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/bad_setter_abstract: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/bad_store: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/bad_type_variable_uses_in_supertypes: TextSerializationFailure
@@ -427,14 +126,14 @@
 general_nnbd_opt_out/casts: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_allocation: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_as_check: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_before_args2: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_before_args: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/check_deferred_before_args2: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_before_call: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_before_write: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_is_check: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/check_deferred_read: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_read_static_field: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_read_type: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/check_deferred_read: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_static_method_call: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/check_deferred_type_declaration: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/circularity-via-initializing-formal: TextSerializationFailure # Was: Pass
@@ -449,22 +148,24 @@
 general_nnbd_opt_out/constructor_cycle: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/constructor_function_types: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/constructor_initializer_invalid: TextSerializationFailure # Was: RuntimeError # Fails execution after recovery
-general_nnbd_opt_out/continue_inference_after_error: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/continue_inference_after_error_lib: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/control_flow_collection: TextSerializationFailure
+general_nnbd_opt_out/continue_inference_after_error: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/control_flow_collection_inference: TextSerializationFailure
+general_nnbd_opt_out/control_flow_collection: TextSerializationFailure
+general_nnbd_opt_out/covariant_equals: TextSerializationFailure
 general_nnbd_opt_out/covariant_generic: TextSerializationFailure # Was: RuntimeError
 general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application: TextSerializationFailure
 general_nnbd_opt_out/cycles: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/default_values: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/deferred_lib: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/deferred_type_annotation: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/duplicated_bad_prefix: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/DeltaBlue: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/duplicated_bad_prefix_lib1: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/duplicated_bad_prefix_lib2: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/duplicated_declarations: TypeCheckError
+general_nnbd_opt_out/duplicated_bad_prefix: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/duplicated_declarations_lib: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/duplicated_declarations_part: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/duplicated_declarations: TypeCheckError
 general_nnbd_opt_out/duplicated_field_initializer: TextSerializationFailure # Was: RuntimeError
 general_nnbd_opt_out/duplicated_named_args_3: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/dynamic_and_void: TextSerializationFailure
@@ -479,8 +180,8 @@
 general_nnbd_opt_out/export_test: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/expressions: TextSerializationFailure # Was: RuntimeError
 general_nnbd_opt_out/extend_with_type_variable: TextSerializationFailure
-general_nnbd_opt_out/external: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/external_import: TextSerializationFailure # Was: RuntimeError # The native extension to import doesn't exist. This is ok.
+general_nnbd_opt_out/external: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/fallthrough: TextSerializationFailure
 general_nnbd_opt_out/ffi_sample: TextSerializationFailure
 general_nnbd_opt_out/fibonacci: TextSerializationFailure # Was: Pass
@@ -502,8 +203,8 @@
 general_nnbd_opt_out/if_null_in_list_literal: TextSerializationFailure
 general_nnbd_opt_out/if_null_in_set_literal: TextSerializationFailure
 general_nnbd_opt_out/ignore_function: TextSerializationFailure
-general_nnbd_opt_out/illegal_named_function_expression: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/illegal_named_function_expression_scope: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/illegal_named_function_expression: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/implicit_const_with_static_fields: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/implicit_new: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/implicit_scope_test: TextSerializationFailure # Was: Pass
@@ -547,7 +248,6 @@
 general_nnbd_opt_out/minimum_int: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/missing_constructor: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/missing_toplevel: TextSerializationFailure
-general_nnbd_opt_out/mixin: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/mixin_application_inferred_parameter_type: TextSerializationFailure
 general_nnbd_opt_out/mixin_application_override: ExpectationFileMismatch
 general_nnbd_opt_out/mixin_application_override: TypeCheckError
@@ -556,6 +256,7 @@
 general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/mixin_super_repeated: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/mixin_with_static_member: TextSerializationFailure
+general_nnbd_opt_out/mixin: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/named_function_scope: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/named_parameters: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/native_as_name: TextSerializationFailure # Was: Pass
@@ -563,17 +264,16 @@
 general_nnbd_opt_out/nested_property_set: TextSerializationFailure
 general_nnbd_opt_out/nested_variable_set: TextSerializationFailure
 general_nnbd_opt_out/nested_variance: TextSerializationFailure
-general_nnbd_opt_out/no_such_method_private_setter: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/no_such_method_private_setter_lib: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/no_such_method_private_setter: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/non_covariant_checks: TextSerializationFailure
-general_nnbd_opt_out/null_aware: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/null_aware_for_in: TextSerializationFailure
 general_nnbd_opt_out/null_aware_postfix: TextSerializationFailure
 general_nnbd_opt_out/null_aware_spread: TextSerializationFailure
+general_nnbd_opt_out/null_aware: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/operator_method_not_found: TextSerializationFailure
 general_nnbd_opt_out/operators: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/optional: TypeCheckError
-general_nnbd_opt_out/override: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/override_check_accessor_after_inference: TypeCheckError # Issue #31620
 general_nnbd_opt_out/override_check_accessor_basic: TypeCheckError # Issue #31620
 general_nnbd_opt_out/override_check_accessor_with_covariant_modifier: TypeCheckError # Issue #31620
@@ -585,24 +285,24 @@
 general_nnbd_opt_out/override_inference_for_setters: TextSerializationFailure
 general_nnbd_opt_out/override_inference_named_parameters_ordering: TextSerializationFailure
 general_nnbd_opt_out/override_setter_with_field: TypeCheckError
-general_nnbd_opt_out/part_as_entry_point: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/override: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/part_as_entry_point_lib: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/part_not_part_of: TextSerializationFailure
+general_nnbd_opt_out/part_as_entry_point: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/part_not_part_of_same_named_library: TextSerializationFailure
+general_nnbd_opt_out/part_not_part_of: TextSerializationFailure
 general_nnbd_opt_out/part_part_of_different_unnamed_library: TextSerializationFailure
 general_nnbd_opt_out/part_part_of_differently_named_library: TextSerializationFailure
 general_nnbd_opt_out/platform: TextSerializationFailure
 general_nnbd_opt_out/prefer_baseclass: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/private_method_tearoff: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/private_method_tearoff_lib: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/private_method_tearoff: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/promoted_access: TextSerializationFailure
-general_nnbd_opt_out/public_method_tearoff: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/public_method_tearoff_lib: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/qualified: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/public_method_tearoff: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/qualified_lib: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/qualified_part: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/qualified: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_constructor: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/redirecting_factory: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_factory_chain_test: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_factory_const_inference: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_factory_metadata: TextSerializationFailure # Was: Pass
@@ -610,16 +310,17 @@
 general_nnbd_opt_out/redirecting_factory_typeargs_test: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_factory_typeparam_test: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_factory_typeparambounds_test: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/redirecting_factory: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_initializer_arguments_assignable_test: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirecting_initializer_arguments_test: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/redirection_chain_type_arguments: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirection_chain_type_arguments_subst: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/redirection_chain_type_arguments: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/redirection_type_arguments: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/reject_generic_function_types_in_bounds: TextSerializationFailure # Was: RuntimeError # Expected
 general_nnbd_opt_out/return_with_unknown_type_in_context: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/sdk_diagnostic: TextSerializationFailure
-general_nnbd_opt_out/spread_collection: TextSerializationFailure # Should be fixed as part of implementing spread collection support
 general_nnbd_opt_out/spread_collection_inference: TextSerializationFailure # Should be fixed as part of implementing spread collection support
+general_nnbd_opt_out/spread_collection: TextSerializationFailure # Should be fixed as part of implementing spread collection support
 general_nnbd_opt_out/statements: Crash
 general_nnbd_opt_out/static_setter: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/store_load: TextSerializationFailure # Was: Pass
@@ -628,8 +329,8 @@
 general_nnbd_opt_out/super_nsm: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/tabs: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/three_typedefs_loop: TextSerializationFailure
-general_nnbd_opt_out/top_level_accessors: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/top_level_accessors_part: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/top_level_accessors: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/top_level_library_method: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/type_literal_as_metadata: TextSerializationFailure
 general_nnbd_opt_out/type_of_null: TextSerializationFailure
@@ -639,49 +340,441 @@
 general_nnbd_opt_out/type_variable_prefix: TextSerializationFailure # Was: RuntimeError
 general_nnbd_opt_out/type_variable_uses: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/typedef: TextSerializationFailure # Was: Pass
-general_nnbd_opt_out/undefined: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/undefined_getter_in_compound_assignment: TextSerializationFailure # Was: Pass
+general_nnbd_opt_out/undefined: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/uninitialized_fields: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/unsound_promotion: TypeCheckError
 general_nnbd_opt_out/unused_methods: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/var_as_type_name: TextSerializationFailure # Was: Pass
 general_nnbd_opt_out/void_methods: TextSerializationFailure
 general_nnbd_opt_out/warn_unresolved_sends: TextSerializationFailure
+general/abstract_members: TypeCheckError
+general/abstract_overrides_concrete_with_no_such_method: TextSerializationFailure
+general/accessors: TextSerializationFailure # Was: RuntimeError
+general/all_variances: TextSerializationFailure
+general/ambiguous_exports: TextSerializationFailure # Was: RuntimeError # Expected, this file exports two main methods.
+general/annotation_eof: TextSerializationFailure # Was: Pass
+general/annotation_on_enum_values: TextSerializationFailure # Was: Pass
+general/annotation_top: TextSerializationFailure # Was: Pass
+general/annotation_typedef_formals_resolution: TextSerializationFailure # Was: Pass
+general/annotation_typedef_formals: TextSerializationFailure # Was: Pass
+general/annotation_variable_declaration: TextSerializationFailure # Was: Pass
+general/argument_mismatch: TextSerializationFailure
+general/argument: TextSerializationFailure # Was: Pass
+general/arithmetic: TextSerializationFailure # Was: Pass
+general/arrow_function: TextSerializationFailure # Was: Pass
+general/assign_to_initializing_formal: TextSerializationFailure
+general/async_function: TextSerializationFailure # Was: Pass
+general/async_nested: TextSerializationFailure # Was: Pass
+general/await_complex: TextSerializationFailure
+general/await_in_cascade: TextSerializationFailure
+general/await_in_non_async: TextSerializationFailure
+general/await: TextSerializationFailure # Was: Pass
+general/bad_setter_abstract: TextSerializationFailure # Was: Pass
+general/bad_store: TextSerializationFailure # Was: Pass
+general/bad_type_variable_uses_in_supertypes: TextSerializationFailure
+general/bounds_check_depends_on_inference: TextSerializationFailure # Was: Pass
+general/bug21938: TypeCheckError
+general/bug30695: TypeCheckError
+general/bug31124: TextSerializationFailure # Was: RuntimeError # Test has no main method (and we shouldn't add one).
+general/bug32414a: TextSerializationFailure # Was: Pass
+general/bug32414b: TextSerializationFailure # Was: Pass
+general/bug32426: TextSerializationFailure # Was: Pass
+general/bug32629: TextSerializationFailure
+general/bug32866: TextSerializationFailure # Was: Pass
+general/bug33099: TextSerializationFailure # Was: Pass
+general/bug33196: TextSerializationFailure # Was: Pass
+general/bug33206: TextSerializationFailure # Was: Pass
+general/bug33298: TextSerializationFailure # Was: Pass
+general/bug34511: TextSerializationFailure # Was: Pass
+general/bug35470: TextSerializationFailure # Was: Pass
+general/bug37476: TextSerializationFailure
+general/call: TypeCheckError
+general/candidate_found: TypeCheckError
+general/cascade: TextSerializationFailure # Was: RuntimeError
+general/casts: TextSerializationFailure # Was: Pass
+general/check_deferred_allocation: TextSerializationFailure # Was: Pass
+general/check_deferred_as_check: TextSerializationFailure # Was: Pass
+general/check_deferred_before_args: TextSerializationFailure # Was: Pass
+general/check_deferred_before_args2: TextSerializationFailure # Was: Pass
+general/check_deferred_before_call: TextSerializationFailure # Was: Pass
+general/check_deferred_before_write: TextSerializationFailure # Was: Pass
+general/check_deferred_is_check: TextSerializationFailure # Was: Pass
+general/check_deferred_read_static_field: TextSerializationFailure # Was: Pass
+general/check_deferred_read_type: TextSerializationFailure # Was: Pass
+general/check_deferred_read: TextSerializationFailure # Was: Pass
+general/check_deferred_static_method_call: TextSerializationFailure # Was: Pass
+general/check_deferred_type_declaration: TextSerializationFailure # Was: Pass
+general/circularity-via-initializing-formal: TextSerializationFailure # Was: Pass
+general/classes: TextSerializationFailure # Was: Pass
+general/clone_function_type: TextSerializationFailure # Was: Pass
+general/closure: TextSerializationFailure # Was: Pass
+general/co19_language_metadata_syntax_t04: TextSerializationFailure # Was: Pass
+general/complex_class_hierarchy: TextSerializationFailure
+general/compound_binary_implicit_as: TextSerializationFailure
+general/const_redirect_to_nonconst: TextSerializationFailure
+general/constant_truncate: TextSerializationFailure
+general/constructor_const_inference: TextSerializationFailure # Was: Pass
+general/constructor_cycle: TextSerializationFailure # Was: Pass
+general/constructor_function_types: TextSerializationFailure # Was: Pass
+general/constructor_initializer_invalid: TextSerializationFailure # Was: RuntimeError # Fails execution after recovery
+general/continue_inference_after_error_lib: TextSerializationFailure # Was: Pass
+general/continue_inference_after_error: TextSerializationFailure # Was: Pass
+general/control_flow_collection_inference: TextSerializationFailure
+general/control_flow_collection: TextSerializationFailure
+general/covariant_equals: TextSerializationFailure
+general/covariant_generic: TextSerializationFailure # Was: RuntimeError
+general/covariant_parameter_in_superclass_of_mixin_application: TextSerializationFailure
+general/cycles: TextSerializationFailure # Was: Pass
+general/default_values: TextSerializationFailure # Was: Pass
+general/deferred_lib: TextSerializationFailure # Was: Pass
+general/deferred_type_annotation: TextSerializationFailure # Was: Pass
+general/DeltaBlue: TextSerializationFailure # Was: Pass
+general/demote_closure_types: TextSerializationFailure
+general/duplicated_bad_prefix_lib1: TextSerializationFailure # Was: Pass
+general/duplicated_bad_prefix_lib2: TextSerializationFailure # Was: Pass
+general/duplicated_bad_prefix: TextSerializationFailure # Was: Pass
+general/duplicated_declarations_lib: TextSerializationFailure # Was: Pass
+general/duplicated_declarations_part: TextSerializationFailure # Was: Pass
+general/duplicated_declarations: TypeCheckError
+general/duplicated_field_initializer: TextSerializationFailure # Was: RuntimeError
+general/duplicated_named_args_3: TextSerializationFailure # Was: Pass
+general/dynamic_and_void: TextSerializationFailure
+general/error_locations/error_location_01: TextSerializationFailure
+general/error_locations/error_location_02: TextSerializationFailure
+general/error_locations/error_location_03: TextSerializationFailure
+general/error_locations/error_location_04: TextSerializationFailure
+general/error_locations/error_location_05: TextSerializationFailure
+general/error_locations/error_location_06: TextSerializationFailure
+general/error_recovery/await_not_in_async: TextSerializationFailure
+general/error_recovery/constructor_recovery_bad_name_general.crash: TextSerializationFailure
+general/error_recovery/constructor_recovery_bad_name_get.crash: TextSerializationFailure
+general/error_recovery/constructor_recovery_bad_name_return_type.crash: TextSerializationFailure
+general/error_recovery/constructor_recovery_bad_name_set.crash: TextSerializationFailure
+general/error_recovery/constructor_recovery_get: TextSerializationFailure
+general/error_recovery/constructor_recovery_ok: TextSerializationFailure
+general/error_recovery/constructor_recovery_operator.crash: TextSerializationFailure
+general/error_recovery/constructor_recovery_return_type: TextSerializationFailure
+general/error_recovery/constructor_recovery_set: TextSerializationFailure
+general/error_recovery/empty_await_for: TextSerializationFailure
+general/error_recovery/empty_for: TextSerializationFailure
+general/error_recovery/issue_38415.crash: TextSerializationFailure
+general/error_recovery/issue_39024.crash: RuntimeError
+general/error_recovery/issue_39026_prime.crash: TextSerializationFailure
+general/error_recovery/issue_39026.crash: TextSerializationFailure
+general/error_recovery/issue_39033.crash: TextSerializationFailure
+general/error_recovery/issue_39058_prime.crash: RuntimeError
+general/error_recovery/issue_39058.crash: RuntimeError
+general/error_recovery/issue_39060: TextSerializationFailure
+general/error_recovery/issue_39202.crash: TextSerializationFailure
+general/error_recovery/issue_39230.crash: TextSerializationFailure
+general/error_recovery/issue_39958_01: TextSerializationFailure
+general/error_recovery/issue_39958_02: TextSerializationFailure
+general/error_recovery/issue_39958_03: TextSerializationFailure
+general/error_recovery/issue_39958_04: TextSerializationFailure
+general/error_recovery/yield_not_in_generator: TextSerializationFailure
+general/escape: TextSerializationFailure # Was: Pass
+general/export_main: TextSerializationFailure # Was: Pass
+general/export_test: TextSerializationFailure # Was: Pass
+general/expressions: TextSerializationFailure # Was: RuntimeError
+general/extend_with_type_variable: TextSerializationFailure
+general/external_import: TextSerializationFailure # Was: RuntimeError # The native extension to import doesn't exist. This is ok.
+general/external: TextSerializationFailure # Was: Pass
+general/fallthrough: TextSerializationFailure
+general/ffi_sample: TextSerializationFailure
+general/fibonacci: TextSerializationFailure # Was: Pass
+general/for_in_scope: TextSerializationFailure # Was: Pass
+general/for_in_without_declaration: TextSerializationFailure
+general/forwarding_stub_for_operator: TextSerializationFailure
+general/function_in_field: TextSerializationFailure # Was: Pass
+general/function_type_assignments: TextSerializationFailure # Was: Pass
+general/function_type_default_value: TextSerializationFailure
+general/function_type_is_check: TextSerializationFailure # Was: Pass
+general/function_type_recovery: TextSerializationFailure # Was: Pass
+general/functions: TextSerializationFailure # Was: Pass
+general/future_or_test: TextSerializationFailure # Was: Pass
+general/generic_function_type_in_message: TextSerializationFailure
+general/getter_call: TextSerializationFailure
+general/having_part_with_part_and_annotation: TextSerializationFailure
+general/having_part_with_parts_and_annotation: TextSerializationFailure
+general/hello: TextSerializationFailure # Was: Pass
+general/if_null_in_cascade: TextSerializationFailure
+general/if_null_in_list_literal: TextSerializationFailure
+general/if_null_in_set_literal: TextSerializationFailure
+general/ignore_function: TextSerializationFailure
+general/illegal_named_function_expression_scope: TextSerializationFailure # Was: Pass
+general/illegal_named_function_expression: TextSerializationFailure # Was: Pass
+general/implicit_const_with_static_fields: TextSerializationFailure # Was: Pass
+general/implicit_new: TextSerializationFailure # Was: Pass
+general/implicit_scope_test: TextSerializationFailure # Was: Pass
+general/implicit_this: TextSerializationFailure # Was: Pass
+general/import_conflicting_getters: TextSerializationFailure
+general/import_conflicting_setters: TextSerializationFailure
+general/import_conflicting_type_member: TextSerializationFailure
+general/import_conflicting_types: TextSerializationFailure
+general/incomplete_field_formal_parameter: TextSerializationFailure # Was: RuntimeError
+general/infer_field_from_multiple: TypeCheckError
+general/infer_field_type: TextSerializationFailure
+general/infer_fixed_generic_return_type: TextSerializationFailure
+general/infer_map_literal_with_closure: TextSerializationFailure
+general/inherit_function: TextSerializationFailure
+general/interface_conflict: TextSerializationFailure
+general/interface_contravariant_from_class: TextSerializationFailure
+general/interface_covariantImpl_from_class: TextSerializationFailure
+general/interface_covariantInterface_from_class: TextSerializationFailure
+general/invalid_assignment: TextSerializationFailure # Was: Pass
+general/invalid_cast: TextSerializationFailure # Was: Pass
+general/invalid_operator: TypeCheckError
+general/invalid_operator2: TextSerializationFailure
+general/invalid_type: TextSerializationFailure
+general/invocations: TextSerializationFailure # Was: RuntimeError
+general/issue129167943: TextSerializationFailure
+general/issue34515: TextSerializationFailure
+general/issue34899: TextSerializationFailure
+general/issue35875: TextSerializationFailure
+general/issue37027: TextSerializationFailure
+general/issue37381: TextSerializationFailure
+general/issue37776: TextSerializationFailure
+general/issue38812: TextSerializationFailure
+general/issue38938: TextSerializationFailure
+general/issue38943: TextSerializationFailure
+general/issue38944: TextSerializationFailure
+general/issue38961: TextSerializationFailure
+general/issue39344: TextSerializationFailure
+general/issue39421: TextSerializationFailure
+general/issue39817: TextSerializationFailure
+general/issue40242: TextSerializationFailure
+general/issue40428: TextSerializationFailure
+general/issue40662: TextSerializationFailure
+general/issue40744: TextSerializationFailure
+general/issue41070: TextSerializationFailure
+general/issue41210a: TypeCheckError
+general/issue41210b/issue41210: TypeCheckError
+general/literals: TextSerializationFailure # Was: Pass
+general/local_generic_function: TextSerializationFailure # Was: Pass
+general/long_chain_of_typedefs: TextSerializationFailure
+general/magic_const: TextSerializationFailure # Was: Pass
+general/many_errors: TextSerializationFailure
+general/map: TextSerializationFailure # Was: Pass
+general/metadata_enum: TextSerializationFailure # Was: Pass
+general/metadata_named_mixin_application: TextSerializationFailure # Was: Pass
+general/micro: TextSerializationFailure # Was: RuntimeError
+general/minimum_int: TextSerializationFailure # Was: Pass
+general/missing_constructor: TextSerializationFailure # Was: Pass
+general/missing_toplevel: TextSerializationFailure
+general/mixin_application_inferred_parameter_type: TextSerializationFailure
+general/mixin_application_override: ExpectationFileMismatch
+general/mixin_application_override: TypeCheckError
+general/mixin_conflicts: TextSerializationFailure
+general/mixin_constructors_with_default_values: TextSerializationFailure # Was: Pass
+general/mixin_covariant: TextSerializationFailure
+general/mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
+general/mixin_interface_conflict: TextSerializationFailure
+general/mixin_super_repeated: TextSerializationFailure # Was: Pass
+general/mixin_with_static_member: TextSerializationFailure
+general/mixin: TextSerializationFailure # Was: Pass
+general/named_function_scope: TextSerializationFailure # Was: Pass
+general/named_parameters: TextSerializationFailure # Was: Pass
+general/native_as_name: TextSerializationFailure # Was: Pass
+general/nested_implicit_const_with_env_var: TextSerializationFailure # Was: Pass
+general/nested_property_set: TextSerializationFailure
+general/nested_variable_set: TextSerializationFailure
+general/nested_variance: TextSerializationFailure
+general/no_such_method_private_setter_lib: TextSerializationFailure # Was: Pass
+general/no_such_method_private_setter: TextSerializationFailure # Was: Pass
+general/non_covariant_checks: TextSerializationFailure
+general/null_aware_for_in: TextSerializationFailure
+general/null_aware_postfix: TextSerializationFailure
+general/null_aware_spread: TextSerializationFailure
+general/null_aware: TextSerializationFailure # Was: Pass
+general/operator_method_not_found: TextSerializationFailure
+general/operators: TextSerializationFailure # Was: Pass
+general/optional: TypeCheckError
+general/override_check_accessor_after_inference: TypeCheckError # Issue #31620
+general/override_check_accessor_basic: TypeCheckError # Issue #31620
+general/override_check_accessor_with_covariant_modifier: TypeCheckError # Issue #31620
+general/override_check_after_inference: TypeCheckError # Issue #31620
+general/override_check_basic: TypeCheckError # Issue #31620
+general/override_check_generic_method_f_bounded: TextSerializationFailure # Was: Pass
+general/override_check_two_substitutions: TextSerializationFailure # Was: Pass
+general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
+general/override_inference_for_getters_and_setters: TextSerializationFailure
+general/override_inference_for_setters: TextSerializationFailure
+general/override_inference_named_parameters_ordering: TextSerializationFailure
+general/override_setter_with_field: TypeCheckError
+general/override: TextSerializationFailure # Was: Pass
+general/part_as_entry_point_lib: TextSerializationFailure # Was: Pass
+general/part_as_entry_point: TextSerializationFailure # Was: Pass
+general/part_not_part_of_same_named_library: TextSerializationFailure
+general/part_not_part_of: TextSerializationFailure
+general/part_part_of_different_unnamed_library: TextSerializationFailure
+general/part_part_of_differently_named_library: TextSerializationFailure
+general/platform_invalid_uris/main: TextSerializationFailure
+general/platform: TextSerializationFailure
+general/prefer_baseclass: TextSerializationFailure # Was: Pass
+general/private_method_tearoff_lib: TextSerializationFailure # Was: Pass
+general/private_method_tearoff: TextSerializationFailure # Was: Pass
+general/promoted_access: TextSerializationFailure
+general/promoted_null_aware_access: TextSerializationFailure
+general/public_method_tearoff_lib: TextSerializationFailure # Was: Pass
+general/public_method_tearoff: TextSerializationFailure # Was: Pass
+general/qualified_lib: TextSerializationFailure # Was: Pass
+general/qualified_part: TextSerializationFailure # Was: Pass
+general/qualified: TextSerializationFailure # Was: Pass
+general/redirecting_constructor: TextSerializationFailure # Was: Pass
+general/redirecting_factory_chain_test: TextSerializationFailure # Was: Pass
+general/redirecting_factory_const_inference: TextSerializationFailure # Was: Pass
+general/redirecting_factory_metadata: TextSerializationFailure # Was: Pass
+general/redirecting_factory_simple_test: TextSerializationFailure # Was: Pass
+general/redirecting_factory_typeargs_test: TextSerializationFailure # Was: Pass
+general/redirecting_factory_typeparam_test: TextSerializationFailure # Was: Pass
+general/redirecting_factory_typeparambounds_test: TextSerializationFailure # Was: Pass
+general/redirecting_factory: TextSerializationFailure # Was: Pass
+general/redirecting_initializer_arguments_assignable_test: TextSerializationFailure # Was: Pass
+general/redirecting_initializer_arguments_test: TextSerializationFailure # Was: Pass
+general/redirection_chain_type_arguments_subst: TextSerializationFailure # Was: Pass
+general/redirection_chain_type_arguments: TextSerializationFailure # Was: Pass
+general/redirection_type_arguments: TextSerializationFailure # Was: Pass
+general/reject_generic_function_types_in_bounds: TextSerializationFailure # Was: RuntimeError # Expected
+general/return_with_unknown_type_in_context: TextSerializationFailure # Was: Pass
+general/sdk_diagnostic: TextSerializationFailure
+general/spread_collection_inference: TextSerializationFailure # Should be fixed as part of implementing spread collection support
+general/spread_collection: TextSerializationFailure # Should be fixed as part of implementing spread collection support
+general/statements: Crash
+general/static_setter: TextSerializationFailure # Was: Pass
+general/store_load: TextSerializationFailure # Was: Pass
+general/stringliteral: TextSerializationFailure # Was: Pass
+general/super_call: TextSerializationFailure # Was: Pass
+general/super_nsm: TextSerializationFailure # Was: Pass
+general/tabs: TextSerializationFailure # Was: Pass
+general/this_field_call: TextSerializationFailure
+general/three_typedefs_loop: TextSerializationFailure
+general/top_level_accessors_part: TextSerializationFailure # Was: Pass
+general/top_level_accessors: TextSerializationFailure # Was: Pass
+general/top_level_library_method: TextSerializationFailure # Was: Pass
+general/type_literal_as_metadata: TextSerializationFailure
+general/type_of_null: TextSerializationFailure
+general/type_parameter_type_named_int: TextSerializationFailure
+general/type_parameter_usage_in_static_method_in_class: TextSerializationFailure
+general/type_parameter_usage_in_static_method_in_extension: TextSerializationFailure
+general/type_parameters_on_dynamic: TextSerializationFailure
+general/type_parameters_on_void: TextSerializationFailure
+general/type_variable_as_super: TextSerializationFailure # Was: RuntimeError
+general/type_variable_bound_access: TypeCheckError
+general/type_variable_prefix: TextSerializationFailure # Was: RuntimeError
+general/type_variable_uses: TextSerializationFailure # Was: Pass
+general/typedef: TextSerializationFailure # Was: Pass
+general/undefined_getter_in_compound_assignment: TextSerializationFailure # Was: Pass
+general/undefined: TextSerializationFailure # Was: Pass
+general/uninitialized_fields: TextSerializationFailure # Was: Pass
+general/unsound_promotion: TypeCheckError
+general/unused_methods: TextSerializationFailure # Was: Pass
+general/var_as_type_name: TextSerializationFailure # Was: Pass
+general/vm_type_ops: TextSerializationFailure
+general/void_methods: TextSerializationFailure
+general/warn_unresolved_sends: TextSerializationFailure
+general/well_boundness_checks_in_outline: TextSerializationFailure
+general/with_dependencies/abstract_members_from_dill/main: TextSerializationFailure
+general/with_dependencies/extension_from_dill/extension_from_dill: TextSerializationFailure
+general/with_dependencies/variance_from_dill/variance_from_dill: TextSerializationFailure
 implicit_getter_calls/getter_call: TextSerializationFailure
 implicit_getter_calls/this_field_call: TextSerializationFailure
+inference_new/const_invocation: TextSerializationFailure # Was: Pass
+inference_new/dependency_only_if_generic_method: TextSerializationFailure # Was: Pass
+inference_new/dependency_only_if_overloaded: TextSerializationFailure # Was: Pass
+inference_new/dependency_only_if_overloaded: TypeCheckError
+inference_new/do_loop: TextSerializationFailure # Was: Pass
+inference_new/downwards_inference_inside_top_level_2: TextSerializationFailure # Was: Pass
+inference_new/downwards_inference_inside_top_level: TextSerializationFailure # Was: Pass
+inference_new/field_inference_circularity: TextSerializationFailure # Was: Pass
+inference_new/for_each_identifier_downwards: TextSerializationFailure # Was: Pass
+inference_new/for_each_invalid_iterable: TextSerializationFailure # Was: Pass
+inference_new/for_each_outer_var_type: TextSerializationFailure # Was: Pass
+inference_new/indexed_assign_combiner: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_implicit_this_upwards: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_implicit_this: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_index_full: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_index_set_vs_get: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_index_super_upwards: TypeCheckError
+inference_new/infer_assign_to_index_super: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_index_this_upwards: TypeCheckError
+inference_new/infer_assign_to_index_this: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_index_upwards: TypeCheckError
+inference_new/infer_assign_to_index: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_local_upwards: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_local: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_property_custom: TypeCheckError
+inference_new/infer_assign_to_property_full: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_property_null_aware_upwards: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_property_null_aware: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_property_super_upwards: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_property_super: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_property_upwards: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_property: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_ref: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_static_upwards: TextSerializationFailure # Was: Pass
+inference_new/infer_assign_to_static: TextSerializationFailure # Was: Pass
+inference_new/infer_field_getter_setter_mismatch: TextSerializationFailure
+inference_new/infer_field_override_accessors: TextSerializationFailure
+inference_new/infer_field_override_getter_overrides_setter: TextSerializationFailure
+inference_new/infer_field_override_setter_overrides_getter: TextSerializationFailure # Was: Pass
+inference_new/infer_instance_accessor_ref: TextSerializationFailure # Was: Pass
+inference_new/infer_instance_field_ref_circular: TextSerializationFailure # Was: Pass
+inference_new/infer_instance_field_ref: TextSerializationFailure # Was: Pass
+inference_new/infer_logical: TextSerializationFailure # Was: Pass
+inference_new/infer_use_of_void: TextSerializationFailure # Was: Pass
+inference_new/invalid_assignment_during_toplevel_inference: TypeCheckError
+inference_new/list_literals_can_infer_null_top_level: TextSerializationFailure # Was: Pass
+inference_new/map_literals_can_infer_null_top_level: TextSerializationFailure # Was: Pass
+inference_new/multiple_interface_inheritance: TextSerializationFailure # Was: Pass
+inference_new/null_aware_property_get: TextSerializationFailure
+inference_new/property_assign_combiner: TextSerializationFailure # Was: Pass
+inference_new/property_get_toplevel: TextSerializationFailure # Was: Pass
+inference_new/static_assign_combiner: TextSerializationFailure # Was: Pass
+inference_new/strongly_connected_component: TextSerializationFailure # Was: Pass
+inference_new/strongly_connected_component: TypeCheckError
+inference_new/super_index_get_substitution: TextSerializationFailure # Was: Pass
+inference_new/super_index_get: TextSerializationFailure # Was: Pass
+inference_new/switch: TextSerializationFailure # Was: Pass
+inference_new/top_level_field_depends_on_multiple_inheritance: ExpectationFileMismatch
+inference_new/top_level_field_depends_on_multiple_inheritance: TextSerializationFailure # Was: Pass
+inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: TextSerializationFailure # Was: Pass
+inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: TextSerializationFailure # Was: Pass
+inference_new/void_return_type_subtypes_dynamic: TextSerializationFailure # Was: Pass
+inference_new/while_loop: TextSerializationFailure # Was: Pass
 inference/abstract_class_instantiation: TextSerializationFailure
-inference/assert: TextSerializationFailure # Was: Pass
 inference/assert_initializer: TextSerializationFailure # Was: Pass
+inference/assert: TextSerializationFailure # Was: Pass
 inference/assign_local: TextSerializationFailure # Was: Pass
 inference/async_await: TextSerializationFailure # Was: Pass
 inference/async_closure_return_type_flatten: TextSerializationFailure # Was: Pass
-inference/async_closure_return_type_future: TextSerializationFailure # Was: Pass
 inference/async_closure_return_type_future_or: TextSerializationFailure # Was: Pass
+inference/async_closure_return_type_future: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_async_all_returns_are_futures: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_async_all_returns_are_values: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_async_mix_of_values_and_futures: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_async_star: TextSerializationFailure # Was: Pass
-inference/block_bodied_lambdas_basic: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_basic_void: TextSerializationFailure # Was: Pass
-inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference: TextSerializationFailure # Was: Pass
+inference/block_bodied_lambdas_basic: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level: TextSerializationFailure # Was: Pass
-inference/block_bodied_lambdas_infer_bottom_async: TextSerializationFailure # Was: Pass
+inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_infer_bottom_async_star: TextSerializationFailure # Was: Pass
-inference/block_bodied_lambdas_infer_bottom_sync: TextSerializationFailure # Was: Pass
+inference/block_bodied_lambdas_infer_bottom_async: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_infer_bottom_sync_star: TextSerializationFailure # Was: Pass
+inference/block_bodied_lambdas_infer_bottom_sync: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_lub: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_nested_lambdas: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_no_return: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_returns: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_sync_star: TextSerializationFailure # Was: Pass
 inference/block_bodied_lambdas_void_context: TextSerializationFailure # Was: Pass
-inference/bottom: TextSerializationFailure # Was: Pass
 inference/bottom_in_closure: TextSerializationFailure # Was: Pass
+inference/bottom: TextSerializationFailure # Was: Pass
 inference/bug30251: TextSerializationFailure # Was: Pass
-inference/bug30620: TextSerializationFailure # Was: Pass
 inference/bug30620_b: TextSerializationFailure # Was: Pass
 inference/bug30620_c: TextSerializationFailure # Was: Pass
 inference/bug30620_d: TextSerializationFailure # Was: Pass
+inference/bug30620: TextSerializationFailure # Was: Pass
 inference/bug30624: TextSerializationFailure # Was: Pass
 inference/bug31132: TextSerializationFailure # Was: Pass
 inference/bug31133: TextSerializationFailure # Was: Pass
@@ -691,29 +784,29 @@
 inference/call_corner_cases: TextSerializationFailure # Was: Pass
 inference/callable_generic_class: TextSerializationFailure # Was: Pass
 inference/circular_method_inference: TextSerializationFailure # Was: Pass
-inference/circular_reference_via_closures: TextSerializationFailure # Was: Pass
 inference/circular_reference_via_closures_initializer_types: TextSerializationFailure # Was: Pass
+inference/circular_reference_via_closures: TextSerializationFailure # Was: Pass
 inference/closure_param_null_to_object: TextSerializationFailure # Was: Pass
 inference/coerce_bottom_and_null_types: TextSerializationFailure # Was: Pass
 inference/complex_predecrement: TextSerializationFailure # Was: Pass
 inference/conditional_lub: TextSerializationFailure # Was: Pass
 inference/conditional_upwards_inference: TextSerializationFailure # Was: Pass
 inference/conflicting_fields: TextSerializationFailure
-inference/conflicts_can_happen2: TextSerializationFailure
 inference/conflicts_can_happen: TextSerializationFailure
+inference/conflicts_can_happen2: TextSerializationFailure
 inference/constructors_downwards_with_constraint: TextSerializationFailure # Was: Pass
-inference/constructors_infer_from_arguments: TextSerializationFailure # Was: Pass
 inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
-inference/constructors_infer_from_arguments_const: TextSerializationFailure # Was: Pass
 inference/constructors_infer_from_arguments_const_with_upper_bound: TextSerializationFailure # Was: Pass
+inference/constructors_infer_from_arguments_const: TextSerializationFailure # Was: Pass
 inference/constructors_infer_from_arguments_downwards_from_constructor: TextSerializationFailure
-inference/constructors_infer_from_arguments_factory: TextSerializationFailure # Was: Pass
 inference/constructors_infer_from_arguments_factory_calls_constructor: TextSerializationFailure # Was: Pass
-inference/constructors_infer_from_arguments_named: TextSerializationFailure # Was: Pass
+inference/constructors_infer_from_arguments_factory: TextSerializationFailure # Was: Pass
 inference/constructors_infer_from_arguments_named_factory: TextSerializationFailure # Was: Pass
-inference/constructors_infer_from_arguments_redirecting: TextSerializationFailure # Was: Pass
-inference/constructors_infer_from_arguments_redirecting_factory: TextSerializationFailure # Was: Pass
+inference/constructors_infer_from_arguments_named: TextSerializationFailure # Was: Pass
 inference/constructors_infer_from_arguments_redirecting_factory_to_factory: TextSerializationFailure # Was: Pass
+inference/constructors_infer_from_arguments_redirecting_factory: TextSerializationFailure # Was: Pass
+inference/constructors_infer_from_arguments_redirecting: TextSerializationFailure # Was: Pass
+inference/constructors_infer_from_arguments: TextSerializationFailure # Was: Pass
 inference/constructors_inference_f_bounded: TextSerializationFailure # Was: Pass
 inference/constructors_reverse_type_parameters: TextSerializationFailure # Was: Pass
 inference/constructors_too_many_positional_arguments: TextSerializationFailure
@@ -724,22 +817,22 @@
 inference/downward_inference_fixes_no_upwards_errors: TextSerializationFailure # Was: Pass
 inference/downward_inference_miscellaneous: TextSerializationFailure # Was: Pass
 inference/downwards_context_from_inferred_field_type: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations: TextSerializationFailure # Was: Pass
 inference/downwards_inference_annotations_class_members: TextSerializationFailure # Was: Pass
 inference/downwards_inference_annotations_for_loop_variable: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_locals: TextSerializationFailure # Was: Pass
 inference/downwards_inference_annotations_locals_referring_to_locals: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_parameter: TextSerializationFailure # Was: Pass
+inference/downwards_inference_annotations_locals: TextSerializationFailure # Was: Pass
 inference/downwards_inference_annotations_parameter_local: TextSerializationFailure # Was: Pass
-inference/downwards_inference_annotations_type_variable: TextSerializationFailure
+inference/downwards_inference_annotations_parameter: TextSerializationFailure # Was: Pass
 inference/downwards_inference_annotations_type_variable_local: TextSerializationFailure # Was: Pass
+inference/downwards_inference_annotations_type_variable: TextSerializationFailure
 inference/downwards_inference_annotations_typedef: TextSerializationFailure # Was: Pass
+inference/downwards_inference_annotations: TextSerializationFailure # Was: Pass
 inference/downwards_inference_assignment_statements: TextSerializationFailure # Was: Pass
 inference/downwards_inference_async_await: TextSerializationFailure # Was: Pass
 inference/downwards_inference_for_each: TextSerializationFailure # Was: Pass
 inference/downwards_inference_initializing_formal_default_formal: TextSerializationFailure # Was: Pass
-inference/downwards_inference_inside_top_level: TextSerializationFailure # Was: Pass
 inference/downwards_inference_inside_top_level_2: TextSerializationFailure # Was: Pass
+inference/downwards_inference_inside_top_level: TextSerializationFailure # Was: Pass
 inference/downwards_inference_on_constructor_arguments_infer_downwards: TextSerializationFailure # Was: Pass
 inference/downwards_inference_on_function_arguments_infer_downwards: TextSerializationFailure # Was: Pass
 inference/downwards_inference_on_function_expressions: TextSerializationFailure # Was: Pass
@@ -765,33 +858,33 @@
 inference/for_loop_initializer_expression: TextSerializationFailure # Was: Pass
 inference/for_loop_promotion: TextSerializationFailure # Was: Pass
 inference/future_or_subtyping: TextSerializationFailure # Was: Pass
-inference/future_then: TextSerializationFailure # Was: Pass
 inference/future_then_2: TextSerializationFailure # Was: Pass
 inference/future_then_3: TextSerializationFailure # Was: Pass
 inference/future_then_4: TextSerializationFailure # Was: Pass
 inference/future_then_5: TextSerializationFailure # Was: Pass
 inference/future_then_6: TextSerializationFailure # Was: Pass
-inference/future_then_conditional: TextSerializationFailure # Was: Pass
 inference/future_then_conditional_2: TextSerializationFailure # Was: Pass
 inference/future_then_conditional_3: TextSerializationFailure # Was: Pass
 inference/future_then_conditional_4: TextSerializationFailure # Was: Pass
 inference/future_then_conditional_5: TextSerializationFailure # Was: Pass
 inference/future_then_conditional_6: TextSerializationFailure # Was: Pass
+inference/future_then_conditional: TextSerializationFailure # Was: Pass
 inference/future_then_downwards_method_target: TextSerializationFailure # Was: Pass
 inference/future_then_explicit_future: TextSerializationFailure
 inference/future_then_ifNull: TextSerializationFailure # Was: Pass
-inference/future_then_upwards: TextSerializationFailure # Was: RuntimeError
 inference/future_then_upwards_2: TextSerializationFailure # Was: RuntimeError
 inference/future_then_upwards_3: TextSerializationFailure # Was: Pass
 inference/future_then_upwards_from_block: TextSerializationFailure # Was: Pass
-inference/future_union_async_conditional: TextSerializationFailure # Was: Pass
+inference/future_then_upwards: TextSerializationFailure # Was: RuntimeError
+inference/future_then: TextSerializationFailure # Was: Pass
 inference/future_union_async_conditional_2: TextSerializationFailure # Was: Pass
-inference/future_union_downwards: TextSerializationFailure # Was: Pass
+inference/future_union_async_conditional: TextSerializationFailure # Was: Pass
 inference/future_union_downwards_2: TextSerializationFailure # Was: Pass
 inference/future_union_downwards_3: TextSerializationFailure # Was: Pass
 inference/future_union_downwards_4: TextSerializationFailure # Was: Pass
 inference/future_union_downwards_generic_method_with_future_return: TextSerializationFailure # Was: Pass
 inference/future_union_downwards_generic_method_with_generic_return: TextSerializationFailure # Was: Pass
+inference/future_union_downwards: TextSerializationFailure # Was: Pass
 inference/future_union_upwards_generic_methods: TextSerializationFailure # Was: Pass
 inference/generator_closure: TextSerializationFailure # Was: Pass
 inference/generic_functions_return_typedef: TextSerializationFailure
@@ -802,8 +895,8 @@
 inference/generic_methods_downwards_inference_affects_arguments: TextSerializationFailure # Was: Pass
 inference/generic_methods_downwards_inference_fold: TextSerializationFailure # Was: Pass
 inference/generic_methods_handle_override_of_non_generic_with_generic: TypeCheckError
-inference/generic_methods_infer_generic_function_parameter_type2: TextSerializationFailure # Was: Pass
 inference/generic_methods_infer_generic_function_parameter_type: TextSerializationFailure # Was: Pass
+inference/generic_methods_infer_generic_function_parameter_type2: TextSerializationFailure # Was: Pass
 inference/generic_methods_infer_generic_function_return_type: TextSerializationFailure # Was: Pass
 inference/generic_methods_infer_generic_instantiation: TextSerializationFailure # Was: Pass
 inference/generic_methods_infer_generic_method_type: TextSerializationFailure # Was: Pass
@@ -814,34 +907,34 @@
 inference/generic_methods_uses_greatest_lower_bound: TextSerializationFailure # Was: Pass
 inference/greatest_closure_multiple_params: TextSerializationFailure # Was: Pass
 inference/inconsistent_overrides: TextSerializationFailure
-inference/index_assign_operator_return_type: TextSerializationFailure # Was: Pass
 inference/index_assign_operator_return_type_2: TextSerializationFailure # Was: Pass
+inference/index_assign_operator_return_type: TextSerializationFailure # Was: Pass
 inference/infer_accessor_from_later_inferred_field: TextSerializationFailure # Was: Pass
-inference/infer_assign_to_implicit_this: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_implicit_this_upwards: TextSerializationFailure # Was: Pass
+inference/infer_assign_to_implicit_this: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_index_full: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_index_super: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_index_this: TextSerializationFailure # Was: Pass
-inference/infer_assign_to_local: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_local_upwards: TextSerializationFailure # Was: Pass
+inference/infer_assign_to_local: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_property_full: TextSerializationFailure # Was: Pass
-inference/infer_assign_to_property_null_aware: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_property_null_aware_upwards: TextSerializationFailure # Was: Pass
-inference/infer_assign_to_property_super: TextSerializationFailure # Was: Pass
+inference/infer_assign_to_property_null_aware: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_property_super_upwards: TextSerializationFailure # Was: Pass
+inference/infer_assign_to_property_super: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_property_upwards: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_ref: TextSerializationFailure # Was: Pass
-inference/infer_assign_to_static: TextSerializationFailure # Was: Pass
 inference/infer_assign_to_static_upwards: TextSerializationFailure # Was: Pass
+inference/infer_assign_to_static: TextSerializationFailure # Was: Pass
 inference/infer_binary_custom: TextSerializationFailure # Was: Pass
 inference/infer_binary_double_double: TextSerializationFailure # Was: Pass
 inference/infer_binary_double_int: TextSerializationFailure # Was: Pass
 inference/infer_binary_int_double: TextSerializationFailure # Was: Pass
 inference/infer_binary_int_int: TextSerializationFailure # Was: Pass
 inference/infer_conditional: TextSerializationFailure # Was: Pass
-inference/infer_consts_transitively_2: TextSerializationFailure # Was: Pass
 inference/infer_consts_transitively_2_a: TextSerializationFailure # Was: Pass
 inference/infer_consts_transitively_2_b: TextSerializationFailure # Was: Pass
+inference/infer_consts_transitively_2: TextSerializationFailure # Was: Pass
 inference/infer_consts_transitively_b: TextSerializationFailure # Was: Pass
 inference/infer_correctly_on_multiple_variables_declared_together: TextSerializationFailure # Was: Pass
 inference/infer_field_from_later_inferred_field: TextSerializationFailure # Was: Pass
@@ -857,20 +950,20 @@
 inference/infer_final_field_getter_only: TextSerializationFailure # Was: Pass
 inference/infer_final_field_setter_only: TextSerializationFailure # Was: Pass
 inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TextSerializationFailure
-inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: TextSerializationFailure # Was: Pass
 inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_cycle_libs_when_flag_is_on2: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_cycle_libs_when_flag_is_on: TextSerializationFailure # Was: Pass
+inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: TextSerializationFailure # Was: Pass
 inference/infer_from_variables_in_cycle_libs_when_flag_is_on_a: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_non_cycle_imports_with_flag2: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_non_cycle_imports_with_flag2_a: TextSerializationFailure # Was: Pass
-inference/infer_from_variables_in_non_cycle_imports_with_flag: TextSerializationFailure # Was: Pass
+inference/infer_from_variables_in_cycle_libs_when_flag_is_on: TextSerializationFailure # Was: Pass
+inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a: TextSerializationFailure # Was: Pass
+inference/infer_from_variables_in_cycle_libs_when_flag_is_on2: TextSerializationFailure # Was: Pass
 inference/infer_from_variables_in_non_cycle_imports_with_flag_a: TextSerializationFailure # Was: Pass
+inference/infer_from_variables_in_non_cycle_imports_with_flag: TextSerializationFailure # Was: Pass
+inference/infer_from_variables_in_non_cycle_imports_with_flag2_a: TextSerializationFailure # Was: Pass
+inference/infer_from_variables_in_non_cycle_imports_with_flag2: TextSerializationFailure # Was: Pass
 inference/infer_generic_field_types: TextSerializationFailure
 inference/infer_generic_method_type_named: TextSerializationFailure # Was: Pass
-inference/infer_generic_method_type_positional2: TextSerializationFailure # Was: Pass
 inference/infer_generic_method_type_positional: TextSerializationFailure # Was: Pass
+inference/infer_generic_method_type_positional2: TextSerializationFailure # Was: Pass
 inference/infer_generic_method_type_required: TextSerializationFailure # Was: Pass
 inference/infer_getter_cross_to_setter: TextSerializationFailure # Was: Pass
 inference/infer_getter_from_later_inferred_getter: TextSerializationFailure # Was: Pass
@@ -882,8 +975,8 @@
 inference/infer_method_missing_params: TypeCheckError
 inference/infer_parameter_type_setter_from_field: TextSerializationFailure # Was: Pass
 inference/infer_parameter_type_setter_from_setter: TextSerializationFailure # Was: Pass
-inference/infer_prefix_expression: TextSerializationFailure # Was: Pass
 inference/infer_prefix_expression_custom: TextSerializationFailure # Was: Pass
+inference/infer_prefix_expression: TextSerializationFailure # Was: Pass
 inference/infer_rethrow: TextSerializationFailure # Was: Pass
 inference/infer_return_of_statement_lambda: TextSerializationFailure # Was: Pass
 inference/infer_return_type_for_static_setter: TextSerializationFailure # Was: Pass
@@ -891,78 +984,78 @@
 inference/infer_setter_from_later_inferred_setter: TextSerializationFailure # Was: Pass
 inference/infer_setter_function_typed: TextSerializationFailure # Was: Pass
 inference/infer_setter_return_type_only: TextSerializationFailure # Was: Pass
-inference/infer_statics_transitively2: TextSerializationFailure # Was: Pass
-inference/infer_statics_transitively3: TextSerializationFailure # Was: Pass
-inference/infer_statics_transitively3_a: TextSerializationFailure # Was: Pass
-inference/infer_statics_transitively: TextSerializationFailure # Was: Pass
 inference/infer_statics_transitively_2_a: TextSerializationFailure # Was: Pass
 inference/infer_statics_transitively_a: TextSerializationFailure # Was: Pass
 inference/infer_statics_transitively_b: TextSerializationFailure # Was: Pass
-inference/infer_statics_with_method_invocations: TextSerializationFailure # Was: Pass
+inference/infer_statics_transitively: TextSerializationFailure # Was: Pass
+inference/infer_statics_transitively2: TextSerializationFailure # Was: Pass
+inference/infer_statics_transitively3_a: TextSerializationFailure # Was: Pass
+inference/infer_statics_transitively3: TextSerializationFailure # Was: Pass
 inference/infer_statics_with_method_invocations_a: TextSerializationFailure # Was: Pass
-inference/infer_throw: TextSerializationFailure # Was: Pass
+inference/infer_statics_with_method_invocations: TextSerializationFailure # Was: Pass
 inference/infer_throw_downwards: TextSerializationFailure # Was: Pass
+inference/infer_throw: TextSerializationFailure # Was: Pass
 inference/infer_type_on_overridden_fields2: TextSerializationFailure # Was: Pass
 inference/infer_type_on_overridden_fields4: TextSerializationFailure # Was: Pass
-inference/infer_type_on_var2: TextSerializationFailure # Was: Pass
-inference/infer_type_on_var: TextSerializationFailure # Was: Pass
 inference/infer_type_on_var_from_field: TextSerializationFailure # Was: Pass
 inference/infer_type_on_var_from_top_level: TextSerializationFailure # Was: Pass
-inference/infer_type_regardless_of_declaration_order_or_cycles: TextSerializationFailure # Was: RuntimeError
+inference/infer_type_on_var: TextSerializationFailure # Was: Pass
+inference/infer_type_on_var2: TextSerializationFailure # Was: Pass
 inference/infer_type_regardless_of_declaration_order_or_cycles_b: TextSerializationFailure # Was: Pass
+inference/infer_type_regardless_of_declaration_order_or_cycles: TextSerializationFailure # Was: RuntimeError
 inference/infer_typed_map_literal: TextSerializationFailure # Was: Pass
 inference/infer_types_on_generic_instantiations_3: TextSerializationFailure # Was: Pass
 inference/infer_types_on_generic_instantiations_4: TextSerializationFailure # Was: RuntimeError
 inference/infer_types_on_generic_instantiations_5: TextSerializationFailure # Was: Pass
-inference/infer_types_on_generic_instantiations_in_library_cycle: TextSerializationFailure # Was: Pass
 inference/infer_types_on_generic_instantiations_in_library_cycle_a: TextSerializationFailure # Was: Pass
+inference/infer_types_on_generic_instantiations_in_library_cycle: TextSerializationFailure # Was: Pass
 inference/infer_types_on_generic_instantiations_infer: TypeCheckError
-inference/infer_types_on_loop_indices_for_each_loop: TextSerializationFailure # Was: Pass
 inference/infer_types_on_loop_indices_for_each_loop_async: TextSerializationFailure # Was: Pass
+inference/infer_types_on_loop_indices_for_each_loop: TextSerializationFailure # Was: Pass
 inference/infer_types_on_loop_indices_for_loop_with_inference: TextSerializationFailure # Was: Pass
 inference/infer_use_of_void_local: TextSerializationFailure # Was: Pass
 inference/infer_variable_void: TextSerializationFailure # Was: Pass
 inference/inferred_initializing_formal_checks_default_value: TextSerializationFailure # Was: Pass
 inference/inferred_nonstatic_field_depends_on_static_field_complex: TextSerializationFailure # Was: Pass
 inference/inferred_nonstatic_field_depends_on_top_level_var_simple: TextSerializationFailure # Was: Pass
-inference/inferred_type_block_closure_no_args_no_return: TextSerializationFailure # Was: Pass
 inference/inferred_type_block_closure_no_args_no_return_void_context: TextSerializationFailure # Was: Pass
+inference/inferred_type_block_closure_no_args_no_return: TextSerializationFailure # Was: Pass
 inference/inferred_type_cascade: TextSerializationFailure # Was: Pass
-inference/inferred_type_custom_binary_op: TextSerializationFailure # Was: Pass
 inference/inferred_type_custom_binary_op_via_interface: TextSerializationFailure # Was: Pass
-inference/inferred_type_custom_index_op: TextSerializationFailure # Was: Pass
+inference/inferred_type_custom_binary_op: TextSerializationFailure # Was: Pass
 inference/inferred_type_custom_index_op_via_interface: TextSerializationFailure # Was: Pass
-inference/inferred_type_custom_unary_op: TextSerializationFailure # Was: Pass
+inference/inferred_type_custom_index_op: TextSerializationFailure # Was: Pass
 inference/inferred_type_custom_unary_op_via_interface: TextSerializationFailure # Was: Pass
-inference/inferred_type_extract_method_tear_off: TextSerializationFailure # Was: Pass
+inference/inferred_type_custom_unary_op: TextSerializationFailure # Was: Pass
 inference/inferred_type_extract_method_tear_off_via_interface: TextSerializationFailure # Was: Pass
+inference/inferred_type_extract_method_tear_off: TextSerializationFailure # Was: Pass
 inference/inferred_type_from_top_level_executable_tear_off: TextSerializationFailure # Was: Pass
-inference/inferred_type_invoke_method: TextSerializationFailure # Was: Pass
 inference/inferred_type_invoke_method_via_interface: TextSerializationFailure # Was: Pass
-inference/inferred_type_is_enum: TextSerializationFailure # Was: Pass
+inference/inferred_type_invoke_method: TextSerializationFailure # Was: Pass
 inference/inferred_type_is_enum_values: TextSerializationFailure # Was: Pass
-inference/inferred_type_is_typedef: TextSerializationFailure # Was: Pass
+inference/inferred_type_is_enum: TextSerializationFailure # Was: Pass
 inference/inferred_type_is_typedef_parameterized: TextSerializationFailure # Was: Pass
-inference/inferred_type_uses_synthetic_function_type: TextSerializationFailure # Was: Pass
+inference/inferred_type_is_typedef: TextSerializationFailure # Was: Pass
 inference/inferred_type_uses_synthetic_function_type_function_typed_param: TextSerializationFailure # Was: Pass
 inference/inferred_type_uses_synthetic_function_type_named_param: TextSerializationFailure # Was: Pass
 inference/inferred_type_uses_synthetic_function_type_positional_param: TextSerializationFailure # Was: Pass
 inference/inferred_type_uses_synthetic_function_type_required_param: TextSerializationFailure # Was: Pass
+inference/inferred_type_uses_synthetic_function_type: TextSerializationFailure # Was: Pass
 inference/inferred_type_via_closure_multiple_levels_of_nesting: TextSerializationFailure # Was: Pass
 inference/inferred_type_via_closure_type_depends_on_args: TextSerializationFailure # Was: Pass
 inference/inferred_type_via_closure_type_independent_of_args_field: TextSerializationFailure # Was: Pass
 inference/inferred_type_via_closure_type_independent_of_args_top_level: TextSerializationFailure # Was: Pass
 inference/inheritance_does_not_imply_circularity: TextSerializationFailure # Was: Pass
 inference/instance_creation_downwards: TextSerializationFailure # Was: Pass
-inference/instantiate_tearoff: TextSerializationFailure # Was: Pass
 inference/instantiate_tearoff_after_contravariance_check: TextSerializationFailure # Was: Pass
 inference/instantiate_tearoff_of_call: TypeCheckError # Issue #31746
-inference/instantiate_to_bounds_generic2_has_bound_defined_after: TextSerializationFailure # Was: Pass
-inference/instantiate_to_bounds_generic2_has_bound_defined_before: TextSerializationFailure # Was: Pass
-inference/instantiate_to_bounds_generic2_no_bound: TextSerializationFailure # Was: Pass
+inference/instantiate_tearoff: TextSerializationFailure # Was: Pass
 inference/instantiate_to_bounds_generic_has_bound_defined_after transform: RuntimeError
 inference/instantiate_to_bounds_generic_has_bound_defined_after: TextSerializationFailure # Was: Pass
 inference/instantiate_to_bounds_generic_has_bound_defined_before: TextSerializationFailure # Was: Pass
+inference/instantiate_to_bounds_generic2_has_bound_defined_after: TextSerializationFailure # Was: Pass
+inference/instantiate_to_bounds_generic2_has_bound_defined_before: TextSerializationFailure # Was: Pass
+inference/instantiate_to_bounds_generic2_no_bound: TextSerializationFailure # Was: Pass
 inference/instantiate_to_bounds_invoke_constructor_no_bound: TextSerializationFailure # Was: Pass
 inference/instantiate_to_bounds_invoke_constructor_type_args_exact: TextSerializationFailure # Was: Pass
 inference/instantiate_to_bounds_not_generic: TextSerializationFailure # Was: Pass
@@ -971,18 +1064,18 @@
 inference/lambda_return_type: TextSerializationFailure # Was: Pass
 inference/lambda_void_context: TextSerializationFailure # Was: Pass
 inference/list_literal_typed: TextSerializationFailure # Was: Pass
-inference/list_literals: TextSerializationFailure # Was: Pass
 inference/list_literals_can_infer_null_bottom: TextSerializationFailure # Was: Pass
 inference/list_literals_top_level: TextSerializationFailure # Was: Pass
+inference/list_literals: TextSerializationFailure # Was: Pass
 inference/local_constructor_from_arguments: TextSerializationFailure # Was: Pass
 inference/local_reference_upwards_local: TextSerializationFailure # Was: Pass
 inference/local_return_and_yield: TextSerializationFailure # Was: Pass
 inference/logical_or_promotion: TextSerializationFailure # Was: Pass
-inference/map_literals: TextSerializationFailure # Was: Pass
 inference/map_literals_can_infer_null: TextSerializationFailure # Was: Pass
 inference/map_literals_top_level: TextSerializationFailure # Was: Pass
-inference/method_call_with_type_arguments_instance_method: TextSerializationFailure # Was: Pass
+inference/map_literals: TextSerializationFailure # Was: Pass
 inference/method_call_with_type_arguments_instance_method_identifier_sequence: TextSerializationFailure # Was: Pass
+inference/method_call_with_type_arguments_instance_method: TextSerializationFailure # Was: Pass
 inference/method_call_with_type_arguments_static_method: TextSerializationFailure # Was: Pass
 inference/method_call_with_type_arguments_top_level_function: TextSerializationFailure # Was: Pass
 inference/mixin_inference_instantiate_to_bounds_1: TextSerializationFailure # Was: Pass
@@ -1001,8 +1094,8 @@
 inference/non_inferrable_getter_setter: TextSerializationFailure # Was: Pass
 inference/null_aware_method_invocation: TextSerializationFailure # Was: Pass
 inference/null_aware_property_get: TextSerializationFailure # Was: Pass
-inference/null_coalescing_operator: TextSerializationFailure # Was: Pass
 inference/null_coalescing_operator_2: TextSerializationFailure # Was: Pass
+inference/null_coalescing_operator: TextSerializationFailure # Was: Pass
 inference/null_literal_should_not_infer_as_bottom: TextSerializationFailure # Was: Pass
 inference/overloaded_int_operators: TextSerializationFailure # Was: Pass
 inference/override_equals: TextSerializationFailure # Was: RuntimeError
@@ -1013,14 +1106,14 @@
 inference/promote_bounds: TextSerializationFailure # Was: Pass
 inference/promote_from_logical_rhs: TextSerializationFailure # Was: Pass
 inference/promotion_subtype_check: TextSerializationFailure # Was: Pass
-inference/propagate_inference_to_field_in_class: TextSerializationFailure # Was: Pass
 inference/propagate_inference_to_field_in_class_dynamic_warnings: TextSerializationFailure # Was: Pass
-inference/propagate_inference_transitively2: TextSerializationFailure # Was: Pass
+inference/propagate_inference_to_field_in_class: TextSerializationFailure # Was: Pass
 inference/propagate_inference_transitively: TextSerializationFailure # Was: Pass
+inference/propagate_inference_transitively2: TextSerializationFailure # Was: Pass
 inference/propagate_variable_get: TextSerializationFailure # Was: Pass
 inference/property_get_toplevel: TextSerializationFailure # Was: Pass
-inference/property_set: TextSerializationFailure # Was: Pass
 inference/property_set_bad_setter: TextSerializationFailure # Was: Pass
+inference/property_set: TextSerializationFailure # Was: Pass
 inference/recursive_generic_function: TextSerializationFailure # Was: Pass
 inference/reference_to_typedef: TextSerializationFailure # Was: Pass
 inference/refine_binary_expression_type_type_parameter_t_double: TextSerializationFailure # Was: Pass
@@ -1034,26 +1127,26 @@
 inference/static_method_tear_off: TextSerializationFailure # Was: Pass
 inference/string_literal: TextSerializationFailure # Was: Pass
 inference/subexpressions_of_explicitly_typed_fields: TextSerializationFailure # Was: Pass
-inference/super_index_set: TextSerializationFailure # Was: Pass
 inference/super_index_set_substitution: TextSerializationFailure # Was: Pass
-inference/super_initializer: TextSerializationFailure # Was: Pass
+inference/super_index_set: TextSerializationFailure # Was: Pass
 inference/super_initializer_substitution: TextSerializationFailure # Was: Pass
-inference/super_method_invocation: TextSerializationFailure # Was: Pass
+inference/super_initializer: TextSerializationFailure # Was: Pass
 inference/super_method_invocation_substitution: TextSerializationFailure # Was: Pass
-inference/super_property_get: TextSerializationFailure # Was: Pass
+inference/super_method_invocation: TextSerializationFailure # Was: Pass
 inference/super_property_get_invoke_function_typed: TextSerializationFailure # Was: Pass
 inference/super_property_get_invoke_implicit_call: TextSerializationFailure # Was: Pass
 inference/super_property_get_substitution: TextSerializationFailure # Was: Pass
 inference/super_property_get_tearoff: TextSerializationFailure # Was: Pass
+inference/super_property_get: TextSerializationFailure # Was: Pass
 inference/super_property_set_substitution: TextSerializationFailure # Was: Pass
 inference/switch_continue: TextSerializationFailure # Was: Pass
 inference/symbol_literal: TextSerializationFailure # Was: Pass
 inference/this_reference: TextSerializationFailure # Was: Pass
 inference/top_level_return_and_yield: TextSerializationFailure # Was: Pass
 inference/toplevel_inference_toplevel_var: TextSerializationFailure # Was: Pass
-inference/try_catch: TextSerializationFailure # Was: Pass
 inference/try_catch_finally: TextSerializationFailure # Was: Pass
 inference/try_catch_promotion: TextSerializationFailure # Was: Pass
+inference/try_catch: TextSerializationFailure # Was: Pass
 inference/try_finally: TextSerializationFailure # Was: Pass
 inference/type_cast: TextSerializationFailure # Was: Pass
 inference/type_promotion_ignores_local_functions: TextSerializationFailure # Was: Pass
@@ -1068,16 +1161,16 @@
 inference/unsafe_block_closure_inference_constructor_call_explicit_type_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_constructor_call_implicit_type_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_constructor_call_no_type_param: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: TextSerializationFailure
 inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: TextSerializationFailure
-inference/unsafe_block_closure_inference_function_call_explicit_type_param: TextSerializationFailure # Was: Pass
+inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: TextSerializationFailure
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: TextSerializationFailure
-inference/unsafe_block_closure_inference_function_call_implicit_type_param: TextSerializationFailure # Was: Pass
+inference/unsafe_block_closure_inference_function_call_explicit_type_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr: TextSerializationFailure # Was: Pass
-inference/unsafe_block_closure_inference_function_call_no_type_param: TextSerializationFailure # Was: Pass
+inference/unsafe_block_closure_inference_function_call_implicit_type_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr: TextSerializationFailure # Was: Pass
+inference/unsafe_block_closure_inference_function_call_no_type_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_in_list_dynamic: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_in_list_typed: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_in_list_untyped: TextSerializationFailure # Was: Pass
@@ -1089,117 +1182,54 @@
 inference/unsafe_block_closure_inference_method_call_implicit_type_param: TextSerializationFailure # Was: Pass
 inference/unsafe_block_closure_inference_method_call_no_type_param: TextSerializationFailure # Was: Pass
 inference/void_return_type_subtypes_dynamic: TextSerializationFailure # Was: Pass
-inference_new/const_invocation: TextSerializationFailure # Was: Pass
-inference_new/dependency_only_if_generic_method: TextSerializationFailure # Was: Pass
-inference_new/dependency_only_if_overloaded: TextSerializationFailure # Was: Pass
-inference_new/dependency_only_if_overloaded: TypeCheckError
-inference_new/do_loop: TextSerializationFailure # Was: Pass
-inference_new/downwards_inference_inside_top_level: TextSerializationFailure # Was: Pass
-inference_new/downwards_inference_inside_top_level_2: TextSerializationFailure # Was: Pass
-inference_new/field_inference_circularity: TextSerializationFailure # Was: Pass
-inference_new/for_each_identifier_downwards: TextSerializationFailure # Was: Pass
-inference_new/for_each_invalid_iterable: TextSerializationFailure # Was: Pass
-inference_new/for_each_outer_var_type: TextSerializationFailure # Was: Pass
-inference_new/indexed_assign_combiner: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_implicit_this: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_implicit_this_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_index: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_index_full: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_index_set_vs_get: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_index_super: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_index_super_upwards: TypeCheckError
-inference_new/infer_assign_to_index_this: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_index_this_upwards: TypeCheckError
-inference_new/infer_assign_to_index_upwards: TypeCheckError
-inference_new/infer_assign_to_local: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_local_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_property: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_property_custom: TypeCheckError
-inference_new/infer_assign_to_property_full: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_property_null_aware: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_property_null_aware_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_property_super: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_property_super_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_property_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_ref: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_static: TextSerializationFailure # Was: Pass
-inference_new/infer_assign_to_static_upwards: TextSerializationFailure # Was: Pass
-inference_new/infer_field_getter_setter_mismatch: TextSerializationFailure
-inference_new/infer_field_override_accessors: TextSerializationFailure
-inference_new/infer_field_override_getter_overrides_setter: TextSerializationFailure
-inference_new/infer_field_override_setter_overrides_getter: TextSerializationFailure # Was: Pass
-inference_new/infer_instance_accessor_ref: TextSerializationFailure # Was: Pass
-inference_new/infer_instance_field_ref: TextSerializationFailure # Was: Pass
-inference_new/infer_instance_field_ref_circular: TextSerializationFailure # Was: Pass
-inference_new/infer_logical: TextSerializationFailure # Was: Pass
-inference_new/infer_use_of_void: TextSerializationFailure # Was: Pass
-inference_new/invalid_assignment_during_toplevel_inference: TypeCheckError
-inference_new/list_literals_can_infer_null_top_level: TextSerializationFailure # Was: Pass
-inference_new/map_literals_can_infer_null_top_level: TextSerializationFailure # Was: Pass
-inference_new/multiple_interface_inheritance: TextSerializationFailure # Was: Pass
-inference_new/null_aware_property_get: TextSerializationFailure
-inference_new/property_assign_combiner: TextSerializationFailure # Was: Pass
-inference_new/property_get_toplevel: TextSerializationFailure # Was: Pass
-inference_new/static_assign_combiner: TextSerializationFailure # Was: Pass
-inference_new/strongly_connected_component: TextSerializationFailure # Was: Pass
-inference_new/strongly_connected_component: TypeCheckError
-inference_new/super_index_get: TextSerializationFailure # Was: Pass
-inference_new/super_index_get_substitution: TextSerializationFailure # Was: Pass
-inference_new/switch: TextSerializationFailure # Was: Pass
-inference_new/top_level_field_depends_on_multiple_inheritance: ExpectationFileMismatch
-inference_new/top_level_field_depends_on_multiple_inheritance: TextSerializationFailure # Was: Pass
-inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: TextSerializationFailure # Was: Pass
-inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: TextSerializationFailure # Was: Pass
-inference_new/void_return_type_subtypes_dynamic: TextSerializationFailure # Was: Pass
-inference_new/while_loop: TextSerializationFailure # Was: Pass
 instantiate_to_bound/all_steps: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_generic_classes_from_dill: TextSerializationFailure # Was: Pass
-instantiate_to_bound/body_literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_literal_list_with_generic_argument: TextSerializationFailure # Was: Pass
+instantiate_to_bound/body_literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_literal_map: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_super_bounded_type: TextSerializationFailure # Was: Pass
-instantiate_to_bound/body_typedef_literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_typedef_literal_list_with_generic_argument: TextSerializationFailure # Was: Pass
+instantiate_to_bound/body_typedef_literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_typedef_literal_map: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_typedef_omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/body_typedef_super_bounded_type: TextSerializationFailure # Was: Pass
-instantiate_to_bound/contravariant_dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/contravariant_dependence_in_literals: TextSerializationFailure # Was: Pass
-instantiate_to_bound/contravariant_mutual_dependence: TextSerializationFailure # Was: Pass
+instantiate_to_bound/contravariant_dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/contravariant_mutual_dependence_in_literals: TextSerializationFailure # Was: Pass
-instantiate_to_bound/covariant_dependence: TextSerializationFailure # Was: Pass
+instantiate_to_bound/contravariant_mutual_dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/covariant_dependence_in_literals: TextSerializationFailure # Was: Pass
-instantiate_to_bound/covariant_mutual_dependence: TextSerializationFailure # Was: Pass
+instantiate_to_bound/covariant_dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/covariant_mutual_dependence_in_literals: TextSerializationFailure # Was: Pass
-instantiate_to_bound/dependence: TextSerializationFailure # Was: Pass
+instantiate_to_bound/covariant_mutual_dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/dependence_in_literals: TextSerializationFailure # Was: Pass
+instantiate_to_bound/dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/generic_classes_from_dill: TextSerializationFailure # Was: Pass
 instantiate_to_bound/inference_constrained_by_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/inference_defaults_to_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/inference_gives_input: TextSerializationFailure # Was: Pass
 instantiate_to_bound/inference_super_bounded_rejected: TextSerializationFailure # Was: Pass
 instantiate_to_bound/instantiated_in_outline: TextSerializationFailure # Was: Pass
-instantiate_to_bound/literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/literal_list_with_generic_argument: TextSerializationFailure # Was: Pass
+instantiate_to_bound/literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/literal_map: TextSerializationFailure # Was: Pass
 instantiate_to_bound/multiple_strongly_connected: TextSerializationFailure # Was: Pass
-instantiate_to_bound/mutual_dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/mutual_dependence_in_literals: TextSerializationFailure # Was: Pass
+instantiate_to_bound/mutual_dependence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_bound_due_to_non_simple: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_bound_due_to_variables: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: TextSerializationFailure # Was: RuntimeError # Expected
 instantiate_to_bound/non_simple_class_typedef_cycle: TextSerializationFailure # Was: Pass
-instantiate_to_bound/non_simple_co_inductive: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_co_inductive_for_each: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_co_inductive_no_dup: TextSerializationFailure # Was: Pass
+instantiate_to_bound/non_simple_co_inductive: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_folded_regress: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_for_each: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_from_compiled: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_generic_function_in_bound_regress: TextSerializationFailure # Was: RuntimeError # Expected
-instantiate_to_bound/non_simple_many: TextSerializationFailure # Was: Pass
-instantiate_to_bound/non_simple_many_libs_same_name_cycle: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_many_libs_same_name_cycle_lib: TextSerializationFailure # Was: Pass
+instantiate_to_bound/non_simple_many_libs_same_name_cycle: TextSerializationFailure # Was: Pass
+instantiate_to_bound/non_simple_many: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_no_dup: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_suppress_consequence: TextSerializationFailure # Was: Pass
 instantiate_to_bound/non_simple_variables_from_same: TextSerializationFailure # Was: Pass
@@ -1209,8 +1239,8 @@
 instantiate_to_bound/super_bounded_type: TextSerializationFailure # Was: Pass
 instantiate_to_bound/supertypes: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_instantiated_in_outline: TextSerializationFailure # Was: Pass
-instantiate_to_bound/typedef_literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_literal_list_with_generic_argument: TextSerializationFailure # Was: Pass
+instantiate_to_bound/typedef_literal_list: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_literal_map: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
@@ -1218,9 +1248,9 @@
 late_lowering/compound: TextSerializationFailure
 late_lowering/definitely_assigned: TextSerializationFailure
 late_lowering/definitely_unassigned: TextSerializationFailure
-late_lowering/initializer_rewrite: TextSerializationFailure
-late_lowering/infer_late_field_type: TextSerializationFailure
 late_lowering/infer_from_late_variable: TextSerializationFailure
+late_lowering/infer_late_field_type: TextSerializationFailure
+late_lowering/initializer_rewrite: TextSerializationFailure
 late_lowering/injected_late_field_checks/main: TextSerializationFailure
 late_lowering/instance_field_with_initializer: TextSerializationFailure
 late_lowering/instance_field_without_initializer: TextSerializationFailure
@@ -1233,6 +1263,9 @@
 late_lowering/issue40373b: TextSerializationFailure
 late_lowering/issue40601: TextSerializationFailure
 late_lowering/issue40805: TextSerializationFailure
+late_lowering/issue41436/issue41436: TextSerializationFailure
+late_lowering/issue41436b: TextSerializationFailure
+late_lowering/issue41436c/issue41436c: TextSerializationFailure
 late_lowering/late_field_inference: TextSerializationFailure
 late_lowering/late_field_with_initializer: TextSerializationFailure
 late_lowering/late_field_without_initializer: TextSerializationFailure
@@ -1252,21 +1285,24 @@
 late_lowering/late_nullable_local_with_initializer: TextSerializationFailure
 late_lowering/late_nullable_local_without_initializer: TextSerializationFailure
 late_lowering/later: TextSerializationFailure
-late_lowering/override: TextSerializationFailure
 late_lowering/override_getter_setter: TextSerializationFailure
+late_lowering/override: TextSerializationFailure
 late_lowering/return_late: TextSerializationFailure
 late_lowering/uninitialized_non_nullable_late_fields: TextSerializationFailure
 new_const_insertion/simple: TextSerializationFailure # Was: Pass
 nnbd/assign_type_variable: TextSerializationFailure
 nnbd/assignability: TextSerializationFailure
 nnbd/bounds_checks: TextSerializationFailure
+nnbd/bounds_from_opt_in: TextSerializationFailure
 nnbd/call: TextSerializationFailure
+nnbd/constant_null_is: TextSerializationFailure
 nnbd/constants: TextSerializationFailure
+nnbd/covariant_equals: TextSerializationFailure
 nnbd/covariant_nnbd_top_merge: TextSerializationFailure
 nnbd/definite_assignment_and_completion: TextSerializationFailure
 nnbd/definitely_assigned: TextSerializationFailure
-nnbd/definitely_unassigned: TextSerializationFailure
 nnbd/definitely_unassigned_late_local_variables: TextSerializationFailure
+nnbd/definitely_unassigned: TextSerializationFailure
 nnbd/demote_closure_types: TextSerializationFailure
 nnbd/export_from_opt_out: TextSerializationFailure
 nnbd/forbidden_supers: TextSerializationFailure
@@ -1286,6 +1322,8 @@
 nnbd/inheritance_from_opt_out: TextSerializationFailure
 nnbd/injected_late_field_checks/main: TextSerializationFailure
 nnbd/intersection_types: TextSerializationFailure
+nnbd/issue_39286_2: TextSerializationFailure
+nnbd/issue_39286: TextSerializationFailure
 nnbd/issue39659: TextSerializationFailure
 nnbd/issue39822: TextSerializationFailure
 nnbd/issue40093: TextSerializationFailure
@@ -1296,12 +1334,12 @@
 nnbd/issue40805: TextSerializationFailure
 nnbd/issue41102: TextSerializationFailure
 nnbd/issue41103: TextSerializationFailure
+nnbd/issue41114: TextSerializationFailure
 nnbd/issue41156: TextSerializationFailure
 nnbd/issue41180: TextSerializationFailure
-nnbd/issue41210a/issue41210: TypeCheckError
-nnbd/issue41210b: TypeCheckError
-nnbd/issue_39286: TextSerializationFailure
-nnbd/issue_39286_2: TextSerializationFailure
+nnbd/issue41210a/issue41210: TextSerializationFailure
+nnbd/issue41210b: TextSerializationFailure
+nnbd/issue41273: TextSerializationFailure
 nnbd/late: TextSerializationFailure
 nnbd/later: TextSerializationFailure
 nnbd/lhs_of_if_null: TextSerializationFailure
@@ -1315,30 +1353,32 @@
 nnbd/missing_required_named_parameter: TextSerializationFailure
 nnbd/mixed_mode_hierarchy_generic_methods: TextSerializationFailure
 nnbd/mixin_from_opt_in: TextSerializationFailure
+nnbd/mixin_from_opt_in_out_in: TextSerializationFailure
 nnbd/mixin_from_opt_out: TextSerializationFailure
 nnbd/never_bound: TextSerializationFailure
 nnbd/never_opt_out: TypeCheckError
 nnbd/never_receiver: TextSerializationFailure
-nnbd/nnbd_opt_out_language_version: TextSerializationFailure
 nnbd/nnbd_opt_out_language_version_try_to_trick: TextSerializationFailure
-nnbd/no_null_shorting: TextSerializationFailure
+nnbd/nnbd_opt_out_language_version: TextSerializationFailure
 nnbd/no_null_shorting_explicit_extension: TextSerializationFailure
 nnbd/no_null_shorting_extension: TextSerializationFailure
+nnbd/no_null_shorting: TextSerializationFailure
 nnbd/non_nullable_field_initialization: TextSerializationFailure
 nnbd/non_nullable_optional: TextSerializationFailure
 nnbd/not_definitely_unassigned_late_local_variables: TextSerializationFailure
 nnbd/nsm_from_opt_in: TextSerializationFailure
 nnbd/null_access: TextSerializationFailure
 nnbd/null_aware_chain: TextSerializationFailure
-nnbd/null_check: TextSerializationFailure
 nnbd/null_check_context: TextSerializationFailure
-nnbd/null_shorting: TextSerializationFailure
+nnbd/null_check: TextSerializationFailure
 nnbd/null_shorting_cascade: TextSerializationFailure
 nnbd/null_shorting_explicit_extension: TextSerializationFailure
 nnbd/null_shorting_extension: TextSerializationFailure
 nnbd/null_shorting_index: TextSerializationFailure
+nnbd/null_shorting: TextSerializationFailure
 nnbd/nullable_access: TextSerializationFailure
 nnbd/nullable_null: TextSerializationFailure
+nnbd/nullable_object_access: TextSerializationFailure
 nnbd/nullable_param: TextSerializationFailure
 nnbd/nullable_receiver: TextSerializationFailure
 nnbd/nullable_rhs_of_typedef: TextSerializationFailure
@@ -1347,11 +1387,13 @@
 nnbd/platform_definite_assignment/main: TextSerializationFailure
 nnbd/platform_nonnullable_fields/main: TextSerializationFailure
 nnbd/platform_optional_parameters/main: TextSerializationFailure
+nnbd/potentially_constant_type_as: TextSerializationFailure
+nnbd/potentially_constant_type_is: TextSerializationFailure
 nnbd/potentially_non_nullable_field: TextSerializationFailure
 nnbd/regress_null_aware: TextSerializationFailure
-nnbd/required: TextSerializationFailure
 nnbd/required_name_override: TextSerializationFailure
 nnbd/required_named_parameter: TextSerializationFailure
+nnbd/required: TextSerializationFailure
 nnbd/return_late: TextSerializationFailure
 nnbd/return_null: TextSerializationFailure
 nnbd/shorting_stop: TextSerializationFailure
@@ -1364,10 +1406,10 @@
 nnbd/tearoff_from_nullable_receiver: TextSerializationFailure
 nnbd/type_parameter_types: TextSerializationFailure
 nnbd/uninitialized_non_nullable_late_fields: TextSerializationFailure
-no_such_method_forwarders/abstract_accessors_from_field: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/abstract_accessors_from_field_one_defined: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/abstract_accessors_from_field_with_substitution: TextSerializationFailure # Was: Pass
+no_such_method_forwarders/abstract_accessors_from_field: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/abstract_interface_nsm_inherited: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/abstract_override_abstract_different_type: TextSerializationFailure
 no_such_method_forwarders/abstract_override_with_different_signature: TextSerializationFailure
@@ -1379,13 +1421,13 @@
 no_such_method_forwarders/interface_with_concrete: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/interface_with_nsm: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/multiple_abstract_setters: TextSerializationFailure
-no_such_method_forwarders/no_forwarders_for_abstract_classes: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/no_forwarders_for_abstract_classes_chain: TextSerializationFailure # Was: Pass
+no_such_method_forwarders/no_forwarders_for_abstract_classes: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/nsm_inherited: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/nsm_mixed_in: TextSerializationFailure # Was: Pass
-no_such_method_forwarders/private: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/private_module: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/private_same: TextSerializationFailure # Was: Pass
+no_such_method_forwarders/private: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/same: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/setter_not_shadowed_by_method: TextSerializationFailure # Was: Pass
 no_such_method_forwarders/subst_on_forwarder: TextSerializationFailure # Was: Pass
@@ -1450,18 +1492,18 @@
 rasta/issue_000080: TextSerializationFailure # Was: Pass
 rasta/issue_000081: TextSerializationFailure # Was: RuntimeError
 rasta/malformed_const_constructor: TextSerializationFailure # Was: RuntimeError
-rasta/malformed_function: TextSerializationFailure # Was: RuntimeError
 rasta/malformed_function_type: TextSerializationFailure # Was: Pass
+rasta/malformed_function: TextSerializationFailure # Was: RuntimeError
 rasta/mandatory_parameter_initializer: TextSerializationFailure
 rasta/mixin_library: TypeCheckError
 rasta/native_is_illegal: TextSerializationFailure # Was: RuntimeError
 rasta/parser_error: TextSerializationFailure # Was: RuntimeError
 rasta/previsit_deferred: TextSerializationFailure # Was: Pass
 rasta/static: TextSerializationFailure # Was: RuntimeError
-rasta/super: TypeCheckError
 rasta/super_initializer: TextSerializationFailure # Was: RuntimeError
 rasta/super_mixin: TypeCheckError
 rasta/super_operator: TypeCheckError
+rasta/super: TypeCheckError
 rasta/supports_reflection: TextSerializationFailure # Was: Pass
 rasta/switch_execution_case_t02: TextSerializationFailure # Was: Pass
 rasta/switch_fall_through: TextSerializationFailure # Was: Pass
@@ -1470,10 +1512,10 @@
 rasta/type_literals: TextSerializationFailure
 rasta/type_with_parse_error: TextSerializationFailure # Was: Pass
 rasta/typedef: TextSerializationFailure
-rasta/unresolved: TextSerializationFailure # Was: RuntimeError
 rasta/unresolved_constructor: TextSerializationFailure # Was: RuntimeError
 rasta/unresolved_for_in: TextSerializationFailure # Was: RuntimeError
 rasta/unresolved_recovery: TypeCheckError
+rasta/unresolved: TextSerializationFailure # Was: RuntimeError
 rasta/unsupported_platform_library: TextSerializationFailure
 regress/issue_29937: TextSerializationFailure # Was: Pass
 regress/issue_29940: TextSerializationFailure # Was: Pass
@@ -1527,12 +1569,12 @@
 regress/issue_33452: TextSerializationFailure # Was: RuntimeError # Test has an intentional error
 regress/issue_33672: TextSerializationFailure # Was: Pass
 regress/issue_34225: TextSerializationFailure # Was: RuntimeError
-regress/issue_34291: TextSerializationFailure # Was: Pass
 regress/issue_34291_lib: TextSerializationFailure # Was: Pass
-regress/issue_34403: TextSerializationFailure # Was: Pass
+regress/issue_34291: TextSerializationFailure # Was: Pass
 regress/issue_34403_lib: TextSerializationFailure # Was: Pass
-regress/issue_34498: TextSerializationFailure # Was: Pass
+regress/issue_34403: TextSerializationFailure # Was: Pass
 regress/issue_34498_lib: TextSerializationFailure # Was: Pass
+regress/issue_34498: TextSerializationFailure # Was: Pass
 regress/issue_34563: TextSerializationFailure # Was: RuntimeError # Test execution after recovery
 regress/issue_34610: TextSerializationFailure # Was: Pass
 regress/issue_34614: TextSerializationFailure # Was: Pass
@@ -1547,8 +1589,8 @@
 regress/issue_35266: TextSerializationFailure # Was: RuntimeError # Expected
 regress/issue_35900: TextSerializationFailure
 regress/issue_36400: TextSerializationFailure
-regress/issue_36647: TextSerializationFailure
 regress/issue_36647_2: TextSerializationFailure
+regress/issue_36647: TextSerializationFailure
 regress/issue_36669: TextSerializationFailure
 regress/issue_36793: TextSerializationFailure
 regress/issue_37285: TextSerializationFailure
@@ -1558,50 +1600,7 @@
 regress/issue_39091_1: RuntimeError
 regress/issue_39091_2: TextSerializationFailure
 regress/issue_39682: TextSerializationFailure
-runtime_checks/call_kinds: TextSerializationFailure # Was: Pass
-runtime_checks/call_kinds_get: TextSerializationFailure # Was: Pass
-runtime_checks/call_kinds_set: TextSerializationFailure # Was: Pass
-runtime_checks/call_method_implicit_tear_off: TextSerializationFailure # Was: Pass
-runtime_checks/call_method_implicit_tear_off_future_or: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_field: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_generic_method_type_parameter: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_generic_return: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_generic_return_null_aware: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_generic_return_tear_off: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_getter: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_getter_return: TextSerializationFailure # Was: Pass
-runtime_checks/contravariant_getter_return_null_aware: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_method_type_parameter: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_parameter: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_parameter_complex: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_parameter_in_interface: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_parameter_in_interface_mixin: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_parameter_in_interface_super: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_parameter_in_interface_super_mixin: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_generic_parameter_tear_off: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_field: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_field_inherited_by_setter: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_setter: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_keyword_setter_inherited_by_field: TextSerializationFailure # Was: Pass
-runtime_checks/covariant_setter: TextSerializationFailure # Was: Pass
-runtime_checks/dynamic_invocation: TextSerializationFailure # Was: Pass
-runtime_checks/dynamic_invocation_generic: TextSerializationFailure # Was: Pass
-runtime_checks/dynamic_invocation_of_getter: TextSerializationFailure # Was: Pass
-runtime_checks/field_forwarding_stub_generic_covariant: ExpectationFileMismatch
-runtime_checks/field_forwarding_stub_generic_covariant: TextSerializationFailure # Was: Pass
-runtime_checks/forwarding_stub_with_default_values: TextSerializationFailure # Was: Pass
-runtime_checks/forwarding_stub_with_non_covariant_param: TextSerializationFailure # Was: Pass
-runtime_checks/generic_covariance_inheritance_setter_field: TextSerializationFailure # Was: Pass
-runtime_checks/generic_vs_explicit_covariance: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_assert_initializer: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_assert_statement: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_constructor_initializer: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_do: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_for_condition: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_if: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_not: TextSerializationFailure # Was: Pass
-runtime_checks/implicit_downcast_while: TextSerializationFailure # Was: Pass
+regress/issue_41265.crash: TextSerializationFailure
 runtime_checks_new/abstract_override_becomes_forwarding_stub: ExpectationFileMismatch
 runtime_checks_new/abstract_override_becomes_forwarding_stub: TextSerializationFailure # Was: Pass
 runtime_checks_new/call_through_this: TextSerializationFailure # Was: Pass
@@ -1624,12 +1623,56 @@
 runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
 runtime_checks_new/stub_checked_via_target: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_contravariant_from_class: TextSerializationFailure # Was: Pass
+runtime_checks_new/stub_from_interface_covariant_from_interface: TextSerializationFailure # Was: Pass
+runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantImpl_from_class: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantImpl_from_interface: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantImpl_from_super: TextSerializationFailure # Was: Pass
 runtime_checks_new/stub_from_interface_covariantInterface_from_class: TextSerializationFailure # Was: Pass
-runtime_checks_new/stub_from_interface_covariant_from_interface: TextSerializationFailure # Was: Pass
-runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
+runtime_checks/call_kinds_get: TextSerializationFailure # Was: Pass
+runtime_checks/call_kinds_set: TextSerializationFailure # Was: Pass
+runtime_checks/call_kinds: TextSerializationFailure # Was: Pass
+runtime_checks/call_method_implicit_tear_off_future_or: TextSerializationFailure # Was: Pass
+runtime_checks/call_method_implicit_tear_off: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_field: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_generic_method_type_parameter: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_generic_return_null_aware: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_generic_return_tear_off: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_generic_return: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_getter_return_null_aware: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_getter_return: TextSerializationFailure # Was: Pass
+runtime_checks/contravariant_getter: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_method_type_parameter: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_parameter_complex: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_parameter_in_interface_mixin: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_parameter_in_interface_super_mixin: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_parameter_in_interface_super: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_parameter_in_interface: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_parameter_tear_off: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_generic_parameter: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_keyword_field_inherited_by_setter: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_keyword_field: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_keyword_setter_inherited_by_field: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_keyword_setter: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_keyword: TextSerializationFailure # Was: Pass
+runtime_checks/covariant_setter: TextSerializationFailure # Was: Pass
+runtime_checks/dynamic_invocation_generic: TextSerializationFailure # Was: Pass
+runtime_checks/dynamic_invocation_of_getter: TextSerializationFailure # Was: Pass
+runtime_checks/dynamic_invocation: TextSerializationFailure # Was: Pass
+runtime_checks/field_forwarding_stub_generic_covariant: ExpectationFileMismatch
+runtime_checks/field_forwarding_stub_generic_covariant: TextSerializationFailure # Was: Pass
+runtime_checks/forwarding_stub_with_default_values: TextSerializationFailure # Was: Pass
+runtime_checks/forwarding_stub_with_non_covariant_param: TextSerializationFailure # Was: Pass
+runtime_checks/generic_covariance_inheritance_setter_field: TextSerializationFailure # Was: Pass
+runtime_checks/generic_vs_explicit_covariance: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_assert_initializer: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_assert_statement: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_constructor_initializer: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_do: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_for_condition: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_if: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_not: TextSerializationFailure # Was: Pass
+runtime_checks/implicit_downcast_while: TextSerializationFailure # Was: Pass
 set_literals/disambiguation_rule: TextSerializationFailure # Was: RuntimeError
 top_level_variance_test: TextSerializationFailure
 triple_shift/invalid_operator: TextSerializationFailure
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.transformed.expect b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.transformed.expect
index 083afec..94f58ef5 100644
--- a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.transformed.expect
@@ -40,7 +40,6 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 static field core::bool* b = false;
 static field core::List<dynamic>* list = <dynamic>[];
@@ -50,7 +49,7 @@
   if(self::b)
     #t1.{core::Map::[]=}(0, 1);
   else {
-    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(self::map0.{core::Map::entries}).{core::Iterable::iterator};
+    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = self::map0.{core::Map::entries}.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final core::MapEntry<dynamic, dynamic>* #t2 = :sync-for-iterator.{core::Iterator::current};
       #t1.{core::Map::[]=}(#t2.{core::MapEntry::key}, #t2.{core::MapEntry::value});
@@ -60,7 +59,7 @@
 static field core::Map<dynamic, dynamic>* map2 = block {
   final core::Map<dynamic, dynamic>* #t3 = <dynamic, dynamic>{};
   if(self::b) {
-    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(self::map0.{core::Map::entries}).{core::Iterable::iterator};
+    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = self::map0.{core::Map::entries}.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final core::MapEntry<dynamic, dynamic>* #t4 = :sync-for-iterator.{core::Iterator::current};
       #t3.{core::Map::[]=}(#t4.{core::MapEntry::key}, #t4.{core::MapEntry::value});
@@ -72,14 +71,14 @@
 static field core::Map<dynamic, dynamic>* map3 = block {
   final core::Map<dynamic, dynamic>* #t5 = <dynamic, dynamic>{};
   if(self::b) {
-    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(self::map0.{core::Map::entries}).{core::Iterable::iterator};
+    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = self::map0.{core::Map::entries}.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final core::MapEntry<dynamic, dynamic>* #t6 = :sync-for-iterator.{core::Iterator::current};
       #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
     }
   }
   else {
-    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, dynamic>*>*>(self::map0.{core::Map::entries}).{core::Iterable::iterator};
+    core::Iterator<core::MapEntry<dynamic, dynamic>*>* :sync-for-iterator = self::map0.{core::Map::entries}.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final core::MapEntry<dynamic, dynamic>* #t7 = :sync-for-iterator.{core::Iterator::current};
       #t5.{core::Map::[]=}(#t7.{core::MapEntry::key}, #t7.{core::MapEntry::value});
@@ -91,7 +90,7 @@
   if(self::b)
     #t8.{core::Map::[]=}(0, 1);
   else {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(self::list).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = self::list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic a = :sync-for-iterator.{core::Iterator::current};
       #t8.{core::Map::[]=}(a, 1);
@@ -101,7 +100,7 @@
 static field core::Map<dynamic, core::int*>* map5 = block {
   final core::Map<dynamic, core::int*>* #t9 = <dynamic, core::int*>{};
   if(self::b) {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(self::list).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = self::list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic a = :sync-for-iterator.{core::Iterator::current};
       #t9.{core::Map::[]=}(a, 1);
@@ -115,11 +114,11 @@
   if(self::b)
     #t10.{core::Map::[]=}(0, 1);
   else {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(self::list).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = self::list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic a = :sync-for-iterator.{core::Iterator::current};
       {
-        core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, core::int*>*>*>(<dynamic, core::int*>{a: 1}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = <dynamic, core::int*>{a: 1}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, core::int*>* #t11 = :sync-for-iterator.{core::Iterator::current};
           #t10.{core::Map::[]=}(#t11.{core::MapEntry::key}, #t11.{core::MapEntry::value});
@@ -131,11 +130,11 @@
 static field core::Map<dynamic, core::int*>* map7 = block {
   final core::Map<dynamic, core::int*>* #t12 = <dynamic, core::int*>{};
   if(self::b) {
-    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(self::list).{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = self::list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       dynamic a = :sync-for-iterator.{core::Iterator::current};
       {
-        core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, core::int*>*>*>(<dynamic, core::int*>{a: 1}.{core::Map::entries}).{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = <dynamic, core::int*>{a: 1}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<dynamic, core::int*>* #t13 = :sync-for-iterator.{core::Iterator::current};
           #t12.{core::Map::[]=}(#t13.{core::MapEntry::key}, #t13.{core::MapEntry::value});
@@ -168,7 +167,7 @@
     #t16.{core::Map::[]=}(0, 1);
   else
     for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, core::int*>*>*>(<dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = <dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, core::int*>* #t17 = :sync-for-iterator.{core::Iterator::current};
         #t16.{core::Map::[]=}(#t17.{core::MapEntry::key}, #t17.{core::MapEntry::value});
@@ -179,7 +178,7 @@
   final core::Map<dynamic, core::int*>* #t18 = <dynamic, core::int*>{};
   if(self::b)
     for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<dynamic, core::int*>*>*>(<dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<dynamic, core::int*>*>* :sync-for-iterator = <dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<dynamic, core::int*>* #t19 = :sync-for-iterator.{core::Iterator::current};
         #t18.{core::Map::[]=}(#t19.{core::MapEntry::key}, #t19.{core::MapEntry::value});
@@ -194,7 +193,7 @@
     #t20.{core::Map::[]=}(0, 1);
   else
     if(self::b) {
-      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::MapEntry<core::int*, core::int*>*>*>(<core::int*, core::int*>{0: 1}.{core::Map::entries}).{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::int*, core::int*>*>* :sync-for-iterator = <core::int*, core::int*>{0: 1}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::int*, core::int*>* #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 4a52efa..5b3a8c9 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -62,5 +62,3 @@
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/never_opt_out: TypeCheckError
-nnbd/issue41210a/issue41210: TypeCheckError
-nnbd/issue41210b: TypeCheckError
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 7676f1d..9276ee9 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -18,7 +18,7 @@
 
 import 'package:kernel/target/targets.dart' show Target, TargetFlags, getTarget;
 
-import 'package:kernel/type_environment.dart' show SubtypeTester;
+import 'package:kernel/src/types.dart' show Types;
 
 import 'package:vm/bytecode/gen_bytecode.dart'
     show createFreshComponentWithBytecode, generateBytecode;
@@ -78,7 +78,7 @@
     stopwatch.stop();
 
     elapsedTimes.add(stopwatch.elapsedMilliseconds.toDouble());
-    List<Object> typeChecks = SubtypeTester.typeChecks;
+    List<Object> typeChecks = Types.typeChecksForTesting;
     if (typeChecks?.isNotEmpty ?? false) {
       BenchMaker.writeTypeChecks("type_checks.json", typeChecks);
     }
@@ -328,7 +328,8 @@
       Component userCode = new Component(
           nameRoot: component.root,
           uriToSource: new Map<Uri, Source>.from(component.uriToSource));
-      userCode.mainMethodName = component.mainMethodName;
+      userCode.setMainMethodAndMode(
+          component.mainMethodName, true, component.mode);
       for (Library library in component.libraries) {
         if (library.importUri.scheme != "dart") {
           userCode.libraries.add(library);
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 17ea976..29106f1 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -61,6 +61,8 @@
   ..addFlag('protobuf-tree-shaker',
       help: 'Enable protobuf tree shaker transformation in AOT mode.',
       defaultsTo: false)
+  ..addFlag('minimal-kernel',
+      help: 'Produce minimal tree-shaken kernel file.', defaultsTo: false)
   ..addFlag('link-platform',
       help:
           'When in batch mode, link platform kernel file into result kernel file.'
@@ -162,7 +164,10 @@
   ..addOption('libraries-spec',
       help: 'A path or uri to the libraries specification JSON file')
   ..addFlag('debugger-module-names',
-      help: 'Use debugger-friendly modules names', defaultsTo: false);
+      help: 'Use debugger-friendly modules names', defaultsTo: false)
+  ..addOption('dartdevc-module-format',
+      help: 'The module format to use on for the dartdevc compiler',
+      defaultsTo: 'amd');
 
 String usage = '''
 Usage: server [options] [input.dart]
@@ -514,17 +519,18 @@
           useGlobalTypeFlowAnalysis: options['tfa'],
           environmentDefines: environmentDefines,
           enableAsserts: options['enable-asserts'],
-          useProtobufTreeShaker: options['protobuf-tree-shaker']));
+          useProtobufTreeShaker: options['protobuf-tree-shaker'],
+          minimalKernel: options['minimal-kernel']));
     }
     if (results.component != null) {
       transformer?.transform(results.component);
 
       if (_compilerOptions.target.name == 'dartdevc') {
-        await writeJavascriptBundle(
-            results, _kernelBinaryFilename, options['filesystem-scheme']);
+        await writeJavascriptBundle(results, _kernelBinaryFilename,
+            options['filesystem-scheme'], options['dartdevc-module-format']);
       }
       await writeDillFile(results, _kernelBinaryFilename,
-          filterExternal: importDill != null,
+          filterExternal: importDill != null || options['minimal-kernel'],
           incrementalSerializer: incrementalSerializer);
 
       _outputStream.writeln(boundaryKey);
@@ -591,7 +597,7 @@
 
   /// Write a JavaScript bundle containg the provided component.
   Future<void> writeJavascriptBundle(KernelCompilationResults results,
-      String filename, String fileSystemScheme) async {
+      String filename, String fileSystemScheme, String moduleFormat) async {
     var packageConfig = await loadPackageConfigUri(
         _compilerOptions.packagesFileUri ?? File('.packages').absolute.uri);
     final Component component = results.component;
@@ -609,7 +615,8 @@
     }
     _bundler = JavaScriptBundler(
         component, strongComponents, fileSystemScheme, packageConfig,
-        useDebuggerModuleNames: useDebuggerModuleNames);
+        useDebuggerModuleNames: useDebuggerModuleNames,
+        moduleFormat: moduleFormat);
     final sourceFileSink = sourceFile.openWrite();
     final manifestFileSink = manifestFile.openWrite();
     final sourceMapsFileSink = sourceMapsFile.openWrite();
@@ -853,8 +860,8 @@
         deltaProgram.uriToSource.keys);
 
     if (_compilerOptions.target.name == 'dartdevc') {
-      await writeJavascriptBundle(
-          results, _kernelBinaryFilename, _options['filesystem-scheme']);
+      await writeJavascriptBundle(results, _kernelBinaryFilename,
+          _options['filesystem-scheme'], _options['dartdevc-module-format']);
     } else {
       await writeDillFile(results, _kernelBinaryFilename,
           incrementalSerializer: _generator.incrementalSerializer);
diff --git a/pkg/frontend_server/lib/src/expression_compiler.dart b/pkg/frontend_server/lib/src/expression_compiler.dart
index 2902fc5..d104a7d 100644
--- a/pkg/frontend_server/lib/src/expression_compiler.dart
+++ b/pkg/frontend_server/lib/src/expression_compiler.dart
@@ -63,7 +63,7 @@
 }
 
 /// DartScopeBuilder finds dart scope information in
-/// [component] on a given [line]:
+/// [component] on a given 1-based [line]:
 /// library, class, locals, formals, and any other
 /// avaiable symbols at that location.
 /// TODO(annagrin): Refine scope detection
@@ -75,11 +75,13 @@
   Procedure _procedure;
   final List<FunctionNode> _functions = [];
   final int _line;
+  final int _column;
+  int _offset;
   final Set<String> _privateFields = {};
   final Map<String, DartType> _definitions = {};
   final List<TypeParameter> _typeParameters = [];
 
-  DartScopeBuilder(this._component, this._line);
+  DartScopeBuilder(this._component, this._line, this._column);
 
   DartScope build() {
     if (_library == null || _procedure == null) return null;
@@ -96,13 +98,14 @@
   @override
   void visitLibrary(Library library) {
     _library = library;
+    _offset = _component.getOffset(_library.fileUri, _line, _column);
 
     super.visitLibrary(library);
   }
 
   @override
   void visitClass(Class cls) {
-    if (_scopeContainsLine(cls.fileOffset, cls.fileEndOffset, _line)) {
+    if (_scopeContainsOffset(cls.fileOffset, cls.fileEndOffset, _offset)) {
       _cls = cls;
       _typeParameters.addAll(cls.typeParameters);
 
@@ -126,7 +129,7 @@
 
   @override
   void visitProcedure(Procedure p) {
-    if (_scopeContainsLine(p.fileOffset, p.fileEndOffset, _line)) {
+    if (_scopeContainsOffset(p.fileOffset, p.fileEndOffset, _offset)) {
       _procedure = p;
 
       super.visitProcedure(p);
@@ -135,7 +138,7 @@
 
   @override
   void visitFunctionNode(FunctionNode fun) {
-    if (_scopeContainsLine(fun.fileOffset, fun.fileEndOffset, _line)) {
+    if (_scopeContainsOffset(fun.fileOffset, fun.fileEndOffset, _offset)) {
       _collectDefinitions(fun);
       _typeParameters.addAll(fun.typeParameters);
 
@@ -171,20 +174,12 @@
     }
   }
 
-  // TODO(annagrin): use offset instead of line to find containing scope
-  // See [issue 40281](https://github.com/dart-lang/sdk/issues/40281)
-  bool _scopeContainsLine(int startOffset, int endOffset, int line) {
-    if (line < 0) return false;
+  static bool _scopeContainsOffset(int startOffset, int endOffset, int offset) {
+    if (offset < 0) return false;
     if (startOffset < 0) return false;
+    if (endOffset < 0) return false;
 
-    var startLine = _getLine(startOffset);
-    var endLine = _getLine(endOffset);
-
-    return line >= startLine && line <= endLine;
-  }
-
-  int _getLine(int offset) {
-    return _component.getLocation(_library.fileUri, offset).line;
+    return startOffset <= offset && offset <= endOffset;
   }
 }
 
@@ -246,6 +241,8 @@
   /// Compiles [expression] in [libraryUri] at [line]:[column] to JavaScript
   /// in [moduleName].
   ///
+  /// [line] and [column] are 1-based.
+  ///
   /// Values listed in [jsFrameValues] are substituted for their names in the
   /// [expression].
   ///
@@ -357,7 +354,7 @@
       return null;
     }
 
-    var builder = DartScopeBuilder(_component, line);
+    var builder = DartScopeBuilder(_component, line, column);
     library.accept(builder);
     var scope = builder.build();
     if (scope == null) {
diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart
index 201d379f..98443f8 100644
--- a/pkg/frontend_server/lib/src/javascript_bundle.dart
+++ b/pkg/frontend_server/lib/src/javascript_bundle.dart
@@ -25,8 +25,9 @@
 class JavaScriptBundler {
   JavaScriptBundler(this._originalComponent, this._strongComponents,
       this._fileSystemScheme, this._packageConfig,
-      {this.useDebuggerModuleNames = false})
-      : compilers = <String, ProgramCompiler>{} {
+      {this.useDebuggerModuleNames = false, String moduleFormat})
+      : compilers = <String, ProgramCompiler>{},
+        _moduleFormat = parseModuleFormat(moduleFormat ?? 'amd') {
     _summaries = <Component>[];
     _summaryUris = <Uri>[];
     _moduleImportForSummary = <Uri, String>{};
@@ -58,6 +59,7 @@
   final PackageConfig _packageConfig;
   final bool useDebuggerModuleNames;
   final Map<String, ProgramCompiler> compilers;
+  final ModuleFormat _moduleFormat;
 
   List<Component> _summaries;
   List<Uri> _summaryUris;
@@ -149,7 +151,7 @@
       }
       final code = jsProgramToCode(
         jsModule,
-        ModuleFormat.amd,
+        _moduleFormat,
         inlineSourceMap: true,
         buildSourceMap: true,
         jsUrl: '$moduleUrl.lib.js',
diff --git a/pkg/frontend_server/test/src/expression_compiler_test.dart b/pkg/frontend_server/test/src/expression_compiler_test.dart
index 4528537..996a103 100644
--- a/pkg/frontend_server/test/src/expression_compiler_test.dart
+++ b/pkg/frontend_server/test/src/expression_compiler_test.dart
@@ -50,6 +50,7 @@
 
   static CompilerOptions getOptions() {
     var options = CompilerOptions()
+      ..verbose = false // set to true for debugging
       ..sdkRoot = sdkRoot
       ..target = DevCompilerTarget(TargetFlags())
       ..librariesSpecificationUri = Uri.base.resolve('sdk/lib/libraries.json')
@@ -240,7 +241,7 @@
     for (int line = 0; line < lines.length; line++) {
       var content = lines[line];
       if (placeholderRegExp.firstMatch(content) != null) {
-        return line;
+        return line + 1;
       }
     }
     return -1;
@@ -259,7 +260,7 @@
           return ret;
         }
       }
-      main => 0;
+      main() => 0;
     ''';
 
     TestDriver driver;
@@ -331,6 +332,8 @@
           return x;
         }
       }
+
+      main() => 0;
       ''';
 
     TestDriver driver;
@@ -649,6 +652,8 @@
           return x;
         }
       }
+
+      main() => 0;
       ''';
 
     TestDriver driver;
@@ -825,6 +830,8 @@
           return x;
         }
       }
+
+      main() => 0;
       ''';
 
     TestDriver driver;
@@ -1192,6 +1199,8 @@
       outerClosure(3);
       return 0;
     }
+
+    main() => 0;
     ''';
 
     TestDriver driver;
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index ce59c92..3c70beb 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 40;
+  UInt32 formatVersion = 42;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
@@ -180,6 +180,7 @@
   UInt32 binaryOffsetForStringTable;
   UInt32 binaryOffsetForConstantTable;
   UInt32 mainMethodReference; // This is a ProcedureReference with a fixed-size integer.
+  UInt32 compilationMode; // enum NonNullableByDefaultCompiledMode { Disabled = 0, Weak = 1, Strong = 2, Agnostic = 3 } with a fixed-size integer.
   UInt32[libraryCount + 1] libraryOffsets;
   UInt32 libraryCount;
   UInt32 componentFileSizeInBytes;
@@ -370,7 +371,7 @@
   FileOffset fileEndOffset;
   UInt flags (isFinal, isConst, isStatic, hasImplicitGetter, hasImplicitSetter,
                 isCovariant, isGenericCovariantImpl, isLate, isExtensionMember,
-                isNonNullableByDefault);
+                isNonNullableByDefault, isInternalImplementation);
   Name name;
   List<Expression> annotations;
   DartType type;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 846cd93..e51b0a8 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1739,6 +1739,7 @@
   static const int FlagLate = 1 << 7;
   static const int FlagExtensionMember = 1 << 8;
   static const int FlagNonNullableByDefault = 1 << 9;
+  static const int FlagInternalImplementation = 1 << 10;
 
   /// Whether the field is declared with the `covariant` keyword.
   bool get isCovariant => flags & FlagCovariant != 0;
@@ -1780,6 +1781,13 @@
   /// Whether the field is declared with the `late` keyword.
   bool get isLate => flags & FlagLate != 0;
 
+  // If `true` this field is not part of the interface but only part of the
+  // class members.
+  //
+  // This is `true` for instance for synthesized fields added for the late
+  // lowering.
+  bool get isInternalImplementation => flags & FlagInternalImplementation != 0;
+
   void set isCovariant(bool value) {
     flags = value ? (flags | FlagCovariant) : (flags & ~FlagCovariant);
   }
@@ -1823,6 +1831,12 @@
     flags = value ? (flags | FlagLate) : (flags & ~FlagLate);
   }
 
+  void set isInternalImplementation(bool value) {
+    flags = value
+        ? (flags | FlagInternalImplementation)
+        : (flags & ~FlagInternalImplementation);
+  }
+
   /// True if the field is neither final nor const.
   bool get isMutable => flags & (FlagFinal | FlagConst) == 0;
   bool get isInstanceMember => !isStatic;
@@ -7922,7 +7936,23 @@
 
   @override
   String toStringInternal() {
-    return "";
+    StringBuffer sb = new StringBuffer();
+    if (_verboseTypeToString) {
+      sb.write(className.toStringInternal());
+    } else {
+      sb.write(classNode.name);
+    }
+    if (typeArguments.isNotEmpty) {
+      sb.write("<");
+      String comma = "";
+      for (DartType typeArgument in typeArguments) {
+        sb.write(comma);
+        sb.write(typeArgument.toStringInternal());
+        comma = ", ";
+      }
+      sb.write(">");
+    }
+    return sb.toString();
   }
 }
 
@@ -8417,7 +8447,12 @@
       <String, MetadataRepository<dynamic>>{};
 
   /// Reference to the main method in one of the libraries.
-  Reference mainMethodName;
+  Reference _mainMethodName;
+  Reference get mainMethodName => _mainMethodName;
+  NonNullableByDefaultCompiledMode _mode;
+  NonNullableByDefaultCompiledMode get mode {
+    return _mode ?? NonNullableByDefaultCompiledMode.Disabled;
+  }
 
   Component(
       {CanonicalName nameRoot,
@@ -8501,8 +8536,12 @@
 
   Procedure get mainMethod => mainMethodName?.asProcedure;
 
-  void set mainMethod(Procedure main) {
-    mainMethodName = getMemberReference(main);
+  void setMainMethodAndMode(Reference main, bool overwriteMainIfSet,
+      NonNullableByDefaultCompiledMode mode) {
+    if (_mainMethodName == null || overwriteMainIfSet) {
+      _mainMethodName = main;
+    }
+    _mode = mode;
   }
 
   R accept<R>(TreeVisitor<R> v) => v.visitComponent(this);
@@ -8523,6 +8562,15 @@
     return uriToSource[file]?.getLocation(file, offset);
   }
 
+  /// Translates line and column numbers to an offset in the given file.
+  ///
+  /// Returns offset of the line and column in the file, or -1 if the
+  /// source is not available or has no lines.
+  /// Throws [RangeError] if line or calculated offset are out of range.
+  int getOffset(Uri file, int line, int column) {
+    return uriToSource[file]?.getOffset(line, column) ?? -1;
+  }
+
   void addMetadataRepository(MetadataRepository repository) {
     metadata[repository.tag] = repository;
   }
@@ -8768,7 +8816,7 @@
     throw "Internal error";
   }
 
-  /// Translates an offset to line and column numbers in the given file.
+  /// Translates an offset to 1-based line and column numbers in the given file.
   Location getLocation(Uri file, int offset) {
     if (lineStarts == null || lineStarts.isEmpty) {
       return new Location(file, TreeNode.noOffset, TreeNode.noOffset);
@@ -8790,6 +8838,21 @@
     int columnNumber = 1 + offset - lineStart;
     return new Location(file, lineNumber, columnNumber);
   }
+
+  /// Translates 1-based line and column numbers to an offset in the given file
+  ///
+  /// Returns offset of the line and column in the file, or -1 if the source
+  /// has no lines.
+  /// Throws [RangeError] if line or calculated offset are out of range.
+  int getOffset(int line, int column) {
+    if (lineStarts == null || lineStarts.isEmpty) {
+      return -1;
+    }
+    RangeError.checkValueInInterval(line, 1, lineStarts.length, 'line');
+    var offset = lineStarts[line - 1] + column - 1;
+    RangeError.checkValueInInterval(offset, 0, lineStarts.last, 'offset');
+    return offset;
+  }
 }
 
 /// Returns the [Reference] object for the given member.
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index aabfcf0..12a494a 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -45,7 +45,7 @@
 }
 
 class _ComponentIndex {
-  static const numberOfFixedFields = 9;
+  static const numberOfFixedFields = 10;
 
   int binaryOffsetForSourceTable;
   int binaryOffsetForCanonicalNames;
@@ -54,6 +54,7 @@
   int binaryOffsetForStringTable;
   int binaryOffsetForConstantTable;
   int mainMethodReference;
+  NonNullableByDefaultCompiledMode compiledMode;
   List<int> libraryOffsets;
   int libraryCount;
   int componentFileSizeInBytes;
@@ -85,6 +86,7 @@
   int _transformerFlags = 0;
   Library _currentLibrary;
   int _componentStartOffset = 0;
+  NonNullableByDefaultCompiledMode compilationMode;
 
   // If something goes wrong, this list should indicate what library,
   // class, and member was being built.
@@ -621,6 +623,7 @@
     result.binaryOffsetForStringTable = _componentStartOffset + readUint32();
     result.binaryOffsetForConstantTable = _componentStartOffset + readUint32();
     result.mainMethodReference = readUint32();
+    result.compiledMode = NonNullableByDefaultCompiledMode.values[readUint32()];
     for (int i = 0; i < result.libraryCount + 1; ++i) {
       result.libraryOffsets[i] = _componentStartOffset + readUint32();
     }
@@ -675,6 +678,12 @@
 
     // Read component index from the end of this ComponentFiles serialized data.
     _ComponentIndex index = _readComponentIndex(componentFileSize);
+    if (compilationMode == null) {
+      compilationMode = index.compiledMode;
+    } else if (compilationMode != index.compiledMode) {
+      throw fail("Mixed compilation mode found: $compilationMode "
+          "and ${index.compiledMode}.");
+    }
 
     _byteOffset = index.binaryOffsetForStringTable;
     readStringTable(_stringTable);
@@ -711,9 +720,9 @@
       }
     }
 
-    var mainMethod =
+    Reference mainMethod =
         getMemberReferenceFromInt(index.mainMethodReference, allowNull: true);
-    component.mainMethodName ??= mainMethod;
+    component.setMainMethodAndMode(mainMethod, false, index.compiledMode);
 
     _byteOffset = _componentStartOffset + componentFileSize;
 
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index dbdee4d..c6f6104 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -730,7 +730,7 @@
     const int kernelFileAlignment = 8;
 
     // Keep this in sync with number of writeUInt32 below.
-    int numComponentIndexEntries = 7 + libraryOffsets.length + 3;
+    int numComponentIndexEntries = 8 + libraryOffsets.length + 3;
 
     int unalignedSize = getBufferOffset() + numComponentIndexEntries * 4;
     int padding =
@@ -760,6 +760,7 @@
     } else {
       writeUInt32(main.index + 1);
     }
+    writeUInt32(component.mode.index);
 
     assert(libraryOffsets.length == libraries.length);
     for (int offset in libraryOffsets) {
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index a18adf3..cec2308 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -149,7 +149,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 = 40;
+  static const int BinaryFormatVersion = 42;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 9d460d4..d649729 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -23,8 +23,36 @@
   void infer(ClassHierarchy hierarchy, Class classNode);
 }
 
+/// Core interface for answering queries needed to compute the subtyping
+/// relation.
+abstract class ClassHierarchyBase {
+  CoreTypes get coreTypes;
+
+  /// Returns the instantiation of [superclass] that is implemented by [type],
+  /// or `null` if [type] does not implement [superclass] at all.
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
+      Library clientLibrary, CoreTypes coreTypes);
+
+  /// Returns the type arguments of the instantiation of [superclass] that is
+  /// implemented by [type], or `null` if [type] does not implement [superclass]
+  /// at all.
+  List<DartType> getTypeArgumentsAsInstanceOf(
+      InterfaceType type, Class superclass);
+
+  /// Returns the possibly abstract interface member of [class_] with the given
+  /// [name].
+  ///
+  /// If [setter] is `false`, only fields, methods, and getters with that name
+  /// will be found.  If [setter] is `true`, only non-final fields and setters
+  /// will be found.
+  ///
+  /// If multiple members with that name are inherited and not overridden, the
+  /// member from the first declared supertype is returned.
+  Member getInterfaceMember(Class class_, Name name, {bool setter: false});
+}
+
 /// Interface for answering various subclassing queries.
-abstract class ClassHierarchy {
+abstract class ClassHierarchy implements ClassHierarchyBase {
   factory ClassHierarchy(Component component, CoreTypes coreTypes,
       {HandleAmbiguousSupertypes onAmbiguousSupertypes,
       MixinInferrer mixinInferrer}) {
@@ -77,17 +105,6 @@
   Supertype getClassAsInstanceOf(Class class_, Class superclass);
 
   /// Returns the instantiation of [superclass] that is implemented by [type],
-  /// or `null` if [type] does not implement [superclass] at all.
-  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
-      Library clientLibrary, CoreTypes coreTypes);
-
-  /// Returns the type arguments of the instantiation of [superclass] that is
-  /// implemented by [type], or `null` if [type] does not implement [superclass]
-  /// at all.
-  List<DartType> getTypeArgumentsAsInstanceOf(
-      InterfaceType type, Class superclass);
-
-  /// Returns the instantiation of [superclass] that is implemented by [type],
   /// or `null` if [type] does not implement [superclass].  [superclass] must
   /// be a generic class.
   Supertype asInstantiationOf(Supertype type, Class superclass);
@@ -119,17 +136,6 @@
   /// The returned list should not be modified.
   List<Member> getDispatchTargets(Class class_, {bool setters: false});
 
-  /// Returns the possibly abstract interface member of [class_] with the given
-  /// [name].
-  ///
-  /// If [setter] is `false`, only fields, methods, and getters with that name
-  /// will be found.  If [setter] is `true`, only non-final fields and setters
-  /// will be found.
-  ///
-  /// If multiple members with that name are inherited and not overridden, the
-  /// member from the first declared supertype is returned.
-  Member getInterfaceMember(Class class_, Name name, {bool setter: false});
-
   /// Returns the list of members denoting the interface for [class_], which
   /// may include abstract members.
   ///
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index bb3dd53..1ebce70 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -79,6 +79,7 @@
   Class _asyncAwaitCompleterClass;
   Class _futureOrClass;
   Constructor _asyncAwaitCompleterConstructor;
+  Procedure _asyncAwaitCompleterStartProcedure;
   Procedure _completeOnAsyncReturnProcedure;
   Procedure _completerCompleteError;
   Constructor _syncIterableDefaultConstructor;
@@ -261,6 +262,11 @@
         index.getMember('dart:async', '_AsyncAwaitCompleter', '');
   }
 
+  Procedure get asyncAwaitCompleterStartProcedure {
+    return _asyncAwaitCompleterStartProcedure ??=
+        index.getMember('dart:async', '_AsyncAwaitCompleter', 'start');
+  }
+
   Member get completeOnAsyncReturn {
     return _completeOnAsyncReturnProcedure ??=
         index.getTopLevelMember('dart:async', '_completeOnAsyncReturn');
diff --git a/pkg/kernel/lib/default_language_version.dart b/pkg/kernel/lib/default_language_version.dart
index 73670a5..b5c8df5 100644
--- a/pkg/kernel/lib/default_language_version.dart
+++ b/pkg/kernel/lib/default_language_version.dart
@@ -8,4 +8,4 @@
 // 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
 
 int defaultLanguageVersionMajor = 2;
-int defaultLanguageVersionMinor = 8;
+int defaultLanguageVersionMinor = 9;
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index e18a1125..ef93768 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -131,6 +131,13 @@
   /// but it additionally accounts for parameter covariance.
   String _checkFunctionOverride(
       Class host, Member ownMember, Member superMember) {
+    if (ownMember is Procedure &&
+        (ownMember.isMemberSignature ||
+            (ownMember.isForwardingStub && !ownMember.isForwardingSemiStub))) {
+      // Synthesized members are not obligated to override super members.
+      return null;
+    }
+
     final FunctionNode ownFunction = ownMember.function;
     final FunctionNode superFunction = superMember.function;
     Substitution ownSubstitution = _makeSubstitutionForMember(host, ownMember);
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index c1ea1f8..4e48572 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -30,6 +30,8 @@
 
 import '../visitor.dart' show DartTypeVisitor, DartTypeVisitor1;
 
+import 'legacy_erasure.dart';
+
 class TypeVariableGraph extends Graph<int> {
   List<int> vertices;
   List<TypeParameter> typeParameters;
@@ -257,6 +259,7 @@
 // TODO(dmitryas):  Remove [typedefInstantiations] when type arguments passed to
 // typedefs are preserved in the Kernel output.
 List<TypeArgumentIssue> findTypeArgumentIssues(
+    Library library,
     DartType type,
     TypeEnvironment typeEnvironment,
     SubtypeCheckMode subtypeCheckMode,
@@ -281,7 +284,7 @@
         requiredParameterCount: functionType.requiredParameterCount,
         typedefType: null);
     typedefRhsResult = findTypeArgumentIssues(
-        cloned, typeEnvironment, subtypeCheckMode, bottomType,
+        library, cloned, typeEnvironment, subtypeCheckMode, bottomType,
         allowSuperBounded: true);
     type = functionType.typedefType;
   }
@@ -295,25 +298,25 @@
   } else if (type is FunctionType) {
     List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
     for (TypeParameter parameter in type.typeParameters) {
-      result.addAll(findTypeArgumentIssues(
-              parameter.bound, typeEnvironment, subtypeCheckMode, bottomType,
+      result.addAll(findTypeArgumentIssues(library, parameter.bound,
+              typeEnvironment, subtypeCheckMode, bottomType,
               allowSuperBounded: true) ??
           const <TypeArgumentIssue>[]);
     }
     for (DartType formal in type.positionalParameters) {
       result.addAll(findTypeArgumentIssues(
-              formal, typeEnvironment, subtypeCheckMode, bottomType,
+              library, formal, typeEnvironment, subtypeCheckMode, bottomType,
               allowSuperBounded: true) ??
           const <TypeArgumentIssue>[]);
     }
     for (NamedType named in type.namedParameters) {
-      result.addAll(findTypeArgumentIssues(
-              named.type, typeEnvironment, subtypeCheckMode, bottomType,
+      result.addAll(findTypeArgumentIssues(library, named.type, typeEnvironment,
+              subtypeCheckMode, bottomType,
               allowSuperBounded: true) ??
           const <TypeArgumentIssue>[]);
     }
-    result.addAll(findTypeArgumentIssues(
-            type.returnType, typeEnvironment, subtypeCheckMode, bottomType,
+    result.addAll(findTypeArgumentIssues(library, type.returnType,
+            typeEnvironment, subtypeCheckMode, bottomType,
             allowSuperBounded: true) ??
         const <TypeArgumentIssue>[]);
     return result.isEmpty ? null : result;
@@ -334,19 +337,21 @@
       // Generic function types aren't allowed as type arguments either.
       result ??= <TypeArgumentIssue>[];
       result.add(new TypeArgumentIssue(i, argument, variables[i], type));
-    } else if (variables[i].bound is! InvalidType &&
-        !typeEnvironment.isSubtypeOf(
-            argument,
-            substitute(variables[i].bound, substitutionMap),
-            subtypeCheckMode)) {
-      // If the bound is InvalidType it's not checked, because an error was
-      // reported already at the time of the creation of InvalidType.
-      result ??= <TypeArgumentIssue>[];
-      result.add(new TypeArgumentIssue(i, argument, variables[i], type));
+    } else if (variables[i].bound is! InvalidType) {
+      DartType bound = substitute(variables[i].bound, substitutionMap);
+      if (!library.isNonNullableByDefault) {
+        bound = legacyErasure(typeEnvironment.coreTypes, bound);
+      }
+      if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
+        // If the bound is InvalidType it's not checked, because an error was
+        // reported already at the time of the creation of InvalidType.
+        result ??= <TypeArgumentIssue>[];
+        result.add(new TypeArgumentIssue(i, argument, variables[i], type));
+      }
     }
 
     List<TypeArgumentIssue> issues = findTypeArgumentIssues(
-        argument, typeEnvironment, subtypeCheckMode, bottomType,
+        library, argument, typeEnvironment, subtypeCheckMode, bottomType,
         allowSuperBounded: true);
     if (issues != null) {
       argumentsResult ??= <TypeArgumentIssue>[];
@@ -413,6 +418,7 @@
 // TODO(dmitryas):  Remove [typedefInstantiations] when type arguments passed to
 // typedefs are preserved in the Kernel output.
 List<TypeArgumentIssue> findTypeArgumentIssuesForInvocation(
+    Library library,
     List<TypeParameter> parameters,
     List<DartType> arguments,
     TypeEnvironment typeEnvironment,
@@ -436,14 +442,19 @@
       // Generic function types aren't allowed as type arguments either.
       result ??= <TypeArgumentIssue>[];
       result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
-    } else if (!typeEnvironment.isSubtypeOf(argument,
-        substitute(parameters[i].bound, substitutionMap), subtypeCheckMode)) {
-      result ??= <TypeArgumentIssue>[];
-      result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
+    } else if (parameters[i].bound is! InvalidType) {
+      DartType bound = substitute(parameters[i].bound, substitutionMap);
+      if (!library.isNonNullableByDefault) {
+        bound = legacyErasure(typeEnvironment.coreTypes, bound);
+      }
+      if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
+        result ??= <TypeArgumentIssue>[];
+        result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
+      }
     }
 
     List<TypeArgumentIssue> issues = findTypeArgumentIssues(
-        argument, typeEnvironment, subtypeCheckMode, bottomType,
+        library, argument, typeEnvironment, subtypeCheckMode, bottomType,
         allowSuperBounded: true);
     if (issues != null) {
       result ??= <TypeArgumentIssue>[];
diff --git a/pkg/kernel/lib/src/hierarchy_based_type_environment.dart b/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
index 2384e50..eadc8fa 100644
--- a/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
+++ b/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
@@ -6,17 +6,17 @@
 
 import '../ast.dart' show Class, DartType, InterfaceType, Library, Member, Name;
 
-import '../class_hierarchy.dart' show ClassHierarchy;
+import '../class_hierarchy.dart' show ClassHierarchyBase;
 
 import '../core_types.dart' show CoreTypes;
 
 import '../type_environment.dart' show TypeEnvironment;
 
 class HierarchyBasedTypeEnvironment extends TypeEnvironment {
-  final ClassHierarchy hierarchy;
+  final ClassHierarchyBase hierarchy;
 
   HierarchyBasedTypeEnvironment(CoreTypes coreTypes, this.hierarchy)
-      : super.fromSubclass(coreTypes);
+      : super.fromSubclass(coreTypes, hierarchy);
 
   @override
   InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
diff --git a/pkg/kernel/lib/src/types.dart b/pkg/kernel/lib/src/types.dart
new file mode 100644
index 0000000..af97773
--- /dev/null
+++ b/pkg/kernel/lib/src/types.dart
@@ -0,0 +1,965 @@
+// 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 '../ast.dart'
+    show
+        BottomType,
+        Class,
+        DartType,
+        DynamicType,
+        FunctionType,
+        InterfaceType,
+        InvalidType,
+        Library,
+        NamedType,
+        NeverType,
+        Nullability,
+        TypeParameter,
+        TypeParameterType,
+        TypedefType,
+        Variance,
+        VoidType;
+
+import '../class_hierarchy.dart' show ClassHierarchyBase;
+
+import '../core_types.dart' show CoreTypes;
+
+import '../type_algebra.dart'
+    show Substitution, combineNullabilitiesForSubstitution;
+
+import '../type_environment.dart' show IsSubtypeOf, SubtypeCheckMode;
+
+import 'future_or.dart';
+
+class Types {
+  final ClassHierarchyBase hierarchy;
+
+  Types(this.hierarchy);
+
+  bool _isSubtypeFromMode(IsSubtypeOf isSubtypeOf, SubtypeCheckMode mode) {
+    switch (mode) {
+      case SubtypeCheckMode.withNullabilities:
+        return isSubtypeOf.isSubtypeWhenUsingNullabilities();
+      case SubtypeCheckMode.ignoringNullabilities:
+        return isSubtypeOf.isSubtypeWhenIgnoringNullabilities();
+      default:
+        throw new StateError("Unhandled subtype checking mode '$mode'");
+    }
+  }
+
+  /// Returns true if [s] is a subtype of [t].
+  bool isSubtypeOf(DartType s, DartType t, SubtypeCheckMode mode) {
+    IsSubtypeOf result = performNullabilityAwareSubtypeCheck(s, t);
+    return _isSubtypeFromMode(result, mode);
+  }
+
+  /// Can be use to collect type checks. To use:
+  /// 1. Rename `performNullabilityAwareSubtypeCheck` to
+  ///    `_performNullabilityAwareSubtypeCheck`.
+  /// 2. Rename `_collect_performNullabilityAwareSubtypeCheck` to
+  ///    `performNullabilityAwareSubtypeCheck`.
+  /// 3. Comment out the call to `_performNullabilityAwareSubtypeCheck` below.
+  // ignore:unused_element
+  bool _collect_performNullabilityAwareSubtypeCheck(
+      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
+    IsSubtypeOf result = const IsSubtypeOf.always();
+    //result = _performNullabilityAwareSubtypeCheck(subtype, supertype, mode);
+    bool booleanResult = _isSubtypeFromMode(result, mode);
+    typeChecksForTesting ??= <Object>[];
+    typeChecksForTesting.add([subtype, supertype, booleanResult]);
+    return booleanResult;
+  }
+
+  IsSubtypeOf performNullabilityAwareSubtypeCheck(DartType s, DartType t) {
+    // TODO(johnniwinther,dmitryas): Ensure complete handling of InvalidType in
+    // the subtype relation.
+    if (s is InvalidType || t is InvalidType) {
+      return const IsSubtypeOf.always();
+    }
+
+    if (s is BottomType) {
+      return const IsSubtypeOf.always(); // Rule 3.
+    }
+    if (t is DynamicType) {
+      return const IsSubtypeOf.always(); // Rule 2.
+    }
+    if (t is VoidType) {
+      return const IsSubtypeOf.always(); // Rule 2.
+    }
+    if (t is BottomType) {
+      return const IsSubtypeOf.never();
+    }
+    if (s is NeverType) {
+      return new IsSubtypeOf.basedSolelyOnNullabilities(
+          s, t, hierarchy.coreTypes.futureOrClass);
+    }
+
+    if (t is InterfaceType) {
+      Class cls = t.classNode;
+      if (cls == hierarchy.coreTypes.objectClass &&
+          !(s is InterfaceType &&
+              s.classNode == hierarchy.coreTypes.futureOrClass)) {
+        return new IsSubtypeOf.basedSolelyOnNullabilities(
+            s, t, hierarchy.coreTypes.futureOrClass);
+      }
+      if (cls == hierarchy.coreTypes.futureOrClass) {
+        const IsFutureOrSubtypeOf relation = const IsFutureOrSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.coreTypes.futureOrClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
+      } else {
+        const IsInterfaceSubtypeOf relation = const IsInterfaceSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.coreTypes.futureOrClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
+      }
+    } else if (t is FunctionType) {
+      const IsFunctionSubtypeOf relation = const IsFunctionSubtypeOf();
+      if (s is DynamicType) {
+        return relation.isDynamicRelated(s, t, this);
+      } else if (s is VoidType) {
+        return relation.isVoidRelated(s, t, this);
+      } else if (s is InterfaceType) {
+        return s.classNode == hierarchy.coreTypes.futureOrClass
+            ? relation.isFutureOrRelated(s, t, this)
+            : relation.isInterfaceRelated(s, t, this);
+      } else if (s is FunctionType) {
+        return relation.isFunctionRelated(s, t, this);
+      } else if (s is TypeParameterType) {
+        return s.promotedBound == null
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
+      } else if (s is TypedefType) {
+        return relation.isTypedefRelated(s, t, this);
+      }
+    } else if (t is TypeParameterType) {
+      if (t.promotedBound == null) {
+        const IsTypeParameterSubtypeOf relation =
+            const IsTypeParameterSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.coreTypes.futureOrClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
+      } else {
+        const IsIntersectionSubtypeOf relation =
+            const IsIntersectionSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.coreTypes.futureOrClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
+      }
+    } else if (t is TypedefType) {
+      const IsTypedefSubtypeOf relation = const IsTypedefSubtypeOf();
+      if (s is DynamicType) {
+        return relation.isDynamicRelated(s, t, this);
+      } else if (s is VoidType) {
+        return relation.isVoidRelated(s, t, this);
+      } else if (s is InterfaceType) {
+        return s.classNode == hierarchy.coreTypes.futureOrClass
+            ? relation.isFutureOrRelated(s, t, this)
+            : relation.isInterfaceRelated(s, t, this);
+      } else if (s is FunctionType) {
+        return relation.isFunctionRelated(s, t, this);
+      } else if (s is TypeParameterType) {
+        return s.promotedBound == null
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
+      } else if (s is TypedefType) {
+        return relation.isTypedefRelated(s, t, this);
+      }
+    } else if (t is NeverType) {
+      const IsNeverTypeSubtypeOf relation = const IsNeverTypeSubtypeOf();
+      if (s is DynamicType) {
+        return relation.isDynamicRelated(s, t, this);
+      } else if (s is VoidType) {
+        return relation.isVoidRelated(s, t, this);
+      } else if (s is InterfaceType) {
+        return relation.isInterfaceRelated(s, t, this);
+      } else if (s is FunctionType) {
+        return relation.isFunctionRelated(s, t, this);
+      } else if (s is TypeParameterType) {
+        return s.promotedBound == null
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
+      } else if (s is TypedefType) {
+        return relation.isTypedefRelated(s, t, this);
+      }
+    } else {
+      throw "Unhandled type: ${t.runtimeType}";
+    }
+    throw "Unhandled type combination: ${t.runtimeType} ${s.runtimeType}";
+  }
+
+  /// Returns true if all type arguments in [s] and [t] pairwise are subtypes
+  /// with respect to the variance of the corresponding [p] type parameter.
+  IsSubtypeOf areTypeArgumentsOfSubtypeKernel(
+      List<DartType> s, List<DartType> t, List<TypeParameter> p) {
+    if (s.length != t.length || s.length != p.length) {
+      throw "Numbers of type arguments don't match $s $t with parameters $p.";
+    }
+    IsSubtypeOf result = const IsSubtypeOf.always();
+    for (int i = 0; i < s.length; i++) {
+      int variance = p[i].variance;
+      if (variance == Variance.contravariant) {
+        result = result.and(performNullabilityAwareSubtypeCheck(t[i], s[i]));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
+        }
+      } else if (variance == Variance.invariant) {
+        result =
+            result.and(performNullabilityAwareMutualSubtypesCheck(s[i], t[i]));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
+        }
+      } else {
+        result = result.and(performNullabilityAwareSubtypeCheck(s[i], t[i]));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
+        }
+      }
+    }
+    return result;
+  }
+
+  static List<Object> typeChecksForTesting;
+
+  Class get futureOrClass => hierarchy.coreTypes.futureOrClass;
+
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
+      Library clientLibrary, CoreTypes coreTypes) {
+    return hierarchy.getTypeAsInstanceOf(
+        type, superclass, clientLibrary, coreTypes);
+  }
+
+  List<DartType> getTypeArgumentsAsInstanceOf(
+      InterfaceType type, Class superclass) {
+    return hierarchy.getTypeArgumentsAsInstanceOf(type, superclass);
+  }
+
+  bool isTop(DartType type) {
+    return type is DynamicType ||
+        type is VoidType ||
+        type == hierarchy.coreTypes.objectLegacyRawType ||
+        type == hierarchy.coreTypes.objectNullableRawType;
+  }
+
+  IsSubtypeOf performNullabilityAwareMutualSubtypesCheck(
+      DartType type1, DartType type2) {
+    return performNullabilityAwareSubtypeCheck(type1, type2)
+        .andSubtypeCheckFor(type2, type1, this);
+  }
+}
+
+abstract class TypeRelation<T extends DartType> {
+  const TypeRelation();
+
+  IsSubtypeOf isDynamicRelated(DynamicType s, T t, Types types);
+
+  IsSubtypeOf isVoidRelated(VoidType s, T t, Types types);
+
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, T t, Types types);
+
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, T t, Types types);
+
+  IsSubtypeOf isFunctionRelated(FunctionType s, T t, Types types);
+
+  IsSubtypeOf isFutureOrRelated(InterfaceType futureOr, T t, Types types);
+
+  IsSubtypeOf isTypeParameterRelated(TypeParameterType s, T t, Types types);
+
+  IsSubtypeOf isTypedefRelated(TypedefType s, T t, Types types);
+}
+
+class IsInterfaceSubtypeOf extends TypeRelation<InterfaceType> {
+  const IsInterfaceSubtypeOf();
+
+  @override
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, InterfaceType t, Types types) {
+    if (s.classNode == types.hierarchy.coreTypes.nullClass) {
+      // This is an optimization, to avoid instantiating unnecessary type
+      // arguments in getKernelTypeAsInstanceOf.
+      return new IsSubtypeOf.basedSolelyOnNullabilities(
+          s, t, types.hierarchy.coreTypes.futureOrClass);
+    }
+    List<DartType> asSupertypeArguments =
+        types.hierarchy.getTypeArgumentsAsInstanceOf(s, t.classNode);
+    if (asSupertypeArguments == null) {
+      return const IsSubtypeOf.never();
+    }
+    return types
+        .areTypeArgumentsOfSubtypeKernel(
+            asSupertypeArguments, t.typeArguments, t.classNode.typeParameters)
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(
+            s, t, types.hierarchy.coreTypes.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, InterfaceType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.parameter.bound, t).and(
+        new IsSubtypeOf.basedSolelyOnNullabilities(
+            s, t, types.hierarchy.coreTypes.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, InterfaceType t, Types types) {
+    List<DartType> arguments = futureOr.typeArguments;
+    // Rules 7.1 and 7.2.
+    return types
+        .performNullabilityAwareSubtypeCheck(arguments.single, t)
+        .andSubtypeCheckFor(
+            new InterfaceType(types.hierarchy.coreTypes.futureClass,
+                Nullability.nonNullable, arguments),
+            t,
+            types)
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(
+            futureOr, t, types.hierarchy.coreTypes.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, InterfaceType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound, t); // Rule 12.
+  }
+
+  @override
+  IsSubtypeOf isDynamicRelated(DynamicType s, InterfaceType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isFunctionRelated(FunctionType s, InterfaceType t, Types types) {
+    return t.classNode == types.hierarchy.coreTypes.functionClass
+        ? new IsSubtypeOf.basedSolelyOnNullabilities(
+            s, t, types.hierarchy.coreTypes.futureOrClass)
+        : const IsSubtypeOf.never(); // Rule 14.
+  }
+
+  @override
+  IsSubtypeOf isTypedefRelated(TypedefType s, InterfaceType t, Types types) {
+    // Rule 5.
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t).and(
+        new IsSubtypeOf.basedSolelyOnNullabilities(
+            s, t, types.hierarchy.coreTypes.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isVoidRelated(VoidType s, InterfaceType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+}
+
+class IsFunctionSubtypeOf extends TypeRelation<FunctionType> {
+  const IsFunctionSubtypeOf();
+
+  @override
+  IsSubtypeOf isFunctionRelated(FunctionType s, FunctionType t, Types types) {
+    List<TypeParameter> sTypeVariables = s.typeParameters;
+    List<TypeParameter> tTypeVariables = t.typeParameters;
+    if (sTypeVariables.length != tTypeVariables.length) {
+      return const IsSubtypeOf.never();
+    }
+    IsSubtypeOf result = const IsSubtypeOf.always();
+    if (sTypeVariables.isNotEmpty) {
+      // If the function types have type variables, we alpha-rename the type
+      // variables of [s] to use those of [t].
+
+      // As an optimization, we first check if the bounds of the type variables
+      // of the two types on the same positions are mutual subtypes without
+      // alpha-renaming them.
+      List<DartType> typeVariableSubstitution = <DartType>[];
+      for (int i = 0; i < sTypeVariables.length; i++) {
+        TypeParameter sTypeVariable = sTypeVariables[i];
+        TypeParameter tTypeVariable = tTypeVariables[i];
+        result = result.and(types.performNullabilityAwareMutualSubtypesCheck(
+            sTypeVariable.bound, tTypeVariable.bound));
+        typeVariableSubstitution.add(new TypeParameterType.forAlphaRenaming(
+            sTypeVariable, tTypeVariable));
+      }
+      Substitution substitution =
+          Substitution.fromPairs(sTypeVariables, typeVariableSubstitution);
+      // If the bounds aren't the same, we need to try again after computing the
+      // substitution of type variables.
+      if (!result.isSubtypeWhenIgnoringNullabilities()) {
+        result = const IsSubtypeOf.always();
+        for (int i = 0; i < sTypeVariables.length; i++) {
+          TypeParameter sTypeVariable = sTypeVariables[i];
+          TypeParameter tTypeVariable = tTypeVariables[i];
+          result = result.and(types.performNullabilityAwareMutualSubtypesCheck(
+              substitution.substituteType(sTypeVariable.bound),
+              tTypeVariable.bound));
+          if (!result.isSubtypeWhenIgnoringNullabilities()) {
+            return const IsSubtypeOf.never();
+          }
+        }
+      }
+      s = substitution.substituteType(s.withoutTypeParameters);
+    }
+    result = result.and(
+        types.performNullabilityAwareSubtypeCheck(s.returnType, t.returnType));
+    if (!result.isSubtypeWhenIgnoringNullabilities()) {
+      return const IsSubtypeOf.never();
+    }
+    List<DartType> sPositional = s.positionalParameters;
+    List<DartType> tPositional = t.positionalParameters;
+    if (s.requiredParameterCount > t.requiredParameterCount) {
+      // Rule 15, n1 <= n2.
+      return const IsSubtypeOf.never();
+    }
+    if (sPositional.length < tPositional.length) {
+      // Rule 15, n1 + k1 >= n2 + k2.
+      return const IsSubtypeOf.never();
+    }
+    for (int i = 0; i < tPositional.length; i++) {
+      result = result.and(types.performNullabilityAwareSubtypeCheck(
+          tPositional[i], sPositional[i]));
+      if (!result.isSubtypeWhenIgnoringNullabilities()) {
+        // Rule 15, Tj <: Sj.
+        return const IsSubtypeOf.never();
+      }
+    }
+    List<NamedType> sNamed = s.namedParameters;
+    List<NamedType> tNamed = t.namedParameters;
+    if (sNamed.isNotEmpty || tNamed.isNotEmpty) {
+      // Rule 16, the number of positional parameters must be the same.
+      if (sPositional.length != tPositional.length) {
+        return const IsSubtypeOf.never();
+      }
+      if (s.requiredParameterCount != t.requiredParameterCount) {
+        return const IsSubtypeOf.never();
+      }
+
+      // Rule 16, the parameter names of [t] must be a subset of those of
+      // [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;
+        }
+        if (sCount == sNamed.length) return const IsSubtypeOf.never();
+        result = result.and(types.performNullabilityAwareSubtypeCheck(
+            tNamed[tCount].type, sNamed[sCount].type));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
+        }
+      }
+    }
+    return result.and(
+        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, FunctionType t, Types types) {
+    if (s.classNode == types.hierarchy.coreTypes.nullClass) {
+      // Rule 4.
+      return new IsSubtypeOf.basedSolelyOnNullabilities(
+          s, t, types.futureOrClass);
+    }
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isDynamicRelated(DynamicType s, FunctionType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, FunctionType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, FunctionType t, Types types) {
+    // Rule 12.
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound, t);
+  }
+
+  @override
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, FunctionType t, Types types) {
+    // Rule 13.
+    return types.performNullabilityAwareSubtypeCheck(s.parameter.bound, t).and(
+        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isTypedefRelated(TypedefType s, FunctionType t, Types types) {
+    // Rule 5.
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
+  }
+
+  @override
+  IsSubtypeOf isVoidRelated(VoidType s, FunctionType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+}
+
+class IsTypeParameterSubtypeOf extends TypeRelation<TypeParameterType> {
+  const IsTypeParameterSubtypeOf();
+
+  @override
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, TypeParameterType t, Types types) {
+    IsSubtypeOf result = const IsSubtypeOf.always();
+    if (s.parameter != t.parameter) {
+      result = types.performNullabilityAwareSubtypeCheck(s.bound, t);
+    }
+    if (s.nullability == Nullability.undetermined &&
+        t.nullability == Nullability.undetermined) {
+      // The two nullabilities are undetermined, but are connected via
+      // additional constraint, namely that they will be equal at run time.
+      return result;
+    }
+    return result.and(
+        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, TypeParameterType t, Types types) {
+    // Nullable types aren't promoted to intersection types.
+    // TODO(dmitryas): Uncomment the following when the inference is updated.
+    //assert(intersection.typeParameterTypeNullability != Nullability.nullable);
+
+    // Rule 8.
+    if (intersection.parameter == t.parameter) {
+      if (intersection.nullability == Nullability.undetermined &&
+          t.nullability == Nullability.undetermined) {
+        // The two nullabilities are undetermined, but are connected via
+        // additional constraint, namely that they will be equal at run time.
+        return const IsSubtypeOf.always();
+      }
+      return new IsSubtypeOf.basedSolelyOnNullabilities(
+          intersection, t, types.futureOrClass);
+    }
+
+    // Rule 12.
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound.withNullability(intersection.nullability),
+        t);
+  }
+
+  @override
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, TypeParameterType t, Types types) {
+    if (s.classNode == types.hierarchy.coreTypes.nullClass) {
+      // Rule 4.
+      return new IsSubtypeOf.basedSolelyOnNullabilities(
+          s, t, types.futureOrClass);
+    }
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isDynamicRelated(
+      DynamicType s, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isFunctionRelated(
+      FunctionType s, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isTypedefRelated(
+      TypedefType s, TypeParameterType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
+  }
+
+  @override
+  IsSubtypeOf isVoidRelated(VoidType s, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+}
+
+class IsTypedefSubtypeOf extends TypeRelation<TypedefType> {
+  const IsTypedefSubtypeOf();
+
+  @override
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
+  }
+
+  @override
+  IsSubtypeOf isDynamicRelated(DynamicType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
+  }
+
+  @override
+  IsSubtypeOf isFunctionRelated(FunctionType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
+  }
+
+  @override
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(futureOr, t.unalias);
+  }
+
+  @override
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(intersection, t.unalias);
+  }
+
+  @override
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
+  }
+
+  @override
+  IsSubtypeOf isTypedefRelated(TypedefType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t.unalias);
+  }
+
+  @override
+  IsSubtypeOf isVoidRelated(VoidType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
+  }
+}
+
+class IsFutureOrSubtypeOf extends TypeRelation<InterfaceType> {
+  const IsFutureOrSubtypeOf();
+
+  @override
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, InterfaceType futureOr, Types types) {
+    List<DartType> arguments = futureOr.typeArguments;
+
+    Nullability unitedNullability = computeNullabilityOfFutureOr(
+        futureOr, types.hierarchy.coreTypes.futureOrClass);
+
+    return types
+        // Rule 11.
+        .performNullabilityAwareSubtypeCheck(
+            s, arguments.single.withNullability(unitedNullability))
+        // Rule 10.
+        .orSubtypeCheckFor(
+            s,
+            new InterfaceType(types.hierarchy.coreTypes.futureClass,
+                unitedNullability, arguments),
+            types);
+  }
+
+  @override
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType sFutureOr, InterfaceType tFutureOr, Types types) {
+    // This follows from combining rules 7, 10, and 11.
+    DartType sArgument = sFutureOr.typeArguments.single;
+    DartType tArgument = tFutureOr.typeArguments.single;
+    DartType sFutureOfArgument = new InterfaceType(
+        types.hierarchy.coreTypes.futureClass,
+        Nullability.nonNullable,
+        sFutureOr.typeArguments);
+    DartType tFutureOfArgument = new InterfaceType(
+        types.hierarchy.coreTypes.futureClass,
+        Nullability.nonNullable,
+        tFutureOr.typeArguments);
+    Nullability sNullability = computeNullabilityOfFutureOr(
+        sFutureOr, types.hierarchy.coreTypes.futureOrClass);
+    Nullability tNullability = computeNullabilityOfFutureOr(
+        tFutureOr, types.hierarchy.coreTypes.futureOrClass);
+    // The following is an optimized is-subtype-of test for the case where
+    // both LHS and RHS are FutureOrs.  It's based on the following:
+    // FutureOr<X> <: FutureOr<Y> iff X <: Y OR (X <: Future<Y> AND
+    // Future<X> <: Y).
+    //
+    // The correctness of that can be shown as follows:
+    //   1. FutureOr<X> <: FutureOr<Y> iff
+    //
+    //          X <: FutureOr<Y> AND Future<X> <: FutureOr<Y>
+    //
+    //   2a. X <: FutureOr<Y> iff
+    //
+    //          X <: Y OR X <: Future<Y>
+    //
+    //   2b. Future<X> <: FutureOr<Y> iff
+    //
+    //          Future<X> <: Y OR Future<X> <: Future<Y>
+    //
+    //   3. 1,2a,2b => FutureOr<X> <: FutureOr<Y> iff
+    //
+    //          (X <: Y OR X <: Future<Y>) AND
+    //            (Future<X> <: Y OR Future<X> <: Future<Y>)
+    //
+    //   4. X <: Y iff Future<X> <: Future<Y>
+    //
+    //   5. 3,4 => FutureOr<X> <: FutureOr<Y> iff
+    //
+    //          (X <: Y OR X <: Future<Y>) AND
+    //            (X <: Y OR Future<X> <: Y) iff
+    //
+    //          X <: Y OR (X <: Future<Y> AND Future<X> <: Y)
+    //
+    return types
+        .performNullabilityAwareSubtypeCheck(sArgument, tArgument)
+        .or(types
+            .performNullabilityAwareSubtypeCheck(sArgument, tFutureOfArgument)
+            .andSubtypeCheckFor(sFutureOfArgument, tArgument, types))
+        .and(new IsSubtypeOf.basedSolelyOnNullabilities(
+            sFutureOr.withNullability(sNullability),
+            tFutureOr.withNullability(tNullability),
+            types.futureOrClass));
+  }
+
+  @override
+  IsSubtypeOf isDynamicRelated(
+      DynamicType s, InterfaceType futureOr, Types types) {
+    // Rule 11.
+    DartType argument = futureOr.typeArguments.single;
+    return types.performNullabilityAwareSubtypeCheck(
+        s,
+        argument.withNullability(computeNullabilityOfFutureOr(
+            futureOr, types.hierarchy.coreTypes.futureOrClass)));
+  }
+
+  @override
+  IsSubtypeOf isVoidRelated(VoidType s, InterfaceType futureOr, Types types) {
+    // Rule 11.
+    DartType argument = futureOr.typeArguments.single;
+    return types.performNullabilityAwareSubtypeCheck(
+        s,
+        argument.withNullability(computeNullabilityOfFutureOr(
+            futureOr, types.hierarchy.coreTypes.futureOrClass)));
+  }
+
+  @override
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, InterfaceType futureOr, Types types) {
+    List<DartType> arguments = futureOr.typeArguments;
+    Nullability unitedNullability = computeNullabilityOfFutureOr(
+        futureOr, types.hierarchy.coreTypes.futureOrClass);
+    // TODO(dmitryas): Revise the original optimization.
+    return types
+        // Rule 11.
+        .performNullabilityAwareSubtypeCheck(
+            s, arguments.single.withNullability(unitedNullability))
+        // Rule 13.
+        .orSubtypeCheckFor(
+            s.parameter.bound.withNullability(
+                combineNullabilitiesForSubstitution(
+                    s.parameter.bound.nullability, s.nullability)),
+            futureOr,
+            types)
+        // Rule 10.
+        .orSubtypeCheckFor(
+            s,
+            new InterfaceType(types.hierarchy.coreTypes.futureClass,
+                unitedNullability, arguments),
+            types);
+  }
+
+  @override
+  IsSubtypeOf isFunctionRelated(
+      FunctionType s, InterfaceType futureOr, Types types) {
+    // Rule 11.
+    DartType argument = futureOr.typeArguments.single;
+    return types.performNullabilityAwareSubtypeCheck(
+        s,
+        argument.withNullability(computeNullabilityOfFutureOr(
+            futureOr, types.hierarchy.coreTypes.futureOrClass)));
+  }
+
+  @override
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, InterfaceType futureOr, Types types) {
+    return isTypeParameterRelated(intersection, futureOr, types) // Rule 8.
+        .orSubtypeCheckFor(
+            intersection.promotedBound, futureOr, types); // Rule 12.
+  }
+
+  @override
+  IsSubtypeOf isTypedefRelated(
+      TypedefType s, InterfaceType futureOr, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, futureOr);
+  }
+}
+
+class IsIntersectionSubtypeOf extends TypeRelation<TypeParameterType> {
+  const IsIntersectionSubtypeOf();
+
+  @override
+  IsSubtypeOf isIntersectionRelated(TypeParameterType sIntersection,
+      TypeParameterType tIntersection, Types types) {
+    // Rule 9.
+    return const IsTypeParameterSubtypeOf()
+        .isIntersectionRelated(sIntersection, tIntersection, types)
+        .andSubtypeCheckFor(sIntersection, tIntersection.promotedBound, types);
+  }
+
+  @override
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, TypeParameterType intersection, Types types) {
+    // Rule 9.
+    return const IsTypeParameterSubtypeOf()
+        .isTypeParameterRelated(s, intersection, types)
+        .andSubtypeCheckFor(s, intersection.promotedBound, types);
+  }
+
+  @override
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, TypeParameterType intersection, Types types) {
+    if (s.classNode == types.hierarchy.coreTypes.nullClass) {
+      // Rule 4.
+      return new IsSubtypeOf.basedSolelyOnNullabilities(
+          s, intersection, types.futureOrClass);
+    }
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isDynamicRelated(
+      DynamicType s, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isFunctionRelated(
+      FunctionType s, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  @override
+  IsSubtypeOf isTypedefRelated(
+      TypedefType s, TypeParameterType intersection, Types types) {
+    // Rule 5.
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, intersection);
+  }
+
+  @override
+  IsSubtypeOf isVoidRelated(
+      VoidType s, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
+  }
+}
+
+class IsNeverTypeSubtypeOf implements TypeRelation<NeverType> {
+  const IsNeverTypeSubtypeOf();
+
+  IsSubtypeOf isDynamicRelated(DynamicType s, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isVoidRelated(VoidType s, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, NeverType t, Types types) {
+    if (s.classNode == types.hierarchy.coreTypes.nullClass) {
+      if (t.nullability == Nullability.nullable ||
+          t.nullability == Nullability.legacy) {
+        return const IsSubtypeOf.always();
+      }
+      if (t.nullability == Nullability.nonNullable) {
+        return const IsSubtypeOf.never();
+      }
+      throw new StateError(
+          "Unexpected nullability '$t.nullability' of type Never");
+    }
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, NeverType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound, t);
+  }
+
+  IsSubtypeOf isFunctionRelated(FunctionType s, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, NeverType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.bound, t).and(
+        new IsSubtypeOf.basedSolelyOnNullabilities(s, t, types.futureOrClass));
+  }
+
+  IsSubtypeOf isTypedefRelated(TypedefType s, NeverType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
+  }
+}
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index d2a9bb6..467af4d 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -1227,6 +1227,37 @@
 Case<FunctionNode> functionNodeSerializer =
     new Case.uninitialized(const FunctionNodeTagger());
 
+class ProcedureTagger implements Tagger<Procedure> {
+  const ProcedureTagger();
+
+  String tag(Procedure node) {
+    String prefix = node.isStatic ? "static-" : "";
+    switch (node.kind) {
+      case ProcedureKind.Method:
+        return "${prefix}method";
+      default:
+        throw new UnsupportedError("${node.kind}");
+    }
+  }
+}
+
+TextSerializer<Procedure> staticMethodSerializer = new Wrapped(
+    unwrapStaticMethod,
+    wrapStaticMethod,
+    new Tuple2Serializer(nameSerializer, functionNodeSerializer));
+
+Tuple2<Name, FunctionNode> unwrapStaticMethod(Procedure procedure) {
+  return new Tuple2(procedure.name, procedure.function);
+}
+
+Procedure wrapStaticMethod(Tuple2<Name, FunctionNode> tuple) {
+  return new Procedure(tuple.first, ProcedureKind.Method, tuple.second,
+      isStatic: true);
+}
+
+Case<Procedure> procedureSerializer =
+    new Case.uninitialized(const ProcedureTagger());
+
 void initializeSerializers() {
   expressionSerializer.tags.addAll([
     "string",
@@ -1358,4 +1389,6 @@
     asyncStarFunctionNodeSerializer,
     syncYieldingStarFunctionNodeSerializer,
   ]);
+  procedureSerializer.tags.addAll(["static-method"]);
+  procedureSerializer.serializers.addAll([staticMethodSerializer]);
 }
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index 25d1d41..6d4444b 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -155,24 +155,42 @@
     //  }
     final CoreTypes coreTypes = staticTypeContext.typeEnvironment.coreTypes;
 
-    // TODO(39565): We should be able to use forInElementType.
-    helper.unsafeCast;
-    final DartType iterableType =
-        stmt.iterable.getStaticType(staticTypeContext);
-    final DartType iterationType = iterableType is InterfaceType
-        ? staticTypeContext.typeEnvironment.forInElementType(stmt, iterableType)
-        : DynamicType();
-    final expectedIterableType = InterfaceType(
-        coreTypes.iterableClass, Nullability.legacy, [iterationType]);
-    final iteratorType = InterfaceType(
-        coreTypes.iteratorClass, Nullability.legacy, [iterationType]);
+    DartType iterableType = stmt.iterable.getStaticType(staticTypeContext);
+    while (iterableType is TypeParameterType) {
+      TypeParameterType typeParameterType = iterableType;
+      iterableType =
+          typeParameterType.promotedBound ?? typeParameterType.parameter.bound;
+    }
 
-    // TODO(39566): Iterable expression is not always well typed in the AST.
-    final typedIterable = StaticInvocation(helper.unsafeCast,
-        Arguments([stmt.iterable], types: [expectedIterableType]));
+    // The CFE might invoke this transformation despite the program having
+    // compile-time errors. So we will not transform this [stmt] if the
+    // `stmt.iterable` is not a subtype of non-nullable/legacy Iterable.
+    if (iterableType is! InterfaceType ||
+        !staticTypeContext.typeEnvironment.isSubtypeOf(
+            iterableType,
+            coreTypes.iterableRawType(staticTypeContext.nonNullable),
+            staticTypeContext.isNonNullableByDefault
+                ? SubtypeCheckMode.withNullabilities
+                : SubtypeCheckMode.ignoringNullabilities)) {
+      return super.visitForInStatement(stmt);
+    }
+
+    final DartType iterationType = staticTypeContext.typeEnvironment
+        .forInElementType(stmt, (iterableType as InterfaceType));
+
+    // The NNBD sdk declares that Iterable.get:iterator returns a non-nullable
+    // `Iterator<E>`.
+    assert(const [
+      Nullability.nonNullable,
+      Nullability.legacy
+    ].contains(coreTypes.iterableGetIterator.function.returnType.nullability));
+
+    final iteratorType = InterfaceType(coreTypes.iteratorClass,
+        staticTypeContext.nonNullable, [iterationType]);
+
     final iterator = VariableDeclaration(':sync-for-iterator',
         initializer: PropertyGet(
-            typedIterable, Name('iterator'), coreTypes.iterableGetIterator)
+            stmt.iterable, Name('iterator'), coreTypes.iterableGetIterator)
           ..fileOffset = stmt.iterable.fileOffset,
         type: iteratorType)
       ..fileOffset = stmt.iterable.fileOffset;
@@ -382,14 +400,16 @@
 }
 
 abstract class AsyncRewriterBase extends ContinuationRewriterBase {
-  final VariableDeclaration nestedClosureVariable =
-      new VariableDeclaration(":async_op");
-  final VariableDeclaration stackTraceVariable =
-      new VariableDeclaration(ContinuationVariables.asyncStackTraceVar);
-  final VariableDeclaration thenContinuationVariable =
-      new VariableDeclaration(":async_op_then");
-  final VariableDeclaration catchErrorContinuationVariable =
-      new VariableDeclaration(":async_op_error");
+  final VariableDeclaration stackTraceVariable;
+
+  // :async_op has type ([dynamic result, dynamic e, StackTrace? s]) -> dynamic
+  final VariableDeclaration nestedClosureVariable;
+
+  // :async_op_then has type (dynamic result) -> dynamic
+  final VariableDeclaration thenContinuationVariable;
+
+  // :async_op_error has type (Object e, StackTrace s) -> dynamic
+  final VariableDeclaration catchErrorContinuationVariable;
 
   LabeledStatement labeledBody;
 
@@ -397,7 +417,24 @@
 
   AsyncRewriterBase(HelperNodes helper, FunctionNode enclosingFunction,
       StaticTypeContext staticTypeContext)
-      : super(helper, enclosingFunction, staticTypeContext) {}
+      : stackTraceVariable =
+            VariableDeclaration(ContinuationVariables.asyncStackTraceVar),
+        nestedClosureVariable = VariableDeclaration(":async_op",
+            type: FunctionType([
+              const DynamicType(),
+              const DynamicType(),
+              helper.coreTypes.stackTraceRawType(staticTypeContext.nullable),
+            ], const DynamicType(), staticTypeContext.nonNullable,
+                requiredParameterCount: 0)),
+        thenContinuationVariable = VariableDeclaration(":async_op_then",
+            type: FunctionType(const [const DynamicType()], const DynamicType(),
+                staticTypeContext.nonNullable)),
+        catchErrorContinuationVariable = VariableDeclaration(":async_op_error",
+            type: FunctionType([
+              helper.coreTypes.objectRawType(staticTypeContext.nonNullable),
+              helper.coreTypes.stackTraceRawType(staticTypeContext.nonNullable),
+            ], const DynamicType(), staticTypeContext.nonNullable)),
+        super(helper, enclosingFunction, staticTypeContext) {}
 
   void setupAsyncContinuations(List<Statement> statements) {
     expressionRewriter = new ExpressionLifter(this);
@@ -476,7 +513,9 @@
     --currentTryDepth;
 
     var exceptionVariable = new VariableDeclaration(":exception");
-    var stackTraceVariable = new VariableDeclaration(":stack_trace");
+    var stackTraceVariable = new VariableDeclaration(":stack_trace",
+        type:
+            helper.coreTypes.stackTraceRawType(staticTypeContext.nonNullable));
 
     return new TryCatch(
       buildReturn(labeledBody),
@@ -845,8 +884,9 @@
       //   }
       var valueVariable = stmt.variable;
 
-      var streamVariable =
-          new VariableDeclaration(':stream', initializer: stmt.iterable);
+      var streamVariable = new VariableDeclaration(':stream',
+          initializer: stmt.iterable,
+          type: stmt.iterable.getStaticType(staticTypeContext));
 
       var asyncStarListenHelper = new ExpressionStatement(new StaticInvocation(
           helper.asyncStarListenHelper,
@@ -1173,7 +1213,8 @@
     var startStatement = new ExpressionStatement(new MethodInvocation(
         new VariableGet(completerVariable),
         new Name('start'),
-        new Arguments([new VariableGet(nestedClosureVariable)]))
+        new Arguments([new VariableGet(nestedClosureVariable)]),
+        helper.asyncAwaitCompleterStartProcedure)
       ..fileOffset = enclosingFunction.fileOffset);
     statements.add(startStatement);
     // return :async_completer.future;
@@ -1243,6 +1284,7 @@
   final Class asyncAwaitCompleterClass;
   final Member completerCompleteError;
   final Member asyncAwaitCompleterConstructor;
+  final Member asyncAwaitCompleterStartProcedure;
   final Member completeOnAsyncReturn;
   final Member completerFuture;
   final Library coreLibrary;
@@ -1283,6 +1325,7 @@
       this.asyncAwaitCompleterClass,
       this.completerCompleteError,
       this.asyncAwaitCompleterConstructor,
+      this.asyncAwaitCompleterStartProcedure,
       this.completeOnAsyncReturn,
       this.completerFuture,
       this.coreLibrary,
@@ -1323,6 +1366,7 @@
         coreTypes.asyncAwaitCompleterClass,
         coreTypes.completerCompleteError,
         coreTypes.asyncAwaitCompleterConstructor,
+        coreTypes.asyncAwaitCompleterStartProcedure,
         coreTypes.completeOnAsyncReturn,
         coreTypes.completerFuture,
         coreTypes.coreLibrary,
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 5320c4a..a5ef956 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -6,22 +6,23 @@
 import 'ast.dart';
 import 'class_hierarchy.dart';
 import 'core_types.dart';
-import 'type_algebra.dart';
 
 import 'src/future_or.dart';
 import 'src/hierarchy_based_type_environment.dart'
     show HierarchyBasedTypeEnvironment;
+import 'src/types.dart';
 
 typedef void ErrorHandler(TreeNode node, String message);
 
-abstract class TypeEnvironment extends SubtypeTester {
+abstract class TypeEnvironment extends Types {
   final CoreTypes coreTypes;
 
   /// An error handler for use in debugging, or `null` if type errors should not
   /// be tolerated.  See [typeError].
   ErrorHandler errorHandler;
 
-  TypeEnvironment.fromSubclass(this.coreTypes);
+  TypeEnvironment.fromSubclass(this.coreTypes, ClassHierarchyBase base)
+      : super(base);
 
   factory TypeEnvironment(CoreTypes coreTypes, ClassHierarchy hierarchy) {
     return new HierarchyBasedTypeEnvironment(coreTypes, hierarchy);
@@ -309,11 +310,12 @@
           unwrappedSupertype =
               (unwrappedSupertype as InterfaceType).typeArguments.single;
         }
-        if (unwrappedSubtype is TypeParameterType &&
-            unwrappedSubtype.promotedBound == null &&
-            unwrappedSupertype is TypeParameterType &&
-            unwrappedSupertype.promotedBound == null &&
-            unwrappedSubtype.parameter == unwrappedSupertype.parameter) {
+        Nullability unwrappedSubtypeNullability =
+            computeNullability(unwrappedSubtype, futureOrClass);
+        Nullability unwrappedSupertypeNullability =
+            computeNullability(unwrappedSupertype, futureOrClass);
+        if (unwrappedSubtypeNullability == unwrappedSupertypeNullability) {
+          // The relationship between the types must be established elsewhere.
           return const IsSubtypeOf.always();
         }
       }
@@ -343,7 +345,7 @@
   /// [IsSubtypeOf.never] because the right-hand side will not change the
   /// overall result anyway.
   IsSubtypeOf andSubtypeCheckFor(
-      DartType subtype, DartType supertype, SubtypeTester tester) {
+      DartType subtype, DartType supertype, Types tester) {
     if (_value == _valueNever) return this;
     return this
         .and(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
@@ -370,7 +372,7 @@
   /// as [IsSubtypeOf.always] because the right-hand side will not change the
   /// overall result anyway.
   IsSubtypeOf orSubtypeCheckFor(
-      DartType subtype, DartType supertype, SubtypeTester tester) {
+      DartType subtype, DartType supertype, Types tester) {
     if (_value == _valueAlways) return this;
     return this
         .or(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
@@ -402,340 +404,6 @@
   ignoringNullabilities,
 }
 
-/// The part of [TypeEnvironment] that deals with subtype tests.
-///
-/// This lives in a separate class so it can be tested independently of the SDK.
-abstract class SubtypeTester {
-  InterfaceType get objectLegacyRawType;
-  InterfaceType get objectNullableRawType;
-  InterfaceType get nullType;
-  InterfaceType get functionLegacyRawType;
-  Class get objectClass;
-  Class get functionClass;
-  Class get futureOrClass;
-  InterfaceType futureType(DartType type, Nullability nullability);
-
-  static List<Object> typeChecks;
-
-  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
-      Library clientLibrary, CoreTypes coreTypes);
-
-  List<DartType> getTypeArgumentsAsInstanceOf(
-      InterfaceType type, Class superclass);
-
-  /// Determines if the given type is at the top of the type hierarchy.  May be
-  /// overridden in subclasses.
-  bool isTop(DartType type) {
-    return type is DynamicType ||
-        type is VoidType ||
-        type == objectLegacyRawType ||
-        type == objectNullableRawType;
-  }
-
-  /// Can be use to collect type checks. To use:
-  /// 1. Rename `isSubtypeOf` to `_isSubtypeOf`.
-  /// 2. Rename `_collect_isSubtypeOf` to `isSubtypeOf`.
-  /// 3. Comment out the call to `_isSubtypeOf` below.
-  // ignore:unused_element
-  bool _collect_isSubtypeOf(
-      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
-    bool result = true;
-    //result = _isSubtypeOf(subtype, supertype, mode);
-    typeChecks ??= <Object>[];
-    typeChecks.add([subtype, supertype, result]);
-    return result;
-  }
-
-  /// Returns true if [subtype] is a subtype of [supertype].
-  bool isSubtypeOf(
-      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
-    IsSubtypeOf result =
-        performNullabilityAwareSubtypeCheck(subtype, supertype);
-    switch (mode) {
-      case SubtypeCheckMode.ignoringNullabilities:
-        return result.isSubtypeWhenIgnoringNullabilities();
-      case SubtypeCheckMode.withNullabilities:
-        return result.isSubtypeWhenUsingNullabilities();
-      default:
-        throw new StateError("Unhandled subtype checking mode '$mode'");
-    }
-  }
-
-  /// Performs a nullability-aware subtype check.
-  ///
-  /// The outcome is described in the comments to [IsSubtypeOf].
-  IsSubtypeOf performNullabilityAwareSubtypeCheck(
-      DartType subtype, DartType supertype) {
-    subtype = subtype.unalias;
-    supertype = supertype.unalias;
-    if (identical(subtype, supertype)) return const IsSubtypeOf.always();
-    if (subtype is BottomType) return const IsSubtypeOf.always();
-    if (subtype is NeverType) {
-      return supertype is BottomType
-          ? const IsSubtypeOf.never()
-          : new IsSubtypeOf.basedSolelyOnNullabilities(
-              subtype, supertype, futureOrClass);
-    }
-    if (subtype == nullType) {
-      // TODO(dmitryas): Remove InvalidType from subtype relation.
-      if (supertype is InvalidType) {
-        // The return value is supposed to keep the backward compatibility.
-        return const IsSubtypeOf.always();
-      }
-
-      Nullability supertypeNullability =
-          computeNullability(supertype, futureOrClass);
-      if (supertypeNullability == Nullability.nullable ||
-          supertypeNullability == Nullability.legacy) {
-        return const IsSubtypeOf.always();
-      }
-      // See rule 4 of the subtype rules from the Dart Language Specification.
-      return supertype is BottomType || supertype is NeverType
-          ? const IsSubtypeOf.never()
-          : const IsSubtypeOf.onlyIfIgnoringNullabilities();
-    }
-    if (isTop(supertype)) return const IsSubtypeOf.always();
-
-    // Handle FutureOr<T> union type.
-    if (subtype is InterfaceType &&
-        identical(subtype.classNode, futureOrClass)) {
-      var subtypeArg = subtype.typeArguments[0];
-      if (supertype is InterfaceType &&
-          identical(supertype.classNode, futureOrClass)) {
-        DartType supertypeArg = supertype.typeArguments[0];
-        Nullability subtypeNullability =
-            computeNullabilityOfFutureOr(subtype, futureOrClass);
-        Nullability supertypeNullability =
-            computeNullabilityOfFutureOr(supertype, futureOrClass);
-        // The following is an optimized is-subtype-of test for the case where
-        // both LHS and RHS are FutureOrs.  It's based on the following:
-        // FutureOr<X> <: FutureOr<Y> iff X <: Y OR (X <: Future<Y> AND
-        // Future<X> <: Y).
-        //
-        // The correctness of that can be shown as follows:
-        //   1. FutureOr<X> <: Y iff X <: Y AND Future<X> <: Y
-        //   2. X <: FutureOr<Y> iff X <: Y OR X <: Future<Y>
-        //   3. 1,2 => FutureOr<X> <: FutureOr<Y> iff
-        //          (X <: Y OR X <: Future<Y>) AND
-        //            (Future<X> <: Y OR Future<X> <: Future<Y>)
-        //   4. X <: Y iff Future<X> <: Future<Y>
-        //   5. 3,4 => FutureOr<X> <: FutureOr<Y> iff
-        //          (X <: Y OR X <: Future<Y>) AND
-        //            (X <: Y OR Future<X> <: Y) iff
-        //          X <: Y OR (X <: Future<Y> AND Future<X> <: Y)
-        return performNullabilityAwareSubtypeCheck(subtypeArg, supertypeArg)
-            .or(performNullabilityAwareSubtypeCheck(subtypeArg,
-                    futureType(supertypeArg, Nullability.nonNullable))
-                .andSubtypeCheckFor(
-                    futureType(subtypeArg, Nullability.nonNullable),
-                    supertypeArg,
-                    this))
-            .and(new IsSubtypeOf.basedSolelyOnNullabilities(
-                subtype.withNullability(subtypeNullability),
-                supertype.withNullability(supertypeNullability),
-                futureOrClass));
-      }
-
-      // given t1 is Future<A> | A, then:
-      // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-      return performNullabilityAwareSubtypeCheck(subtypeArg, supertype)
-          .andSubtypeCheckFor(
-              futureType(subtypeArg, Nullability.nonNullable), supertype, this)
-          .and(new IsSubtypeOf.basedSolelyOnNullabilities(
-              subtype, supertype, futureOrClass));
-    }
-
-    if (supertype is InterfaceType && supertype.classNode == objectClass) {
-      assert(supertype.nullability == Nullability.nonNullable);
-      return new IsSubtypeOf.basedSolelyOnNullabilities(
-          subtype, supertype, futureOrClass);
-    }
-
-    if (supertype is InterfaceType &&
-        identical(supertype.classNode, futureOrClass)) {
-      // given t2 is Future<A> | A, then:
-      // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
-      Nullability unitedNullability =
-          computeNullabilityOfFutureOr(supertype, futureOrClass);
-      DartType supertypeArg = supertype.typeArguments[0];
-      DartType supertypeFuture = futureType(supertypeArg, unitedNullability);
-      return performNullabilityAwareSubtypeCheck(subtype, supertypeFuture)
-          .orSubtypeCheckFor(
-              subtype, supertypeArg.withNullability(unitedNullability), this);
-    }
-
-    if (subtype is InterfaceType && supertype is InterfaceType) {
-      Class supertypeClass = supertype.classNode;
-      List<DartType> upcastTypeArguments =
-          getTypeArgumentsAsInstanceOf(subtype, supertypeClass);
-      if (upcastTypeArguments == null) return const IsSubtypeOf.never();
-      IsSubtypeOf result = const IsSubtypeOf.always();
-      for (int i = 0; i < upcastTypeArguments.length; ++i) {
-        // Termination: the 'supertype' parameter decreases in size.
-        int variance = supertypeClass.typeParameters[i].variance;
-        DartType leftType = upcastTypeArguments[i];
-        DartType rightType = supertype.typeArguments[i];
-        if (variance == Variance.contravariant) {
-          result = result
-              .and(performNullabilityAwareSubtypeCheck(rightType, leftType));
-          if (!result.isSubtypeWhenIgnoringNullabilities()) {
-            return const IsSubtypeOf.never();
-          }
-        } else if (variance == Variance.invariant) {
-          result = result.and(
-              performNullabilityAwareMutualSubtypesCheck(leftType, rightType));
-          if (!result.isSubtypeWhenIgnoringNullabilities()) {
-            return const IsSubtypeOf.never();
-          }
-        } else {
-          result = result
-              .and(performNullabilityAwareSubtypeCheck(leftType, rightType));
-          if (!result.isSubtypeWhenIgnoringNullabilities()) {
-            return const IsSubtypeOf.never();
-          }
-        }
-      }
-      return result.and(new IsSubtypeOf.basedSolelyOnNullabilities(
-          subtype, supertype, futureOrClass));
-    }
-    if (subtype is TypeParameterType) {
-      if (supertype is TypeParameterType) {
-        IsSubtypeOf result = const IsSubtypeOf.always();
-        if (subtype.parameter == supertype.parameter) {
-          if (supertype.promotedBound != null) {
-            return performNullabilityAwareSubtypeCheck(
-                    subtype,
-                    new TypeParameterType(supertype.parameter,
-                        supertype.typeParameterTypeNullability))
-                .andSubtypeCheckFor(subtype, supertype.bound, this);
-          } else {
-            // Promoted bound should always be a subtype of the declared bound.
-            // TODO(dmitryas): Use the following assertion when type promotion
-            // is updated.
-            // assert(subtype.promotedBound == null ||
-            //     performNullabilityAwareSubtypeCheck(
-            //         subtype.bound, supertype.bound)
-            //         .isSubtypeWhenUsingNullabilities());
-            assert(subtype.promotedBound == null ||
-                performNullabilityAwareSubtypeCheck(
-                        subtype.bound, supertype.bound)
-                    .isSubtypeWhenIgnoringNullabilities());
-            result = const IsSubtypeOf.always();
-          }
-        } else {
-          result =
-              performNullabilityAwareSubtypeCheck(subtype.bound, supertype);
-        }
-        if (subtype.nullability == Nullability.undetermined &&
-            supertype.nullability == Nullability.undetermined) {
-          // The two nullabilities are undetermined, but are connected via
-          // additional constraint, namely that they will be equal at run time.
-          return result;
-        }
-        return result.and(new IsSubtypeOf.basedSolelyOnNullabilities(
-            subtype, supertype, futureOrClass));
-      }
-      // Termination: if there are no cyclically bound type parameters, this
-      // recursive call can only occur a finite number of times, before reaching
-      // a shrinking recursive call (or terminating).
-      return performNullabilityAwareSubtypeCheck(subtype.bound, supertype).and(
-          new IsSubtypeOf.basedSolelyOnNullabilities(
-              subtype, supertype, futureOrClass));
-    }
-    if (subtype is FunctionType) {
-      if (supertype is InterfaceType && supertype.classNode == functionClass) {
-        return new IsSubtypeOf.basedSolelyOnNullabilities(
-            subtype, supertype, futureOrClass);
-      }
-      if (supertype is FunctionType) {
-        return _performNullabilityAwareFunctionSubtypeCheck(subtype, supertype);
-      }
-    }
-    return const IsSubtypeOf.never();
-  }
-
-  IsSubtypeOf performNullabilityAwareMutualSubtypesCheck(
-      DartType type1, DartType type2) {
-    // TODO(dmitryas): Replace it with one recursive descent instead of two.
-    return performNullabilityAwareSubtypeCheck(type1, type2)
-        .andSubtypeCheckFor(type2, type1, this);
-  }
-
-  IsSubtypeOf _performNullabilityAwareFunctionSubtypeCheck(
-      FunctionType subtype, FunctionType supertype) {
-    if (subtype.requiredParameterCount > supertype.requiredParameterCount) {
-      return const IsSubtypeOf.never();
-    }
-    if (subtype.positionalParameters.length <
-        supertype.positionalParameters.length) {
-      return const IsSubtypeOf.never();
-    }
-    if (subtype.typeParameters.length != supertype.typeParameters.length) {
-      return const IsSubtypeOf.never();
-    }
-
-    IsSubtypeOf result = const IsSubtypeOf.always();
-    if (subtype.typeParameters.isNotEmpty) {
-      var substitution = <TypeParameter, DartType>{};
-      for (int i = 0; i < subtype.typeParameters.length; ++i) {
-        var subParameter = subtype.typeParameters[i];
-        var superParameter = supertype.typeParameters[i];
-        substitution[subParameter] = new TypeParameterType.forAlphaRenaming(
-            subParameter, superParameter);
-      }
-      for (int i = 0; i < subtype.typeParameters.length; ++i) {
-        var subParameter = subtype.typeParameters[i];
-        var superParameter = supertype.typeParameters[i];
-        var subBound = substitute(subParameter.bound, substitution);
-        // Termination: if there are no cyclically bound type parameters, this
-        // recursive call can only occur a finite number of times before
-        // reaching a shrinking recursive call (or terminating).
-        result = result.and(performNullabilityAwareMutualSubtypesCheck(
-            superParameter.bound, subBound));
-        if (!result.isSubtypeWhenIgnoringNullabilities()) {
-          return const IsSubtypeOf.never();
-        }
-      }
-      subtype = substitute(subtype.withoutTypeParameters, substitution);
-    }
-    result = result.and(performNullabilityAwareSubtypeCheck(
-        subtype.returnType, supertype.returnType));
-    if (!result.isSubtypeWhenIgnoringNullabilities()) {
-      return const IsSubtypeOf.never();
-    }
-    for (int i = 0; i < supertype.positionalParameters.length; ++i) {
-      var supertypeParameter = supertype.positionalParameters[i];
-      var subtypeParameter = subtype.positionalParameters[i];
-      // Termination: Both types shrink in size.
-      result = result.and(performNullabilityAwareSubtypeCheck(
-          supertypeParameter, subtypeParameter));
-      if (!result.isSubtypeWhenIgnoringNullabilities()) {
-        return const IsSubtypeOf.never();
-      }
-    }
-    int subtypeNameIndex = 0;
-    for (NamedType supertypeParameter in supertype.namedParameters) {
-      while (subtypeNameIndex < subtype.namedParameters.length &&
-          subtype.namedParameters[subtypeNameIndex].name !=
-              supertypeParameter.name) {
-        ++subtypeNameIndex;
-      }
-      if (subtypeNameIndex == subtype.namedParameters.length) {
-        return const IsSubtypeOf.never();
-      }
-      NamedType subtypeParameter = subtype.namedParameters[subtypeNameIndex];
-      // Termination: Both types shrink in size.
-      result = result.and(performNullabilityAwareSubtypeCheck(
-          supertypeParameter.type, subtypeParameter.type));
-      if (!result.isSubtypeWhenIgnoringNullabilities()) {
-        return const IsSubtypeOf.never();
-      }
-    }
-    return result.and(new IsSubtypeOf.basedSolelyOnNullabilities(
-        subtype, supertype, futureOrClass));
-  }
-}
-
 /// Context object needed for computing `Expression.getStaticType`.
 ///
 /// The [StaticTypeContext] provides access to the [TypeEnvironment] and the
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 7eb39c7..2857826 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -13,31 +13,14 @@
   test();
 }
 
-// Wrappers for testing.
-Statement readStatement(String input, DeserializationState state) {
-  TextIterator stream = new TextIterator(input, 0);
-  stream.moveNext();
-  Statement result = statementSerializer.readFrom(stream, state);
-  if (stream.moveNext()) {
-    throw StateError("extra cruft in basic literal");
-  }
-  return result;
-}
-
-String writeStatement(Statement statement, SerializationState state) {
-  StringBuffer buffer = new StringBuffer();
-  statementSerializer.writeTo(buffer, statement, state);
-  return buffer.toString();
-}
-
-class TestCase {
+abstract class TestCase<T extends Node> {
   final String name;
-  final Node node;
+  final T node;
   final SerializationState serializationState;
   final DeserializationState deserializationState;
   final String expectation;
 
-  TestCase(
+  TestCase._(
       {this.name,
       this.node,
       this.expectation,
@@ -47,27 +30,93 @@
             serializationState ?? new SerializationState(null),
         this.deserializationState = deserializationState ??
             new DeserializationState(null, new CanonicalName.root());
+
+  T readNode(String input, DeserializationState state);
+
+  String writeNode(T node, SerializationState state);
+}
+
+class StatementTestCase extends TestCase<Statement> {
+  StatementTestCase(
+      {String name,
+      Statement node,
+      String expectation,
+      SerializationState serializationState,
+      DeserializationState deserializationState})
+      : super._(
+            name: name,
+            node: node,
+            expectation: expectation,
+            serializationState: serializationState,
+            deserializationState: deserializationState);
+
+  Statement readNode(String input, DeserializationState state) {
+    TextIterator stream = new TextIterator(input, 0);
+    stream.moveNext();
+    Statement result = statementSerializer.readFrom(stream, state);
+    if (stream.moveNext()) {
+      throw new StateError("Found extra tokens at the end of the statement.");
+    }
+    return result;
+  }
+
+  String writeNode(Statement statement, SerializationState state) {
+    StringBuffer buffer = new StringBuffer();
+    statementSerializer.writeTo(buffer, statement, state);
+    return buffer.toString();
+  }
+}
+
+class ProcedureTestCase extends TestCase<Procedure> {
+  ProcedureTestCase(
+      {String name,
+      Procedure node,
+      String expectation,
+      SerializationState serializationState,
+      DeserializationState deserializationState})
+      : super._(
+            name: name,
+            node: node,
+            expectation: expectation,
+            serializationState: serializationState,
+            deserializationState: deserializationState);
+
+  Procedure readNode(String input, DeserializationState state) {
+    TextIterator stream = new TextIterator(input, 0);
+    stream.moveNext();
+    Procedure result = procedureSerializer.readFrom(stream, state);
+    if (stream.moveNext()) {
+      throw new StateError("Found extra tokens at the end of the procedure.");
+    }
+    return result;
+  }
+
+  String writeNode(Procedure procedure, SerializationState state) {
+    StringBuffer buffer = new StringBuffer();
+    procedureSerializer.writeTo(buffer, procedure, state);
+    return buffer.toString();
+  }
 }
 
 void test() {
   List<String> failures = [];
   List<TestCase> tests = <TestCase>[
-    new TestCase(
-        name: "let dynamic x = 42 in x;",
+    new StatementTestCase(
+        name: 'let dynamic x = 42 in x;',
         node: () {
-          VariableDeclaration x = new VariableDeclaration("x",
+          VariableDeclaration x = new VariableDeclaration('x',
               type: const DynamicType(), initializer: new IntLiteral(42));
           return new ExpressionStatement(new Let(x, new VariableGet(x)));
         }(),
         expectation: ''
             '(expr (let (var "x^0" (dynamic) (int 42) ())'
             ' (get-var "x^0" _)))'),
-    new TestCase(
-        name: "let dynamic x = 42 in let Bottom x^0 = null in x;",
+    new StatementTestCase(
+        name: 'let dynamic x = 42 in let Bottom x^0 = null in x;',
         node: () {
-          VariableDeclaration outterLetVar = new VariableDeclaration("x",
+          VariableDeclaration outterLetVar = new VariableDeclaration('x',
               type: const DynamicType(), initializer: new IntLiteral(42));
-          VariableDeclaration innerLetVar = new VariableDeclaration("x",
+          VariableDeclaration innerLetVar = new VariableDeclaration('x',
               type: const BottomType(), initializer: new NullLiteral());
           return new ExpressionStatement(new Let(outterLetVar,
               new Let(innerLetVar, new VariableGet(outterLetVar))));
@@ -76,12 +125,12 @@
             '(expr (let (var "x^0" (dynamic) (int 42) ())'
             ' (let (var "x^1" (bottom) (null) ())'
             ' (get-var "x^0" _))))'),
-    new TestCase(
-        name: "let dynamic x = 42 in let Bottom x^0 = null in x^0;",
+    new StatementTestCase(
+        name: 'let dynamic x = 42 in let Bottom x^0 = null in x^0;',
         node: () {
-          VariableDeclaration outterLetVar = new VariableDeclaration("x",
+          VariableDeclaration outterLetVar = new VariableDeclaration('x',
               type: const DynamicType(), initializer: new IntLiteral(42));
-          VariableDeclaration innerLetVar = new VariableDeclaration("x",
+          VariableDeclaration innerLetVar = new VariableDeclaration('x',
               type: const BottomType(), initializer: new NullLiteral());
           return new ExpressionStatement(new Let(outterLetVar,
               new Let(innerLetVar, new VariableGet(innerLetVar))));
@@ -92,31 +141,31 @@
             ' (get-var "x^1" _))))'),
     () {
       VariableDeclaration x =
-          new VariableDeclaration("x", type: const DynamicType());
-      return new TestCase(
-          name: "/* suppose: dynamic x; */ x = 42;",
+          new VariableDeclaration('x', type: const DynamicType());
+      return new StatementTestCase(
+          name: '/* suppose: dynamic x; */ x = 42;',
           node: new ExpressionStatement(new VariableSet(x, new IntLiteral(42))),
           expectation: '(expr (set-var "x^0" (int 42)))',
           serializationState: new SerializationState(
             new SerializationEnvironment(null)
-              ..addBinder(x, "x^0")
+              ..addBinder(x, 'x^0')
               ..close(),
           ),
           deserializationState: new DeserializationState(
               new DeserializationEnvironment(null)
-                ..addBinder("x^0", x)
+                ..addBinder('x^0', x)
                 ..close(),
               new CanonicalName.root()));
     }(),
     () {
-      Field field = new Field(new Name("field"), type: const DynamicType());
+      Field field = new Field(new Name('field'), type: const DynamicType());
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           fields: <Field>[field]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
-      return new TestCase(
-          name: "/* suppose top-level: dynamic field; */ field;",
+      return new StatementTestCase(
+          name: '/* suppose top-level: dynamic field; */ field;',
           node: new ExpressionStatement(new StaticGet(field)),
           expectation: ''
               '(expr (get-static "package:foo/bar.dart::@fields::field"))',
@@ -124,14 +173,14 @@
           deserializationState: new DeserializationState(null, component.root));
     }(),
     () {
-      Field field = new Field(new Name("field"), type: const DynamicType());
+      Field field = new Field(new Name('field'), type: const DynamicType());
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           fields: <Field>[field]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
-      return new TestCase(
-          name: "/* suppose top-level: dynamic field; */ field = 1;",
+      return new StatementTestCase(
+          name: '/* suppose top-level: dynamic field; */ field = 1;',
           node:
               new ExpressionStatement(new StaticSet(field, new IntLiteral(1))),
           expectation: ''
@@ -142,19 +191,19 @@
     }(),
     () {
       Procedure topLevelProcedure = new Procedure(
-          new Name("foo"),
+          new Name('foo'),
           ProcedureKind.Method,
           new FunctionNode(null, positionalParameters: <VariableDeclaration>[
-            new VariableDeclaration("x", type: const DynamicType())
+            new VariableDeclaration('x', type: const DynamicType())
           ]),
           isStatic: true);
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           procedures: <Procedure>[topLevelProcedure]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
-      return new TestCase(
-          name: "/* suppose top-level: foo(dynamic x) {...}; */ foo(42);",
+      return new StatementTestCase(
+          name: '/* suppose top-level: foo(dynamic x) {...}; */ foo(42);',
           node: new ExpressionStatement(new StaticInvocation.byReference(
               topLevelProcedure.reference,
               new Arguments(<Expression>[new IntLiteral(42)]),
@@ -167,19 +216,19 @@
     }(),
     () {
       Procedure factoryConstructor = new Procedure(
-          new Name("foo"), ProcedureKind.Factory, new FunctionNode(null),
+          new Name('foo'), ProcedureKind.Factory, new FunctionNode(null),
           isStatic: true, isConst: true);
       Class klass =
-          new Class(name: "A", procedures: <Procedure>[factoryConstructor]);
+          new Class(name: 'A', procedures: <Procedure>[factoryConstructor]);
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           classes: <Class>[klass]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
-      return new TestCase(
-          name: ""
-              "/* suppose A { const A(); const factory A.foo() = A; } */"
-              " const A.foo();",
+      return new StatementTestCase(
+          name: ''
+              '/* suppose A { const A(); const factory A.foo() = A; } */'
+              ' const A.foo();',
           node: new ExpressionStatement(new StaticInvocation.byReference(
               factoryConstructor.reference, new Arguments([]),
               isConst: true)),
@@ -191,18 +240,18 @@
           deserializationState: new DeserializationState(null, component.root));
     }(),
     () {
-      Field field = new Field(new Name("field"), type: const DynamicType());
-      Class klass = new Class(name: "A", fields: <Field>[field]);
+      Field field = new Field(new Name('field'), type: const DynamicType());
+      Class klass = new Class(name: 'A', fields: <Field>[field]);
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           classes: <Class>[klass]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
 
       VariableDeclaration x =
-          new VariableDeclaration("x", type: const DynamicType());
-      return new TestCase(
-          name: "/* suppose A {dynamic field;} A x; */ x.{A::field};",
+          new VariableDeclaration('x', type: const DynamicType());
+      return new StatementTestCase(
+          name: '/* suppose A {dynamic field;} A x; */ x.{A::field};',
           node: new ExpressionStatement(new DirectPropertyGet.byReference(
               new VariableGet(x), field.reference)),
           expectation: ''
@@ -210,27 +259,27 @@
               ' "package:foo/bar.dart::A::@fields::field"))',
           serializationState:
               new SerializationState(new SerializationEnvironment(null)
-                ..addBinder(x, "x^0")
+                ..addBinder(x, 'x^0')
                 ..close()),
           deserializationState: new DeserializationState(
               new DeserializationEnvironment(null)
-                ..addBinder("x^0", x)
+                ..addBinder('x^0', x)
                 ..close(),
               component.root));
     }(),
     () {
-      Field field = new Field(new Name("field"), type: const DynamicType());
-      Class klass = new Class(name: "A", fields: <Field>[field]);
+      Field field = new Field(new Name('field'), type: const DynamicType());
+      Class klass = new Class(name: 'A', fields: <Field>[field]);
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           classes: <Class>[klass]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
 
       VariableDeclaration x =
-          new VariableDeclaration("x", type: const DynamicType());
-      return new TestCase(
-          name: "/* suppose A {dynamic field;} A x; */ x.{A::field} = 42;",
+          new VariableDeclaration('x', type: const DynamicType());
+      return new StatementTestCase(
+          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))),
           expectation: ''
@@ -238,29 +287,29 @@
               ' "package:foo/bar.dart::A::@fields::field" (int 42)))',
           serializationState:
               new SerializationState(new SerializationEnvironment(null)
-                ..addBinder(x, "x^0")
+                ..addBinder(x, 'x^0')
                 ..close()),
           deserializationState: new DeserializationState(
               new DeserializationEnvironment(null)
-                ..addBinder("x^0", x)
+                ..addBinder('x^0', x)
                 ..close(),
               component.root));
     }(),
     () {
       Procedure method = new Procedure(
-          new Name("foo"), ProcedureKind.Method, new FunctionNode(null),
+          new Name('foo'), ProcedureKind.Method, new FunctionNode(null),
           isStatic: true, isConst: true);
-      Class klass = new Class(name: "A", procedures: <Procedure>[method]);
+      Class klass = new Class(name: 'A', procedures: <Procedure>[method]);
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           classes: <Class>[klass]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
 
       VariableDeclaration x =
-          new VariableDeclaration("x", type: const DynamicType());
-      return new TestCase(
-          name: "/* suppose A {foo() {...}} A x; */ x.{A::foo}();",
+          new VariableDeclaration('x', type: const DynamicType());
+      return new StatementTestCase(
+          name: '/* suppose A {foo() {...}} A x; */ x.{A::foo}();',
           node: new ExpressionStatement(new DirectMethodInvocation.byReference(
               new VariableGet(x), method.reference, new Arguments([]))),
           expectation: ''
@@ -269,26 +318,26 @@
               ' () () ()))',
           serializationState:
               new SerializationState(new SerializationEnvironment(null)
-                ..addBinder(x, "x^0")
+                ..addBinder(x, 'x^0')
                 ..close()),
           deserializationState: new DeserializationState(
               new DeserializationEnvironment(null)
-                ..addBinder("x^0", x)
+                ..addBinder('x^0', x)
                 ..close(),
               component.root));
     }(),
     () {
       Constructor constructor =
-          new Constructor(new FunctionNode(null), name: new Name("foo"));
+          new Constructor(new FunctionNode(null), name: new Name('foo'));
       Class klass =
-          new Class(name: "A", constructors: <Constructor>[constructor]);
+          new Class(name: 'A', constructors: <Constructor>[constructor]);
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           classes: <Class>[klass]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
-      return new TestCase(
-          name: "/* suppose A {A.foo();} */ new A();",
+      return new StatementTestCase(
+          name: '/* suppose A {A.foo();} */ new A();',
           node: new ExpressionStatement(new ConstructorInvocation.byReference(
               constructor.reference, new Arguments([]))),
           expectation: ''
@@ -300,16 +349,16 @@
     }(),
     () {
       Constructor constructor = new Constructor(new FunctionNode(null),
-          name: new Name("foo"), isConst: true);
+          name: new Name('foo'), isConst: true);
       Class klass =
-          new Class(name: "A", constructors: <Constructor>[constructor]);
+          new Class(name: 'A', constructors: <Constructor>[constructor]);
       Library library = new Library(
-          new Uri(scheme: "package", path: "foo/bar.dart"),
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
           classes: <Class>[klass]);
       Component component = new Component(libraries: <Library>[library]);
       component.computeCanonicalNames();
-      return new TestCase(
-          name: "/* suppose A {const A.foo();} */ const A();",
+      return new StatementTestCase(
+          name: '/* suppose A {const A.foo();} */ const A();',
           node: new ExpressionStatement(new ConstructorInvocation.byReference(
               constructor.reference, new Arguments([]),
               isConst: true)),
@@ -322,11 +371,11 @@
     }(),
     () {
       TypeParameter outterParam =
-          new TypeParameter("T", const DynamicType(), const DynamicType());
+          new TypeParameter('T', const DynamicType(), const DynamicType());
       TypeParameter innerParam =
-          new TypeParameter("T", const DynamicType(), const DynamicType());
-      return new TestCase(
-          name: "/* T Function<T>(T Function<T>()); */",
+          new TypeParameter('T', const DynamicType(), const DynamicType());
+      return new StatementTestCase(
+          name: '/* T Function<T>(T Function<T>()); */',
           node: new ExpressionStatement(new TypeLiteral(new FunctionType(
               [
                 new FunctionType(
@@ -349,13 +398,13 @@
     }(),
     () {
       TypeParameter t =
-          new TypeParameter("T", const DynamicType(), const DynamicType());
-      VariableDeclaration t1 = new VariableDeclaration("t1",
+          new TypeParameter('T', const DynamicType(), const DynamicType());
+      VariableDeclaration t1 = new VariableDeclaration('t1',
           type: new TypeParameterType(t, Nullability.legacy));
-      VariableDeclaration t2 = new VariableDeclaration("t2",
+      VariableDeclaration t2 = new VariableDeclaration('t2',
           type: new TypeParameterType(t, Nullability.legacy));
-      return new TestCase(
-          name: "/* <T>(T t1, [T t2]) => t1; */",
+      return new StatementTestCase(
+          name: '/* <T>(T t1, [T t2]) => t1; */',
           node: new ExpressionStatement(new FunctionExpression(new FunctionNode(
               new ReturnStatement(new VariableGet(t1)),
               typeParameters: [t],
@@ -373,10 +422,33 @@
           deserializationState: new DeserializationState(
               new DeserializationEnvironment(null), null));
     }(),
+    () {
+      VariableDeclaration x = VariableDeclaration('x', type: DynamicType());
+      Procedure foo = Procedure(
+          Name('foo'),
+          ProcedureKind.Method,
+          FunctionNode(ReturnStatement(VariableGet(x)),
+              positionalParameters: [x]),
+          isStatic: true);
+      Library library = Library(Uri(scheme: 'package', path: 'foo/bar.dart'),
+          procedures: [foo]);
+      Component component = Component(libraries: [library]);
+      component.computeCanonicalNames();
+      return new ProcedureTestCase(
+          name: 'foo(x) => x;',
+          node: foo,
+          expectation: ''
+              '(static-method (public "foo")'
+              ' (sync () () () ((var "x^0" (dynamic) _ ())) () () (dynamic) (ret (get-var "x^0" _))))',
+          serializationState:
+              new SerializationState(new SerializationEnvironment(null)),
+          deserializationState: new DeserializationState(
+              new DeserializationEnvironment(null), null));
+    }(),
   ];
   for (TestCase testCase in tests) {
     String roundTripInput =
-        writeStatement(testCase.node, testCase.serializationState);
+        testCase.writeNode(testCase.node, testCase.serializationState);
     if (roundTripInput != testCase.expectation) {
       failures.add(''
           '* initial serialization for test "${testCase.name}"'
@@ -384,9 +456,9 @@
     }
 
     TreeNode deserialized =
-        readStatement(roundTripInput, testCase.deserializationState);
+        testCase.readNode(roundTripInput, testCase.deserializationState);
     String roundTripOutput =
-        writeStatement(deserialized, testCase.serializationState);
+        testCase.writeNode(deserialized, testCase.serializationState);
     if (roundTripOutput != roundTripInput) {
       failures.add(''
           '* input "${testCase.name}" gave output "${roundTripOutput}"');
diff --git a/pkg/native_stack_traces/CHANGELOG.md b/pkg/native_stack_traces/CHANGELOG.md
index 06b1702..222b0d9 100644
--- a/pkg/native_stack_traces/CHANGELOG.md
+++ b/pkg/native_stack_traces/CHANGELOG.md
@@ -1,5 +1,17 @@
 # Changelog
 
+## 0.3.3
+
+- No externally visible changes.
+
+## 0.3.2
+
+- The `find` command can now look up addresses given as offsets from static
+  symbols, not just hexadecimal virtual or absolute addresses.
+- Integer inputs (addresses or offsets) without an '0x' prefix or hexadecimal
+  digits will now be parsed as decimal unless the `-x`/`--force_hexadecimal`
+  flag is used.
+
 ## 0.3.1
 
 - Uses dynamic symbol information embedded in stack frame lines when available.
@@ -15,7 +27,7 @@
 
 ## 0.2.1
 
-- Added static method Dwarf.fromBuffer.
+- Added static method `Dwarf.fromBuffer`.
 
 ## 0.2.0
 
diff --git a/pkg/native_stack_traces/bin/decode.dart b/pkg/native_stack_traces/bin/decode.dart
index 4b864c0..22a5e7e 100644
--- a/pkg/native_stack_traces/bin/decode.dart
+++ b/pkg/native_stack_traces/bin/decode.dart
@@ -34,6 +34,10 @@
     _createBaseDebugParser(ArgParser(allowTrailingOptions: true))
       ..addMultiOption('location',
           abbr: 'l', help: 'PC address to find', valueHelp: 'PC')
+      ..addFlag('force_hexadecimal',
+          abbr: 'x',
+          negatable: false,
+          help: 'Always parse integers as hexadecimal')
       ..addOption('vm_start',
           help: 'Absolute address for start of VM instructions',
           valueHelp: 'PC')
@@ -88,19 +92,30 @@
 Usage: convert_stack_traces find [options] <PC> ...
 
 The find command looks up program counter (PC) addresses, either given as
-arguments on the command line or via the -l option. For each PC address,
-it outputs the file, function, and line number information if found.
+arguments on the command line or via the -l/--location option. For each
+successful PC lookup, it outputs the call information in one of two formats:
 
-PC addresses are expected to be hexadecimal numbers with or without an initial
-"0x" marker.
+- If the location corresponds to a call site in Dart source code, the call
+  information includes the file, function, and line number information.
+- If it corresponds to a Dart VM stub, the call information includes the dynamic
+  symbol name for the instructions payload and an offset into that payload.
 
 The -l option may be provided multiple times, or a single use of the -l option
 may be given multiple arguments separated by commas.
 
-By default, PC addresses are assumed to be virtual addresses valid for the
-given debugging information. To find absolute PC addresses, use both the
---vm_start and --isolate_start arguments tp provide the absolute addresses of
-the VM and isolate instructions sections.
+PC addresses can be provided in one of two formats:
+
+- An integer, e.g. 0x2a3f or 15049
+- A static symbol in the VM snapshot plus an integer offset, e.g.,
+  _kDartIsolateSnapshotInstructions+1523 or _kDartVMSnapshotInstructions+0x403f
+
+Integers without an "0x" prefix that do not includes hexadecimal digits are
+assumed to be decimal unless the -x/--force_hexadecimal flag is used.
+
+By default, integer PC addresses are assumed to be virtual addresses valid for
+the given debugging information. Otherwise, use both the --vm_start and
+--isolate_start arguments to provide the appropriate starting addresses of the
+VM and isolate instructions sections.
 
 Options shared by all commands:
 ${_argParser.usage}
@@ -159,67 +174,74 @@
 }
 
 void find(ArgResults options) {
+  final bool verbose = options['verbose'];
+  final bool forceHexadecimal = options['force_hexadecimal'];
+
   void usageError(String message) => errorWithUsage(message, command: 'find');
-  int convertAddress(String s) => int.tryParse(s, radix: 16);
+  int parseIntAddress(String s) {
+    if (!forceHexadecimal && !s.startsWith("0x")) {
+      final decimal = int.tryParse(s);
+      if (decimal != null) return decimal;
+    }
+    return int.tryParse(s.startsWith("0x") ? s.substring(2) : s, radix: 16);
+  }
+
+  PCOffset convertAddress(StackTraceHeader header, String s) {
+    final parsedOffset = tryParseSymbolOffset(s, forceHexadecimal);
+    if (parsedOffset != null) return parsedOffset;
+
+    final address = parseIntAddress(s);
+    if (address != null) return header.offsetOf(address);
+
+    return null;
+  }
 
   final dwarf = _loadFromFile(options['debug'], usageError);
-  if (dwarf == null) {
-    return;
-  }
+  if (dwarf == null) return;
+
   if (options['dump_debug_file_contents']) {
     print(dwarf.dumpFileInfo());
   }
-  final verbose = options['verbose'];
 
-  int vm_start;
+  if ((options['vm_start'] == null) != (options['isolate_start'] == null)) {
+    return usageError("need both VM start and isolate start");
+  }
+
+  int vmStart = dwarf.vmStartAddress;
   if (options['vm_start'] != null) {
-    vm_start = convertAddress(options['vm_start']);
-    if (vm_start == null) {
+    vmStart = parseIntAddress(options['vm_start']);
+    if (vmStart == null) {
       return usageError('could not parse VM start address '
           '${options['vm_start']}');
     }
   }
 
-  int isolate_start;
+  int isolateStart = dwarf.isolateStartAddress;
   if (options['isolate_start'] != null) {
-    isolate_start = convertAddress(options['isolate_start']);
-    if (isolate_start == null) {
+    isolateStart = parseIntAddress(options['isolate_start']);
+    if (isolateStart == null) {
       return usageError('could not parse isolate start address '
           '${options['isolate_start']}');
     }
   }
 
-  if ((vm_start == null) != (isolate_start == null)) {
-    return usageError("need both VM start and isolate start");
-  }
+  final header = StackTraceHeader(isolateStart, vmStart);
 
-  final locations = <int>[];
-  for (final s in options['location'] + options.rest) {
-    final location = convertAddress(s);
-    if (location == null) {
-      return usageError('could not parse PC address ${s}');
-    }
+  final locations = <PCOffset>[];
+  for (final String s in options['location'] + options.rest) {
+    final location = convertAddress(header, s);
+    if (location == null) return usageError('could not parse PC address ${s}');
     locations.add(location);
   }
   if (locations.isEmpty) return usageError('no PC addresses to find');
 
-  // Used to approximate how many hex digits we should have in the final output.
-  final maxDigits = options['location']
-      .fold(0, ((acc, s) => s.startsWith('0x') ? s.length - 2 : s.length));
-
-  Iterable<int> addresses = locations;
-  if (vm_start != null) {
-    final header = StackTraceHeader(isolate_start, vm_start);
-    addresses =
-        locations.map((l) => header.offsetOf(l).virtualAddressIn(dwarf));
-  }
-  for (final addr in addresses) {
+  for (final offset in locations) {
+    final addr = dwarf.virtualAddressOf(offset);
     final frames = dwarf
         .callInfoFor(addr, includeInternalFrames: verbose)
         ?.map((CallInfo c) => "  " + c.toString());
-    final addrString = addr > 0
-        ? "0x" + addr.toRadixString(16).padLeft(maxDigits, '0')
-        : addr.toString();
+    final addrString =
+        addr > 0 ? "0x" + addr.toRadixString(16) : addr.toString();
     print("For virtual address ${addrString}:");
     if (frames == null) {
       print("  Invalid virtual address.");
diff --git a/pkg/native_stack_traces/lib/native_stack_traces.dart b/pkg/native_stack_traces/lib/native_stack_traces.dart
index bbb59f7..13e28ff 100644
--- a/pkg/native_stack_traces/lib/native_stack_traces.dart
+++ b/pkg/native_stack_traces/lib/native_stack_traces.dart
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 export 'src/convert.dart'
-    show collectPCOffsets, DwarfStackTraceDecoder, StackTraceHeader;
+    show
+        collectPCOffsets,
+        tryParseSymbolOffset,
+        DwarfStackTraceDecoder,
+        StackTraceHeader;
 export 'src/dwarf.dart'
     show CallInfo, DartCallInfo, StubCallInfo, Dwarf, PCOffset;
diff --git a/pkg/native_stack_traces/lib/src/convert.dart b/pkg/native_stack_traces/lib/src/convert.dart
index df32604..f0a2d48 100644
--- a/pkg/native_stack_traces/lib/src/convert.dart
+++ b/pkg/native_stack_traces/lib/src/convert.dart
@@ -8,7 +8,8 @@
 import 'constants.dart' as constants;
 import "dwarf.dart";
 
-String _stackTracePiece(CallInfo call, int depth) => "#${depth}\t${call}";
+String _stackTracePiece(CallInfo call, int depth) =>
+    "#${depth.toString().padRight(6)} ${call}";
 
 // A pattern matching the last line of the non-symbolic stack trace header.
 //
@@ -55,42 +56,66 @@
 ///   - The virtual address of the program counter, if the snapshot was
 ///     loaded as a dynamic library, otherwise not present.
 ///   - The location of the virtual address, which is one of the following:
-///     - A dynamic symbol name, a plus sign, and a hexadecimal offset.
+///     - A dynamic symbol name, a plus sign, and an integer offset.
 ///     - The path to the snapshot, if it was loaded as a dynamic library,
 ///       otherwise the string "<unknown>".
-const _symbolREString = r'(?:(?<symbol>' +
+const _symbolOffsetREString = r'(?<symbol>' +
     constants.vmSymbolName +
     r'|' +
     constants.isolateSymbolName +
-    r')\+0x(?<offset>[\da-f]+))';
+    r')\+(?<offset>(?:0x)?[\da-f]+)';
+final _symbolOffsetRE = RegExp(_symbolOffsetREString);
 final _traceLineRE = RegExp(
-    r'    #(\d{2}) abs (?<address>[\da-f]+)(?: virt ([\da-f]+))? (?:' +
-        _symbolREString +
-        r'|.*)$');
+    r'    #(\d{2}) abs (?<address>[\da-f]+)(?: virt ([\da-f]+))? (?<rest>.*)$');
+
+/// Parses strings of the format <static symbol>+<integer offset>, where
+/// <static symbol> is one of the static symbols used for Dart instruction
+/// sections.
+///
+/// Unless forceHexadecimal is true, an integer offset without a "0x" prefix or
+/// 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]) {
+  final match = _symbolOffsetRE.firstMatch(s);
+  if (match == null) return null;
+  final symbolString = match.namedGroup('symbol');
+  final offsetString = match.namedGroup('offset');
+  int offset;
+  if (!forceHexadecimal && !offsetString.startsWith("0x")) {
+    offset = int.tryParse(offsetString);
+  }
+  if (offset == null) {
+    final digits = offsetString.startsWith("0x")
+        ? offsetString.substring(2)
+        : offsetString;
+    offset = int.tryParse(digits, radix: 16);
+  }
+  if (offset == null) return null;
+  switch (symbolString) {
+    case constants.vmSymbolName:
+      return PCOffset(offset, InstructionsSection.vm);
+    case constants.isolateSymbolName:
+      return PCOffset(offset, InstructionsSection.isolate);
+    default:
+      break;
+  }
+  return null;
+}
 
 PCOffset _retrievePCOffset(StackTraceHeader header, RegExpMatch match) {
   if (match == null) return null;
-  // Try using the symbol information first, since we don't need the header
+  final restString = match.namedGroup('rest');
+  // Try checking for symbol information first, since we don't need the header
   // information to translate it.
-  final symbolString = match.namedGroup('symbol');
-  final offsetString = match.namedGroup('offset');
-  if (symbolString != null && offsetString != null) {
-    final offset = int.tryParse(offsetString, radix: 16);
-    if (offset != null) {
-      switch (symbolString) {
-        case constants.vmSymbolName:
-          return PCOffset(offset, InstructionsSection.vm);
-        case constants.isolateSymbolName:
-          return PCOffset(offset, InstructionsSection.isolate);
-        default:
-          break;
-      }
-    }
+  if (restString.isNotEmpty) {
+    final offset = tryParseSymbolOffset(restString);
+    if (offset != null) return offset;
   }
   // 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.
-  final addressString = match.namedGroup('address');
-  if (addressString != null && header != null) {
+  if (header != null) {
+    final addressString = match.namedGroup('address');
     final address = int.tryParse(addressString, radix: 16);
     return header.offsetOf(address);
   }
diff --git a/pkg/native_stack_traces/lib/src/dwarf.dart b/pkg/native_stack_traces/lib/src/dwarf.dart
index 88c75b1..0b20555 100644
--- a/pkg/native_stack_traces/lib/src/dwarf.dart
+++ b/pkg/native_stack_traces/lib/src/dwarf.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:collection';
 import 'dart:math';
 import 'dart:typed_data';
 
@@ -119,60 +120,84 @@
   final _AttributeName name;
   final _AttributeForm form;
 
-  _Attribute(this.name, this.form);
+  _Attribute._(this.name, this.form);
+
+  static _Attribute fromReader(Reader reader) {
+    final nameInt = reader.readLEB128EncodedInteger();
+    final formInt = reader.readLEB128EncodedInteger();
+    if (nameInt == 0 && formInt == 0) return null;
+    if (!_attributeNames.containsKey(nameInt)) {
+      throw FormatException("Unexpected DW_AT value 0x${paddedHex(nameInt)}");
+    }
+    if (!_attributeForms.containsKey(formInt)) {
+      throw FormatException("Unexpected DW_FORM value 0x${paddedHex(formInt)}");
+    }
+    return _Attribute._(_attributeNames[nameInt], _attributeForms[formInt]);
+  }
+
+  Object read(Reader reader, CompilationUnitHeader header) {
+    switch (form) {
+      case _AttributeForm.string:
+        return reader.readNullTerminatedString();
+      case _AttributeForm.address:
+        return reader.readBytes(header.addressSize);
+      case _AttributeForm.sectionOffset:
+        return reader.readBytes(4);
+      case _AttributeForm.constant:
+        return reader.readLEB128EncodedInteger();
+      case _AttributeForm.reference4:
+        return reader.readBytes(4);
+    }
+    return null;
+  }
+
+  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);
+      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)";
+        return '0x${unresolvedValue} (origin: ${name})';
+    }
+    return "<unknown>";
+  }
 }
 
 class _Abbreviation {
-  final Reader reader;
+  final int code;
+  final _Tag tag;
+  final bool children;
+  final List<_Attribute> attributes;
 
-  _Tag tag;
-  bool children;
-  List<_Attribute> attributes;
-
-  _Abbreviation.fromReader(this.reader) {
-    _read();
-  }
+  _Abbreviation._(this.code, this.tag, this.children, this.attributes);
 
   // Constants from the DWARF specification.
   static const _DW_CHILDREN_no = 0x00;
   static const _DW_CHILDREN_yes = 0x01;
 
-  bool _readChildren() {
-    switch (reader.readByte()) {
-      case _DW_CHILDREN_no:
-        return false;
-      case _DW_CHILDREN_yes:
-        return true;
-      default:
-        throw FormatException("Expected DW_CHILDREN_no or DW_CHILDREN_yes");
-    }
-  }
-
-  void _read() {
-    reader.reset();
+  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)}");
     }
-    tag = _tags[tagInt];
-    children = _readChildren();
-    attributes = <_Attribute>[];
-    while (!reader.done) {
-      final nameInt = reader.readLEB128EncodedInteger();
-      final formInt = reader.readLEB128EncodedInteger();
-      if (nameInt == 0 && formInt == 0) {
-        break;
-      }
-      if (!_attributeNames.containsKey(nameInt)) {
-        throw FormatException("Unexpected DW_AT value 0x${paddedHex(nameInt)}");
-      }
-      if (!_attributeForms.containsKey(formInt)) {
-        throw FormatException(
-            "Unexpected DW_FORM value 0x${paddedHex(formInt)}");
-      }
-      attributes
-          .add(_Attribute(_attributeNames[nameInt], _attributeForms[formInt]));
+    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: "
+          "${childrenByte}");
     }
+    final children = childrenByte == _DW_CHILDREN_yes;
+    final attributes = reader.readRepeated(_Attribute.fromReader).toList();
+    return _Abbreviation._(code, tag, children, attributes);
   }
 
   void writeToStringBuffer(StringBuffer buffer) {
@@ -200,30 +225,18 @@
 }
 
 class _AbbreviationsTable {
-  final Reader reader;
+  final Map<int, _Abbreviation> _abbreviations;
 
-  Map<int, _Abbreviation> _abbreviations;
-
-  _AbbreviationsTable.fromReader(this.reader) {
-    _read();
-  }
+  _AbbreviationsTable._(this._abbreviations);
 
   bool containsKey(int code) => _abbreviations.containsKey(code);
   _Abbreviation operator [](int code) => _abbreviations[code];
 
-  void _read() {
-    reader.reset();
-    _abbreviations = <int, _Abbreviation>{};
-    while (!reader.done) {
-      final code = reader.readLEB128EncodedInteger();
-      // Code of 0 marks end of abbreviations table.
-      if (code == 0) {
-        break;
-      }
-      final abbrev = _Abbreviation.fromReader(reader.shrink(reader.offset));
-      _abbreviations[code] = abbrev;
-      reader.seek(abbrev.reader.offset);
-    }
+  static _AbbreviationsTable fromReader(Reader reader) {
+    final abbreviations = Map.fromEntries(reader
+        .readRepeated(_Abbreviation.fromReader)
+        .map((abbr) => MapEntry(abbr.code, abbr)));
+    return _AbbreviationsTable._(abbreviations);
   }
 
   void writeToStringBuffer(StringBuffer buffer) {
@@ -248,110 +261,44 @@
 
 /// A DWARF Debug Information Entry (DIE).
 class DebugInformationEntry {
-  final Reader reader;
-  final CompilationUnit compilationUnit;
+  // The index of the entry in the abbreviation table for this DIE.
+  final int code;
+  final Map<_Attribute, Object> attributes;
+  final Map<int, DebugInformationEntry> children;
 
-  // The index of the entry in the abbreviation table for this DIE. If 0, then
-  // this is not actually a full DIE, but an end marker for a list of entries.
-  int code;
-  Map<_Attribute, Object> attributes;
-  List<DebugInformationEntry> children;
+  DebugInformationEntry._(this.code, this.attributes, this.children);
 
-  DebugInformationEntry.fromReader(this.reader, this.compilationUnit) {
-    _read();
-  }
-
-  Object _readAttribute(_Attribute attribute) {
-    switch (attribute.form) {
-      case _AttributeForm.string:
-        return reader.readNullTerminatedString();
-      case _AttributeForm.address:
-        return reader.readBytes(compilationUnit.addressSize);
-      case _AttributeForm.sectionOffset:
-        return reader.readBytes(4);
-      case _AttributeForm.constant:
-        return reader.readLEB128EncodedInteger();
-      case _AttributeForm.reference4:
-        return reader.readBytes(4);
-    }
-    return null;
-  }
-
-  String _nameOfOrigin(int offset) {
-    if (!compilationUnit.referenceTable.containsKey(offset)) {
-      throw ArgumentError(
-          "${paddedHex(offset)} is not the offset of an abbreviated unit");
-    }
-    final origin = compilationUnit.referenceTable[offset];
-    assert(origin.containsKey(_AttributeName.name));
-    return origin[_AttributeName.name] as String;
-  }
-
-  String _attributeValueToString(_Attribute attribute, Object value) {
-    switch (attribute.form) {
-      case _AttributeForm.string:
-        return value as String;
-      case _AttributeForm.address:
-        return paddedHex(value as int, compilationUnit.addressSize);
-      case _AttributeForm.sectionOffset:
-        return paddedHex(value as int, 4);
-      case _AttributeForm.constant:
-        return value.toString();
-      case _AttributeForm.reference4:
-        return paddedHex(value as int, 4) +
-            " (origin: ${_nameOfOrigin(value as int)})";
-    }
-    return "<unknown>";
-  }
-
-  int get _unitOffset => reader.start - compilationUnit.reader.start;
-
-  void _read() {
-    reader.reset();
-    code = reader.readLEB128EncodedInteger();
+  static DebugInformationEntry fromReader(
+      Reader reader, CompilationUnitHeader header) {
+    final code = reader.readLEB128EncodedInteger();
     // DIEs with an abbreviation table index of 0 are list end markers.
-    if (code == 0) {
-      return;
-    }
-    if (!compilationUnit.abbreviations.containsKey(code)) {
+    if (code == 0) return null;
+    if (!header.abbreviations.containsKey(code)) {
       throw FormatException("Unknown abbreviation code 0x${paddedHex(code)}");
     }
-    final abbreviation = compilationUnit.abbreviations[code];
-    attributes = <_Attribute, Object>{};
+    final abbreviation = header.abbreviations[code];
+    final attributes = <_Attribute, Object>{};
     for (final attribute in abbreviation.attributes) {
-      attributes[attribute] = _readAttribute(attribute);
+      attributes[attribute] = attribute.read(reader, header);
     }
-    compilationUnit.referenceTable[_unitOffset] = this;
-    if (!abbreviation.children) return;
-    children = <DebugInformationEntry>[];
-    while (!reader.done) {
-      final child = DebugInformationEntry.fromReader(
-          reader.shrink(reader.offset), compilationUnit);
-      reader.seek(child.reader.offset);
-      if (child.code == 0) {
-        break;
-      }
-      children.add(child);
+    Map<int, DebugInformationEntry> children;
+    if (abbreviation.children) {
+      children = Map.fromEntries(reader.readRepeatedWithOffsets(
+          (r) => DebugInformationEntry.fromReader(r, header),
+          absolute: true));
     }
+    assert((children != null) == abbreviation.children);
+    return DebugInformationEntry._(code, attributes, children);
   }
 
-  _Attribute _attributeForName(_AttributeName name) => attributes.keys
+  _Attribute _namedAttribute(_AttributeName name) => attributes.keys
       .firstWhere((_Attribute k) => k.name == name, orElse: () => null);
 
-  bool containsKey(_AttributeName name) => _attributeForName(name) != null;
+  bool containsKey(_AttributeName name) => _namedAttribute(name) != null;
 
-  Object operator [](_AttributeName name) {
-    final key = _attributeForName(name);
-    if (key == null) {
-      return null;
-    }
-    return attributes[key];
-  }
+  Object operator [](_AttributeName name) => attributes[_namedAttribute(name)];
 
-  DebugInformationEntry get abstractOrigin {
-    final index = this[_AttributeName.abstractOrigin] as int;
-    return compilationUnit.referenceTable[index];
-  }
+  int get abstractOrigin => this[_AttributeName.abstractOrigin] as int;
 
   int get lowPC => this[_AttributeName.lowProgramCounter] as int;
 
@@ -366,49 +313,49 @@
 
   int get callLine => this[_AttributeName.callLine] as int;
 
-  _Tag get tag => compilationUnit.abbreviations[code].tag;
+  List<CallInfo> callInfo(
+      CompilationUnit unit, LineNumberProgram lineNumberProgram, int address) {
+    String callFilename(int index) =>
+        lineNumberProgram.header.filesInfo[index].name;
+    if (!containsPC(address)) return null;
 
-  List<CallInfo> callInfo(int address, LineNumberProgram lineNumberProgram) {
-    String callFilename(int index) => lineNumberProgram.filesInfo[index].name;
-    if (!containsPC(address)) {
-      return null;
-    }
+    final tag = unit.header.abbreviations[code].tag;
     final inlined = tag == _Tag.inlinedSubroutine;
-    for (final unit in children) {
-      final callInfo = unit.callInfo(address, lineNumberProgram);
-      if (callInfo == null) {
-        continue;
+    if (children != null) {
+      for (final child in children.values) {
+        final callInfo = child.callInfo(unit, lineNumberProgram, address);
+        if (callInfo == null) continue;
+
+        if (tag == _Tag.compileUnit) return callInfo;
+
+        return callInfo
+          ..add(DartCallInfo(
+              function: unit.nameOfOrigin(abstractOrigin),
+              inlined: inlined,
+              filename: callFilename(child.callFileIndex),
+              line: child.callLine));
       }
-      if (tag != _Tag.compileUnit) {
-        callInfo.add(DartCallInfo(
-            function: abstractOrigin.name,
-            inlined: inlined,
-            filename: callFilename(unit.callFileIndex),
-            line: unit.callLine));
-      }
-      return callInfo;
     }
-    if (tag == _Tag.compileUnit) {
-      return null;
-    }
+
+    if (tag == _Tag.compileUnit) return null;
+
     final filename = lineNumberProgram.filename(address);
     final line = lineNumberProgram.lineNumber(address);
     return [
       DartCallInfo(
-          function: abstractOrigin.name,
+          function: unit.nameOfOrigin(abstractOrigin),
           inlined: inlined,
           filename: filename,
           line: line)
     ];
   }
 
-  void writeToStringBuffer(StringBuffer buffer, {String indent = ''}) {
+  void writeToStringBuffer(StringBuffer buffer,
+      {CompilationUnit unit, String indent = ''}) {
     buffer
       ..write(indent)
-      ..write('Abbreviated unit (code ')
+      ..write('Abbreviation code: ')
       ..write(code)
-      ..write(', offset ')
-      ..write(paddedHex(_unitOffset))
       ..writeln('):');
     for (final attribute in attributes.keys) {
       buffer
@@ -416,30 +363,28 @@
         ..write('  ')
         ..write(_attributeNameStrings[attribute.name])
         ..write(' => ')
-        ..writeln(_attributeValueToString(attribute, attributes[attribute]));
+        ..writeln(attribute.valueToString(attributes[attribute], unit));
     }
-    if (children == null || children.isEmpty) {
+    if (children != null) {
       buffer
         ..write(indent)
-        ..writeln('Has no children.');
-      return;
-    }
-    buffer
-      ..write(indent)
-      ..write('Has ')
-      ..write(children.length)
-      ..write(' ')
-      ..write(children.length == 1 ? "child" : "children")
-      ..writeln(':');
-    for (int i = 0; i < children.length; i++) {
-      buffer
-        ..write(indent)
-        ..write('Child ')
-        ..write(i)
-        ..write(' of unit at offset ')
-        ..write(paddedHex(_unitOffset))
-        ..writeln(':');
-      children[i].writeToStringBuffer(buffer, indent: indent + '  ');
+        ..write('Children (')
+        ..write(children.length)
+        ..writeln('):');
+      final sortedChildren = children.entries.toList()
+        ..sort((kv1, kv2) => Comparable.compare(kv1.key, kv2.key));
+      for (int i = 0; i < sortedChildren.length; i++) {
+        final offset = sortedChildren[i].key;
+        final child = sortedChildren[i].value;
+        buffer
+          ..write(indent)
+          ..write('Child ')
+          ..write(i)
+          ..write(' (at offset 0x')
+          ..write(paddedHex(offset))
+          ..writeln('):');
+        child.writeToStringBuffer(buffer, unit: unit, indent: indent + '  ');
+      }
     }
   }
 
@@ -450,82 +395,124 @@
   }
 }
 
-/// A class representing a DWARF compilation unit.
-class CompilationUnit {
-  final Reader reader;
-  final Map<int, _AbbreviationsTable> _abbreviationsTables;
-  final LineNumberInfo _lineNumberInfo;
+class CompilationUnitHeader {
+  final int size;
+  final int version;
+  final int abbreviationsOffset;
+  final int addressSize;
+  final _AbbreviationsTable abbreviations;
 
-  int size;
-  int version;
-  int abbreviationOffset;
-  int addressSize;
-  List<DebugInformationEntry> contents;
-  Map<int, DebugInformationEntry> referenceTable;
+  CompilationUnitHeader._(this.size, this.version, this.abbreviationsOffset,
+      this.addressSize, this.abbreviations);
 
-  CompilationUnit.fromReader(
-      this.reader, this._abbreviationsTables, this._lineNumberInfo) {
-    _read();
-  }
-
-  void _read() {
-    reader.reset();
-    size = _initialLengthValue(reader);
+  static CompilationUnitHeader fromReader(
+      Reader reader, Map<int, _AbbreviationsTable> abbreviationsTables) {
+    final size = _initialLengthValue(reader);
     // An empty unit is an ending marker.
-    if (size == 0) {
-      return;
-    }
-    version = reader.readBytes(2);
+    if (size == 0) return null;
+    final version = reader.readBytes(2);
     if (version != 2) {
       throw FormatException("Expected DWARF version 2, got $version");
     }
-    abbreviationOffset = reader.readBytes(4);
-    if (!_abbreviationsTables.containsKey(abbreviationOffset)) {
+    final abbreviationsOffset = reader.readBytes(4);
+    if (!abbreviationsTables.containsKey(abbreviationsOffset)) {
       throw FormatException("No abbreviation table found for offset "
-          "0x${paddedHex(abbreviationOffset, 4)}");
+          "0x${paddedHex(abbreviationsOffset, 4)}");
     }
-    addressSize = reader.readByte();
-    contents = <DebugInformationEntry>[];
-    referenceTable = <int, DebugInformationEntry>{};
-    while (!reader.done) {
-      final subunit =
-          DebugInformationEntry.fromReader(reader.shrink(reader.offset), this);
-      reader.seek(subunit.reader.offset);
-      if (subunit.code == 0) {
-        break;
-      }
-      assert(subunit.tag == _Tag.compileUnit);
-      contents.add(subunit);
-    }
+    final addressSize = reader.readByte();
+    return CompilationUnitHeader._(size, version, abbreviationsOffset,
+        addressSize, abbreviationsTables[abbreviationsOffset]);
   }
 
-  Iterable<CallInfo> callInfo(int address) {
-    for (final unit in contents) {
-      final lineNumberProgram =
-          _lineNumberInfo[unit[_AttributeName.statementList]];
-      final callInfo = unit.callInfo(address, lineNumberProgram);
-      if (callInfo != null) {
-        return callInfo;
-      }
-    }
-    return null;
-  }
-
-  _AbbreviationsTable get abbreviations =>
-      _abbreviationsTables[abbreviationOffset];
-
   void writeToStringBuffer(StringBuffer buffer) {
     buffer
       ..writeln('Compilation unit:')
+      ..write('  Size: ')
+      ..writeln(size)
       ..write('  Version: ')
       ..writeln(version)
-      ..write('  Abbreviation offset: ')
-      ..writeln(paddedHex(abbreviationOffset, 4))
+      ..write('  Abbreviations offset: 0x')
+      ..writeln(paddedHex(abbreviationsOffset, 4))
       ..write('  Address size: ')
       ..writeln(addressSize)
       ..writeln();
-    for (final die in contents) {
-      die.writeToStringBuffer(buffer);
+  }
+
+  @override
+  String toString() {
+    final buffer = StringBuffer();
+    writeToStringBuffer(buffer);
+    return buffer.toString();
+  }
+}
+
+/// A class representing a DWARF compilation unit.
+class CompilationUnit {
+  CompilationUnitHeader header;
+  Map<int, DebugInformationEntry> referenceTable;
+
+  CompilationUnit._(this.header, this.referenceTable);
+
+  static CompilationUnit fromReader(
+      Reader reader, Map<int, _AbbreviationsTable> abbreviationsTables) {
+    final header =
+        CompilationUnitHeader.fromReader(reader, abbreviationsTables);
+    if (header == null) return null;
+
+    final referenceTable = Map.fromEntries(reader.readRepeatedWithOffsets(
+        (r) => DebugInformationEntry.fromReader(r, header),
+        absolute: true));
+    _addChildEntries(referenceTable);
+    return CompilationUnit._(header, referenceTable);
+  }
+
+  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);
+      }
+    }
+    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);
+      }
+    }
+  }
+
+  Iterable<CallInfo> callInfo(LineNumberInfo lineNumberInfo, int address) {
+    for (final die in referenceTable.values) {
+      final lineNumberProgram =
+          lineNumberInfo[die[_AttributeName.statementList]];
+      final callInfo = die.callInfo(this, lineNumberProgram, address);
+      if (callInfo != null) return callInfo;
+    }
+    return null;
+  }
+
+  String nameOfOrigin(int offset) {
+    if (!referenceTable.containsKey(offset)) {
+      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];
+      buffer
+        ..write('Debug information entry at offset 0x')
+        ..write(paddedHex(offset))
+        ..writeln(':');
+      die.writeToStringBuffer(buffer, unit: this);
       buffer.writeln();
     }
   }
@@ -540,37 +527,23 @@
 
 /// A class representing a DWARF `.debug_info` section.
 class DebugInfo {
-  final Reader reader;
-  final Map<int, _AbbreviationsTable> _abbreviationsTables;
-  final LineNumberInfo _lineNumberInfo;
+  final List<CompilationUnit> units;
 
-  List<CompilationUnit> units;
+  DebugInfo._(this.units);
 
-  DebugInfo.fromReader(
-      this.reader, this._abbreviationsTables, this._lineNumberInfo) {
-    _read();
+  static DebugInfo fromReader(
+      Reader reader, Map<int, _AbbreviationsTable> abbreviationsTable) {
+    final units = reader
+        .readRepeated(
+            (r) => CompilationUnit.fromReader(reader, abbreviationsTable))
+        .toList();
+    return DebugInfo._(units);
   }
 
-  void _read() {
-    reader.reset();
-    units = <CompilationUnit>[];
-    while (!reader.done) {
-      final unit = CompilationUnit.fromReader(
-          reader.shrink(reader.offset), _abbreviationsTables, _lineNumberInfo);
-      reader.seek(unit.reader.offset);
-      if (unit.size == 0) {
-        break;
-      }
-      units.add(unit);
-    }
-  }
-
-  Iterable<CallInfo> callInfo(int address) {
+  Iterable<CallInfo> callInfo(LineNumberInfo lineNumberInfo, int address) {
     for (final unit in units) {
-      final callInfo = unit.callInfo(address);
-      if (callInfo != null) {
-        return callInfo;
-      }
+      final callInfo = unit.callInfo(lineNumberInfo, address);
+      if (callInfo != null) return callInfo;
     }
     return null;
   }
@@ -590,26 +563,21 @@
 }
 
 class FileEntry {
-  final Reader reader;
+  final String name;
+  final int directoryIndex;
+  final int lastModified;
+  final int size;
 
-  String name;
-  int directoryIndex;
-  int lastModified;
-  int size;
+  FileEntry._(this.name, this.directoryIndex, this.lastModified, this.size);
 
-  FileEntry.fromReader(this.reader) {
-    _read();
-  }
-
-  void _read() {
-    reader.reset();
-    name = reader.readNullTerminatedString();
-    if (name == "") {
-      return;
-    }
-    directoryIndex = reader.readLEB128EncodedInteger();
-    lastModified = reader.readLEB128EncodedInteger();
-    size = reader.readLEB128EncodedInteger();
+  static FileEntry fromReader(Reader reader) {
+    final name = reader.readNullTerminatedString();
+    // An empty null-terminated string marks the table end.
+    if (name == "") return null;
+    final directoryIndex = reader.readLEB128EncodedInteger();
+    final lastModified = reader.readLEB128EncodedInteger();
+    final size = reader.readLEB128EncodedInteger();
+    return FileEntry._(name, directoryIndex, lastModified, size);
   }
 
   @override
@@ -620,28 +588,18 @@
 }
 
 class FileInfo {
-  final Reader reader;
+  final Map<int, FileEntry> _files;
 
-  Map<int, FileEntry> _files;
+  FileInfo._(this._files);
 
-  FileInfo.fromReader(this.reader) {
-    _read();
-  }
-
-  void _read() {
-    reader.reset();
-    _files = <int, FileEntry>{};
-    int index = 1;
-    while (!reader.done) {
-      final file = FileEntry.fromReader(reader.shrink(reader.offset));
-      reader.seek(file.reader.offset);
-      // An empty null-terminated string marks the table end.
-      if (file.name == "") {
-        break;
-      }
-      _files[index] = file;
-      index++;
+  static FileInfo fromReader(Reader reader) {
+    final offsetFiles = reader.readRepeated(FileEntry.fromReader).toList();
+    final files = <int, FileEntry>{};
+    for (int i = 0; i < offsetFiles.length; i++) {
+      // File entries are one-based, not zero-based.
+      files[i + 1] = offsetFiles[i];
     }
+    return FileInfo._(files);
   }
 
   bool containsKey(int index) => _files.containsKey(index);
@@ -757,207 +715,85 @@
       "  Is ${endSequence ? "" : "not "}just after the end of a sequence.";
 }
 
-/// A class representing a DWARF line number program.
-class LineNumberProgram {
-  final Reader reader;
+class LineNumberProgramHeader {
+  final int size;
+  final int version;
+  final int headerLength;
+  final int minimumInstructionLength;
+  final bool defaultIsStatement;
+  final int lineBase;
+  final int lineRange;
+  final int opcodeBase;
+  final Map<int, int> standardOpcodeLengths;
+  final List<String> includeDirectories;
+  final FileInfo filesInfo;
 
-  int size;
-  int version;
-  int headerLength;
-  int minimumInstructionLength;
-  bool defaultIsStatement;
-  int lineBase;
-  int lineRange;
-  int opcodeBase;
-  Map<int, int> standardOpcodeLengths;
-  List<String> includeDirectories;
-  FileInfo filesInfo;
-  List<LineNumberState> calculatedMatrix;
-  Map<int, LineNumberState> cachedLookups;
+  LineNumberProgramHeader._(
+      this.size,
+      this.version,
+      this.headerLength,
+      this.minimumInstructionLength,
+      this.defaultIsStatement,
+      this.lineBase,
+      this.lineRange,
+      this.opcodeBase,
+      this.standardOpcodeLengths,
+      this.includeDirectories,
+      this.filesInfo);
 
-  LineNumberProgram.fromReader(this.reader) {
-    _read();
-  }
+  static LineNumberProgramHeader fromReader(Reader reader) {
+    final size = _initialLengthValue(reader);
+    if (size == 0) return null;
+    final version = reader.readBytes(2);
 
-  void _read() {
-    reader.reset();
-    size = _initialLengthValue(reader);
-    if (size == 0) {
-      return;
+    final headerLength = reader.readBytes(4);
+    // We'll need this later as a double-check that we've read the entire
+    // header.
+    final headerStart = reader.offset;
+    final minimumInstructionLength = reader.readByte();
+    final isStmtByte = reader.readByte();
+    if (isStmtByte < 0 || isStmtByte > 1) {
+      throw FormatException(
+          "Unexpected value for default_is_stmt: ${isStmtByte}");
     }
-    version = reader.readBytes(2);
-    headerLength = reader.readBytes(4);
-    minimumInstructionLength = reader.readByte();
-    switch (reader.readByte()) {
-      case 0:
-        defaultIsStatement = false;
-        break;
-      case 1:
-        defaultIsStatement = true;
-        break;
-      default:
-        throw FormatException("Unexpected value for default_is_stmt");
-    }
-    lineBase = reader.readByte(signed: true);
-    lineRange = reader.readByte();
-    opcodeBase = reader.readByte();
-    standardOpcodeLengths = <int, int>{};
+    final defaultIsStatement = isStmtByte == 1;
+    final lineBase = reader.readByte(signed: true);
+    final lineRange = reader.readByte();
+    final opcodeBase = reader.readByte();
+    final standardOpcodeLengths = <int, int>{};
     // Standard opcode numbering starts at 1.
     for (int i = 1; i < opcodeBase; i++) {
       standardOpcodeLengths[i] = reader.readLEB128EncodedInteger();
     }
-    includeDirectories = <String>[];
+    final includeDirectories = <String>[];
     while (!reader.done) {
       final directory = reader.readNullTerminatedString();
-      if (directory == "") {
-        break;
-      }
+      if (directory == "") break;
       includeDirectories.add(directory);
     }
-    filesInfo = FileInfo.fromReader(reader.shrink(reader.offset));
-    reader.seek(filesInfo.reader.offset);
-    // Header length doesn't include the 4-byte length or 2-byte version fields.
-    assert(reader.offset == headerLength + 6);
-    calculatedMatrix = <LineNumberState>[];
-    final currentState = LineNumberState(defaultIsStatement);
-    while (!reader.done) {
-      _applyNextOpcode(currentState);
+    if (reader.done) {
+      throw FormatException("Unterminated directory entry");
     }
-    if (calculatedMatrix.isEmpty) {
-      throw FormatException("No line number information generated by program");
-    }
-    // Set the offset to the declared size in case of padding.  The declared
-    // size does not include the size of the size field itself.
-    reader.seek(size + 4);
-    cachedLookups = <int, LineNumberState>{};
-  }
+    final filesInfo = FileInfo.fromReader(reader);
 
-  void _addStateToMatrix(LineNumberState state) {
-    calculatedMatrix.add(state.clone());
-  }
-
-  void _applyNextOpcode(LineNumberState state) {
-    void applySpecialOpcode(int opcode) {
-      final adjustedOpcode = opcode - opcodeBase;
-      state.address = adjustedOpcode ~/ lineRange;
-      state.line += lineBase + (adjustedOpcode % lineRange);
+    // Header length doesn't include the 2-byte version or 4-byte length fields.
+    if (reader.offset != headerStart + headerLength) {
+      throw FormatException("At offset ${reader.offset} after header, "
+          "expected to be at offset ${headerStart + headerLength}");
     }
 
-    final opcode = reader.readByte();
-    if (opcode >= opcodeBase) {
-      return applySpecialOpcode(opcode);
-    }
-    switch (opcode) {
-      case 0: // Extended opcodes
-        final extendedLength = reader.readByte();
-        final subOpcode = reader.readByte();
-        switch (subOpcode) {
-          case 0:
-            throw FormatException(
-                "Attempted to execute extended opcode ${subOpcode} (padding?)");
-          case 1: // DW_LNE_end_sequence
-            state.endSequence = true;
-            _addStateToMatrix(state);
-            state.reset();
-            break;
-          case 2: // DW_LNE_set_address
-            // The length includes the subopcode.
-            final valueLength = extendedLength - 1;
-            assert(valueLength == 4 || valueLength == 8);
-            final newAddress = reader.readBytes(valueLength);
-            state.address = newAddress;
-            break;
-          case 3: // DW_LNE_define_file
-            throw FormatException("DW_LNE_define_file instruction not handled");
-          default:
-            throw FormatException(
-                "Extended opcode ${subOpcode} not in DWARF 2");
-        }
-        break;
-      case 1: // DW_LNS_copy
-        _addStateToMatrix(state);
-        state.basicBlock = false;
-        break;
-      case 2: // DW_LNS_advance_pc
-        final increment = reader.readLEB128EncodedInteger();
-        state.address += minimumInstructionLength * increment;
-        break;
-      case 3: // DW_LNS_advance_line
-        state.line += reader.readLEB128EncodedInteger(signed: true);
-        break;
-      case 4: // DW_LNS_set_file
-        state.fileIndex = reader.readLEB128EncodedInteger();
-        break;
-      case 5: // DW_LNS_set_column
-        state.column = reader.readLEB128EncodedInteger();
-        break;
-      case 6: // DW_LNS_negate_stmt
-        state.isStatement = !state.isStatement;
-        break;
-      case 7: // DW_LNS_set_basic_block
-        state.basicBlock = true;
-        break;
-      case 8: // DW_LNS_const_add_pc
-        applySpecialOpcode(255);
-        break;
-      case 9: // DW_LNS_fixed_advance_pc
-        state.address += reader.readBytes(2);
-        break;
-      default:
-        throw FormatException("Standard opcode ${opcode} not in DWARF 2");
-    }
-  }
-
-  bool containsKey(int address) {
-    assert(calculatedMatrix.last.endSequence);
-    return address >= calculatedMatrix.first.address &&
-        address < calculatedMatrix.last.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);
-    var minIndex = 0;
-    var maxIndex = calculatedMatrix.length - 1;
-    while (true) {
-      if (minIndex == maxIndex || minIndex + 1 == maxIndex) {
-        final found = calculatedMatrix[minIndex];
-        cachedLookups[address] = found;
-        return found;
-      }
-      final index = minIndex + ((maxIndex - minIndex) ~/ 2);
-      final compared = calculatedMatrix[index].address.compareTo(address);
-      if (compared == 0) {
-        return calculatedMatrix[index];
-      } else if (compared < 0) {
-        minIndex = index;
-      } else if (compared > 0) {
-        maxIndex = index;
-      }
-    }
-  }
-
-  String filename(int address) {
-    final state = this[address];
-    if (state == null) {
-      return null;
-    }
-    return filesInfo[state.fileIndex].name;
-  }
-
-  int lineNumber(int address) {
-    final state = this[address];
-    if (state == null) {
-      return null;
-    }
-    return state.line;
+    return LineNumberProgramHeader._(
+        size,
+        version,
+        headerLength,
+        minimumInstructionLength,
+        defaultIsStatement,
+        lineBase,
+        lineRange,
+        opcodeBase,
+        standardOpcodeLengths,
+        includeDirectories,
+        filesInfo);
   }
 
   void writeToStringBuffer(StringBuffer buffer) {
@@ -999,6 +835,153 @@
     }
 
     filesInfo.writeToStringBuffer(buffer);
+  }
+
+  @override
+  String toString() {
+    final buffer = StringBuffer();
+    writeToStringBuffer(buffer);
+    return buffer.toString();
+  }
+}
+
+/// A class representing a DWARF line number program.
+class LineNumberProgram {
+  final LineNumberProgramHeader header;
+  final List<LineNumberState> calculatedMatrix;
+  final Map<int, LineNumberState> cachedLookups;
+
+  LineNumberProgram._(this.header, this.calculatedMatrix) : cachedLookups = {};
+
+  static LineNumberProgram fromReader(Reader reader) {
+    final header = LineNumberProgramHeader.fromReader(reader);
+    if (header == null) return null;
+    final calculatedMatrix = _readOpcodes(reader, header).toList();
+    if (calculatedMatrix.isEmpty) {
+      throw FormatException("No line number information generated by program");
+    }
+    return LineNumberProgram._(header, calculatedMatrix);
+  }
+
+  static Iterable<LineNumberState> _readOpcodes(
+      Reader reader, LineNumberProgramHeader header) sync* {
+    final state = LineNumberState(header.defaultIsStatement);
+
+    void applySpecialOpcode(int opcode) {
+      final adjustedOpcode = opcode - header.opcodeBase;
+      state.address = adjustedOpcode ~/ header.lineRange;
+      state.line += header.lineBase + (adjustedOpcode % header.lineRange);
+    }
+
+    while (!reader.done) {
+      final opcode = reader.readByte();
+      if (opcode >= header.opcodeBase) {
+        applySpecialOpcode(opcode);
+        continue;
+      }
+      switch (opcode) {
+        case 0: // Extended opcodes
+          final extendedLength = reader.readByte();
+          final subOpcode = reader.readByte();
+          switch (subOpcode) {
+            case 0:
+              throw FormatException("Attempted to execute extended opcode 0");
+            case 1: // DW_LNE_end_sequence
+              state.endSequence = true;
+              yield state.clone();
+              state.reset();
+              break;
+            case 2: // DW_LNE_set_address
+              // The length includes the subopcode.
+              final valueLength = extendedLength - 1;
+              assert(valueLength == 4 || valueLength == 8);
+              final newAddress = reader.readBytes(valueLength);
+              state.address = newAddress;
+              break;
+            case 3: // DW_LNE_define_file
+              throw FormatException(
+                  "DW_LNE_define_file instruction not handled");
+            default:
+              throw FormatException(
+                  "Extended opcode ${subOpcode} not in DWARF 2");
+          }
+          break;
+        case 1: // DW_LNS_copy
+          yield state.clone();
+          state.basicBlock = false;
+          break;
+        case 2: // DW_LNS_advance_pc
+          final increment = reader.readLEB128EncodedInteger();
+          state.address += header.minimumInstructionLength * increment;
+          break;
+        case 3: // DW_LNS_advance_line
+          state.line += reader.readLEB128EncodedInteger(signed: true);
+          break;
+        case 4: // DW_LNS_set_file
+          state.fileIndex = reader.readLEB128EncodedInteger();
+          break;
+        case 5: // DW_LNS_set_column
+          state.column = reader.readLEB128EncodedInteger();
+          break;
+        case 6: // DW_LNS_negate_stmt
+          state.isStatement = !state.isStatement;
+          break;
+        case 7: // DW_LNS_set_basic_block
+          state.basicBlock = true;
+          break;
+        case 8: // DW_LNS_const_add_pc
+          applySpecialOpcode(255);
+          break;
+        case 9: // DW_LNS_fixed_advance_pc
+          state.address += reader.readBytes(2);
+          break;
+        default:
+          throw FormatException("Standard opcode ${opcode} not in DWARF 2");
+      }
+    }
+  }
+
+  bool containsKey(int address) {
+    assert(calculatedMatrix.last.endSequence);
+    return address >= calculatedMatrix.first.address &&
+        address < calculatedMatrix.last.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);
+    var minIndex = 0;
+    var maxIndex = calculatedMatrix.length - 1;
+    while (true) {
+      if (minIndex == maxIndex || minIndex + 1 == maxIndex) {
+        final found = calculatedMatrix[minIndex];
+        cachedLookups[address] = found;
+        return found;
+      }
+      final index = minIndex + ((maxIndex - minIndex) ~/ 2);
+      final compared = calculatedMatrix[index].address.compareTo(address);
+      if (compared == 0) {
+        return calculatedMatrix[index];
+      } else if (compared < 0) {
+        minIndex = index;
+      } else if (compared > 0) {
+        maxIndex = index;
+      }
+    }
+  }
+
+  String filename(int address) =>
+      header.filesInfo[this[address]?.fileIndex]?.name;
+
+  int lineNumber(int address) => this[address]?.line;
+
+  void writeToStringBuffer(StringBuffer buffer) {
+    header.writeToStringBuffer(buffer);
 
     buffer.writeln("Results of line number program:");
     for (final state in calculatedMatrix) {
@@ -1015,26 +998,14 @@
 
 /// A class representing a DWARF .debug_line section.
 class LineNumberInfo {
-  final Reader reader;
+  final Map<int, LineNumberProgram> programs;
 
-  Map<int, LineNumberProgram> programs;
+  LineNumberInfo._(this.programs);
 
-  LineNumberInfo.fromReader(this.reader) {
-    _read();
-  }
-
-  void _read() {
-    reader.reset();
-    programs = <int, LineNumberProgram>{};
-    while (!reader.done) {
-      final start = reader.offset;
-      final program = LineNumberProgram.fromReader(reader.shrink(start));
-      reader.seek(program.reader.offset);
-      if (program.size == 0) {
-        break;
-      }
-      programs[start] = program;
-    }
+  static LineNumberInfo fromReader(Reader reader) {
+    final programs = Map.fromEntries(
+        reader.readRepeatedWithOffsets(LineNumberProgram.fromReader));
+    return LineNumberInfo._(programs);
   }
 
   bool containsKey(int address) => programs.containsKey(address);
@@ -1132,7 +1103,7 @@
   }
 
   @override
-  String toString() => "${name} + ${offset}";
+  String toString() => "${name}+0x${offset.toRadixString(16)}";
 }
 
 /// The instructions section in which a program counter address is located.
@@ -1167,6 +1138,9 @@
         offset == other.offset &&
         section == other.section;
   }
+
+  @override
+  String toString() => 'PCOffset($section, $offset)';
 }
 
 /// The DWARF debugging information for a Dart snapshot.
@@ -1175,11 +1149,17 @@
   final Map<int, _AbbreviationsTable> _abbreviationTables;
   final DebugInfo _debugInfo;
   final LineNumberInfo _lineNumberInfo;
-  final int _vmStartAddress;
-  final int _isolateStartAddress;
+
+  /// Virtual address of the start of the VM instructions section in the DWARF
+  /// information.
+  final int vmStartAddress;
+
+  /// Virtual address of the start of the isolate instructions section in the
+  /// DWARF information.
+  final int isolateStartAddress;
 
   Dwarf._(this._elf, this._abbreviationTables, this._debugInfo,
-      this._lineNumberInfo, this._vmStartAddress, this._isolateStartAddress);
+      this._lineNumberInfo, this.vmStartAddress, this.isolateStartAddress);
 
   /// Attempts to load the DWARF debugging information from the reader.
   ///
@@ -1188,7 +1168,7 @@
     // Currently, the only DWARF-containing format we recognize is ELF.
     final elf = Elf.fromReader(reader);
     if (elf == null) return null;
-    return Dwarf._loadSectionsFromElf(elf);
+    return Dwarf._loadSectionsFromElf(reader, elf);
   }
 
   /// Attempts to load the DWARF debugging information from the given bytes.
@@ -1202,24 +1182,19 @@
   /// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
   static Dwarf fromFile(String path) => Dwarf.fromReader(Reader.fromFile(path));
 
-  static Dwarf _loadSectionsFromElf(Elf elf) {
+  static Dwarf _loadSectionsFromElf(Reader reader, Elf elf) {
     final abbrevSection = elf.namedSections(".debug_abbrev").single;
-    final abbreviationTables = <int, _AbbreviationsTable>{};
-    var abbreviationOffset = 0;
-    while (abbreviationOffset < abbrevSection.reader.length) {
-      final table = _AbbreviationsTable.fromReader(
-          abbrevSection.reader.shrink(abbreviationOffset));
-      abbreviationTables[abbreviationOffset] = table;
-      abbreviationOffset += table.reader.offset;
-    }
-    assert(abbreviationOffset == abbrevSection.reader.length);
+    final abbrevReader = abbrevSection.refocusedCopy(reader);
+    final abbreviationTables = Map.fromEntries(
+        abbrevReader.readRepeatedWithOffsets(_AbbreviationsTable.fromReader));
 
     final lineNumberSection = elf.namedSections(".debug_line").single;
-    final lineNumberInfo = LineNumberInfo.fromReader(lineNumberSection.reader);
+    final lineNumberInfo =
+        LineNumberInfo.fromReader(lineNumberSection.refocusedCopy(reader));
 
     final infoSection = elf.namedSections(".debug_info").single;
     final debugInfo = DebugInfo.fromReader(
-        infoSection.reader, abbreviationTables, lineNumberInfo);
+        infoSection.refocusedCopy(reader), abbreviationTables);
 
     final vmStartSymbol = elf.dynamicSymbolFor(constants.vmSymbolName);
     if (vmStartSymbol == null) {
@@ -1248,7 +1223,7 @@
   /// to user or library code is returned.
   Iterable<CallInfo> callInfoFor(int address,
       {bool includeInternalFrames = false}) {
-    var calls = _debugInfo.callInfo(address);
+    var calls = _debugInfo.callInfo(_lineNumberInfo, address);
     if (calls == null) {
       // Since we're dealing with return addresses in stack frames, subtract
       // one in case the return address is just off the end of the stub (since
@@ -1259,8 +1234,8 @@
         calls = <CallInfo>[StubCallInfo(name: symbol.name, offset: offset)];
       }
     }
-    if (calls != null && !includeInternalFrames) {
-      return calls.where((CallInfo c) => !c.isInternal);
+    if (!includeInternalFrames) {
+      return calls?.where((CallInfo c) => !c.isInternal);
     }
     return calls;
   }
@@ -1269,9 +1244,9 @@
   int virtualAddressOf(PCOffset pcOffset) {
     switch (pcOffset.section) {
       case InstructionsSection.vm:
-        return pcOffset.offset + _vmStartAddress;
+        return pcOffset.offset + vmStartAddress;
       case InstructionsSection.isolate:
-        return pcOffset.offset + _isolateStartAddress;
+        return pcOffset.offset + isolateStartAddress;
       default:
         throw "Unexpected value for instructions section";
     }
diff --git a/pkg/native_stack_traces/lib/src/elf.dart b/pkg/native_stack_traces/lib/src/elf.dart
index 64b325a..6b4e305 100644
--- a/pkg/native_stack_traces/lib/src/elf.dart
+++ b/pkg/native_stack_traces/lib/src/elf.dart
@@ -65,94 +65,84 @@
   }
 }
 
+/// The header of the ELF file, which includes information necessary to parse
+/// the rest of the file.
 class ElfHeader {
-  final Reader startingReader;
+  final int wordSize;
+  final Endian endian;
+  final int entry;
+  final int flags;
+  final int headerSize;
+  final int programHeaderOffset;
+  final int programHeaderCount;
+  final int programHeaderEntrySize;
+  final int sectionHeaderOffset;
+  final int sectionHeaderCount;
+  final int sectionHeaderEntrySize;
+  final int sectionHeaderStringsIndex;
 
-  int wordSize;
-  Endian endian;
-  int entry;
-  int flags;
-  int headerSize;
-  int programHeaderOffset;
-  int sectionHeaderOffset;
-  int programHeaderCount;
-  int sectionHeaderCount;
-  int programHeaderEntrySize;
-  int sectionHeaderEntrySize;
-  int sectionHeaderStringsIndex;
+  ElfHeader._(
+      this.wordSize,
+      this.endian,
+      this.entry,
+      this.flags,
+      this.headerSize,
+      this.programHeaderOffset,
+      this.sectionHeaderOffset,
+      this.programHeaderCount,
+      this.sectionHeaderCount,
+      this.programHeaderEntrySize,
+      this.sectionHeaderEntrySize,
+      this.sectionHeaderStringsIndex);
 
-  int get programHeaderSize => programHeaderCount * programHeaderEntrySize;
-  int get sectionHeaderSize => sectionHeaderCount * sectionHeaderEntrySize;
+  static ElfHeader fromReader(Reader reader) {
+    final fileSize = reader.length;
 
-  // Constants used within the ELF specification.
-  static const _ELFMAG = "\x7fELF";
-  static const _ELFCLASS32 = 0x01;
-  static const _ELFCLASS64 = 0x02;
-  static const _ELFDATA2LSB = 0x01;
-  static const _ELFDATA2MSB = 0x02;
-
-  ElfHeader.fromReader(this.startingReader) {
-    _read();
-  }
-
-  static bool startsWithMagicNumber(Reader reader) {
-    reader.reset();
     for (final sigByte in _ELFMAG.codeUnits) {
       if (reader.readByte() != sigByte) {
-        return false;
+        return null;
       }
     }
-    return true;
-  }
 
-  int _readWordSize(Reader reader) {
+    int wordSize;
     switch (reader.readByte()) {
       case _ELFCLASS32:
-        return 4;
+        wordSize = 4;
+        break;
       case _ELFCLASS64:
-        return 8;
+        wordSize = 8;
+        break;
       default:
         throw FormatException("Unexpected e_ident[EI_CLASS] value");
     }
-  }
+    final calculatedHeaderSize = 0x18 + 3 * wordSize + 0x10;
 
-  int get calculatedHeaderSize => 0x18 + 3 * wordSize + 0x10;
-
-  Endian _readEndian(Reader reader) {
-    switch (reader.readByte()) {
-      case _ELFDATA2LSB:
-        return Endian.little;
-      case _ELFDATA2MSB:
-        return Endian.big;
-      default:
-        throw FormatException("Unexpected e_indent[EI_DATA] value");
-    }
-  }
-
-  void _read() {
-    startingReader.reset();
-    for (final sigByte in _ELFMAG.codeUnits) {
-      if (startingReader.readByte() != sigByte) {
-        throw FormatException("Not an ELF file");
-      }
-    }
-    wordSize = _readWordSize(startingReader);
-    final fileSize = startingReader.bdata.buffer.lengthInBytes;
     if (fileSize < calculatedHeaderSize) {
       throw FormatException("ELF file too small for header: "
           "file size ${fileSize} < "
           "calculated header size $calculatedHeaderSize");
     }
-    endian = _readEndian(startingReader);
-    if (startingReader.readByte() != 0x01) {
+
+    Endian endian;
+    switch (reader.readByte()) {
+      case _ELFDATA2LSB:
+        endian = Endian.little;
+        break;
+      case _ELFDATA2MSB:
+        endian = Endian.big;
+        break;
+      default:
+        throw FormatException("Unexpected e_indent[EI_DATA] value");
+    }
+
+    if (reader.readByte() != 0x01) {
       throw FormatException("Unexpected e_ident[EI_VERSION] value");
     }
 
     // After this point, we need the reader to be correctly set up re: word
     // size and endianness, since we start reading more than single bytes.
-    final reader = Reader.fromTypedData(startingReader.bdata,
-        wordSize: wordSize, endian: endian);
-    reader.seek(startingReader.offset);
+    reader.endian = endian;
+    reader.wordSize = wordSize;
 
     // Skip rest of e_ident/e_type/e_machine, i.e. move to e_version.
     reader.seek(0x14, absolute: true);
@@ -160,16 +150,26 @@
       throw FormatException("Unexpected e_version value");
     }
 
-    entry = _readElfAddress(reader);
-    programHeaderOffset = _readElfOffset(reader);
-    sectionHeaderOffset = _readElfOffset(reader);
-    flags = _readElfWord(reader);
-    headerSize = _readElfHalf(reader);
-    programHeaderEntrySize = _readElfHalf(reader);
-    programHeaderCount = _readElfHalf(reader);
-    sectionHeaderEntrySize = _readElfHalf(reader);
-    sectionHeaderCount = _readElfHalf(reader);
-    sectionHeaderStringsIndex = _readElfHalf(reader);
+    final entry = _readElfAddress(reader);
+    final programHeaderOffset = _readElfOffset(reader);
+    final sectionHeaderOffset = _readElfOffset(reader);
+    final flags = _readElfWord(reader);
+    final headerSize = _readElfHalf(reader);
+
+    final programHeaderEntrySize = _readElfHalf(reader);
+    final programHeaderCount = _readElfHalf(reader);
+    final programHeaderSize = programHeaderEntrySize * programHeaderCount;
+
+    final sectionHeaderEntrySize = _readElfHalf(reader);
+    final sectionHeaderCount = _readElfHalf(reader);
+    final sectionHeaderSize = sectionHeaderEntrySize * sectionHeaderCount;
+
+    final sectionHeaderStringsIndex = _readElfHalf(reader);
+
+    if (reader.offset != headerSize) {
+      throw FormatException("Only read ${reader.offset} bytes, not the "
+          "full header size ${headerSize}");
+    }
 
     if (headerSize != calculatedHeaderSize) {
       throw FormatException("Stored ELF header size ${headerSize} != "
@@ -187,8 +187,32 @@
     if (fileSize < sectionHeaderOffset + sectionHeaderSize) {
       throw FormatException("File is truncated within the section header");
     }
+
+    return ElfHeader._(
+        wordSize,
+        endian,
+        entry,
+        flags,
+        headerSize,
+        programHeaderOffset,
+        sectionHeaderOffset,
+        programHeaderCount,
+        sectionHeaderCount,
+        programHeaderEntrySize,
+        sectionHeaderEntrySize,
+        sectionHeaderStringsIndex);
   }
 
+  int get programHeaderSize => programHeaderCount * programHeaderEntrySize;
+  int get sectionHeaderSize => sectionHeaderCount * sectionHeaderEntrySize;
+
+  // Constants used within the ELF specification.
+  static const _ELFMAG = "\x7fELF";
+  static const _ELFCLASS32 = 0x01;
+  static const _ELFCLASS64 = 0x02;
+  static const _ELFDATA2LSB = 0x01;
+  static const _ELFDATA2MSB = 0x02;
+
   void writeToStringBuffer(StringBuffer buffer) {
     buffer..write('Format is ')..write(wordSize * 8)..write(' bits');
     switch (endian) {
@@ -228,17 +252,18 @@
   }
 }
 
+/// An entry in the [ProgramHeader] describing a memory segment loaded into
+/// memory and used during runtime.
 class ProgramHeaderEntry {
-  Reader reader;
-
-  int type;
-  int flags;
-  int offset;
-  int vaddr;
-  int paddr;
-  int filesz;
-  int memsz;
-  int align;
+  final int type;
+  final int flags;
+  final int offset;
+  final int vaddr;
+  final int paddr;
+  final int filesz;
+  final int memsz;
+  final int align;
+  final int wordSize;
 
   // p_type constants from ELF specification.
   static const _PT_NULL = 0;
@@ -246,26 +271,27 @@
   static const _PT_DYNAMIC = 2;
   static const _PT_PHDR = 6;
 
-  ProgramHeaderEntry.fromReader(this.reader) {
-    assert(reader.wordSize == 4 || reader.wordSize == 8);
-    _read();
-  }
+  ProgramHeaderEntry._(this.type, this.flags, this.offset, this.vaddr,
+      this.paddr, this.filesz, this.memsz, this.align, this.wordSize);
 
-  void _read() {
-    reader.reset();
-    type = _readElfWord(reader);
+  static ProgramHeaderEntry fromReader(Reader reader) {
+    assert(reader.wordSize == 4 || reader.wordSize == 8);
+    final type = _readElfWord(reader);
+    int flags;
     if (reader.wordSize == 8) {
       flags = _readElfWord(reader);
     }
-    offset = _readElfOffset(reader);
-    vaddr = _readElfAddress(reader);
-    paddr = _readElfAddress(reader);
-    filesz = _readElfNative(reader);
-    memsz = _readElfNative(reader);
+    final offset = _readElfOffset(reader);
+    final vaddr = _readElfAddress(reader);
+    final paddr = _readElfAddress(reader);
+    final filesz = _readElfNative(reader);
+    final memsz = _readElfNative(reader);
     if (reader.wordSize == 4) {
       flags = _readElfWord(reader);
     }
-    align = _readElfNative(reader);
+    final align = _readElfNative(reader);
+    return ProgramHeaderEntry._(type, flags, offset, vaddr, paddr, filesz,
+        memsz, align, reader.wordSize);
   }
 
   static const _typeStrings = <int, String>{
@@ -289,17 +315,17 @@
       ..write('Flags: 0x')
       ..writeln(paddedHex(flags, 4))
       ..write('Offset: 0x')
-      ..writeln(paddedHex(offset, reader.wordSize))
+      ..writeln(paddedHex(offset, wordSize))
       ..write('Virtual address: 0x')
-      ..writeln(paddedHex(vaddr, reader.wordSize))
+      ..writeln(paddedHex(vaddr, wordSize))
       ..write('Physical address: 0x')
-      ..writeln(paddedHex(paddr, reader.wordSize))
+      ..writeln(paddedHex(paddr, wordSize))
       ..write('Size in file: ')
       ..writeln(filesz)
       ..write('Size in memory')
       ..writeln(memsz)
       ..write('Alignment: 0x')
-      ..write(paddedHex(align, reader.wordSize));
+      ..write(paddedHex(align, wordSize));
   }
 
   String toString() {
@@ -309,28 +335,22 @@
   }
 }
 
+/// A list of [ProgramHeaderEntry]s describing the memory segments loaded at
+/// runtime when this file is used.
 class ProgramHeader {
-  final Reader reader;
-  final int entrySize;
-  final int entryCount;
+  final List<ProgramHeaderEntry> _entries;
 
-  List<ProgramHeaderEntry> _entries;
-
-  ProgramHeader.fromReader(this.reader, {this.entrySize, this.entryCount}) {
-    _read();
-  }
+  ProgramHeader._(this._entries);
 
   int get length => _entries.length;
   ProgramHeaderEntry operator [](int index) => _entries[index];
 
-  void _read() {
-    reader.reset();
-    _entries = <ProgramHeaderEntry>[];
-    for (var i = 0; i < entryCount; i++) {
-      final entry = ProgramHeaderEntry.fromReader(
-          reader.shrink(i * entrySize, entrySize));
-      _entries.add(entry);
-    }
+  static ProgramHeader fromReader(Reader reader, ElfHeader header) {
+    final programReader = reader.refocusedCopy(
+        header.programHeaderOffset, header.programHeaderSize);
+    final entries =
+        programReader.readRepeated(ProgramHeaderEntry.fromReader).toList();
+    return ProgramHeader._(entries);
   }
 
   void writeToStringBuffer(StringBuffer buffer) {
@@ -351,23 +371,47 @@
   }
 }
 
+/// An entry in the [SectionHeader] that describes a single [Section].
 class SectionHeaderEntry {
-  final Reader reader;
-
-  int nameIndex;
+  final int nameIndex;
+  final int type;
+  final int flags;
+  final int addr;
+  final int offset;
+  final int size;
+  final int link;
+  final int info;
+  final int addrAlign;
+  final int entrySize;
+  final int wordSize;
   String _cachedName;
-  int type;
-  int flags;
-  int addr;
-  int offset;
-  int size;
-  int link;
-  int info;
-  int addrAlign;
-  int entrySize;
 
-  SectionHeaderEntry.fromReader(this.reader) {
-    _read();
+  SectionHeaderEntry._(
+      this.nameIndex,
+      this.type,
+      this.flags,
+      this.addr,
+      this.offset,
+      this.size,
+      this.link,
+      this.info,
+      this.addrAlign,
+      this.entrySize,
+      this.wordSize);
+
+  static SectionHeaderEntry fromReader(Reader reader) {
+    final nameIndex = _readElfWord(reader);
+    final type = _readElfWord(reader);
+    final flags = _readElfNative(reader);
+    final addr = _readElfAddress(reader);
+    final offset = _readElfOffset(reader);
+    final size = _readElfNative(reader);
+    final link = _readElfWord(reader);
+    final info = _readElfWord(reader);
+    final addrAlign = _readElfNative(reader);
+    final entrySize = _readElfNative(reader);
+    return SectionHeaderEntry._(nameIndex, type, flags, addr, offset, size,
+        link, info, addrAlign, entrySize, reader.wordSize);
   }
 
   // sh_type constants from ELF specification.
@@ -380,20 +424,6 @@
   static const _SHT_NOBITS = 8;
   static const _SHT_DYNSYM = 11;
 
-  void _read() {
-    reader.reset();
-    nameIndex = _readElfWord(reader);
-    type = _readElfWord(reader);
-    flags = _readElfNative(reader);
-    addr = _readElfAddress(reader);
-    offset = _readElfOffset(reader);
-    size = _readElfNative(reader);
-    link = _readElfWord(reader);
-    info = _readElfWord(reader);
-    addrAlign = _readElfNative(reader);
-    entrySize = _readElfNative(reader);
-  }
-
   void setName(StringTable nameTable) {
     _cachedName = nameTable[nameIndex];
   }
@@ -434,11 +464,11 @@
       ..write('Type: ')
       ..writeln(_typeToString(type))
       ..write('Flags: 0x')
-      ..writeln(paddedHex(flags, reader.wordSize))
+      ..writeln(paddedHex(flags, wordSize))
       ..write('Address: 0x')
-      ..writeln(paddedHex(addr, reader.wordSize))
+      ..writeln(paddedHex(addr, wordSize))
       ..write('Offset: 0x')
-      ..writeln(paddedHex(offset, reader.wordSize))
+      ..writeln(paddedHex(offset, wordSize))
       ..write('Size: ')
       ..writeln(size)
       ..write('Link: ')
@@ -446,7 +476,7 @@
       ..write('Info: 0x')
       ..writeln(paddedHex(info, 4))
       ..write('Address alignment: 0x')
-      ..writeln(paddedHex(addrAlign, reader.wordSize))
+      ..writeln(paddedHex(addrAlign, wordSize))
       ..write('Entry size: ')
       ..write(entrySize);
   }
@@ -458,61 +488,30 @@
   }
 }
 
+/// A list of [SectionHeaderEntry]s describing the [Section]s in the ELF file.
 class SectionHeader {
-  final Reader reader;
-  final int entrySize;
-  final int entryCount;
-  final int stringsIndex;
+  final List<SectionHeaderEntry> entries;
 
-  List<SectionHeaderEntry> _entries;
-  StringTable nameTable;
+  SectionHeader._(this.entries);
 
-  SectionHeader.fromReader(this.reader,
-      {this.entrySize, this.entryCount, this.stringsIndex}) {
-    _read();
-  }
-
-  SectionHeaderEntry _readSectionHeaderEntry(int index) {
-    final ret = SectionHeaderEntry.fromReader(
-        reader.shrink(index * entrySize, entrySize));
-    if (nameTable != null) {
-      ret.setName(nameTable);
-    }
-    return ret;
-  }
-
-  void _read() {
-    reader.reset();
-    // Set up the section header string table first so we can use it
-    // for the other section header entries.
-    final nameTableEntry = _readSectionHeaderEntry(stringsIndex);
+  static SectionHeader fromReader(Reader reader, ElfHeader header) {
+    final headerReader = reader.refocusedCopy(
+        header.sectionHeaderOffset, header.sectionHeaderSize);
+    final entries =
+        headerReader.readRepeated(SectionHeaderEntry.fromReader).toList();
+    final nameTableEntry = entries[header.sectionHeaderStringsIndex];
     assert(nameTableEntry.type == SectionHeaderEntry._SHT_STRTAB);
-    nameTable = StringTable(nameTableEntry,
-        reader.refocus(nameTableEntry.offset, nameTableEntry.size));
-    nameTableEntry.setName(nameTable);
-
-    _entries = <SectionHeaderEntry>[];
-    for (var i = 0; i < entryCount; i++) {
-      // We don't need to reparse the shstrtab entry.
-      if (i == stringsIndex) {
-        _entries.add(nameTableEntry);
-      } else {
-        _entries.add(_readSectionHeaderEntry(i));
-      }
-    }
+    return SectionHeader._(entries);
   }
 
-  int get length => _entries.length;
-  SectionHeaderEntry operator [](int index) => _entries[index];
-
   void writeToStringBuffer(StringBuffer buffer) {
-    for (var i = 0; i < length; i++) {
+    for (var i = 0; i < entries.length; i++) {
       if (i != 0) buffer..writeln()..writeln();
       buffer
         ..write('Entry ')
         ..write(i)
         ..writeln(':');
-      _entries[i].writeToStringBuffer(buffer);
+      entries[i].writeToStringBuffer(buffer);
     }
   }
 
@@ -524,27 +523,39 @@
   }
 }
 
+/// A section in an ELF file.
+///
+/// Some sections correspond to segments from the [ProgramHeader] and contain
+/// the information that will be loaded into memory for that segment, whereas
+/// others include information, like debugging sections, that are not loaded
+/// at runtime.
+///
+/// Only some sections are currently parsed by the  ELF reader; most are left
+/// unparsed as they are not needed for DWARF address translation.
 class Section {
-  final Reader reader;
   final SectionHeaderEntry headerEntry;
 
-  Section(this.headerEntry, this.reader);
+  Section._(this.headerEntry);
 
-  factory Section.fromEntryAndReader(SectionHeaderEntry entry, Reader reader) {
+  static Section fromReader(Reader reader, SectionHeaderEntry entry) {
     switch (entry.type) {
       case SectionHeaderEntry._SHT_STRTAB:
-        return StringTable(entry, reader);
+        return StringTable.fromReader(reader, entry);
       case SectionHeaderEntry._SHT_SYMTAB:
-        return SymbolTable(entry, reader);
+        return SymbolTable.fromReader(reader, entry);
       case SectionHeaderEntry._SHT_DYNSYM:
-        return SymbolTable(entry, reader);
+        return SymbolTable.fromReader(reader, entry);
       default:
-        return Section(entry, reader);
+        return Section._(entry);
     }
   }
 
+  int get offset => headerEntry.offset;
   int get virtualAddress => headerEntry.addr;
-  int get length => reader.bdata.lengthInBytes;
+  int get length => headerEntry.size;
+
+  // Convenience function for preparing a reader to read a particular section.
+  Reader refocusedCopy(Reader reader) => reader.refocusedCopy(offset, length);
 
   void writeToStringBuffer(StringBuffer buffer) {
     buffer
@@ -557,19 +568,24 @@
 
   @override
   String toString() {
-    StringBuffer buffer;
+    final buffer = StringBuffer();
     writeToStringBuffer(buffer);
     return buffer.toString();
   }
 }
 
+/// A map from table offsets to strings, used to store names of ELF objects.
 class StringTable extends Section {
   final _entries;
 
-  StringTable(SectionHeaderEntry entry, Reader reader)
-      : _entries = Map<int, String>.fromEntries(
-            reader.readRepeated((r) => r.readNullTerminatedString())),
-        super(entry, reader);
+  StringTable._(entry, this._entries) : super._(entry);
+
+  static StringTable fromReader(Reader reader, SectionHeaderEntry entry) {
+    final sectionReader = reader.refocusedCopy(entry.offset, entry.size);
+    final entries = Map.fromEntries(sectionReader
+        .readRepeatedWithOffsets((r) => r.readNullTerminatedString()));
+    return StringTable._(entry, entries);
+  }
 
   String operator [](int index) => _entries[index];
   bool containsKey(int index) => _entries.containsKey(index);
@@ -608,6 +624,7 @@
   STV_PROTECTED,
 }
 
+/// A symbol in an ELF file, which names a portion of the virtual address space.
 class Symbol {
   final int nameIndex;
   final int info;
@@ -699,16 +716,20 @@
   }
 }
 
+/// A table of (static or dynamic) [Symbol]s.
 class SymbolTable extends Section {
   final List<Symbol> _entries;
-  final _nameCache = Map<String, Symbol>();
+  final _nameCache;
 
-  SymbolTable(SectionHeaderEntry entry, Reader reader)
-      : _entries = reader
-            .readRepeated(Symbol.fromReader)
-            .map((kv) => kv.value)
-            .toList(),
-        super(entry, reader);
+  SymbolTable._(SectionHeaderEntry entry, this._entries)
+      : _nameCache = {},
+        super._(entry);
+
+  static SymbolTable fromReader(Reader reader, SectionHeaderEntry entry) {
+    final sectionReader = reader.refocusedCopy(entry.offset, entry.size);
+    final entries = sectionReader.readRepeated(Symbol.fromReader).toList();
+    return SymbolTable._(entry, entries);
+  }
 
   void _cacheNames(StringTable stringTable) {
     _nameCache.clear();
@@ -719,6 +740,7 @@
   }
 
   Iterable<String> get keys => _nameCache.keys;
+  Iterable<Symbol> get values => _nameCache.values;
   Symbol operator [](String name) => _nameCache[name];
   bool containsKey(String name) => _nameCache.containsKey(name);
 
@@ -736,23 +758,16 @@
   }
 }
 
+/// Information parsed from an Executable and Linking Format (ELF) file.
 class Elf {
-  ElfHeader _header;
-  ProgramHeader _programHeader;
-  SectionHeader _sectionHeader;
-  Map<SectionHeaderEntry, Section> _sections;
+  final ElfHeader _header;
+  final ProgramHeader _programHeader;
+  final SectionHeader _sectionHeader;
+  final Map<SectionHeaderEntry, Section> _sections;
+  final Map<String, Set<Section>> _sectionsByName;
 
-  Elf._(this._header, this._programHeader, this._sectionHeader, this._sections);
-
-  /// Creates an [Elf] from the data pointed to by [reader].
-  ///
-  /// Returns null if the file does not start with the ELF magic number.
-  static Elf fromReader(Reader reader) {
-    final start = reader.offset;
-    if (!ElfHeader.startsWithMagicNumber(reader)) return null;
-    reader.seek(start, absolute: true);
-    return Elf._read(reader);
-  }
+  Elf._(this._header, this._programHeader, this._sectionHeader, this._sections,
+      this._sectionsByName);
 
   /// Creates an [Elf] from [bytes].
   ///
@@ -765,76 +780,73 @@
   /// Returns null if the file does not start with the ELF magic number.
   static Elf fromFile(String path) => Elf.fromReader(Reader.fromFile(path));
 
+  Iterable<Section> namedSections(String name) => _sectionsByName[name];
+
   /// 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")) {
-      if (dynsym.containsKey(name)) {
-        return dynsym[name];
-      }
+      if (dynsym.containsKey(name)) return dynsym[name];
     }
     return null;
   }
 
-  /// The [Section]s whose names match [name].
-  Iterable<Section> namedSections(String name) {
-    return _sections.keys
-        .where((entry) => entry.name == name)
-        .map((entry) => _sections[entry]);
-  }
-
   /// 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')) {
-      for (final name in table.keys) {
-        final symbol = table[name];
-        if (symbol.value <= address && address < (symbol.value + symbol.size)) {
-          return symbol;
-        }
+      for (final symbol in table.values) {
+        final start = symbol.value;
+        final end = start + symbol.size;
+        if (start <= address && address < end) return symbol;
       }
     }
     return null;
   }
 
-  static Elf _read(Reader startingReader) {
-    final header = ElfHeader.fromReader(startingReader.copy());
-    // Now use the word size and endianness information from the header.
-    final reader = Reader.fromTypedData(startingReader.bdata,
-        wordSize: header.wordSize, endian: header.endian);
-    final programHeader = ProgramHeader.fromReader(
-        reader.refocus(header.programHeaderOffset, header.programHeaderSize),
-        entrySize: header.programHeaderEntrySize,
-        entryCount: header.programHeaderCount);
-    final sectionHeader = SectionHeader.fromReader(
-        reader.refocus(header.sectionHeaderOffset, header.sectionHeaderSize),
-        entrySize: header.sectionHeaderEntrySize,
-        entryCount: header.sectionHeaderCount,
-        stringsIndex: header.sectionHeaderStringsIndex);
+  /// Creates an [Elf] from the data pointed to by [reader].
+  ///
+  /// After succesful completion, the [endian] and [wordSize] fields of the
+  /// reader are set to match the values read from the ELF header. The position
+  /// of the reader will be unchanged.
+  ///
+  /// Returns null if the file does not start with the ELF magic number.
+  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)
+    // has an internal offset of 0 so absolute offsets can be used directly.
+    final reader = Reader.fromTypedData(ByteData.sublistView(
+        elfReader.bdata, elfReader.bdata.offsetInBytes + elfReader.offset));
+    final header = ElfHeader.fromReader(reader);
+    // Only happens if the file didn't start with the expected magic number.
+    if (header == null) return null;
+    // At this point, the endianness and wordSize should have been set
+    // during ElfHeader.fromReader.
+    assert(reader.endian != null && reader.wordSize != null);
+    final programHeader = ProgramHeader.fromReader(reader, header);
+    final sectionHeader = SectionHeader.fromReader(reader, header);
     final sections = <SectionHeaderEntry, Section>{};
-    for (var i = 0; i < sectionHeader.length; i++) {
-      final entry = sectionHeader[i];
-      if (i == header.sectionHeaderStringsIndex) {
-        sections[entry] = sectionHeader.nameTable;
-        continue;
-      }
-      sections[entry] = Section.fromEntryAndReader(
-          entry, reader.refocus(entry.offset, entry.size));
+    for (var i = 0; i < sectionHeader.entries.length; i++) {
+      final entry = sectionHeader.entries[i];
+      sections[entry] = Section.fromReader(reader, entry);
+    }
+    // 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]];
+    final sectionsByName = <String, Set<Section>>{};
+    for (final entry in sectionHeader.entries) {
+      entry.setName(sectionHeaderStringTable);
+      sectionsByName.putIfAbsent(entry.name, () => {}).add(sections[entry]);
     }
     void _cacheSymbolNames(String stringTableTag, String symbolTableTag) {
-      final stringTables = <SectionHeaderEntry, StringTable>{};
-      final symbolTables = <SymbolTable>[];
-      for (final entry in sections.keys) {
-        if (entry.name == stringTableTag) {
-          stringTables[entry] = sections[entry];
-        } else if (entry.name == symbolTableTag) {
-          symbolTables.add(sections[entry]);
-        }
-      }
-      for (final symbolTable in symbolTables) {
+      final stringTables = Map.fromEntries(sectionsByName[stringTableTag]
+          .map((s) => MapEntry(s.headerEntry, s)));
+      for (final SymbolTable symbolTable in sectionsByName[symbolTableTag]) {
         final link = symbolTable.headerEntry.link;
-        final entry = sectionHeader[link];
+        final entry = sectionHeader.entries[link];
         if (!stringTables.containsKey(entry)) {
           throw FormatException(
               "String table not found at section header entry ${link}");
@@ -845,7 +857,11 @@
 
     _cacheSymbolNames('.strtab', '.symtab');
     _cacheSymbolNames('.dynstr', '.dynsym');
-    return Elf._(header, programHeader, sectionHeader, sections);
+    // Set the wordSize and endian of the original reader before returning.
+    elfReader.wordSize = reader.wordSize;
+    elfReader.endian = reader.endian;
+    return Elf._(
+        header, programHeader, sectionHeader, sections, sectionsByName);
   }
 
   void writeToStringBuffer(StringBuffer buffer) {
@@ -878,7 +894,7 @@
       ..writeln('                 Section information')
       ..writeln('-----------------------------------------------------')
       ..writeln();
-    for (final entry in _sections.keys) {
+    for (final entry in _sectionHeader.entries) {
       _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 8f6b637..21f6297 100644
--- a/pkg/native_stack_traces/lib/src/reader.dart
+++ b/pkg/native_stack_traces/lib/src/reader.dart
@@ -12,8 +12,10 @@
 
 class Reader {
   final ByteData bdata;
-  final Endian endian;
-  final int wordSize;
+  // 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;
 
   int _offset = 0;
 
@@ -24,25 +26,10 @@
             ByteData.view(data.buffer, data.offsetInBytes, data.lengthInBytes);
 
   Reader.fromFile(String path, {this.wordSize, this.endian})
-      // TODO(sstrickl): Once Dart > 2.7.1 has been released, rewrite
-      // ByteData.view(<x>.buffer) => ByteData.sublistView(<x>).
-      : bdata = ByteData.view(File(path).readAsBytesSync().buffer);
+      : bdata = ByteData.sublistView(File(path).readAsBytesSync());
 
-  Reader copy() =>
-      Reader.fromTypedData(bdata, wordSize: wordSize, endian: endian);
-
-  Reader shrink(int offset, [int size = -1]) {
-    if (size < 0) size = bdata.lengthInBytes - offset;
-    assert(offset >= 0 && offset < bdata.lengthInBytes);
-    assert(size >= 0 && (offset + size) <= bdata.lengthInBytes);
-    return Reader.fromTypedData(
-        ByteData.view(bdata.buffer, bdata.offsetInBytes + offset, size),
-        wordSize: wordSize,
-        endian: endian);
-  }
-
-  Reader refocus(int pos, [int size = -1]) {
-    if (size < 0) size = bdata.lengthInBytes - pos;
+  /// 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),
@@ -60,37 +47,33 @@
     _offset = newOffset;
   }
 
-  void reset() {
-    seek(0, absolute: true);
-  }
-
   int readBytes(int size, {bool signed = false}) {
-    assert(_offset + size < length);
-    int ret;
+    if (_offset + size > length) {
+      throw ArgumentError("attempt to read ${size} bytes with only "
+          "${length - _offset} bytes remaining in the reader");
+    }
+    final start = _offset;
+    _offset += size;
     switch (size) {
       case 1:
-        ret = signed ? bdata.getInt8(_offset) : bdata.getUint8(_offset);
-        break;
+        return signed ? bdata.getInt8(start) : bdata.getUint8(start);
       case 2:
-        ret = signed
-            ? bdata.getInt16(_offset, endian)
-            : bdata.getUint16(_offset, endian);
-        break;
+        return signed
+            ? bdata.getInt16(start, endian)
+            : bdata.getUint16(start, endian);
       case 4:
-        ret = signed
-            ? bdata.getInt32(_offset, endian)
-            : bdata.getUint32(_offset, endian);
+        return signed
+            ? bdata.getInt32(start, endian)
+            : bdata.getUint32(start, endian);
         break;
       case 8:
-        ret = signed
-            ? bdata.getInt64(_offset, endian)
-            : bdata.getUint64(_offset, endian);
-        break;
+        return signed
+            ? bdata.getInt64(start, endian)
+            : bdata.getUint64(start, endian);
       default:
+        _offset -= size;
         throw ArgumentError("invalid request to read $size bytes");
     }
-    _offset += size;
-    return ret;
   }
 
   int readByte({bool signed = false}) => readBytes(1, signed: signed);
@@ -123,13 +106,30 @@
     return ret;
   }
 
-  Iterable<MapEntry<int, S>> readRepeated<S>(
-      S Function(Reader) callback) sync* {
+  /// Repeatedly calls [callback] with this reader to retrieve items.
+  ///
+  /// The key of the returned [MapEntry]s are the offsets of the items. If
+  /// absolute is false, the offsets are from the reader position when
+  /// [readRepeated] was invoked, otherwise they are absolute offsets from
+  /// the start of the reader.
+  ///
+  /// 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,
+      {bool absolute = false}) sync* {
+    final start = offset;
     while (!done) {
-      yield MapEntry<int, S>(offset, callback(this));
+      final itemStart = offset;
+      final item = callback(this);
+      if (item == null) break;
+      yield MapEntry(absolute ? itemStart : itemStart - start, item);
     }
   }
 
+  Iterable<S> readRepeated<S>(S Function(Reader) callback) =>
+      readRepeatedWithOffsets(callback).map((kv) => kv.value);
+
   void writeCurrentReaderPosition(StringBuffer buffer,
       {int maxSize = 0, int bytesPerLine = 16}) {
     var baseData = ByteData.view(bdata.buffer, 0, bdata.buffer.lengthInBytes);
@@ -159,20 +159,28 @@
   String toString() {
     final buffer = StringBuffer();
     buffer
+      ..write("Word size: ")
+      ..write(wordSize)
+      ..writeln();
+    buffer
+      ..write("Endianness: ")
+      ..write(endian)
+      ..writeln();
+    buffer
       ..write("Start:  0x")
-      ..write(paddedHex(start, wordSize))
+      ..write(paddedHex(start, wordSize ?? 0))
       ..write(" (")
       ..write(start)
       ..writeln(")");
     buffer
       ..write("Offset: 0x")
-      ..write(paddedHex(offset, wordSize))
+      ..write(paddedHex(offset, wordSize ?? 0))
       ..write(" (")
       ..write(offset)
       ..writeln(")");
     buffer
       ..write("Length: 0x")
-      ..write(paddedHex(length, wordSize))
+      ..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 ad15e37..b0aa7df 100644
--- a/pkg/native_stack_traces/pubspec.yaml
+++ b/pkg/native_stack_traces/pubspec.yaml
@@ -1,6 +1,6 @@
 name: native_stack_traces
 description: Utilities for working with non-symbolic stack traces.
-version: 0.3.1
+version: 0.3.3
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/native_stack_traces
 
diff --git a/pkg/nnbd_migration/lib/fix_reason_target.dart b/pkg/nnbd_migration/lib/fix_reason_target.dart
new file mode 100644
index 0000000..d1c0caa
--- /dev/null
+++ b/pkg/nnbd_migration/lib/fix_reason_target.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.
+
+import 'package:analyzer/src/generated/utilities_general.dart';
+
+/// Data structure representing a part of a type.  When a fix has multiple
+/// reasons (due to a complex type having different nullabilities at different
+/// locations), this data structure allows us to tell which part of the type
+/// 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();
+
+  const FixReasonTarget._();
+
+  /// Gets a fix reason target representing the type's return type.
+  FixReasonTarget get returnType => _FixReasonTarget_ReturnType(this);
+
+  /// Returns a description of the fix reason target that's suitable for
+  /// appending to a description of a nullability trace.
+  ///
+  /// For example, `root.returnType.suffix` returns ` for return type`.  This
+  /// can be attached to a string like `nullability reason` to form
+  /// `nullability reason for return type`.
+  String get suffix => _describe('for');
+
+  /// Gets a fix reason target representing the type's yielded type.  This
+  /// represents the type argument of `Future` or `FutureOr`, or in the case
+  /// where `await` is applied to a non-future type, the type itself.
+  FixReasonTarget get yieldedType => _FixReasonTarget_YieldedType(this);
+
+  /// Gets a fix reason target representing one of the type's named parameters.
+  FixReasonTarget namedParameter(String name) =>
+      _FixReasonTarget_NamedParameter(this, name);
+
+  /// Gets a fix reason target representing one of the type's positional
+  /// parameters.
+  FixReasonTarget positionalParameter(int i) =>
+      _FixReasonTarget_PositionalParameter(this, i);
+
+  /// Gets a fix reason target representing one of the type's type arguments.
+  FixReasonTarget typeArgument(int i) => _FixReasonTarget_TypeArgument(this, i);
+
+  String _describe(String preposition);
+}
+
+/// Fix reason target representing a named parameter of a function type.
+class _FixReasonTarget_NamedParameter extends _FixReasonTarget_Part {
+  final String name;
+
+  _FixReasonTarget_NamedParameter(FixReasonTarget inner, this.name)
+      : super(inner);
+
+  @override
+  int get hashCode => JenkinsSmiHash.hash3(2, inner.hashCode, name.hashCode);
+
+  @override
+  bool operator ==(Object other) =>
+      other is _FixReasonTarget_NamedParameter &&
+      inner == other.inner &&
+      name == other.name;
+
+  @override
+  String _describe(String preposition) =>
+      ' $preposition parameter $name${inner._describe('of')}';
+}
+
+/// Fix reason target representing a type that forms part of a larger type (e.g.
+/// the `int` part of `List<int>`).
+abstract class _FixReasonTarget_Part extends FixReasonTarget {
+  final FixReasonTarget inner;
+
+  _FixReasonTarget_Part(this.inner) : super._();
+}
+
+/// Fix reason target representing a positional parameter of a function type.
+class _FixReasonTarget_PositionalParameter extends _FixReasonTarget_Part {
+  final int index;
+
+  _FixReasonTarget_PositionalParameter(FixReasonTarget inner, this.index)
+      : super(inner);
+
+  @override
+  int get hashCode => JenkinsSmiHash.hash3(1, inner.hashCode, index);
+
+  @override
+  bool operator ==(Object other) =>
+      other is _FixReasonTarget_PositionalParameter &&
+      inner == other.inner &&
+      index == other.index;
+
+  @override
+  String _describe(String preposition) =>
+      ' $preposition parameter $index${inner._describe('of')}';
+}
+
+/// Fix reason target representing the return type of a function type.
+class _FixReasonTarget_ReturnType extends _FixReasonTarget_Part {
+  _FixReasonTarget_ReturnType(FixReasonTarget inner) : super(inner);
+
+  @override
+  int get hashCode => JenkinsSmiHash.hash2(3, inner.hashCode);
+
+  @override
+  bool operator ==(Object other) =>
+      other is _FixReasonTarget_ReturnType && inner == other.inner;
+
+  @override
+  String _describe(String preposition) =>
+      ' $preposition return type${inner._describe('of')}';
+}
+
+/// Fix reason target representing the root of the type in question.
+class _FixReasonTarget_Root extends FixReasonTarget {
+  const _FixReasonTarget_Root() : super._();
+
+  @override
+  int get hashCode => 0;
+
+  @override
+  bool operator ==(Object other) => other is _FixReasonTarget_Root;
+
+  @override
+  String _describe(String preposition) => '';
+}
+
+/// Fix reason target representing a type argument of an interface type.
+class _FixReasonTarget_TypeArgument extends _FixReasonTarget_Part {
+  final int index;
+
+  _FixReasonTarget_TypeArgument(FixReasonTarget inner, this.index)
+      : super(inner);
+
+  @override
+  int get hashCode => JenkinsSmiHash.hash3(5, inner.hashCode, index);
+
+  @override
+  bool operator ==(Object other) =>
+      other is _FixReasonTarget_TypeArgument &&
+      inner == other.inner &&
+      index == other.index;
+
+  @override
+  String _describe(String preposition) =>
+      ' $preposition type argument $index${inner._describe('of')}';
+}
+
+/// Fix reason target representing the type argument of `Future` or `FutureOr`,
+/// or in the case where `await` is applied to a non-future type, the type
+/// itself.
+///
+/// This allows the migration tool to describe a type correspondence that exists
+/// in a subtype check involving `FutureOr`, for example if the user tries to
+/// assign `List<int?>` to `FutureOr<List<int*>>`, then the migration tool
+/// determines that it needs to change `*` into `?`.  To make this determination
+/// it has to form a correspondence between the type argument of the source type
+/// and the type argument of the type argument of the destination type.  To
+/// explain to the user which part of the two types is involved in the
+/// correspondence, we need an ambiguous way of referring to either "type
+/// argument of type argument of" or simply "type argument".  The solution is to
+/// describe the fix reason target as "type argument of yielded type".
+class _FixReasonTarget_YieldedType extends _FixReasonTarget_Part {
+  _FixReasonTarget_YieldedType(FixReasonTarget inner) : super(inner);
+
+  @override
+  int get hashCode => JenkinsSmiHash.hash2(4, inner.hashCode);
+
+  @override
+  bool operator ==(Object other) =>
+      other is _FixReasonTarget_YieldedType && inner == other.inner;
+
+  @override
+  String _describe(String preposition) =>
+      ' $preposition yielded type${inner._describe('from')}';
+}
diff --git a/pkg/nnbd_migration/lib/isolate_server.dart b/pkg/nnbd_migration/lib/isolate_server.dart
new file mode 100644
index 0000000..c4ecfa2
--- /dev/null
+++ b/pkg/nnbd_migration/lib/isolate_server.dart
@@ -0,0 +1,164 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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 library implements [ServerBase], except unlike analysis_server_client's
+/// `Server`, [Server] runs the analysis server in an isolate.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:isolate';
+
+import 'package:analysis_server/starter.dart';
+import 'package:analysis_server_client/listener/server_listener.dart';
+import 'package:analysis_server_client/src/server_base.dart';
+import 'package:analysis_server_client/protocol.dart';
+import 'package:stream_channel/isolate_channel.dart';
+
+/// Wrap server arguments and communication port into a single parameter
+/// for [Isolate.spawn].
+class _IsolateParameters {
+  final List<String> arguments;
+  final SendPort sendPort;
+
+  _IsolateParameters(this.arguments, this.sendPort);
+}
+
+/// Manage an analysis_server launched in an isolate.
+class Server extends ServerBase {
+  /// Server isolate object, or `null` if server hasn't been started yet
+  /// or if the server has already been stopped.
+  Isolate _isolate;
+
+  /// The [ReceivePort] data subscription via an [IsolateChannel], or `null`
+  /// if either [listenToOutput] has not been called or [stop] has been called.
+  StreamSubscription<String> _receiveSubscription;
+
+  /// Construct a Server.
+  ///
+  /// [isolate] and [isolateChannel] are testing-only parameters, allowing
+  /// you to bypass start().
+  Server(
+      {ServerListener listener,
+      Isolate isolate,
+      IsolateChannel isolateChannel,
+      bool stdioPassthrough = false})
+      : _isolate = isolate,
+        _isolateChannel = isolateChannel,
+        super(listener: listener, stdioPassthrough: stdioPassthrough);
+
+  /// Completes when the [_isolate] has exited.
+  Completer isolateExited = Completer();
+
+  /// The [IsolateChannel] by which this class communicates with the [_isolate].
+  IsolateChannel _isolateChannel;
+
+  /// Force kill the server.  The returned future completes when the isolate
+  /// is dead.
+  Future<void> kill({String reason = 'none'}) {
+    listener?.killingServerProcess(reason);
+    final isolate = _isolate;
+    final isolateExitedOriginal = isolateExited;
+    _isolate = null;
+    isolateExited = null;
+    isolate.kill(priority: Isolate.immediate);
+    return isolateExitedOriginal.future;
+  }
+
+  /// Start listening to output from the server,
+  /// and deliver notifications to [notificationProcessor].
+  void listenToOutput({NotificationProcessor notificationProcessor}) {
+    _receiveSubscription = _isolateChannel.stream
+        .transform(utf8.decoder)
+        .transform(LineSplitter())
+        .listen((line) => outputProcessor(line, notificationProcessor));
+  }
+
+  /// Send a command to the server. An 'id' will be automatically assigned.
+  /// The returned [Future] will be completed when the server acknowledges
+  /// the command with a response.
+  /// If the server acknowledges the command with a normal (non-error) response,
+  /// the future will be completed with the 'result' field from the response.
+  /// If the server acknowledges the command with an error response,
+  /// the future will be completed with an error.
+  Future<Map<String, dynamic>> send(
+          String method, Map<String, dynamic> params) =>
+      sendCommandWith(method, params, _isolateChannel.sink.add);
+
+  /// Start the server in a new [Isolate].
+  Future start({
+    String clientId,
+    String clientVersion,
+    int diagnosticPort,
+    String instrumentationLogFile,
+    String sdkPath,
+    bool suppressAnalytics = true,
+    bool useAnalysisHighlight2 = false,
+  }) async {
+    if (_isolate != null) {
+      throw Exception('Isolate already started');
+    }
+
+    // Even though this is an isolate, most of the analysis server code
+    // can't tell the difference.  So we construct "command line" arguments
+    // just the same as analysis_server_client.
+    List<String> arguments = [];
+    arguments.addAll(getServerArguments(
+        clientId: clientId,
+        clientVersion: clientVersion,
+        suppressAnalytics: suppressAnalytics,
+        diagnosticPort: diagnosticPort,
+        instrumentationLogFile: instrumentationLogFile,
+        sdkPath: sdkPath,
+        useAnalysisHighlight2: useAnalysisHighlight2));
+
+    listener?.startingServer('((isolate))', arguments);
+    ReceivePort receivePort = ReceivePort();
+    ReceivePort onExitReceivePort = ReceivePort();
+    ReceivePort onErrorReceivePort = ReceivePort();
+    onExitReceivePort.listen((_) {
+      isolateExited.complete(0);
+    });
+    onErrorReceivePort.listen((_) {
+      listener?.unexpectedStop(null);
+    });
+    _isolateChannel = IsolateChannel<List<int>>.connectReceive(receivePort);
+    _isolate = await Isolate.spawn(
+        _runIsolate, _IsolateParameters(arguments, receivePort.sendPort),
+        onExit: onExitReceivePort.sendPort);
+  }
+
+  /// This is the function passed to [Isolate.spawn] to actually begin
+  /// the server.
+  static void _runIsolate(_IsolateParameters parameters) {
+    ServerStarter starter = ServerStarter();
+    // TODO(jcollins-g): consider a refactor that does not require passing
+    // text arguments to start the server.
+    starter.start(parameters.arguments, parameters.sendPort);
+  }
+
+  /// Attempt to gracefully shutdown the server.
+  /// If that fails, then kill the isolate.
+  Future<void> stop({Duration timeLimit}) async {
+    timeLimit ??= const Duration(seconds: 5);
+    if (_isolate == null) {
+      // isolate already exited
+      return;
+    }
+    final future = send(SERVER_REQUEST_SHUTDOWN, null);
+    final isolate = _isolate;
+    _isolate = null;
+    await future
+        // fall through to wait for exit
+        .timeout(timeLimit, onTimeout: () {
+      return null;
+    }).whenComplete(() async {
+      await _receiveSubscription?.cancel();
+      _receiveSubscription = null;
+    });
+    return isolateExited.future.timeout(timeLimit, onTimeout: () {
+      listener?.killingServerProcess('server failed to exit');
+      isolate.kill(priority: Isolate.immediate);
+    });
+  }
+}
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index 677c7fa..d32b605 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -21,27 +21,37 @@
     appliedMessage:
         'Discarded a condition which is always false, and the "then" branch '
         'that follows',
-    kind: NullabilityFixKind.discardThen,
+    kind: NullabilityFixKind.removeDeadCode,
   );
 
   /// An if-test or conditional expression needs to have its condition
   /// discarded.
   static const discardCondition = const NullabilityFixDescription._(
     appliedMessage: 'Discarded a condition which is always true',
-    kind: NullabilityFixKind.discardCondition,
+    kind: NullabilityFixKind.removeDeadCode,
   );
 
   /// An if-test or conditional expression needs to have its condition and
   /// "else" branch discarded.
   static const discardElse = const NullabilityFixDescription._(
     appliedMessage: 'Discarded an unreachable conditional else branch',
-    kind: NullabilityFixKind.discardElse,
+    kind: NullabilityFixKind.removeDeadCode,
   );
 
   /// An if-test needs to be discarded completely.
   static const discardIf = const NullabilityFixDescription._(
     appliedMessage: 'Discarded an if-test with no effect',
-    kind: NullabilityFixKind.discardIf,
+    kind: NullabilityFixKind.removeDeadCode,
+  );
+
+  static const downcastExpression = const NullabilityFixDescription._(
+    appliedMessage: 'Added a downcast to an expression',
+    kind: NullabilityFixKind.downcastExpression,
+  );
+
+  static const otherCastExpression = const NullabilityFixDescription._(
+    appliedMessage: 'Added a cast to an expression (non-downcast)',
+    kind: NullabilityFixKind.otherCastExpression,
   );
 
   /// An expression's value needs to be null-checked.
@@ -50,6 +60,12 @@
     kind: NullabilityFixKind.checkExpression,
   );
 
+  /// An expression's value will be null-checked due to a hint.
+  static const checkExpressionDueToHint = const NullabilityFixDescription._(
+    appliedMessage: 'Accepted a null check hint',
+    kind: NullabilityFixKind.checkExpressionDueToHint,
+  );
+
   /// An unnecessary downcast has been discarded.
   static const removeLanguageVersionComment = const NullabilityFixDescription._(
     appliedMessage: 'Removed language version comment so that NNBD features '
@@ -68,7 +84,7 @@
   static const removeNullAwareness = const NullabilityFixDescription._(
       appliedMessage:
           'Changed a null-aware access into an ordinary access, because the target cannot be null',
-      kind: NullabilityFixKind.removeNullAwareness);
+      kind: NullabilityFixKind.removeDeadCode);
 
   /// A message used to indicate a fix has been applied.
   final String appliedMessage;
@@ -85,6 +101,13 @@
         kind: NullabilityFixKind.addRequired,
       );
 
+  /// An explicit type needs to be added.
+  factory NullabilityFixDescription.addType(String typeText) =>
+      NullabilityFixDescription._(
+        appliedMessage: "Add the explicit type '$typeText'",
+        kind: NullabilityFixKind.replaceVar,
+      );
+
   /// An explicit type mentioned in the source program needs to be made
   /// nullable.
   factory NullabilityFixDescription.makeTypeNullable(String type) =>
@@ -93,6 +116,22 @@
         kind: NullabilityFixKind.makeTypeNullable,
       );
 
+  /// An explicit type mentioned in the source program will be made
+  /// nullable due to a nullability hint.
+  factory NullabilityFixDescription.makeTypeNullableDueToHint(String type) =>
+      NullabilityFixDescription._(
+        appliedMessage:
+            "Changed type '$type' to be nullable, due to a nullability hint",
+        kind: NullabilityFixKind.makeTypeNullableDueToHint,
+      );
+
+  /// A 'var' declaration needs to be replaced with an explicit type.
+  factory NullabilityFixDescription.replaceVar(String typeText) =>
+      NullabilityFixDescription._(
+        appliedMessage: "Replace 'var' with '$typeText'",
+        kind: NullabilityFixKind.replaceVar,
+      );
+
   /// An explicit type mentioned in the source program does not need to be made
   /// nullable.
   factory NullabilityFixDescription.typeNotMadeNullable(String type) =>
@@ -101,6 +140,14 @@
         kind: NullabilityFixKind.typeNotMadeNullable,
       );
 
+  /// An explicit type mentioned in the source program does not need to be made
+  /// nullable.
+  factory NullabilityFixDescription.typeNotMadeNullableDueToHint(String type) =>
+      NullabilityFixDescription._(
+        appliedMessage: "Type '$type' was not made nullable due to a hint",
+        kind: NullabilityFixKind.typeNotMadeNullableDueToHint,
+      );
+
   const NullabilityFixDescription._(
       {@required this.appliedMessage, @required this.kind});
 
@@ -127,15 +174,18 @@
 enum NullabilityFixKind {
   addRequired,
   checkExpression,
-  discardCondition,
-  discardElse,
-  discardIf,
-  discardThen,
+  checkExpressionDueToHint,
+  downcastExpression,
+  addType,
   makeTypeNullable,
+  makeTypeNullableDueToHint,
+  otherCastExpression,
   removeAs,
+  removeDeadCode,
   removeLanguageVersionComment,
-  removeNullAwareness,
+  replaceVar,
   typeNotMadeNullable,
+  typeNotMadeNullableDueToHint,
 }
 
 /// Provisional API for DartFix to perform nullability migration.
diff --git a/pkg/nnbd_migration/lib/src/conditional_discard.dart b/pkg/nnbd_migration/lib/src/conditional_discard.dart
index ab4c7c8..abecbd5 100644
--- a/pkg/nnbd_migration/lib/src/conditional_discard.dart
+++ b/pkg/nnbd_migration/lib/src/conditional_discard.dart
@@ -53,8 +53,5 @@
   /// to `true` is reachable after migration.
   bool get keepTrue => trueGuard == null || trueGuard.isNullable;
 
-  Iterable<FixReasonInfo> get reasons sync* {
-    if (!keepTrue) yield trueGuard;
-    if (!keepFalse) yield falseGuard;
-  }
+  FixReasonInfo get reason => !keepTrue ? trueGuard : falseGuard;
 }
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index bba1dd7..6111ba3 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/conditional_discard.dart';
@@ -66,13 +67,13 @@
       {@required DecoratedType source,
       @required DecoratedType destination,
       @required bool hard}) {
-    super._checkAssignment(origin,
+    super._checkAssignment(origin, FixReasonTarget.root,
         source: source, destination: destination, hard: hard);
   }
 
   @override
-  void _connect(
-      NullabilityNode source, NullabilityNode destination, EdgeOrigin origin,
+  void _connect(NullabilityNode source, NullabilityNode destination,
+      EdgeOrigin origin, FixReasonTarget edgeTarget,
       {bool hard = false, bool checkable = true}) {
     _graph.connect(source, destination, origin,
         hard: hard, checkable: checkable);
@@ -207,6 +208,8 @@
 
   final Set<PromotableElement> _lateHintedLocals = {};
 
+  Map<Token, NullabilityComment> _nullCheckHints = {};
+
   EdgeBuilder(this.typeProvider, this._typeSystem, this._variables, this._graph,
       this.source, this.listener, this._decoratedClassHierarchy,
       {this.instrumentation})
@@ -279,7 +282,7 @@
         node, _typeSystem as TypeSystemImpl)) {
       _variables.recordUnnecessaryCast(source, node);
     }
-    node.type.accept(this);
+    _dispatch(node.type);
     final typeNode = _variables.decoratedTypeAnnotation(source, node.type);
     _handleAssignment(node.expression, destinationType: typeNode);
     _flowAnalysis.asExpression_end(node.expression, typeNode);
@@ -298,7 +301,7 @@
       }
     }
     _flowAnalysis.assert_afterCondition(node.condition);
-    node.message?.accept(this);
+    _dispatch(node.message);
     _flowAnalysis.assert_end();
     return null;
   }
@@ -315,7 +318,7 @@
       }
     }
     _flowAnalysis.assert_afterCondition(node.condition);
-    node.message?.accept(this);
+    _dispatch(node.message);
     _flowAnalysis.assert_end();
     return null;
   }
@@ -344,7 +347,7 @@
 
   @override
   DecoratedType visitAwaitExpression(AwaitExpression node) {
-    var expressionType = node.expression.accept(this);
+    var expressionType = _dispatch(node.expression);
     // TODO(paulberry) Handle subclasses of Future.
     if (expressionType.type.isDartAsyncFuture ||
         expressionType.type.isDartAsyncFutureOr) {
@@ -359,9 +362,9 @@
     var leftOperand = node.leftOperand;
     var rightOperand = node.rightOperand;
     if (operatorType == TokenType.EQ_EQ || operatorType == TokenType.BANG_EQ) {
-      var leftType = leftOperand.accept(this);
+      var leftType = _dispatch(leftOperand);
       _flowAnalysis.equalityOp_rightBegin(leftOperand);
-      var rightType = rightOperand.accept(this);
+      var rightType = _dispatch(rightOperand);
       bool notEqual = operatorType == TokenType.BANG_EQ;
       _flowAnalysis.equalityOp_end(node, rightOperand, notEqual: notEqual);
 
@@ -399,20 +402,20 @@
       return _makeNonNullableBoolType(node);
     } else if (operatorType == TokenType.QUESTION_QUESTION) {
       DecoratedType expressionType;
-      var leftType = leftOperand.accept(this);
+      var leftType = _dispatch(leftOperand);
       _flowAnalysis.ifNullExpression_rightBegin(node.leftOperand);
       try {
         _guards.add(leftType.node);
         DecoratedType rightType;
         _postDominatedLocals.doScoped(action: () {
-          rightType = rightOperand.accept(this);
+          rightType = _dispatch(rightOperand);
         });
         var ifNullNode = NullabilityNode.forIfNotNull(node);
         expressionType = _decorateUpperOrLowerBound(
             node, node.staticType, leftType, rightType, true,
             node: ifNullNode);
-        _connect(
-            rightType.node, expressionType.node, IfNullOrigin(source, node));
+        _connect(rightType.node, expressionType.node,
+            IfNullOrigin(source, node), null);
       } finally {
         _flowAnalysis.ifNullExpression_end();
         _guards.removeLast();
@@ -423,7 +426,7 @@
       var targetType = _checkExpressionNotNull(leftOperand);
       var callee = node.staticElement;
       if (callee == null) {
-        rightOperand.accept(this);
+        _dispatch(rightOperand);
         return _makeNullableDynamicType(node);
       } else {
         var calleeType =
@@ -435,8 +438,8 @@
       }
     } else {
       // TODO(paulberry)
-      leftOperand.accept(this);
-      rightOperand.accept(this);
+      _dispatch(leftOperand);
+      _dispatch(rightOperand);
       _unimplemented(
           node, 'Binary expression with operator ${node.operator.lexeme}');
     }
@@ -465,7 +468,7 @@
     var oldCascadeTargetType = _currentCascadeTargetType;
     try {
       _currentCascadeTargetType = _checkExpressionNotNull(node.target);
-      node.cascadeSections.accept(this);
+      _dispatchList(node.cascadeSections);
       return _currentCascadeTargetType;
     } finally {
       _currentCascadeTargetType = oldCascadeTargetType;
@@ -477,10 +480,10 @@
     _flowAnalysis.tryCatchStatement_catchBegin(
         node.exceptionParameter?.staticElement as PromotableElement,
         node.stackTraceParameter?.staticElement as PromotableElement);
-    node.exceptionType?.accept(this);
+    _dispatch(node.exceptionType);
     // The catch clause may not execute, so create a new scope for
     // post-dominators.
-    _postDominatedLocals.doScoped(action: () => node.body.accept(this));
+    _postDominatedLocals.doScoped(action: () => _dispatch(node.body));
     _flowAnalysis.tryCatchStatement_catchEnd();
     return null;
   }
@@ -488,10 +491,10 @@
   @override
   DecoratedType visitClassDeclaration(ClassDeclaration node) {
     visitClassOrMixinOrExtensionDeclaration(node);
-    node.extendsClause?.accept(this);
-    node.implementsClause?.accept(this);
-    node.withClause?.accept(this);
-    node.typeParameters?.accept(this);
+    _dispatch(node.extendsClause);
+    _dispatch(node.implementsClause);
+    _dispatch(node.withClause);
+    _dispatch(node.typeParameters);
     return null;
   }
 
@@ -519,8 +522,8 @@
               true) {
         _handleUninitializedFields(node, _fieldsNotInitializedAtDeclaration);
       }
-      node.metadata.accept(this);
-      members.accept(this);
+      _dispatchList(node.metadata);
+      _dispatchList(members);
       _fieldsNotInitializedAtDeclaration = null;
     } finally {
       _currentClassOrExtension = null;
@@ -530,9 +533,9 @@
 
   @override
   DecoratedType visitClassTypeAlias(ClassTypeAlias node) {
-    node.superclass.accept(this);
-    node.implementsClause?.accept(this);
-    node.withClause?.accept(this);
+    _dispatch(node.superclass);
+    _dispatch(node.implementsClause);
+    _dispatch(node.withClause);
     var classElement = node.declaredElement;
     var supertype = classElement.supertype;
     var superElement = supertype.element;
@@ -575,9 +578,9 @@
     // define variables.
     _postDominatedLocals.doScoped(action: () {
       _flowAnalysis.conditional_thenBegin(node.condition);
-      thenType = node.thenExpression.accept(this);
+      thenType = _dispatch(node.thenExpression);
       _flowAnalysis.conditional_elseBegin(node.thenExpression);
-      elseType = node.elseExpression.accept(this);
+      elseType = _dispatch(node.elseExpression);
       _flowAnalysis.conditional_end(node, node.elseExpression);
     });
 
@@ -591,7 +594,7 @@
   DecoratedType visitConstructorDeclaration(ConstructorDeclaration node) {
     _fieldsNotInitializedByConstructor =
         _fieldsNotInitializedAtDeclaration.toSet();
-    node.redirectedConstructor?.type?.typeArguments?.accept(this);
+    _dispatch(node.redirectedConstructor?.type?.typeArguments);
     _handleExecutableDeclaration(
         node,
         node.declaredElement,
@@ -628,7 +631,7 @@
 
   @override
   DecoratedType visitDefaultFormalParameter(DefaultFormalParameter node) {
-    node.parameter.accept(this);
+    _dispatch(node.parameter);
     var defaultValue = node.defaultValue;
     if (defaultValue == null) {
       if (node.declaredElement.hasRequired) {
@@ -649,7 +652,7 @@
   @override
   DecoratedType visitDoStatement(DoStatement node) {
     _flowAnalysis.doStatement_bodyBegin(node);
-    node.body.accept(this);
+    _dispatch(node.body);
     _flowAnalysis.doStatement_conditionBegin();
     _checkExpressionNotNull(node.condition);
     _flowAnalysis.doStatement_end(node.condition);
@@ -677,14 +680,14 @@
 
   DecoratedType visitExtensionDeclaration(ExtensionDeclaration node) {
     visitClassOrMixinOrExtensionDeclaration(node);
-    node.extendedType.accept(this);
+    _dispatch(node.extendedType);
     return null;
   }
 
   @override
   DecoratedType visitFieldFormalParameter(FieldFormalParameter node) {
-    node.metadata.accept(this);
-    node.parameters?.accept(this);
+    _dispatchList(node.metadata);
+    _dispatch(node.parameters);
     var parameterElement = node.declaredElement as FieldFormalParameterElement;
     var parameterType = _variables.decoratedElementType(parameterElement);
     var field = parameterElement.field;
@@ -694,8 +697,8 @@
     if (node.type == null) {
       _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
     } else {
-      node.type.accept(this);
-      _checkAssignment(origin,
+      _dispatch(node.type);
+      _checkAssignment(origin, FixReasonTarget.root,
           source: parameterType, destination: fieldType, hard: true);
     }
 
@@ -712,24 +715,24 @@
   @override
   DecoratedType visitForStatement(ForStatement node) {
     _handleForLoopParts(
-        node, node.forLoopParts, node.body, (body) => body.accept(this));
+        node, node.forLoopParts, node.body, (body) => _dispatch(body));
     return null;
   }
 
   @override
   DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
-    node.metadata.accept(this);
-    node.returnType?.accept(this);
+    _dispatchList(node.metadata);
+    _dispatch(node.returnType);
     if (_flowAnalysis != null) {
       // This is a local function.
       _flowAnalysis.functionExpression_begin(node);
-      node.functionExpression.accept(this);
+      _dispatch(node.functionExpression);
       _flowAnalysis.functionExpression_end();
     } else {
       _createFlowAnalysis(node, node.functionExpression.parameters);
       // Initialize a new postDominator scope that contains only the parameters.
       try {
-        node.functionExpression.accept(this);
+        _dispatch(node.functionExpression);
         _flowAnalysis.finish();
       } finally {
         _flowAnalysis = null;
@@ -742,8 +745,8 @@
   @override
   DecoratedType visitFunctionExpression(FunctionExpression node) {
     // TODO(mfairhurst): enable edge builder "_insideFunction" hard edge tests.
-    node.parameters?.accept(this);
-    node.typeParameters?.accept(this);
+    _dispatch(node.parameters);
+    _dispatch(node.typeParameters);
     if (node.parent is! FunctionDeclaration) {
       _flowAnalysis.functionExpression_begin(node);
     }
@@ -754,7 +757,7 @@
     try {
       _postDominatedLocals.doScoped(
           elements: node.declaredElement.parameters,
-          action: () => node.body.accept(this));
+          action: () => _dispatch(node.body));
       return _currentFunctionType;
     } finally {
       if (node.parent is! FunctionDeclaration) {
@@ -769,7 +772,7 @@
       FunctionExpressionInvocation node) {
     final argumentList = node.argumentList;
     final typeArguments = node.typeArguments;
-    typeArguments?.accept(this);
+    _dispatch(typeArguments);
     DecoratedType calleeType = _checkExpressionNotNull(node.function);
     DecoratedType result;
     if (calleeType.type is FunctionType) {
@@ -778,10 +781,10 @@
           invokeType: node.staticInvokeType);
     } else {
       // Invocation of type `dynamic` or `Function`.
-      argumentList.accept(this);
+      _dispatch(argumentList);
       result = _makeNullableDynamicType(node);
     }
-    return _handleNullCheckHint(node, result);
+    return result;
   }
 
   @override
@@ -840,7 +843,7 @@
       _flowAnalysis.ifStatement_thenBegin(node.condition);
       // We branched, so create a new scope for post-dominators.
       _postDominatedLocals.doScoped(
-          action: () => node.thenStatement.accept(this));
+          action: () => _dispatch(node.thenStatement));
     } finally {
       if (trueGuard != null) {
         _guards.removeLast();
@@ -855,7 +858,7 @@
         _flowAnalysis.ifStatement_elseBegin();
         // We branched, so create a new scope for post-dominators.
         _postDominatedLocals.doScoped(
-            action: () => node.elseStatement?.accept(this));
+            action: () => _dispatch(node.elseStatement));
       }
     } finally {
       _flowAnalysis.ifStatement_end(elseStatement != null);
@@ -893,7 +896,7 @@
         result = calleeType.returnType;
       }
     }
-    return _handleNullCheckHint(node, result);
+    return result;
   }
 
   @override
@@ -908,7 +911,7 @@
     var target =
         NullabilityNodeTarget.text('constructed type').withCodeRef(node);
     if (typeArguments != null) {
-      typeArguments.accept(this);
+      _dispatch(typeArguments);
       typeArgumentTypes = typeArguments.arguments.map((t) => t.type);
       decoratedTypeArguments = typeArguments.arguments
           .map((t) => _variables.decoratedTypeAnnotation(source, t))
@@ -951,6 +954,7 @@
     var calleeType = getOrComputeElementType(callee, targetType: createdType);
     for (var i = 0; i < decoratedTypeArguments.length; ++i) {
       _checkAssignment(parameterEdgeOrigins?.elementAt(i),
+          FixReasonTarget.root.typeArgument(i),
           source: decoratedTypeArguments[i],
           destination:
               _variables.decoratedTypeParameterBound(typeParameters[i]),
@@ -969,7 +973,7 @@
   @override
   DecoratedType visitIsExpression(IsExpression node) {
     var type = node.type;
-    type.accept(this);
+    _dispatch(type);
     var decoratedType = _variables.decoratedTypeAnnotation(source, type);
     if (type is NamedType) {
       // The main type of the is check historically could not be nullable.
@@ -986,7 +990,7 @@
       _unimplemented(node, 'Is expression with GenericFunctionType');
     }
     var expression = node.expression;
-    expression.accept(this);
+    _dispatch(expression);
     _flowAnalysis.isExpression_end(
         node, expression, node.notOperator != null, decoratedType);
     return _makeNonNullableBoolType(node);
@@ -1002,7 +1006,7 @@
   @override
   DecoratedType visitLibraryDirective(LibraryDirective node) {
     // skip directives, but not their metadata
-    node.metadata.accept(this);
+    _dispatchList(node.metadata);
     return null;
   }
 
@@ -1019,7 +1023,7 @@
         instrumentation?.implicitTypeArguments(source, node, [elementType]);
         _currentLiteralElementType = elementType;
       } else {
-        node.typeArguments.accept(this);
+        _dispatch(node.typeArguments);
         _currentLiteralElementType = _variables.decoratedTypeAnnotation(
             source, node.typeArguments.arguments[0]);
       }
@@ -1044,7 +1048,7 @@
   DecoratedType visitMethodDeclaration(MethodDeclaration node) {
     _handleExecutableDeclaration(node, node.declaredElement, node.metadata,
         node.returnType, node.parameters, null, node.body, null);
-    node.typeParameters?.accept(this);
+    _dispatch(node.typeParameters);
     return null;
   }
 
@@ -1055,7 +1059,7 @@
     bool isNullAware = node.isNullAware;
     var callee = node.methodName.staticElement;
     bool calleeIsStatic = callee is ExecutableElement && callee.isStatic;
-    node.typeArguments?.accept(this);
+    _dispatch(node.typeArguments);
 
     if (node.isCascaded) {
       targetType = _currentCascadeTargetType;
@@ -1063,9 +1067,9 @@
       if (_isPrefix(target)) {
         // Nothing to do.
       } else if (calleeIsStatic) {
-        target.accept(this);
+        _dispatch(target);
       } else if (isNullAware) {
-        targetType = target.accept(this);
+        targetType = _dispatch(target);
       } else {
         targetType = _handleTarget(target, node.methodName.name, callee);
       }
@@ -1077,7 +1081,7 @@
       // Dynamic dispatch.  The return type is `dynamic`.
       // TODO(paulberry): would it be better to assume a return type of `Never`
       // so that we don't unnecessarily propagate nullabilities everywhere?
-      node.argumentList.accept(this);
+      _dispatch(node.argumentList);
       expressionType = _makeNullableDynamicType(node);
     } else {
       var calleeType = getOrComputeElementType(callee, targetType: targetType);
@@ -1098,22 +1102,32 @@
         _variables.recordDecoratedExpressionType(node, expressionType);
       }
     }
-    return _handleNullCheckHint(node, expressionType);
+    return expressionType;
   }
 
   @override
   DecoratedType visitMixinDeclaration(MixinDeclaration node) {
     visitClassOrMixinOrExtensionDeclaration(node);
-    node.implementsClause?.accept(this);
-    node.onClause?.accept(this);
-    node.typeParameters?.accept(this);
+    _dispatch(node.implementsClause);
+    _dispatch(node.onClause);
+    _dispatch(node.typeParameters);
     return null;
   }
 
   @override
   DecoratedType visitNamespaceDirective(NamespaceDirective node) {
     // skip directives, but not their metadata
-    node.metadata.accept(this);
+    _dispatchList(node.metadata);
+    return null;
+  }
+
+  @override
+  DecoratedType visitNode(AstNode node) {
+    for (var child in node.childEntities) {
+      if (child is AstNode) {
+        _dispatch(child);
+      }
+    }
     return null;
   }
 
@@ -1129,15 +1143,15 @@
 
   @override
   DecoratedType visitParenthesizedExpression(ParenthesizedExpression node) {
-    var result = node.expression.accept(this);
+    var result = _dispatch(node.expression);
     _flowAnalysis.parenthesizedExpression(node, node.expression);
-    return _handleNullCheckHint(node, result);
+    return result;
   }
 
   @override
   DecoratedType visitPartOfDirective(PartOfDirective node) {
     // skip directives, but not their metadata
-    node.metadata.accept(this);
+    _dispatchList(node.metadata);
     return null;
   }
 
@@ -1176,9 +1190,8 @@
       // TODO(paulberry)
       _unimplemented(node, 'PrefixedIdentifier with a prefix');
     } else {
-      var type = _handlePropertyAccess(
+      return _handlePropertyAccess(
           node, node.prefix, node.identifier, false, false);
-      return _handleNullCheckHint(node, type);
     }
   }
 
@@ -1223,9 +1236,8 @@
 
   @override
   DecoratedType visitPropertyAccess(PropertyAccess node) {
-    var type = _handlePropertyAccess(node, node.target, node.propertyName,
+    return _handlePropertyAccess(node, node.target, node.propertyName,
         node.isNullAware, node.isCascaded);
-    return _handleNullCheckHint(node, type);
   }
 
   @override
@@ -1260,7 +1272,7 @@
           typeProvider, typeProvider.nullType, _graph, target);
       var origin = ImplicitNullReturnOrigin(source, node);
       _graph.makeNullable(implicitNullType.node, origin);
-      _checkAssignment(origin,
+      _checkAssignment(origin, FixReasonTarget.root,
           source:
               isAsync ? _futureOf(implicitNullType, node) : implicitNullType,
           destination: returnType,
@@ -1297,7 +1309,7 @@
           _currentLiteralElementType = elementType;
         } else {
           assert(typeArguments.length == 1);
-          node.typeArguments.accept(this);
+          _dispatch(node.typeArguments);
           _currentLiteralElementType =
               _variables.decoratedTypeAnnotation(source, typeArguments[0]);
         }
@@ -1329,7 +1341,7 @@
               ?.implicitTypeArguments(source, node, [keyType, valueType]);
         } else {
           assert(typeArguments.length == 2);
-          node.typeArguments.accept(this);
+          _dispatch(node.typeArguments);
           _currentMapKeyType =
               _variables.decoratedTypeAnnotation(source, typeArguments[0]);
           _currentMapValueType =
@@ -1393,7 +1405,7 @@
       _unimplemented(node,
           'Simple identifier with a static element of type ${staticElement.runtimeType}');
     }
-    return _handleNullCheckHint(node, result);
+    return result;
   }
 
   @override
@@ -1479,18 +1491,18 @@
 
   @override
   DecoratedType visitSwitchStatement(SwitchStatement node) {
-    node.expression.accept(this);
+    _dispatch(node.expression);
     _flowAnalysis.switchStatement_expressionEnd(node);
     var hasDefault = false;
     for (var member in node.members) {
       var hasLabel = member.labels.isNotEmpty;
       _flowAnalysis.switchStatement_beginCase(hasLabel, node);
       if (member is SwitchCase) {
-        member.expression.accept(this);
+        _dispatch(member.expression);
       } else {
         hasDefault = true;
       }
-      member.statements.accept(this);
+      _dispatchList(member.statements);
     }
     _flowAnalysis.switchStatement_end(hasDefault);
     return null;
@@ -1503,13 +1515,12 @@
 
   @override
   DecoratedType visitThisExpression(ThisExpression node) {
-    var type = _thisOrSuper(node);
-    return _handleNullCheckHint(node, type);
+    return _thisOrSuper(node);
   }
 
   @override
   DecoratedType visitThrowExpression(ThrowExpression node) {
-    node.expression.accept(this);
+    _dispatch(node.expression);
     // TODO(paulberry): do we need to check the expression type?  I think not.
     _flowAnalysis.handleExit();
     var target =
@@ -1530,16 +1541,16 @@
       _flowAnalysis.tryCatchStatement_bodyBegin();
     }
     var body = node.body;
-    body.accept(this);
+    _dispatch(body);
     if (catchClauses.isNotEmpty) {
       _flowAnalysis.tryCatchStatement_bodyEnd(body);
-      catchClauses.accept(this);
+      _dispatchList(catchClauses);
       _flowAnalysis.tryCatchStatement_end();
     }
     if (finallyBlock != null) {
       _flowAnalysis.tryFinallyStatement_finallyBegin(
           catchClauses.isNotEmpty ? node : body);
-      finallyBlock.accept(this);
+      _dispatch(finallyBlock);
       _flowAnalysis.tryFinallyStatement_end(finallyBlock);
     }
     return null;
@@ -1606,6 +1617,7 @@
             }
             _checkAssignment(
                 TypeParameterInstantiationOrigin(source, typeArguments[i]),
+                FixReasonTarget.root,
                 source: argumentType,
                 destination: bound,
                 hard: true);
@@ -1626,10 +1638,10 @@
     var parent = node.parent;
     bool isTopLevel =
         parent is FieldDeclaration || parent is TopLevelVariableDeclaration;
-    node.metadata.accept(this);
-    node.type?.accept(this);
+    _dispatchList(node.metadata);
+    _dispatch(node.type);
     for (var variable in node.variables) {
-      variable.metadata.accept(this);
+      _dispatchList(variable.metadata);
       var initializer = variable.initializer;
       var declaredElement = variable.declaredElement;
       if (isTopLevel) {
@@ -1716,7 +1728,7 @@
     _flowAnalysis.whileStatement_conditionBegin(node);
     _checkExpressionNotNull(node.condition);
     _flowAnalysis.whileStatement_bodyBegin(node, node.condition);
-    _postDominatedLocals.doScoped(action: () => node.body.accept(this));
+    _postDominatedLocals.doScoped(action: () => _dispatch(node.body));
     _flowAnalysis.whileStatement_end();
     return null;
   }
@@ -1738,7 +1750,7 @@
     if (_isPrefix(expression)) {
       throw ArgumentError('cannot check non-nullability of a prefix');
     }
-    sourceType ??= expression.accept(this);
+    sourceType ??= _dispatch(expression);
     if (sourceType == null) {
       throw StateError('No type computed for ${expression.runtimeType} '
           '(${expression.toSource()}) offset=${expression.offset}');
@@ -1748,19 +1760,19 @@
         hard: _postDominatedLocals.isReferenceInScope(expression),
         guards: _guards);
     if (origin is ExpressionChecksOrigin) {
-      origin.checks.edges.add(edge);
+      origin.checks.edges[FixReasonTarget.root] = edge;
     }
     return sourceType;
   }
 
   @override
-  void _connect(
-      NullabilityNode source, NullabilityNode destination, EdgeOrigin origin,
+  void _connect(NullabilityNode source, NullabilityNode destination,
+      EdgeOrigin origin, FixReasonTarget edgeTarget,
       {bool hard = false, bool checkable = true}) {
     var edge = _graph.connect(source, destination, origin,
         hard: hard, checkable: checkable, guards: _guards);
     if (origin is ExpressionChecksOrigin) {
-      origin.checks.edges.add(edge);
+      origin.checks.edges[edgeTarget] = edge;
     }
   }
 
@@ -1950,6 +1962,21 @@
     _unimplemented(astNode, '_decorateUpperOrLowerBound');
   }
 
+  DecoratedType _dispatch(AstNode node, {bool skipNullCheckHint = false}) {
+    var type = node?.accept(this);
+    if (!skipNullCheckHint && node is Expression) {
+      type = _handleNullCheckHint(node, type);
+    }
+    return type;
+  }
+
+  void _dispatchList(NodeList nodeList) {
+    if (nodeList == null) return;
+    for (var node in nodeList) {
+      _dispatch(node);
+    }
+  }
+
   DecoratedType _fixNumericTypes(
       DecoratedType decoratedType, DartType undecoratedType) {
     if (decoratedType.type.isDartCoreNum && undecoratedType.isDartCoreInt) {
@@ -2009,7 +2036,7 @@
       if (destinationLocalVariable != null) {
         destinationType = getOrComputeElementType(destinationLocalVariable);
       } else {
-        destinationType = destinationExpression.accept(this);
+        destinationType = _dispatch(destinationExpression);
       }
     }
 
@@ -2020,7 +2047,7 @@
     }
     DecoratedType sourceType;
     try {
-      sourceType = expression.accept(this);
+      sourceType = _dispatch(expression);
       if (wrapFuture) {
         sourceType = _wrapFuture(sourceType, expression);
       }
@@ -2034,6 +2061,7 @@
         if (compoundOperatorMethod != null) {
           _checkAssignment(
               CompoundAssignmentOrigin(source, compoundOperatorInfo),
+              FixReasonTarget.root,
               source: destinationType,
               destination: _createNonNullableType(compoundOperatorInfo),
               hard: _postDominatedLocals
@@ -2042,7 +2070,7 @@
               compoundOperatorMethod,
               targetType: destinationType);
           assert(compoundOperatorType.positionalParameters.length > 0);
-          _checkAssignment(edgeOrigin,
+          _checkAssignment(edgeOrigin, FixReasonTarget.root,
               source: sourceType,
               destination: compoundOperatorType.positionalParameters[0],
               hard: _postDominatedLocals.isReferenceInScope(expression),
@@ -2051,6 +2079,7 @@
               compoundOperatorType.returnType, compoundOperatorInfo.staticType);
           _checkAssignment(
               CompoundAssignmentOrigin(source, compoundOperatorInfo),
+              FixReasonTarget.root,
               source: sourceType,
               destination: destinationType,
               hard: false);
@@ -2058,7 +2087,7 @@
           sourceType = _makeNullableDynamicType(compoundOperatorInfo);
         }
       } else {
-        _checkAssignment(edgeOrigin,
+        _checkAssignment(edgeOrigin, FixReasonTarget.root,
             source: sourceType,
             destination: destinationType,
             hard: questionAssignNode == null &&
@@ -2093,7 +2122,7 @@
       return _handleAssignment(element,
           destinationType: _currentLiteralElementType);
     } else {
-      return element.accept(this);
+      return _dispatch(element);
     }
   }
 
@@ -2124,22 +2153,22 @@
       FunctionBody body,
       ConstructorName redirectedConstructor) {
     assert(_currentFunctionType == null);
-    metadata.accept(this);
-    returnType?.accept(this);
+    _dispatchList(metadata);
+    _dispatch(returnType);
     _createFlowAnalysis(node, parameters);
-    parameters?.accept(this);
+    _dispatch(parameters);
     _currentFunctionType = _variables.decoratedElementType(declaredElement);
     _addParametersToFlowAnalysis(parameters);
     // Push a scope of post-dominated declarations on the stack.
     _postDominatedLocals.pushScope(elements: declaredElement.parameters);
     try {
-      initializers?.accept(this);
+      _dispatchList(initializers);
       if (declaredElement is ConstructorElement &&
           !declaredElement.isFactory &&
           declaredElement.redirectedConstructor == null) {
         _handleUninitializedFields(node, _fieldsNotInitializedByConstructor);
       }
-      body.accept(this);
+      _dispatch(body);
       if (redirectedConstructor != null) {
         _handleConstructorRedirection(parameters, redirectedConstructor);
       }
@@ -2185,7 +2214,8 @@
       var overriddenFieldType =
           decoratedOverriddenField.substitute(substitution);
       if (method.isGetter) {
-        _checkAssignment(ReturnTypeInheritanceOrigin(source, node),
+        _checkAssignment(
+            ReturnTypeInheritanceOrigin(source, node), FixReasonTarget.root,
             source: _currentFunctionType.returnType,
             destination: overriddenFieldType,
             hard: true);
@@ -2194,7 +2224,8 @@
         DecoratedType currentParameterType =
             _currentFunctionType.positionalParameters.single;
         DecoratedType overriddenParameterType = overriddenFieldType;
-        _checkAssignment(ParameterInheritanceOrigin(source, node),
+        _checkAssignment(
+            ParameterInheritanceOrigin(source, node), FixReasonTarget.root,
             source: overriddenParameterType,
             destination: currentParameterType,
             hard: true);
@@ -2209,9 +2240,10 @@
             _currentFunctionType.returnType,
             overriddenFunctionType.returnType,
             ReturnTypeInheritanceOrigin(source, node),
-            isUnion: true);
+            isUnion: false);
       } else {
-        _checkAssignment(ReturnTypeInheritanceOrigin(source, node),
+        _checkAssignment(
+            ReturnTypeInheritanceOrigin(source, node), FixReasonTarget.root,
             source: _currentFunctionType.returnType,
             destination: overriddenFunctionType.returnType,
             hard: true);
@@ -2250,9 +2282,9 @@
             if (_isUntypedParameter(normalParameter)) {
               _linkDecoratedTypes(
                   overriddenParameterType, currentParameterType, origin,
-                  isUnion: true);
+                  isUnion: false);
             } else {
-              _checkAssignment(origin,
+              _checkAssignment(origin, FixReasonTarget.root,
                   source: overriddenParameterType,
                   destination: currentParameterType,
                   hard: false,
@@ -2291,11 +2323,13 @@
       }
       var overriddenType = unsubstitutedOverriddenType.substitute(substitution);
       if (overriddenElement.isGetter) {
-        _checkAssignment(ReturnTypeInheritanceOrigin(source, node),
+        _checkAssignment(
+            ReturnTypeInheritanceOrigin(source, node), FixReasonTarget.root,
             source: type, destination: overriddenType, hard: true);
       } else {
         assert(overriddenElement.isSetter);
-        _checkAssignment(ParameterInheritanceOrigin(source, node),
+        _checkAssignment(
+            ParameterInheritanceOrigin(source, node), FixReasonTarget.root,
             source: overriddenType, destination: type, hard: true);
       }
     } else {
@@ -2307,9 +2341,9 @@
       DecoratedType Function(AstNode) bodyHandler) {
     if (parts is ForParts) {
       if (parts is ForPartsWithDeclarations) {
-        parts.variables?.accept(this);
+        _dispatch(parts.variables);
       } else if (parts is ForPartsWithExpression) {
-        parts.initialization?.accept(this);
+        _dispatch(parts.initialization);
       }
       _flowAnalysis.for_conditionBegin(node);
       if (parts.condition != null) {
@@ -2323,7 +2357,7 @@
         var variableElement = parts.loopVariable.declaredElement;
         _flowAnalysis.declare(variableElement, true);
         lhsElement = variableElement;
-        parts.loopVariable?.type?.accept(this);
+        _dispatch(parts.loopVariable?.type);
       } else if (parts is ForEachPartsWithIdentifier) {
         lhsElement = parts.identifier.staticElement;
       } else {
@@ -2341,7 +2375,8 @@
               .asInstanceOf(
                   iterableType, typeProvider.iterableDynamicType.element)
               .typeArguments[0];
-          _checkAssignment(ForEachVariableOrigin(source, parts),
+          _checkAssignment(
+              ForEachVariableOrigin(source, parts), FixReasonTarget.root,
               source: elementType, destination: lhsType, hard: false);
         }
       }
@@ -2358,7 +2393,7 @@
 
       if (parts is ForParts) {
         _flowAnalysis.for_updaterBegin();
-        parts.updaters.accept(this);
+        _dispatchList(parts.updaters);
         _flowAnalysis.for_end();
       } else {
         _flowAnalysis.forEach_end();
@@ -2371,7 +2406,8 @@
   DecoratedType _handleInstantiation(DecoratedType type,
       List<DecoratedType> argumentTypes, List<EdgeOrigin> edgeOrigins) {
     for (var i = 0; i < argumentTypes.length; ++i) {
-      _checkAssignment(edgeOrigins?.elementAt(i),
+      _checkAssignment(
+          edgeOrigins?.elementAt(i), FixReasonTarget.root.typeArgument(i),
           source: argumentTypes[i],
           destination: DecoratedTypeParameterBounds.current
               .get((type.type as FunctionType).typeFormals[i]),
@@ -2488,7 +2524,12 @@
     // `/*!*/`s because they're not expression null check hints, they're type
     // non-nullability hints (which are handled by NodeBuilder).
     if (_typeNameNesting > 0) return type;
-    switch (getPostfixHint(expression)) {
+    var token = expression.endToken;
+    if (_nullCheckHints.containsKey(token)) {
+      // Already visited this location.
+      return type;
+    }
+    switch (_nullCheckHints[token] = getPostfixHint(token)) {
       case NullabilityComment.bang:
         _variables.recordNullCheckHint(source, expression);
         return type.withNode(_graph.never);
@@ -2505,11 +2546,11 @@
     if (isCascaded) {
       targetType = _currentCascadeTargetType;
     } else if (_isPrefix(target)) {
-      return propertyName.accept(this);
+      return _dispatch(propertyName, skipNullCheckHint: true);
     } else if (calleeIsStatic) {
-      target.accept(this);
+      _dispatch(target);
     } else if (isNullAware) {
-      targetType = target.accept(this);
+      targetType = _dispatch(target);
     } else {
       targetType = _handleTarget(target, propertyName.name, callee);
     }
@@ -2539,7 +2580,7 @@
 
   DecoratedType _handleTarget(Expression target, String name, Element method) {
     if (isDeclaredOnObject(name)) {
-      return target.accept(this);
+      return _dispatch(target);
     } else if (method is MethodElement &&
         method.enclosingElement is ExtensionElement) {
       // Extension methods can be called on a `null` target, when the `on` type
@@ -2547,7 +2588,7 @@
       _handleAssignment(target,
           destinationType:
               _variables.decoratedElementType(method.enclosingElement));
-      return target.accept(this);
+      return _dispatch(target);
     } else {
       return _checkExpressionNotNull(target);
     }
@@ -2615,8 +2656,8 @@
     if (sourceType.type.isDynamic) {
       return DynamicAssignmentOrigin(source, expression);
     } else {
-      ExpressionChecksOrigin expressionChecksOrigin = ExpressionChecksOrigin(
-          source, expression, ExpressionChecks(expression.end));
+      ExpressionChecksOrigin expressionChecksOrigin =
+          ExpressionChecksOrigin(source, expression, ExpressionChecks());
       _variables.recordExpressionChecks(
           source, expression, expressionChecksOrigin);
       return expressionChecksOrigin;
@@ -2769,7 +2810,7 @@
   /// created.  [hard] indicates whether a hard edge should be created.
   /// [sourceIsFunctionLiteral] indicates whether the source of the assignment
   /// is a function literal expression.
-  void _checkAssignment(EdgeOrigin origin,
+  void _checkAssignment(EdgeOrigin origin, FixReasonTarget edgeTarget,
       {@required DecoratedType source,
       @required DecoratedType destination,
       @required bool hard,
@@ -2792,12 +2833,12 @@
           _assumeNonNullabilityInCasts,
           'side cast not supported without assuming non-nullability:'
           ' $sourceType to $destinationType');
-      _connect(source.node, destination.node, origin, hard: hard);
+      _connect(source.node, destination.node, origin, edgeTarget, hard: hard);
       return;
     }
-    _connect(source.node, destination.node, origin,
+    _connect(source.node, destination.node, origin, edgeTarget,
         hard: hard, checkable: checkable);
-    _checkAssignment_recursion(origin,
+    _checkAssignment_recursion(origin, edgeTarget,
         source: source,
         destination: destination,
         sourceIsFunctionLiteral: sourceIsFunctionLiteral);
@@ -2807,7 +2848,7 @@
   /// constituting [source] and [destination], and creating the appropriate
   /// edges between them.  [sourceIsFunctionLiteral] indicates whether the
   /// source of the assignment is a function literal expression.
-  void _checkAssignment_recursion(EdgeOrigin origin,
+  void _checkAssignment_recursion(EdgeOrigin origin, FixReasonTarget edgeTarget,
       {@required DecoratedType source,
       @required DecoratedType destination,
       bool sourceIsFunctionLiteral = false}) {
@@ -2851,7 +2892,8 @@
         // So the RHS of the "or" is redundant, and we can simplify to:
         // - S0 <: S1.
         var s0 = source.typeArguments[0];
-        _checkAssignment(origin, source: s0, destination: s1, hard: false);
+        _checkAssignment(origin, edgeTarget.yieldedType,
+            source: s0, destination: s1, hard: false);
         return;
       }
       // (From the subtyping spec):
@@ -2866,7 +2908,8 @@
       // - or T0 <: S1
       else if (_typeSystem.isSubtypeOf(sourceType, s1.type)) {
         // E.g. FutureOr<int> = (... as int)
-        _checkAssignment_recursion(origin, source: source, destination: s1);
+        _checkAssignment_recursion(origin, edgeTarget.yieldedType,
+            source: source, destination: s1);
         return;
       }
       // - or T0 is X0 and X0 has bound S0 and S0 <: T1
@@ -2891,7 +2934,7 @@
       } else {
         // Effectively this is an assignment from the type parameter's bound to
         // the destination type.
-        _checkAssignment(origin,
+        _checkAssignment(origin, edgeTarget,
             source: _getTypeParameterTypeBound(source),
             destination: destination,
             hard: false);
@@ -2910,7 +2953,7 @@
       assert(rewrittenSource.typeArguments.length ==
           destination.typeArguments.length);
       for (int i = 0; i < rewrittenSource.typeArguments.length; i++) {
-        _checkAssignment(origin,
+        _checkAssignment(origin, edgeTarget.typeArgument(i),
             source: rewrittenSource.typeArguments[i],
             destination: destination.typeArguments[i],
             hard: false,
@@ -2921,7 +2964,7 @@
       // function returning non-null is required, we will insure that the
       // function literal has a non-nullable return type (e.g. by inserting null
       // checks into the function literal).
-      _checkAssignment(origin,
+      _checkAssignment(origin, edgeTarget.returnType,
           source: source.returnType,
           destination: destination.returnType,
           hard: sourceIsFunctionLiteral,
@@ -2935,7 +2978,7 @@
               i < destination.positionalParameters.length;
           i++) {
         // Note: source and destination are swapped due to contravariance.
-        _checkAssignment(origin,
+        _checkAssignment(origin, edgeTarget.positionalParameter(i),
             source: destination.positionalParameters[i],
             destination: source.positionalParameters[i],
             hard: false,
@@ -2943,7 +2986,7 @@
       }
       for (var entry in destination.namedParameters.entries) {
         // Note: source and destination are swapped due to contravariance.
-        _checkAssignment(origin,
+        _checkAssignment(origin, edgeTarget.namedParameter(entry.key),
             source: entry.value,
             destination: source.namedParameters[entry.key],
             hard: false,
@@ -2966,7 +3009,8 @@
     var destinationType = destination.type;
     assert(_typeSystem.isSubtypeOf(destinationType, source.type));
     // Nullability should narrow to maintain subtype relationship.
-    _connect(source.node, destination.node, origin, hard: hard);
+    _connect(source.node, destination.node, origin, FixReasonTarget.root,
+        hard: hard);
 
     if (source.type.isDynamic ||
         source.type.isDartCoreObject ||
@@ -2984,7 +3028,7 @@
     } else if (destinationType is TypeParameterType) {
       if (source.type is! TypeParameterType) {
         // Assume an assignment to the type parameter's bound.
-        _checkAssignment(origin,
+        _checkAssignment(origin, FixReasonTarget.root,
             source: source,
             destination: _getTypeParameterTypeBound(destination),
             hard: false);
@@ -2996,6 +3040,7 @@
       if (destination.type.isDartAsyncFuture) {
         // FutureOr<T?> is nullable, so the Future<T> should be nullable too.
         _connect(source.typeArguments[0].node, destination.node, origin,
+            FixReasonTarget.root.yieldedType,
             hard: hard);
         _checkDowncast(origin,
             source: source.typeArguments[0],
@@ -3039,8 +3084,8 @@
     }
   }
 
-  void _connect(
-      NullabilityNode source, NullabilityNode destination, EdgeOrigin origin,
+  void _connect(NullabilityNode source, NullabilityNode destination,
+      EdgeOrigin origin, FixReasonTarget edgeTarget,
       {bool hard = false, bool checkable = true});
 
   /// Given a [type] representing a type parameter, retrieves the type's bound.
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index 00931b3..300dd76 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 
@@ -128,7 +129,7 @@
   final NullabilityFixDescription description;
 
   /// The reasons for the edit.
-  final List<FixReasonInfo> fixReasons;
+  final Map<FixReasonTarget, FixReasonInfo> fixReasons;
 
   AtomicEditInfo(this.description, this.fixReasons);
 }
@@ -500,16 +501,10 @@
   /// text.
   ///
   /// [parentNode] should be the innermost AST node containing [token].
-  EditPlan replaceToken(
-      AstNode parentNode, Token token, List<AtomicEdit> replacement,
+  EditPlan replaceToken(AstNode parentNode, Token token, String replacement,
       {AtomicEditInfo info}) {
-    assert(!replacement.any((edit) => !edit.isInsertion),
-        'All edits should be insertions');
     return _TokenChangePlan(parentNode, {
-      token.offset: [
-        AtomicEdit.delete(token.length, info: info),
-        ...replacement
-      ]
+      token.offset: [AtomicEdit.replace(token.length, replacement, info: info)]
     });
   }
 
@@ -554,10 +549,10 @@
     var innerChanges =
         innerPlan._getChanges(parensNeeded) ?? <int, List<AtomicEdit>>{};
     if (prefix != null) {
-      (innerChanges[innerPlan.sourceNode.offset] ??= []).insertAll(0, prefix);
+      (innerChanges[innerPlan.offset] ??= []).insertAll(0, prefix);
     }
     if (suffix != null) {
-      (innerChanges[innerPlan.sourceNode.end] ??= []).addAll(suffix);
+      (innerChanges[innerPlan.end] ??= []).addAll(suffix);
     }
     return _SimpleEditPlan(
         innerPlan.sourceNode,
@@ -715,11 +710,17 @@
 
   NodeProducingEditPlan._(this.sourceNode) : super._();
 
+  /// Offset just past the end of the source text affected by this plan.
+  int get end => sourceNode.end;
+
   /// If the result of executing this [EditPlan] will be an expression,
   /// indicates whether the expression will end in an unparenthesized cascade.
   @visibleForTesting
   bool get endsInCascade;
 
+  /// Offset of the start of the source text affected by this plan.
+  int get offset => sourceNode.offset;
+
   @override
   AstNode get parentNode => sourceNode.parent;
 
@@ -748,8 +749,8 @@
   Map<int, List<AtomicEdit>> _createAddParenChanges(
       Map<int, List<AtomicEdit>> changes) {
     changes ??= {};
-    (changes[sourceNode.offset] ??= []).insert(0, const AtomicEdit.insert('('));
-    (changes[sourceNode.end] ??= []).add(const AtomicEdit.insert(')'));
+    (changes[offset] ??= []).insert(0, const AtomicEdit.insert('('));
+    (changes[end] ??= []).add(const AtomicEdit.insert(')'));
     return changes;
   }
 
@@ -829,16 +830,16 @@
     // Extract the inner expression.
     // TODO(paulberry): don't remove comments
     changes = _removeCode(
-            sourceNode.offset,
-            innerPlan.sourceNode.offset,
+            offset,
+            innerPlan.offset,
             _planner.removeViaComments
                 ? _RemovalStyle.commentSpace
                 : _RemovalStyle.delete,
             _infoBefore) +
         changes +
         _removeCode(
-            innerPlan.sourceNode.end,
-            sourceNode.end,
+            innerPlan.end,
+            end,
             _planner.removeViaComments
                 ? _RemovalStyle.spaceComment
                 : _RemovalStyle.delete,
@@ -1203,6 +1204,9 @@
       }
     }
     changes += innerPlan._getChanges(parensNeeded);
+    // Note: we use innerPlan.sourceNode.end here instead of innerPlan.end,
+    // because what we care about is the input grammar, so we don't want to be
+    // fooled by any whitespace or comments included in the innerPlan.
     if (endsInCascade == null && innerPlan.sourceNode.end == node.end) {
       endsInCascade = !parensNeeded && innerPlan.endsInCascade;
     }
@@ -1415,8 +1419,8 @@
     var changes = innerPlan._getChanges(false);
     if (!parens) {
       changes ??= {};
-      (changes[sourceNode.offset] ??= []).insert(0, const AtomicEdit.delete(1));
-      (changes[sourceNode.end - 1] ??= []).add(const AtomicEdit.delete(1));
+      (changes[offset] ??= []).insert(0, const AtomicEdit.delete(1));
+      (changes[end - 1] ??= []).add(const AtomicEdit.delete(1));
     }
     return changes;
   }
diff --git a/pkg/nnbd_migration/lib/src/expression_checks.dart b/pkg/nnbd_migration/lib/src/expression_checks.dart
index 17d4459..5c281e4 100644
--- a/pkg/nnbd_migration/lib/src/expression_checks.dart
+++ b/pkg/nnbd_migration/lib/src/expression_checks.dart
@@ -4,12 +4,10 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
-import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/edge_origin.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
-import 'package:nnbd_migration/src/potential_modification.dart';
 
 /// Container for information gathered during nullability migration about the
 /// set of runtime checks that might need to be performed on the value of an
@@ -19,60 +17,11 @@
 /// based on the nullability of the type itself (which can be checked by adding
 /// a trailing `!`) from checks based on type parameters (which will have to be
 /// checked using an `as` expression).
-class ExpressionChecks extends PotentialModification {
-  /// Source offset where a trailing `!` might need to be inserted.
-  final int offset;
+class ExpressionChecks {
+  /// All nullability edges that are related to this potential check.
+  final Map<FixReasonTarget, NullabilityEdge> edges = {};
 
-  /// List of all nullability edges that are related to this potential check.
-  ///
-  /// TODO(paulberry): update this data structure to keep track of all the ways
-  /// in which edges can be related to an [ExpressionChecks], including:
-  ///
-  /// - An edge which, if unsatisfied, indicates that the expression needs to be
-  ///   null-checked.
-  /// - An edge which, if unsatisfied, indicates that a type parameter of the
-  ///   expression needs to be checked for nullability (e.g. by the migration
-  ///   engine inserting a test like `as List<int>?`)
-  /// - An edge which, if unsatisfied, indicates that a return type of the
-  ///   expression needs to be checked for nullability (e.g. by the migration
-  ///   engine inserting a test like `as int Function(...)?`)
-  /// - An edge which, if unsatisfied, indicates that a parameter type of the
-  ///   expression needs to be checked for nullability (e.g. by the migration
-  ///   engine inserting a test like `as void Function(int?)?`)
-  ///
-  /// ...and so on.
-  final List<NullabilityEdge> edges = [];
-
-  ExpressionChecks(this.offset);
-
-  @override
-  NullabilityFixDescription get description =>
-      NullabilityFixDescription.checkExpression;
-
-  @override
-  bool get isEmpty {
-    for (var edge in edges) {
-      if (!edge.isSatisfied) return false;
-    }
-    return true;
-  }
-
-  @override
-  Iterable<SourceEdit> get modifications {
-    // TODO(paulberry): this assumes that the check that needs to be done is for
-    // the nullability of the type itself (in which case all we need is a simple
-    // null check).  Need to support checks that will have to be addressed by
-    // adding an `as` expression, e.g. `as List<int>?` to verify that a list is
-    // reified to contain only non-null ints.
-    return isEmpty ? [] : [SourceEdit(offset, 0, '!')];
-  }
-
-  @override
-  Iterable<FixReasonInfo> get reasons sync* {
-    for (var edge in edges) {
-      if (!edge.isSatisfied) yield edge;
-    }
-  }
+  ExpressionChecks();
 }
 
 /// [EdgeOrigin] object associated with [ExpressionChecks].  This is a separate
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index 5a77827..bcf9379 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -9,6 +9,7 @@
 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:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
@@ -265,7 +266,7 @@
       return aggregator.planner.extract(node,
           aggregator.planForNode(node.expression) as NodeProducingEditPlan,
           infoAfter:
-              AtomicEditInfo(NullabilityFixDescription.removeAs, const []));
+              AtomicEditInfo(NullabilityFixDescription.removeAs, const {}));
     } else {
       return super._apply(node, aggregator);
     }
@@ -285,10 +286,10 @@
     if (removeLanguageVersionComment) {
       final comment = (node as CompilationUnitImpl).languageVersionToken;
       assert(comment != null);
-      innerPlans.add(aggregator.planner.replaceToken(node, comment, [],
+      innerPlans.add(aggregator.planner.replaceToken(node, comment, '',
           info: AtomicEditInfo(
               NullabilityFixDescription.removeLanguageVersionComment,
-              const [])));
+              const {})));
     }
     innerPlans.addAll(aggregator.innerPlansForNode(node));
     return aggregator.planner.passThrough(node, innerPlans: innerPlans);
@@ -304,9 +305,9 @@
   /// conditional is dead code and should be eliminated.
   bool conditionValue;
 
-  /// If [conditionValue] is not `null`, the reasons that should be included in
+  /// If [conditionValue] is not `null`, the reason that should be included in
   /// the [AtomicEditInfo] for the edit that removes the dead code.
-  List<FixReasonInfo> conditionReasons;
+  FixReasonInfo conditionReason;
 
   /// If dead code removal is warranted for [node], returns an [EditPlan] that
   /// removes the dead code (and performs appropriate updates within any
@@ -333,8 +334,8 @@
         nodeToKeep is Block && nodeToKeep.statements.isEmpty) {
       // The conditional node collapses to a no-op, so try to remove it
       // entirely.
-      var info =
-          AtomicEditInfo(NullabilityFixDescription.discardIf, conditionReasons);
+      var info = AtomicEditInfo(NullabilityFixDescription.discardIf,
+          {FixReasonTarget.root: conditionReason});
       var removeNode = aggregator.planner.tryRemoveNode(node, info: info);
       if (removeNode != null) {
         return removeNode;
@@ -357,8 +358,10 @@
         }
       }
     }
-    var infoBefore = AtomicEditInfo(descriptionBefore, conditionReasons);
-    var infoAfter = AtomicEditInfo(descriptionAfter, conditionReasons);
+    var infoBefore = AtomicEditInfo(
+        descriptionBefore, {FixReasonTarget.root: conditionReason});
+    var infoAfter = AtomicEditInfo(
+        descriptionAfter, {FixReasonTarget.root: conditionReason});
     if (nodeToKeep is Block && nodeToKeep.statements.length == 1) {
       var singleStatement = (nodeToKeep as Block).statements[0];
       if (singleStatement is VariableDeclarationStatement) {
@@ -428,6 +431,13 @@
   /// Indicates whether [addNullCheck] has been called.
   bool get addsNullCheck => _addsNullCheck;
 
+  /// Gets the info for any introduced "as" cast
+  AtomicEditInfo get introducesAsInfo => _introduceAsInfo;
+
+  /// Gets the type for any introduced "as" cast, or `null` if no "as" cast is
+  /// being introduced.
+  DartType get introducesAsType => _introducesAsType;
+
   /// Causes a null check to be added to this expression, with the given [info].
   void addNullCheck(AtomicEditInfo info) {
     assert(!_addsNullCheck);
@@ -536,8 +546,8 @@
   EditPlan _applyNullAware(N node, FixAggregator aggregator) {
     if (!removeNullAwareness) return null;
     return aggregator.planner.removeNullAwareness(node,
-        info:
-            AtomicEditInfo(NullabilityFixDescription.removeNullAwareness, []));
+        info: AtomicEditInfo(
+            NullabilityFixDescription.removeNullAwareness, const {}));
   }
 }
 
@@ -587,37 +597,61 @@
 /// Implementation of [NodeChange] specialized for operating on [TypeAnnotation]
 /// nodes.
 class NodeChangeForTypeAnnotation extends NodeChange<TypeAnnotation> {
-  /// Indicates whether the type should be made nullable by adding a `?`.
-  bool makeNullable = false;
+  bool _makeNullable = false;
+
+  bool _nullabilityDueToHint = false;
 
   /// The decorated type of the type annotation, or `null` if there is no
   /// decorated type info of interest.  If [makeNullable] is `true`, the node
   /// from this type will be attached to the edit that adds the `?`. If
-  /// [makeNullable] is `false`, the node from this type will be attached to the
+  /// [_makeNullable] is `false`, the node from this type will be attached to the
   /// information about why the node wasn't made nullable.
-  DecoratedType decoratedType;
+  DecoratedType _decoratedType;
 
   NodeChangeForTypeAnnotation() : super._();
 
   @override
-  bool get isInformative => !makeNullable;
+  bool get isInformative => !_makeNullable;
+
+  /// Indicates whether the type should be made nullable by adding a `?`.
+  bool get makeNullable => _makeNullable;
+
+  /// Indicates whether we are making the type nullable due to a hint.
+  bool get makeNullableDueToHint => _nullabilityDueToHint;
+
+  void recordNullability(DecoratedType decoratedType, bool makeNullable,
+      {bool nullabilityDueToHint: false}) {
+    _decoratedType = decoratedType;
+    _makeNullable = makeNullable;
+    _nullabilityDueToHint = nullabilityDueToHint;
+  }
 
   @override
   EditPlan _apply(TypeAnnotation node, FixAggregator aggregator) {
     var innerPlan = aggregator.innerPlanForNode(node);
-    if (decoratedType == null) return innerPlan;
-    if (makeNullable) {
+    if (_decoratedType == null) return innerPlan;
+    var typeName = _decoratedType.type.getDisplayString(withNullability: false);
+    var fixReasons = {FixReasonTarget.root: _decoratedType.node};
+    if (_makeNullable) {
+      NullabilityFixDescription description;
+      if (_nullabilityDueToHint) {
+        description =
+            NullabilityFixDescription.makeTypeNullableDueToHint(typeName);
+      } else {
+        description = NullabilityFixDescription.makeTypeNullable(typeName);
+      }
       return aggregator.planner.makeNullable(innerPlan,
-          info: AtomicEditInfo(
-              NullabilityFixDescription.makeTypeNullable(
-                  decoratedType.type.getDisplayString(withNullability: false)),
-              [decoratedType.node]));
+          info: AtomicEditInfo(description, fixReasons));
     } else {
+      NullabilityFixDescription description;
+      if (_nullabilityDueToHint) {
+        description =
+            NullabilityFixDescription.typeNotMadeNullableDueToHint(typeName);
+      } else {
+        description = NullabilityFixDescription.typeNotMadeNullable(typeName);
+      }
       return aggregator.planner.explainNonNullable(innerPlan,
-          info: AtomicEditInfo(
-              NullabilityFixDescription.typeNotMadeNullable(
-                  decoratedType.type.getDisplayString(withNullability: false)),
-              [decoratedType.node]));
+          info: AtomicEditInfo(description, fixReasons));
     }
   }
 }
@@ -648,13 +682,17 @@
     if (addExplicitType != null) {
       var typeText = addExplicitType.getDisplayString(withNullability: true);
       if (node.keyword?.keyword == Keyword.VAR) {
+        var info =
+            AtomicEditInfo(NullabilityFixDescription.replaceVar(typeText), {});
         innerPlans.add(aggregator.planner
-            .replaceToken(node, node.keyword, [AtomicEdit.insert(typeText)]));
+            .replaceToken(node, node.keyword, typeText, info: info));
       } else {
+        var info =
+            AtomicEditInfo(NullabilityFixDescription.addType(typeText), {});
         innerPlans.add(aggregator.planner.insertText(
             node,
             node.variables.first.offset,
-            [AtomicEdit.insert(typeText), AtomicEdit.insert(' ')]));
+            [AtomicEdit.insert(typeText, info: info), AtomicEdit.insert(' ')]));
       }
     }
     innerPlans.addAll(aggregator.innerPlansForNode(node));
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index ae684e3..087a8ae 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -25,6 +25,7 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
@@ -301,7 +302,7 @@
           var conditionValue = conditionalDiscard.keepTrue;
           (_fixBuilder._getChange(node) as NodeChangeForConditional)
             ..conditionValue = conditionValue
-            ..conditionReasons = conditionalDiscard.reasons.toList();
+            ..conditionReason = conditionalDiscard.reason;
           return conditionValue;
         }
       });
@@ -399,8 +400,11 @@
       _wrapExceptions(node, () => type, () {
         if (_fixBuilder._variables.hasNullCheckHint(_fixBuilder.source, node)) {
           type = _addNullCheck(node, type,
-              info: AtomicEditInfo(NullabilityFixDescription.checkExpression,
-                  [FixReason_NullCheckHint(CodeReference.fromAstNode(node))]));
+              info: AtomicEditInfo(
+                  NullabilityFixDescription.checkExpressionDueToHint, {
+                FixReasonTarget.root:
+                    FixReason_NullCheckHint(CodeReference.fromAstNode(node))
+              }));
         }
         if (type.isDynamic) return type;
         var ancestor = _findNullabilityContextAncestor(node);
@@ -413,7 +417,7 @@
           if (_fixBuilder._typeSystem.isSubtypeOf(nonNullType, context)) {
             return _addNullCheck(node, type);
           } else {
-            return _addCast(node, context);
+            return _addCast(node, type, context);
           }
         }
         if (!_fixBuilder._typeSystem.isNullable(type)) return type;
@@ -442,13 +446,17 @@
     _flowAnalysis = flowAnalysis;
   }
 
-  DartType _addCast(Expression node, DartType contextType) {
+  DartType _addCast(
+      Expression node, DartType expressionType, DartType contextType) {
+    var isDowncast =
+        _fixBuilder._typeSystem.isSubtypeOf(contextType, expressionType);
     var checks =
         _fixBuilder._variables.expressionChecks(_fixBuilder.source, node);
-    var info = checks != null
-        ? AtomicEditInfo(
-            NullabilityFixDescription.checkExpression, checks.edges)
-        : null;
+    var info = AtomicEditInfo(
+        isDowncast
+            ? NullabilityFixDescription.downcastExpression
+            : NullabilityFixDescription.otherCastExpression,
+        checks != null ? checks.edges : {});
     (_fixBuilder._getChange(node) as NodeChangeForExpression)
         .introduceAs(contextType, info);
     _flowAnalysis.asExpression_end(node, contextType);
@@ -694,9 +702,7 @@
     var decoratedType = _fixBuilder._variables
         .decoratedTypeAnnotation(_fixBuilder.source, node);
     if (!typeIsNonNullableByContext(node)) {
-      (_fixBuilder._getChange(node) as NodeChangeForTypeAnnotation)
-        ..makeNullable = decoratedType.node.isNullable
-        ..decoratedType = decoratedType;
+      _makeTypeNameNullable(node, decoratedType);
     }
     (node as GenericFunctionTypeImpl).type =
         _fixBuilder._variables.toFinalType(decoratedType);
@@ -710,9 +716,7 @@
     if (!typeIsNonNullableByContext(node)) {
       var type = decoratedType.type;
       if (!type.isDynamic && !type.isVoid) {
-        (_fixBuilder._getChange(node) as NodeChangeForTypeAnnotation)
-          ..makeNullable = decoratedType.node.isNullable
-          ..decoratedType = decoratedType;
+        _makeTypeNameNullable(node, decoratedType);
       }
     }
     node.type = _fixBuilder._variables.toFinalType(decoratedType);
@@ -729,7 +733,7 @@
     var info = AtomicEditInfo(
         NullabilityFixDescription.addRequired(
             cls.name, method.name, element.name),
-        [node]);
+        {FixReasonTarget.root: node});
     var metadata = parameter.metadata;
     for (var annotation in metadata) {
       if (annotation.elementAnnotation.isRequired) {
@@ -746,4 +750,12 @@
       ..addRequiredKeyword = true
       ..addRequiredKeywordInfo = info;
   }
+
+  void _makeTypeNameNullable(TypeAnnotation node, DecoratedType decoratedType) {
+    (_fixBuilder._getChange(node) as NodeChangeForTypeAnnotation)
+        .recordNullability(
+            decoratedType, decoratedType.node.isNullable,
+            nullabilityDueToHint:
+                _fixBuilder._variables.hasNullabilityHint(source, node));
+  }
 }
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 256a199..d5a1de0 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -16,7 +16,6 @@
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:nnbd_migration/src/nullability_node_target.dart';
-import 'package:nnbd_migration/src/potential_modification.dart';
 import 'package:nnbd_migration/src/utilities/completeness_tracker.dart';
 import 'package:nnbd_migration/src/utilities/hint_utils.dart';
 import 'package:nnbd_migration/src/utilities/permissive_mode.dart';
@@ -203,7 +202,6 @@
           '(${node.parent.parent.toSource()}) offset=${node.offset}');
     }
     decoratedType.node.trackPossiblyOptional();
-    _variables.recordPossiblyOptional(source, node, decoratedType.node);
     return null;
   }
 
@@ -421,8 +419,7 @@
     if (type.isVoid || type.isDynamic) {
       var nullabilityNode = NullabilityNode.forTypeAnnotation(target);
       var decoratedType = DecoratedType(type, nullabilityNode);
-      _variables.recordDecoratedTypeAnnotation(
-          source, node, decoratedType, null);
+      _variables.recordDecoratedTypeAnnotation(source, node, decoratedType);
       return decoratedType;
     }
     var typeArguments = const <DecoratedType>[];
@@ -495,20 +492,17 @@
           positionalParameters: positionalParameters,
           namedParameters: namedParameters);
     }
-    _variables.recordDecoratedTypeAnnotation(
-        source,
-        node,
-        decoratedType,
-        PotentiallyAddQuestionSuffix(
-            nullabilityNode, decoratedType.type, node.end));
-    switch (getPostfixHint(node)) {
+    _variables.recordDecoratedTypeAnnotation(source, node, decoratedType);
+    switch (getPostfixHint(node.endToken)) {
       case NullabilityComment.bang:
         _graph.makeNonNullableUnion(
             decoratedType.node, NullabilityCommentOrigin(source, node, false));
+        _variables.recordNullabilityHint(source, node);
         break;
       case NullabilityComment.question:
         _graph.makeNullableUnion(
             decoratedType.node, NullabilityCommentOrigin(source, node, true));
+        _variables.recordNullabilityHint(source, node);
         break;
       case NullabilityComment.none:
         break;
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 48d2fbc..38e69fe 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -97,7 +97,7 @@
         library.typeSystem as TypeSystemImpl,
         _variables,
         library,
-        listener,
+        _permissive ? listener : null,
         unit);
     try {
       DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
diff --git a/pkg/nnbd_migration/lib/src/potential_modification.dart b/pkg/nnbd_migration/lib/src/potential_modification.dart
index 1e170f9..08bf83e 100644
--- a/pkg/nnbd_migration/lib/src/potential_modification.dart
+++ b/pkg/nnbd_migration/lib/src/potential_modification.dart
@@ -3,16 +3,11 @@
 // 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_plugin/protocol/protocol_common.dart' show SourceEdit;
-import 'package:nnbd_migration/instrumentation.dart';
-import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/conditional_discard.dart';
-import 'package:nnbd_migration/src/nullability_node.dart';
 
 /// Records information about how a conditional expression or statement might
 /// need to be modified.
-class ConditionalModification extends PotentialModification {
+class ConditionalModification {
   final int offset;
 
   final int end;
@@ -53,134 +48,6 @@
 
   ConditionalModification._(this.offset, this.end, this.isStatement,
       this.discard, this.condition, this.thenStatement, this.elseStatement);
-
-  @override
-  NullabilityFixDescription get description => discard.keepFalse
-      ? NullabilityFixDescription.discardThen
-      : (elseStatement == null
-          ? NullabilityFixDescription.discardCondition
-          : NullabilityFixDescription.discardElse);
-
-  @override
-  bool get isEmpty => discard.keepTrue && discard.keepFalse;
-
-  @override
-  Iterable<SourceEdit> get modifications {
-    if (isEmpty) return const [];
-    // TODO(paulberry): move the following logic into DartEditBuilder (see
-    // dartbug.com/35872).
-    var result = <SourceEdit>[];
-    var keepNodes = <_KeepNode>[];
-    if (!discard.pureCondition) {
-      keepNodes.add(condition); // TODO(paulberry): test
-    }
-    if (discard.keepTrue) {
-      keepNodes.add(thenStatement); // TODO(paulberry): test
-    }
-    if (discard.keepFalse && elseStatement != null) {
-      keepNodes.add(elseStatement); // TODO(paulberry): test
-    }
-    // TODO(paulberry): test thoroughly
-    for (int i = 0; i < keepNodes.length; i++) {
-      var keepNode = keepNodes[i];
-      if (i == 0 && keepNode.offset != offset) {
-        result.add(SourceEdit(offset, 0, '/* '));
-      }
-      if (i != 0 || keepNode.offset != offset) {
-        result.add(SourceEdit(keepNode.offset, 0, '*/ '));
-      }
-      if (i != keepNodes.length - 1 || keepNode.end != end) {
-        result.add(SourceEdit(keepNode.end, 0,
-            keepNode.isExpression && isStatement ? '; /*' : ' /*'));
-      }
-      if (i == keepNodes.length - 1 && keepNode.end != end) {
-        result.add(SourceEdit(end, 0, ' */'));
-      }
-    }
-    return result;
-  }
-
-  @override
-  Iterable<FixReasonInfo> get reasons => discard.reasons;
-}
-
-/// Records information about the possible addition of a `?` suffix to a type in
-/// the source code.
-class PotentiallyAddQuestionSuffix extends PotentialModification {
-  final NullabilityNode node;
-  final DartType type;
-  final int _offset;
-
-  PotentiallyAddQuestionSuffix(this.node, this.type, this._offset);
-
-  @override
-  NullabilityFixDescription get description =>
-      NullabilityFixDescription.makeTypeNullable(
-          type.getDisplayString(withNullability: false));
-
-  @override
-  bool get isEmpty => !node.isNullable;
-
-  @override
-  Iterable<SourceEdit> get modifications =>
-      isEmpty ? [] : [SourceEdit(_offset, 0, '?')];
-
-  @override
-  Iterable<FixReasonInfo> get reasons => [node];
-}
-
-/// Records information about the possible addition of a `required` keyword
-/// to the source code.
-class PotentiallyAddRequired extends PotentialModification {
-  final NullabilityNode _node;
-
-  final int _offset;
-  final String className;
-  final String methodName;
-  final String parameterName;
-
-  factory PotentiallyAddRequired(
-      DefaultFormalParameter parameter, NullabilityNode node) {
-    final element = parameter.declaredElement;
-    final method = element.enclosingElement;
-    final cls = method.enclosingElement;
-    return PotentiallyAddRequired._(
-        node, parameter.offset, cls.name, method.name, element.name);
-  }
-
-  PotentiallyAddRequired._(this._node, this._offset, this.className,
-      this.methodName, this.parameterName);
-
-  @override
-  NullabilityFixDescription get description =>
-      NullabilityFixDescription.addRequired(
-          className, methodName, parameterName);
-
-  @override
-  bool get isEmpty => _node.isNullable;
-
-  @override
-  Iterable<SourceEdit> get modifications =>
-      isEmpty ? const [] : [SourceEdit(_offset, 0, 'required ')];
-
-  @override
-  Iterable<FixReasonInfo> get reasons => [_node];
-}
-
-/// Interface used by data structures representing potential modifications to
-/// the code being migrated.
-abstract class PotentialModification {
-  /// Gets a [NullabilityFixDescription] describing this modification.
-  NullabilityFixDescription get description;
-
-  bool get isEmpty;
-
-  /// Gets the individual migrations that need to be done, considering the
-  /// solution to the constraint equations.
-  Iterable<SourceEdit> get modifications;
-
-  /// Gets the reasons for this potential modification.
-  Iterable<FixReasonInfo> get reasons;
 }
 
 /// Helper object used by [ConditionalModification] to keep track of AST nodes
diff --git a/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart b/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
index 3249985..d0fa9c8 100644
--- a/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
-import 'package:analyzer/dart/ast/ast.dart';
 
 /// Determine if the given token is a nullability hint, and if so, return the
 /// type of nullability hint it is.
@@ -15,10 +14,10 @@
   return NullabilityComment.none;
 }
 
-/// Determine if the given [node] is followed by a nullability hint, and if so,
+/// Determine if the given [token] is followed by a nullability hint, and if so,
 /// return the type of nullability hint it is followed by.
-NullabilityComment getPostfixHint(AstNode node) {
-  var commentToken = node.endToken.next.precedingComments;
+NullabilityComment getPostfixHint(Token token) {
+  var commentToken = token.next.precedingComments;
   var commentType = classifyComment(commentToken);
   return commentType;
 }
@@ -31,7 +30,11 @@
       if (nextComment == null) break;
       commentToken = nextComment;
     }
-    if (commentToken.lexeme == '/*late*/') return PrefixHintComment.late_;
+    var lexeme = commentToken.lexeme;
+    if (lexeme.startsWith('/*') && lexeme.endsWith('*/') && lexeme.length > 4) {
+      var commentText = lexeme.substring(2, lexeme.length - 2).trim();
+      if (commentText == 'late') return PrefixHintComment.late_;
+    }
   }
   return PrefixHintComment.none;
 }
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 6b4096c..6b751af 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -26,7 +26,6 @@
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/postmortem_file.dart';
-import 'package:nnbd_migration/src/potential_modification.dart';
 
 /// Data structure used by [Variables.spanForUniqueIdentifier] to return an
 /// offset/end pair.
@@ -61,7 +60,7 @@
 
   final _nullCheckHints = <Source, Set<int>>{};
 
-  final _potentialModifications = <Source, List<PotentialModification>>{};
+  final _nullabilityHints = <Source, Set<int>>{};
 
   final _unnecessaryCasts = <Source, Set<int>>{};
 
@@ -167,8 +166,12 @@
   ConditionalDiscard getConditionalDiscard(Source source, AstNode node) =>
       (_conditionalDiscards[source] ?? {})[node.offset];
 
-  Map<Source, List<PotentialModification>> getPotentialModifications() =>
-      _potentialModifications;
+  /// Queries whether the given [node] is preceded by a `/*?*/` hint.  See
+  /// [recordNullabilityHint].
+  bool hasNullabilityHint(Source source, TypeAnnotation node) {
+    return (_nullabilityHints[source] ?? {})
+        .contains(uniqueIdentifierForSpan(node.offset, node.end));
+  }
 
   /// Queries whether the given [expression] is followed by a null check hint
   /// (`/*!*/`).  See [recordNullCheckHint].
@@ -188,8 +191,6 @@
   void recordConditionalDiscard(
       Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
     (_conditionalDiscards[source] ??= {})[node.offset] = conditionalDiscard;
-    _addPotentialModification(
-        source, ConditionalModification(node, conditionalDiscard));
   }
 
   /// Associates a [class_] with decorated type information for the superclasses
@@ -220,11 +221,9 @@
   void recordDecoratedExpressionType(Expression node, DecoratedType type) {}
 
   /// Associates decorated type information with the given [type] node.
-  void recordDecoratedTypeAnnotation(Source source, TypeAnnotation node,
-      DecoratedType type, PotentiallyAddQuestionSuffix potentialModification) {
+  void recordDecoratedTypeAnnotation(
+      Source source, TypeAnnotation node, DecoratedType type) {
     instrumentation?.explicitTypeNullability(source, node, type.node);
-    if (potentialModification != null)
-      _addPotentialModification(source, potentialModification);
     var id = uniqueIdentifierForSpan(node.offset, node.end);
     (_decoratedTypeAnnotations[source] ??= {})[id] = type;
     postmortemFileWriter?.storeFileDecorations(source.fullName, id, type);
@@ -233,7 +232,6 @@
   /// Associates a set of nullability checks with the given expression [node].
   void recordExpressionChecks(
       Source source, Expression expression, ExpressionChecksOrigin origin) {
-    _addPotentialModification(source, origin.checks);
     (_expressionChecks[source] ??=
             {})[uniqueIdentifierForSpan(expression.offset, expression.end)] =
         origin.checks;
@@ -244,6 +242,12 @@
     (_lateHints[source] ??= {}).add(node.offset);
   }
 
+  /// Records that the given [node] was followed by a `/*?*/` or `/*!*/` hint.
+  void recordNullabilityHint(Source source, TypeAnnotation node) {
+    (_nullabilityHints[source] ??= {})
+        .add(uniqueIdentifierForSpan(node.offset, node.end));
+  }
+
   /// Records that the given [expression] is followed by a null check hint
   /// (`/*!*/`), for later recall by [hasNullCheckHint].
   void recordNullCheckHint(Source source, Expression expression) {
@@ -251,15 +255,6 @@
         .add(uniqueIdentifierForSpan(expression.offset, expression.end));
   }
 
-  /// Records that [node] is associated with the question of whether the named
-  /// [parameter] should be optional (should not have a `required`
-  /// annotation added to it).
-  void recordPossiblyOptional(
-      Source source, DefaultFormalParameter parameter, NullabilityNode node) {
-    var modification = PotentiallyAddRequired(parameter, node);
-    _addPotentialModification(source, modification);
-  }
-
   /// Records the fact that prior to migration, an unnecessary cast existed at
   /// [node].
   void recordUnnecessaryCast(Source source, AsExpression node) {
@@ -342,11 +337,6 @@
       (_unnecessaryCasts[source] ?? const {})
           .contains(uniqueIdentifierForSpan(node.offset, node.end));
 
-  void _addPotentialModification(
-      Source source, PotentialModification potentialModification) {
-    (_potentialModifications[source] ??= []).add(potentialModification);
-  }
-
   /// Creates a decorated type for the given [element], which should come from
   /// an already-migrated library (or the SDK).
   DecoratedType _createDecoratedElementType(Element element) {
diff --git a/pkg/nnbd_migration/pubspec.yaml b/pkg/nnbd_migration/pubspec.yaml
index 5a21236..55968c0 100644
--- a/pkg/nnbd_migration/pubspec.yaml
+++ b/pkg/nnbd_migration/pubspec.yaml
@@ -3,10 +3,11 @@
 environment:
   sdk: '>=2.6.0 <3.0.0'
 dependencies:
-  _fe_analyzer_shared: 1.0.0
+  _fe_analyzer_shared: ^2.0.0
   analyzer: ^0.37.0
   analyzer_plugin: ^0.2.2
   path: ^1.6.2
+  stream_channel: any
   yaml: any
 dev_dependencies:
   args: ^1.5.2
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index dd1dc53..b69cf77 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -1719,6 +1719,14 @@
     await _checkSingleFileChanges(content, expected, removeViaComments: true);
   }
 
+  Future<void> test_expression_bang_hint_unnecessary_literal() async {
+    var content = 'int/*?*/ f() => 1/*!*/;';
+    // The user requested a null check so we should add it even if it's not
+    // required to avoid compile errors.
+    var expected = 'int?/*?*/ f() => 1!/*!*/;';
+    await _checkSingleFileChanges(content, expected, removeViaComments: true);
+  }
+
   Future<void> test_expression_bang_hint_with_cast() async {
     var content = 'int f(Object/*?*/ o) => o/*!*/;';
     // TODO(paulberry): it would be better to remove the `/*` and `*/` so we
@@ -2643,6 +2651,64 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_implicit_parameter_type_override_does_not_union() async {
+    var content = '''
+abstract class A {
+  void f(int/*?*/ i);
+}
+abstract class B {
+  void f(int i);
+}
+class C implements A, B {
+  void f(i) {}
+}
+''';
+    // Even though the parameter type of C.f is implicit, its nullability
+    // shouldn't be unioned with that of A and B, because that would
+    // unnecessarily force B.f's parameter type to be nullable.
+    var expected = '''
+abstract class A {
+  void f(int?/*?*/ i);
+}
+abstract class B {
+  void f(int i);
+}
+class C implements A, B {
+  void f(i) {}
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_implicit_return_type_override_does_not_union() async {
+    var content = '''
+abstract class A {
+  int/*?*/ f();
+}
+abstract class B {
+  int f();
+}
+class C implements A, B {
+  f() => 0;
+}
+''';
+    // Even though the return type of C.f is implicit, its nullability shouldn't
+    // be unioned with that of A and B, because that would unnecessarily force
+    // B.f's return type to be nullable.
+    var expected = '''
+abstract class A {
+  int?/*?*/ f();
+}
+abstract class B {
+  int f();
+}
+class C implements A, B {
+  f() => 0;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_implicit_type_parameter_bound_nullable() async {
     var content = '''
 class C<T> {
@@ -2686,78 +2752,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  Future<void> test_inferred_method_parameter_type_non_nullable() async {
-    var content = '''
-class B {
-  void f(int i) {
-    assert(i != null);
-  }
-}
-class C extends B {
-  void f(i) {}
-}
-void g(C c, int i, bool b) {
-  if (b) {
-    c.f(i);
-  }
-}
-void h(C c) {
-  g(c, null, false);
-}
-''';
-    // B.f's parameter type is `int`.  Since C.f's parameter type is inferred
-    // from B.f's, it has a parameter type of `int` too.  Therefore there must
-    // be a null check in g().
-    var expected = '''
-class B {
-  void f(int i) {
-    assert(i != null);
-  }
-}
-class C extends B {
-  void f(i) {}
-}
-void g(C c, int? i, bool b) {
-  if (b) {
-    c.f(i!);
-  }
-}
-void h(C c) {
-  g(c, null, false);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
-  Future<void> test_inferred_method_parameter_type_nullable() async {
-    var content = '''
-class B {
-  void f(int i) {}
-}
-class C extends B {
-  void f(i) {}
-}
-void g(C c) {
-  c.f(null);
-}
-''';
-    // The call to C.f from g forces C.f's parameter to be nullable.  Since
-    // C.f's parameter type is inferred from B.f's parameter type, B.f's
-    // parameter must be nullable too.
-    var expected = '''
-class B {
-  void f(int? i) {}
-}
-class C extends B {
-  void f(i) {}
-}
-void g(C c) {
-  c.f(null);
-}
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
   Future<void> test_inferred_method_return_type_non_nullable() async {
     var content = '''
 class B {
@@ -2783,31 +2777,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  Future<void> test_inferred_method_return_type_nullable() async {
-    var content = '''
-class B {
-  int f() => null;
-}
-class C extends B {
-  f() => 1;
-}
-int g(C c) => c.f();
-''';
-    // B.f's return type is `int?`.  Since C.f's return type is inferred from
-    // B.f's, it has a return type of `int?` too.  Therefore g's return type
-    // must be `int?`.
-    var expected = '''
-class B {
-  int? f() => null;
-}
-class C extends B {
-  f() => 1;
-}
-int? g(C c) => c.f();
-''';
-    await _checkSingleFileChanges(content, expected);
-  }
-
   Future<void> test_insert_as_prefixed_type() async {
     var content = '''
 import 'dart:async' as a;
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index b529b8c..bb1e7e2 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -9,9 +9,12 @@
 import 'package:analyzer/dart/element/type_provider.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/error/hint_codes.dart';
-import 'package:analyzer/src/generated/resolver.dart' show TypeSystemImpl;
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
@@ -36,6 +39,8 @@
     with EdgeTester, DecoratedTypeTester {
   static const EdgeOrigin origin = const _TestEdgeOrigin();
 
+  LibraryElementImpl _myLibrary;
+
   ClassElement _myListOfListClass;
 
   DecoratedType _myListOfListSupertype;
@@ -53,6 +58,8 @@
 
   factory AssignmentCheckerTest() {
     var typeProvider = TestTypeProvider();
+    _setCoreLibrariesTypeSystem(typeProvider);
+
     var graph = NullabilityGraphForTesting();
     var decoratedClassHierarchy = _DecoratedClassHierarchyForTesting();
     var checker = AssignmentCheckerForTesting(
@@ -80,10 +87,12 @@
   }
 
   DecoratedType myListOfList(DecoratedType elementType) {
+    _initMyLibrary();
     if (_myListOfListClass == null) {
       var t = typeParameter('T', object());
       _myListOfListSupertype = list(list(typeParameterType(t)));
       _myListOfListClass = ClassElementImpl('MyListOfList', 0)
+        ..enclosingElement = _myLibrary.definingCompilationUnit
         ..typeParameters = [t]
         ..supertype = _myListOfListSupertype.type as InterfaceType;
     }
@@ -438,6 +447,63 @@
     checker.bounds[t] = bound;
     return t;
   }
+
+  void _initMyLibrary() {
+    if (_myLibrary != null) {
+      return;
+    }
+
+    var coreLibrary = typeProvider.boolElement.library as LibraryElementImpl;
+    var analysisContext = coreLibrary.context;
+    var analysisSession = coreLibrary.session;
+    var typeSystem = coreLibrary.typeSystem;
+
+    var uriStr = 'package:test/test.dart';
+
+    _myLibrary = LibraryElementImpl(analysisContext, analysisSession, uriStr,
+        -1, 0, typeSystem.isNonNullableByDefault);
+    _myLibrary.typeSystem = typeSystem;
+    _myLibrary.typeProvider = coreLibrary.typeProvider;
+
+    var uri = Uri.parse(uriStr);
+    var source = _MockSource(uri);
+
+    var definingUnit = CompilationUnitElementImpl();
+    definingUnit.source = source;
+    definingUnit.librarySource = source;
+
+    definingUnit.enclosingElement = _myLibrary;
+    _myLibrary.definingCompilationUnit = definingUnit;
+  }
+
+  static void _setCoreLibrariesTypeSystem(TestTypeProvider typeProvider) {
+    var typeSystem = TypeSystemImpl(
+      isNonNullableByDefault: false,
+      implicitCasts: true,
+      strictInference: false,
+      typeProvider: typeProvider,
+    );
+    _setLibraryTypeSystem(
+      typeProvider.objectElement.library,
+      typeProvider,
+      typeSystem,
+    );
+    _setLibraryTypeSystem(
+      typeProvider.futureElement.library,
+      typeProvider,
+      typeSystem,
+    );
+  }
+
+  static void _setLibraryTypeSystem(
+    LibraryElement libraryElement,
+    TypeProvider typeProvider,
+    TypeSystem typeSystem,
+  ) {
+    var libraryElementImpl = libraryElement as LibraryElementImpl;
+    libraryElementImpl.typeProvider = typeProvider as TypeProviderImpl;
+    libraryElementImpl.typeSystem = typeSystem as TypeSystemImpl;
+  }
 }
 
 @reflectiveTest
@@ -482,7 +548,7 @@
   /// needed.
   void assertNullCheck(
       ExpressionChecksOrigin expressionChecks, NullabilityEdge expectedEdge) {
-    expect(expressionChecks.checks.edges, contains(expectedEdge));
+    expect(expressionChecks.checks.edges.values, contains(expectedEdge));
   }
 
   /// Gets the [ExpressionChecks] associated with the expression whose text
@@ -3292,7 +3358,7 @@
   f();
 }
 ''');
-    var optional_i = possiblyOptionalParameter('int i');
+    var optional_i = decoratedTypeAnnotation('int i').node;
     expect(getEdges(always, optional_i), isNotEmpty);
   }
 
@@ -3308,8 +3374,6 @@
 }
 ''');
     // The call at `f()` is presumed to be in error; no constraint is recorded.
-    var optional_i = possiblyOptionalParameter('int i');
-    expect(optional_i, isNull);
     var nullable_i = decoratedTypeAnnotation('int i').node;
     assertNoUpstreamNullability(nullable_i);
   }
@@ -3902,8 +3966,8 @@
     var nullable_c_t = decoratedTypeAnnotation('C<int>').typeArguments[0].node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_c_t_or_nullable_t = check_i.checks.edges.single.destinationNode
-        as NullabilityNodeForSubstitution;
+    var nullable_c_t_or_nullable_t = check_i.checks.edges[FixReasonTarget.root]
+        .destinationNode as NullabilityNodeForSubstitution;
     expect(nullable_c_t_or_nullable_t.innerNode, same(nullable_c_t));
     expect(nullable_c_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -3921,8 +3985,8 @@
     var nullable_c_t = decoratedTypeAnnotation('C<int>').typeArguments[0].node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_c_t_or_nullable_t = check_i.checks.edges.single.destinationNode
-        as NullabilityNodeForSubstitution;
+    var nullable_c_t_or_nullable_t = check_i.checks.edges[FixReasonTarget.root]
+        .destinationNode as NullabilityNodeForSubstitution;
     expect(nullable_c_t_or_nullable_t.innerNode, same(nullable_c_t));
     expect(nullable_c_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -4279,7 +4343,7 @@
 ''');
     var bReturnType = decoratedMethodType('f/*B*/').positionalParameters[0];
     var cReturnType = decoratedMethodType('f/*C*/').positionalParameters[0];
-    assertUnion(bReturnType.node, cReturnType.node);
+    assertEdge(bReturnType.node, cReturnType.node, hard: true);
   }
 
   Future<void> test_method_parameterType_inferred_named() async {
@@ -4293,7 +4357,7 @@
 ''');
     var bReturnType = decoratedMethodType('f/*B*/').namedParameters['x'];
     var cReturnType = decoratedMethodType('f/*C*/').namedParameters['x'];
-    assertUnion(bReturnType.node, cReturnType.node);
+    assertEdge(bReturnType.node, cReturnType.node, hard: true);
   }
 
   Future<void> test_method_returnType_inferred() async {
@@ -4307,7 +4371,7 @@
 ''');
     var bReturnType = decoratedMethodType('f/*B*/').returnType;
     var cReturnType = decoratedMethodType('f/*C*/').returnType;
-    assertUnion(bReturnType.node, cReturnType.node);
+    assertEdge(cReturnType.node, bReturnType.node, hard: true);
   }
 
   Future<void>
@@ -4624,8 +4688,8 @@
     var nullable_c_t = decoratedTypeAnnotation('C<int>').typeArguments[0].node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_c_t_or_nullable_t = check_i.checks.edges.single.destinationNode
-        as NullabilityNodeForSubstitution;
+    var nullable_c_t_or_nullable_t = check_i.checks.edges[FixReasonTarget.root]
+        .destinationNode as NullabilityNodeForSubstitution;
     expect(nullable_c_t_or_nullable_t.innerNode, same(nullable_c_t));
     expect(nullable_c_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -4651,7 +4715,9 @@
     assertEdge(nullable_t, never, hard: true, checkable: false);
     var check_i = checkExpression('i/*check*/');
     var nullable_list_t_or_nullable_t = check_i
-        .checks.edges.single.destinationNode as NullabilityNodeForSubstitution;
+        .checks
+        .edges[FixReasonTarget.root]
+        .destinationNode as NullabilityNodeForSubstitution;
     expect(nullable_list_t_or_nullable_t.innerNode, same(nullable_list_t));
     expect(nullable_list_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -4669,8 +4735,8 @@
     var nullable_f_t = decoratedTypeAnnotation('int>').node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_f_t_or_nullable_t = check_i.checks.edges.single.destinationNode
-        as NullabilityNodeForSubstitution;
+    var nullable_f_t_or_nullable_t = check_i.checks.edges[FixReasonTarget.root]
+        .destinationNode as NullabilityNodeForSubstitution;
     expect(nullable_f_t_or_nullable_t.innerNode, same(nullable_f_t));
     expect(nullable_f_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -4784,8 +4850,8 @@
     var check_i = checkExpression('(f<int>(1))');
     var t_bound = decoratedTypeAnnotation('Object').node;
     var nullable_f_t = decoratedTypeAnnotation('int>').node;
-    var nullable_f_t_or_nullable_t = check_i.checks.edges.single.sourceNode
-        as NullabilityNodeForSubstitution;
+    var nullable_f_t_or_nullable_t = check_i.checks.edges[FixReasonTarget.root]
+        .sourceNode as NullabilityNodeForSubstitution;
     var nullable_t = decoratedTypeAnnotation('T f').node;
     expect(nullable_f_t_or_nullable_t.innerNode, same(nullable_f_t));
     expect(nullable_f_t_or_nullable_t.outerNode, same(nullable_t));
@@ -7401,6 +7467,16 @@
   }
 }
 
+class _MockSource implements Source {
+  @override
+  final Uri uri;
+
+  _MockSource(this.uri);
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
 class _TestEdgeOrigin implements EdgeOrigin {
   const _TestEdgeOrigin();
 
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index 5cb8c7f..120b97c 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -1122,8 +1122,8 @@
     await analyze('var x = 1;');
     var variableDeclarationList = findNode.variableDeclarationList('var x');
     checkPlan(
-        planner.replaceToken(variableDeclarationList,
-            variableDeclarationList.keyword, [AtomicEdit.insert('int')]),
+        planner.replaceToken(
+            variableDeclarationList, variableDeclarationList.keyword, 'int'),
         'int x = 1;');
   }
 
diff --git a/pkg/nnbd_migration/test/fix_aggregator_test.dart b/pkg/nnbd_migration/test/fix_aggregator_test.dart
index 6abb6ef..8b15727 100644
--- a/pkg/nnbd_migration/test/fix_aggregator_test.dart
+++ b/pkg/nnbd_migration/test/fix_aggregator_test.dart
@@ -695,9 +695,10 @@
     var typeName = findNode.typeName('int');
     var previewInfo = run({
       typeName: NodeChangeForTypeAnnotation()
-        ..makeNullable = true
-        ..decoratedType = MockDecoratedType(
-            MockDartType(toStringValueWithoutNullability: 'int'))
+        ..recordNullability(
+            MockDecoratedType(
+                MockDartType(toStringValueWithoutNullability: 'int')),
+            true)
     });
     expect(previewInfo.applyTo(code), 'f(int? x) {}');
   }
@@ -707,8 +708,10 @@
     var typeName = findNode.typeName('int');
     var previewInfo = run({
       typeName: NodeChangeForTypeAnnotation()
-        ..decoratedType = MockDecoratedType(
-            MockDartType(toStringValueWithoutNullability: 'int'))
+        ..recordNullability(
+            MockDecoratedType(
+                MockDartType(toStringValueWithoutNullability: 'int')),
+            false)
     });
     expect(previewInfo.applyTo(code), 'int x = 0;');
     expect(previewInfo.applyTo(code, includeInformative: true), 'int  x = 0;');
@@ -934,9 +937,10 @@
       findNode.unit: NodeChangeForCompilationUnit()
         ..removeLanguageVersionComment = true,
       findNode.typeAnnotation('int'): NodeChangeForTypeAnnotation()
-        ..makeNullable = true
-        ..decoratedType = MockDecoratedType(
-            MockDartType(toStringValueWithoutNullability: 'int'))
+        ..recordNullability(
+            MockDecoratedType(
+                MockDartType(toStringValueWithoutNullability: 'int')),
+            true)
     });
     // TODO(mfairhurst): Remove beginning \n once it renders properly in preview
     expect(previewInfo.applyTo(code), '\nint? f() => null;\n');
@@ -987,9 +991,10 @@
       methodInvocation: NodeChangeForMethodInvocation()
         ..removeNullAwareness = true,
       typeAnnotation: NodeChangeForTypeAnnotation()
-        ..makeNullable = true
-        ..decoratedType = MockDecoratedType(
-            MockDartType(toStringValueWithoutNullability: 'int'))
+        ..recordNullability(
+            MockDecoratedType(
+                MockDartType(toStringValueWithoutNullability: 'int')),
+            true)
     });
     expect(previewInfo.applyTo(code), 'f(x) => x.m<int?>();');
   }
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 3bdfcf7..dd306f7 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -10,10 +10,12 @@
 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';
 import 'package:nnbd_migration/src/fix_aggregator.dart';
 import 'package:nnbd_migration/src/fix_builder.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -46,7 +48,16 @@
           .having((c) => c.addRequiredKeyword, 'addRequiredKeyword', true);
 
   static final isMakeNullable = TypeMatcher<NodeChangeForTypeAnnotation>()
-      .having((c) => c.makeNullable, 'makeNullable', true);
+      .having((c) => c.makeNullable, 'makeNullable', true)
+      .having((c) => c.makeNullableDueToHint, 'makeNullableDueToHint', false);
+
+  static final isMakeNullableDueToHint =
+      TypeMatcher<NodeChangeForTypeAnnotation>()
+          .having((c) => c.makeNullable, 'makeNullable', true)
+          .having(
+              (c) => c.makeNullableDueToHint, 'makeNullableDueToHint', true);
+
+  static const isEdge = TypeMatcher<NullabilityEdge>();
 
   static final isExplainNonNullable = TypeMatcher<NodeChangeForTypeAnnotation>()
       .having((c) => c.makeNullable, 'makeNullable', false);
@@ -1100,7 +1111,8 @@
     await analyze('''
 int _f({int/*?*/ x}) => 1;
 ''');
-    visitAll(changes: {findNode.typeName('int/*?*/ x'): isMakeNullable});
+    visitAll(
+        changes: {findNode.typeName('int/*?*/ x'): isMakeNullableDueToHint});
   }
 
   Future<void>
@@ -1140,7 +1152,7 @@
 ''');
     visitAll(changes: {
       findNode.annotation('required'): isRequiredAnnotationToRequiredKeyword,
-      findNode.typeName('int'): isMakeNullable,
+      findNode.typeName('int'): isMakeNullableDueToHint,
     });
   }
 
@@ -1383,6 +1395,17 @@
     visitStatement(findNode.statement('if'));
   }
 
+  Future<void> test_implicit_downcast() async {
+    await analyze('int f(num x) => x;');
+    var xRef = findNode.simple('x;');
+    visitSubexpression(xRef, 'int', changes: {
+      xRef: isNodeChangeForExpression.havingIndroduceAsWithInfo(
+          'int',
+          isInfo(NullabilityFixDescription.downcastExpression,
+              {FixReasonTarget.root: isEdge}))
+    });
+  }
+
   Future<void> test_indexExpression_dynamic() async {
     await analyze('''
 Object/*!*/ _f(dynamic d, int/*?*/ i) => d[i];
@@ -2566,8 +2589,8 @@
     var xRef = findNode.simple('x/*!*/');
     visitSubexpression(xRef, 'int', changes: {
       xRef: isNodeChangeForExpression.havingNullCheckWithInfo(isInfo(
-          NullabilityFixDescription.checkExpression,
-          [TypeMatcher<FixReason_NullCheckHint>()]))
+          NullabilityFixDescription.checkExpressionDueToHint,
+          {FixReasonTarget.root: TypeMatcher<FixReason_NullCheckHint>()}))
     });
   }
 
@@ -2578,6 +2601,22 @@
     visitSubexpression(findNode.stringLiteral("'foo'"), 'String');
   }
 
+  Future<void> test_suspicious_cast() async {
+    await analyze('''
+int f(Object o) {
+  if (o is! String) return 0;
+  return o;
+}
+''');
+    var xRef = findNode.simple('o;');
+    visitSubexpression(xRef, 'int', changes: {
+      xRef: isNodeChangeForExpression.havingIndroduceAsWithInfo(
+          'int',
+          isInfo(NullabilityFixDescription.otherCastExpression,
+              {FixReasonTarget.root: isEdge}))
+    });
+  }
+
   Future<void> test_symbolLiteral() async {
     await analyze('''
 f() => #foo;
@@ -2859,7 +2898,14 @@
 }
 
 extension on TypeMatcher<NodeChangeForExpression> {
-  TypeMatcher<NodeChangeForExpression> havingNullCheckWithInfo(matcher) =>
+  TypeMatcher<NodeChangeForExpression> havingNullCheckWithInfo(
+          dynamic matcher) =>
       having((c) => c.addsNullCheck, 'addsNullCheck', true)
           .having((c) => c.addNullCheckInfo, 'addNullCheckInfo', matcher);
+
+  TypeMatcher<NodeChangeForExpression> havingIndroduceAsWithInfo(
+          dynamic typeStringMatcher, dynamic infoMatcher) =>
+      having((c) => c.introducesAsType.toString(), 'introducesAsType (string)',
+              typeStringMatcher)
+          .having((c) => c.introducesAsInfo, 'introducesAsInfo', infoMatcher);
 }
diff --git a/pkg/nnbd_migration/test/fix_reason_target_test.dart b/pkg/nnbd_migration/test/fix_reason_target_test.dart
new file mode 100644
index 0000000..c36391f
--- /dev/null
+++ b/pkg/nnbd_migration/test/fix_reason_target_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 'package:nnbd_migration/fix_reason_target.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FixReasonTargetTest);
+  });
+}
+
+@reflectiveTest
+class FixReasonTargetTest {
+  void test_suffix_complex() {
+    var root = FixReasonTarget.root;
+    expect(root.returnType.typeArgument(0).suffix,
+        ' for type argument 0 of return type');
+    expect(root.yieldedType.namedParameter('foo').suffix,
+        ' for parameter foo of yielded type');
+    expect(root.namedParameter('foo').positionalParameter(0).suffix,
+        ' for parameter 0 of parameter foo');
+    expect(root.positionalParameter(0).returnType.suffix,
+        ' for return type of parameter 0');
+    expect(root.typeArgument(0).yieldedType.suffix,
+        ' for yielded type from type argument 0');
+  }
+
+  void test_suffix_simple() {
+    var root = FixReasonTarget.root;
+    expect(root.suffix, '');
+    expect(root.returnType.suffix, ' for return type');
+    expect(root.yieldedType.suffix, ' for yielded type');
+    expect(root.namedParameter('foo').suffix, ' for parameter foo');
+    expect(root.positionalParameter(0).suffix, ' for parameter 0');
+    expect(root.typeArgument(0).suffix, ' for type argument 0');
+  }
+}
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index d9d01f1..e6c1681 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
@@ -217,7 +218,7 @@
         var info = edit.info;
         expect(info.description,
             NullabilityFixDescription.addRequired(null, '_f', 'i'));
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -233,7 +234,7 @@
         var info = edit.info;
         expect(info.description,
             NullabilityFixDescription.addRequired('C', '_f', 'i'));
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -254,7 +255,7 @@
       for (var edit in change) {
         var info = edit.info;
         expect(info.description, NullabilityFixDescription.discardCondition);
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -273,7 +274,7 @@
       for (var edit in change) {
         var info = edit.info;
         expect(info.description, NullabilityFixDescription.discardCondition);
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -296,13 +297,13 @@
     expect(dropCondition.isDeletion, true);
     expect(dropCondition.info.description,
         NullabilityFixDescription.discardCondition);
-    expect(dropCondition.info.fixReasons.single,
+    expect(dropCondition.info.fixReasons[FixReasonTarget.root],
         same(explicitTypeNullability[intAnnotation]));
     // Change #2: drop the else.
     var dropElse = changes[findNode.statement('return i').end].single;
     expect(dropElse.isDeletion, true);
     expect(dropElse.info.description, NullabilityFixDescription.discardElse);
-    expect(dropElse.info.fixReasons.single,
+    expect(dropElse.info.fixReasons[FixReasonTarget.root],
         same(explicitTypeNullability[intAnnotation]));
   }
 
@@ -321,7 +322,7 @@
       for (var edit in change) {
         var info = edit.info;
         expect(info.description, NullabilityFixDescription.discardIf);
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -344,7 +345,7 @@
       for (var edit in change) {
         var info = edit.info;
         expect(info.description, NullabilityFixDescription.discardThen);
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -365,7 +366,7 @@
       for (var edit in change) {
         var info = edit.info;
         expect(info.description, NullabilityFixDescription.discardIf);
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -393,7 +394,7 @@
     expect(info.description, NullabilityFixDescription.checkExpression);
     var reasons = info.fixReasons;
     expect(reasons, hasLength(1));
-    var edge = reasons[0] as EdgeInfo;
+    var edge = reasons[FixReasonTarget.root] as EdgeInfo;
     expect(edge.sourceNode,
         same(explicitTypeNullability[findNode.typeAnnotation('int y')]));
     expect(edge.destinationNode,
@@ -417,7 +418,8 @@
     expect(info.description, NullabilityFixDescription.makeTypeNullable('int'));
     var reasons = info.fixReasons;
     expect(reasons, hasLength(1));
-    expect(reasons.single, same(explicitTypeNullability[intAnnotation]));
+    expect(reasons[FixReasonTarget.root],
+        same(explicitTypeNullability[intAnnotation]));
   }
 
   Future<void> test_fix_reason_remove_question_from_question_dot() async {
@@ -489,7 +491,7 @@
         var info = edit.info;
         expect(info.description,
             NullabilityFixDescription.addRequired(null, '_f', 'i'));
-        expect(info.fixReasons.single,
+        expect(info.fixReasons[FixReasonTarget.root],
             same(explicitTypeNullability[intAnnotation]));
       }
     }
@@ -991,8 +993,8 @@
             .node;
     expect(
         edges.where((e) =>
-            e.sourceNode == derivedParamArgNode &&
-            e.destinationNode == baseParamArgNode),
+            e.sourceNode == baseParamArgNode &&
+            e.destinationNode == derivedParamArgNode),
         hasLength(1));
   }
 
diff --git a/pkg/nnbd_migration/test/isolate_server_test.dart b/pkg/nnbd_migration/test/isolate_server_test.dart
new file mode 100644
index 0000000..c352204
--- /dev/null
+++ b/pkg/nnbd_migration/test/isolate_server_test.dart
@@ -0,0 +1,264 @@
+// 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:convert';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:analysis_server_client/protocol.dart';
+import 'package:async/src/stream_sink_transformer.dart';
+import 'package:nnbd_migration/isolate_server.dart';
+import 'package:stream_channel/isolate_channel.dart';
+import 'package:stream_channel/src/stream_channel_transformer.dart';
+import 'package:stream_channel/stream_channel.dart';
+import 'package:test/test.dart';
+
+void main() {
+  FakeIsolate isolate;
+  FakeIsolateChannel isolateChannel;
+  Server server;
+
+  setUp(() async {
+    isolate = FakeIsolate();
+    isolateChannel = FakeIsolateChannel();
+    server = Server(isolate: isolate, isolateChannel: isolateChannel);
+  });
+
+  group('listenToOutput', () {
+    test('good', () async {
+      isolateChannel.stream = _goodMessage();
+
+      final future = server.send('blahMethod', null);
+      server.listenToOutput();
+
+      final response = await future;
+      expect(response['foo'], 'bar');
+    });
+
+    test('error', () async {
+      isolateChannel.stream = _badMessage();
+
+      final future = server.send('blahMethod', null);
+      future.catchError((e) {
+        expect(e, const TypeMatcher<RequestError>());
+        final error = e as RequestError;
+        expect(error.code, RequestErrorCode.UNKNOWN_REQUEST);
+        expect(error.message, 'something went wrong');
+        expect(error.stackTrace, 'some long stack trace');
+      });
+      server.listenToOutput();
+    });
+
+    test('event', () async {
+      isolateChannel.stream = _eventMessage();
+
+      final completer = Completer();
+      void eventHandler(Notification notification) {
+        expect(notification.event, 'fooEvent');
+        expect(notification.params.length, 2);
+        expect(notification.params['foo'] as String, 'bar');
+        expect(notification.params['baz'] as String, 'bang');
+        completer.complete();
+      }
+
+      server.send('blahMethod', null);
+      server.listenToOutput(notificationProcessor: eventHandler);
+      await completer.future;
+    });
+  });
+
+  group('stop', () {
+    test('ok', () async {
+      final fakeOut = StreamController<List<int>>();
+      isolateChannel.stream = fakeOut.stream;
+      // ignore: unawaited_futures
+      isolateChannel.fakeIn.controller.stream.first.then((_) {
+        var encoded = json.encode({'id': '0'});
+        fakeOut.add(utf8.encoder.convert('$encoded\n'));
+      });
+      server.isolateExited.complete();
+      server.listenToOutput();
+      await server.stop(timeLimit: const Duration(milliseconds: 1));
+      expect(isolate.killed, isFalse);
+    });
+    test('stopped', () async {
+      final fakeOut = StreamController<List<int>>();
+      isolateChannel.stream = fakeOut.stream;
+
+      server.isolateExited.complete();
+      server.listenToOutput();
+      await server.stop(timeLimit: const Duration(milliseconds: 1));
+      expect(isolate.killed, isFalse);
+    });
+    test('kill', () async {
+      final fakeOut = StreamController<List<int>>();
+      isolateChannel.stream = fakeOut.stream;
+
+      server.listenToOutput();
+      await server.stop(timeLimit: const Duration(milliseconds: 10));
+      expect(isolate.killed, isTrue);
+    });
+  });
+}
+
+final _badErrorMessage = {
+  'code': 'UNKNOWN_REQUEST',
+  'message': 'something went wrong',
+  'stackTrace': 'some long stack trace'
+};
+
+Stream<List<int>> _badMessage() async* {
+  yield utf8.encoder.convert('Observatory listening on foo bar\n');
+  final sampleJson = {
+    'id': '0',
+    'error': _badErrorMessage,
+  };
+  yield utf8.encoder.convert(json.encode(sampleJson));
+}
+
+Stream<List<int>> _eventMessage() async* {
+  yield utf8.encoder.convert('Observatory listening on foo bar\n');
+  final sampleJson = {
+    'event': 'fooEvent',
+    'params': {'foo': 'bar', 'baz': 'bang'}
+  };
+  yield utf8.encoder.convert(json.encode(sampleJson));
+}
+
+Stream<List<int>> _goodMessage() async* {
+  yield utf8.encoder.convert('Observatory listening on foo bar\n');
+  final sampleJson = {
+    'id': '0',
+    'result': {'foo': 'bar'}
+  };
+  yield utf8.encoder.convert(json.encode(sampleJson));
+}
+
+class FakeIsolate implements Isolate {
+  bool killed = false;
+
+  @override
+  void addErrorListener(SendPort port) => throw UnimplementedError();
+
+  @override
+  void addOnExitListener(SendPort port, {Object response}) =>
+      throw UnimplementedError();
+
+  @override
+  SendPort get controlPort => throw UnimplementedError();
+
+  @override
+  String get debugName => throw UnimplementedError();
+
+  @override
+  Stream get errors => throw UnimplementedError();
+
+  @override
+  Capability get pauseCapability => throw UnimplementedError();
+
+  @override
+  void ping(SendPort port,
+          {Object response, int priority = Isolate.immediate}) =>
+      throw UnimplementedError();
+
+  @override
+  void removeErrorListener(SendPort port) => throw UnimplementedError();
+
+  @override
+  void removeOnExitListener(SendPort port) => throw UnimplementedError();
+
+  @override
+  void resume(Capability capability) => throw UnimplementedError();
+
+  @override
+  Capability get terminateCapability => throw UnimplementedError();
+
+  @override
+  void kill({int priority = Isolate.beforeNextEvent}) {
+    killed = true;
+  }
+
+  @override
+  Capability pause([Capability resumeCapability]) => throw UnimplementedError();
+
+  @override
+  void setErrorsFatal(bool errorsAreFatal) => throw UnimplementedError();
+}
+
+class FakeIsolateChannel<T> implements IsolateChannel<T> {
+  FakeIsolateInput fakeIn = FakeIsolateInput();
+
+  @override
+  StreamChannel<S> cast<S>() => throw UnimplementedError();
+
+  @override
+  StreamChannel<T> changeSink(
+          StreamSink<T> Function(StreamSink<T> sink) change) =>
+      throw UnimplementedError();
+
+  @override
+  StreamChannel<T> changeStream(Stream<T> Function(Stream<T> stream) change) =>
+      throw UnimplementedError();
+
+  @override
+  void pipe(StreamChannel<T> other) => throw UnimplementedError();
+
+  @override
+  StreamSink<T> get sink => fakeIn as StreamSink<T>;
+
+  @override
+  Stream<T> stream;
+
+  @override
+  StreamChannel<S> transform<S>(StreamChannelTransformer<S, T> transformer) =>
+      throw UnimplementedError();
+
+  @override
+  StreamChannel<T> transformSink(StreamSinkTransformer<T, T> transformer) =>
+      throw UnimplementedError();
+
+  @override
+  StreamChannel<T> transformStream(StreamTransformer<T, T> transformer) =>
+      throw UnimplementedError();
+}
+
+class FakeIsolateInput implements IOSink {
+  final controller = StreamController<String>();
+
+  @override
+  Encoding encoding;
+
+  @override
+  Future get done => null;
+
+  @override
+  void add(List<int> data) {
+    controller.add(utf8.decode(data));
+  }
+
+  @override
+  void addError(Object error, [StackTrace stackTrace]) {}
+
+  @override
+  Future addStream(Stream<List<int>> stream) => null;
+
+  @override
+  Future close() => null;
+
+  @override
+  Future flush() => null;
+
+  @override
+  void write(Object obj) {}
+
+  @override
+  void writeAll(Iterable objects, [String separator = '']) {}
+
+  @override
+  void writeCharCode(int charCode) {}
+
+  @override
+  void writeln([Object obj = '']) {}
+}
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index 1224e07..3f50cd6 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -292,8 +292,6 @@
 
   final _expressionChecks = <Expression, ExpressionChecksOrigin>{};
 
-  final _possiblyOptional = <DefaultFormalParameter, NullabilityNode>{};
-
   InstrumentedVariables(NullabilityGraph graph, TypeProvider typeProvider)
       : super(graph, typeProvider);
 
@@ -309,11 +307,6 @@
   DecoratedType decoratedExpressionType(Expression expression) =>
       _decoratedExpressionTypes[_normalizeExpression(expression)];
 
-  /// Gets the [NullabilityNode] associated with the possibility that
-  /// [parameter] may be optional.
-  NullabilityNode possiblyOptionalParameter(DefaultFormalParameter parameter) =>
-      _possiblyOptional[parameter];
-
   @override
   void recordConditionalDiscard(
       Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
@@ -333,13 +326,6 @@
     _expressionChecks[_normalizeExpression(expression)] = origin;
   }
 
-  @override
-  void recordPossiblyOptional(
-      Source source, DefaultFormalParameter parameter, NullabilityNode node) {
-    _possiblyOptional[parameter] = node;
-    super.recordPossiblyOptional(source, parameter, node);
-  }
-
   /// Unwraps any parentheses surrounding [expression].
   Expression _normalizeExpression(Expression expression) {
     while (expression is ParenthesizedExpression) {
@@ -422,10 +408,6 @@
         .having((cr) => cr.function, 'function', function);
   }
 
-  NullabilityNode possiblyOptionalParameter(String text) {
-    return variables.possiblyOptionalParameter(findNode.defaultParameter(text));
-  }
-
   void setUp() {
     DecoratedTypeParameterBounds.current = decoratedTypeParameterBounds;
     super.setUp();
diff --git a/pkg/nnbd_migration/test/node_builder_test.dart b/pkg/nnbd_migration/test/node_builder_test.dart
index 33013e5..082f902 100644
--- a/pkg/nnbd_migration/test/node_builder_test.dart
+++ b/pkg/nnbd_migration/test/node_builder_test.dart
@@ -1737,6 +1737,14 @@
         true);
   }
 
+  Future<void> test_variableDeclaration_late_hint_with_spaces() async {
+    await analyze('/* late */ int i;');
+    expect(
+        variables.isLateHinted(
+            testSource, findNode.variableDeclarationList('int i')),
+        true);
+  }
+
   Future<void> test_variableDeclaration_type_simple() async {
     await analyze('''
 main() {
diff --git a/pkg/nnbd_migration/test/test_all.dart b/pkg/nnbd_migration/test/test_all.dart
index 76a9844..b7902da 100644
--- a/pkg/nnbd_migration/test/test_all.dart
+++ b/pkg/nnbd_migration/test/test_all.dart
@@ -18,7 +18,9 @@
 import 'fantasyland/test_all.dart' as fantasyland;
 import 'fix_aggregator_test.dart' as fix_aggregator_test;
 import 'fix_builder_test.dart' as fix_builder_test;
+import 'fix_reason_target_test.dart' as fix_reason_target_test;
 import 'instrumentation_test.dart' as instrumentation_test;
+import 'isolate_server_test.dart' as isolate_server_test;
 import 'node_builder_test.dart' as node_builder_test;
 import 'nullability_node_test.dart' as nullability_node_test;
 import 'utilities/test_all.dart' as utilities;
@@ -37,7 +39,9 @@
     fantasyland.main();
     fix_aggregator_test.main();
     fix_builder_test.main();
+    fix_reason_target_test.main();
     instrumentation_test.main();
+    isolate_server_test.main();
     node_builder_test.main();
     nullability_node_test.main();
     utilities.main();
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 18134be..087dfe4 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -24,6 +24,8 @@
 analyzer/test/src/summary/resynthesize_kernel_test: Slow, Pass
 analyzer/test/src/task/strong/checker_test: Slow, Pass
 analyzer_plugin/test/plugin/folding_mixin_test: Slow, Pass
+dartdev/test/commands/analyze_test: Slow, Pass
+dartdev/test/commands/help_test: Slow, Pass
 dev_compiler/test/modular/*: Slow, Pass
 dev_compiler/test/options/*: Skip # test needs fixes
 dev_compiler/test/sourcemap/*: SkipByDesign # Skip sourcemap tests
@@ -53,6 +55,7 @@
 kernel/test/closures_test: Slow, Pass
 kernel/testcases/*: Skip # These are not tests but input for tests.
 vm/test/frontend_server_test: Slow, Pass
+vm/test/kernel_front_end_test: Skip # Issue http://dartbug.com/41489
 vm/test/transformations/type_flow/transformer_test: Slow, Pass
 vm/testcases/*: SkipByDesign # These are not tests but input for tests.
 
@@ -117,6 +120,7 @@
 analyzer/test/src/task/strong/inferred_type_test: Slow, Pass
 analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test: Slow, Pass
 analyzer_plugin/test/src/utilities/completion/optype_test: Slow, Pass
+dartdev/test/*: Slow, Pass
 mutation_observer: Skip # Skip tests on the VM if the package depends on dart:html
 
 [ $runtime != vm ]
diff --git a/pkg/smith/lib/builder.dart b/pkg/smith/lib/builder.dart
index 17b2e4e..673b0a9 100644
--- a/pkg/smith/lib/builder.dart
+++ b/pkg/smith/lib/builder.dart
@@ -97,11 +97,12 @@
   final System system;
   final Mode mode;
   final Architecture arch;
+  final Sanitizer sanitizer;
   final Runtime runtime;
   final List<Configuration> testedConfigurations;
 
   Builder(this.name, this.description, this.steps, this.system, this.mode,
-      this.arch, this.runtime, this.testedConfigurations);
+      this.arch, this.sanitizer, this.runtime, this.testedConfigurations);
 
   /// Create a [Builder] from its name, a list of 'step templates', the
   /// supported named configurations and a description.
@@ -115,6 +116,7 @@
     var systemName = _findPart(builderParts, System.names);
     var modeName = _findPart(builderParts, Mode.names);
     var archName = _findPart(builderParts, Architecture.names);
+    var sanitizerName = _findPart(builderParts, Sanitizer.names);
     var runtimeName = _findPart(builderParts, Runtime.names);
     var parsedSteps = steps
         .map((step) => Step.parse(
@@ -123,6 +125,7 @@
               "system": systemName,
               "mode": modeName,
               "arch": archName,
+              "sanitizer": sanitizerName,
               "runtime": runtimeName,
             },
             configurations))
@@ -135,6 +138,7 @@
         _findIfNotNull(System.find, systemName),
         _findIfNotNull(Mode.find, modeName),
         _findIfNotNull(Architecture.find, archName),
+        _findIfNotNull(Sanitizer.find, sanitizerName),
         _findIfNotNull(Runtime.find, runtimeName),
         testedConfigurations);
   }
@@ -157,7 +161,7 @@
 /// Replace the use of supported variable names with the their value given
 /// in [values] and throws an exception if an unsupported variable name is used.
 String _expandVariables(String string, Map<String, String> values) {
-  for (var variable in ["system", "mode", "arch", "runtime"]) {
+  for (var variable in ["system", "mode", "arch", "sanitizer", "runtime"]) {
     string = _tryReplace(string, variable, values[variable]);
   }
   return string;
diff --git a/pkg/test_runner/lib/src/co19_test_config.dart b/pkg/test_runner/lib/src/co19_test_config.dart
index 912545a..9a6337f 100644
--- a/pkg/test_runner/lib/src/co19_test_config.dart
+++ b/pkg/test_runner/lib/src/co19_test_config.dart
@@ -7,7 +7,7 @@
 import 'test_suite.dart';
 
 class Co19TestSuite extends StandardTestSuite {
-  static final _testRegExp = RegExp(r"t[0-9]{2}.dart$");
+  static final _testRegExp = RegExp(r"t[0-9]{2,3}.dart$");
 
   Co19TestSuite(TestConfiguration configuration, String selector)
       : super(configuration, selector, Path("tests/$selector/src"), [
diff --git a/pkg/test_runner/lib/src/configuration.dart b/pkg/test_runner/lib/src/configuration.dart
index b5cf4ea..239ffcd 100644
--- a/pkg/test_runner/lib/src/configuration.dart
+++ b/pkg/test_runner/lib/src/configuration.dart
@@ -39,6 +39,7 @@
       this.silentFailures,
       this.printTiming,
       this.printReport,
+      this.reportFailures,
       this.reportInJson,
       this.resetBrowser,
       this.skipCompilation,
@@ -89,6 +90,7 @@
   final bool silentFailures;
   final bool printTiming;
   final bool printReport;
+  final bool reportFailures;
   final bool reportInJson;
   final bool resetBrowser;
   final bool skipCompilation;
@@ -496,12 +498,11 @@
   static const silent = Progress._('silent');
   static const status = Progress._('status');
   static const buildbot = Progress._('buildbot');
-  static const diff = Progress._('diff');
 
   static final List<String> names = _all.keys.toList();
 
   static final _all = Map<String, Progress>.fromIterable(
-      [compact, color, line, verbose, silent, status, buildbot, diff],
+      [compact, color, line, verbose, silent, status, buildbot],
       key: (progress) => (progress as Progress).name);
 
   static Progress find(String name) {
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 80224dd..648bd24 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -202,7 +202,7 @@
         '''Progress indication mode.
 
 Allowed values are:
-compact, color, line, verbose, silent, status, buildbot, diff''',
+compact, color, line, verbose, silent, status, buildbot''',
         abbr: 'p',
         values: Progress.names,
         defaultsTo: Progress.compact.name,
@@ -211,6 +211,8 @@
     _Option.bool('report',
         'Print a summary report of the number of tests, by expectation.',
         hide: true),
+    _Option.bool('report_failures', 'Print a summary of the tests that failed.',
+        hide: true),
     _Option.int('tasks', 'The number of parallel tasks to run.',
         abbr: 'j', defaultsTo: Platform.numberOfProcessors),
     _Option.int('shards',
@@ -366,6 +368,7 @@
     'progress',
     'repeat',
     'report',
+    'report_failures',
     'safari',
     'shard',
     'shards',
@@ -612,9 +615,8 @@
     // Only one value in the configuration map is mutable:
     if (selectors.containsKey('observatory_ui')) {
       if (selectors.length == 1) {
-        configuration['packages'] = Repository.uri
-            .resolve('runtime/observatory/.packages')
-            .toFilePath();
+        configuration['packages'] =
+            Repository.uri.resolve('.packages').toFilePath();
       } else {
         // Make a new configuration whose selectors map only contains
         // observatory_ui, and remove observatory_ui from the original
@@ -627,9 +629,8 @@
         selectors.remove('observatory_ui');
 
         // Set the packages flag.
-        observatoryConfiguration['packages'] = Repository.uri
-            .resolve('runtime/observatory/.packages')
-            .toFilePath();
+        observatoryConfiguration['packages'] =
+            Repository.uri.resolve('.packages').toFilePath();
 
         return [
           ..._expandConfigurations(configuration, selectors),
@@ -726,6 +727,7 @@
           silentFailures: data["silent_failures"] as bool,
           printTiming: data["time"] as bool,
           printReport: data["report"] as bool,
+          reportFailures: data["report_failures"] as bool,
           reportInJson: data["report_in_json"] as bool,
           resetBrowser: data["reset_browser_configuration"] as bool,
           skipCompilation: data["skip_compilation"] as bool,
diff --git a/pkg/test_runner/lib/src/summary_report.dart b/pkg/test_runner/lib/src/summary_report.dart
index bde80df..81aef69 100644
--- a/pkg/test_runner/lib/src/summary_report.dart
+++ b/pkg/test_runner/lib/src/summary_report.dart
@@ -6,6 +6,7 @@
 
 import "package:status_file/expectation.dart";
 
+import "terminal.dart";
 import "test_case.dart";
 
 final summaryReport = SummaryReport();
@@ -125,6 +126,6 @@
 
   void printReport() {
     if (_total == 0) return;
-    print(report);
+    Terminal.print(report);
   }
 }
diff --git a/pkg/test_runner/lib/src/terminal.dart b/pkg/test_runner/lib/src/terminal.dart
new file mode 100644
index 0000000..a96c846
--- /dev/null
+++ b/pkg/test_runner/lib/src/terminal.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';
+
+// TODO(rnystrom): Move all print calls to go through this. Unify with DebugLog.
+/// Interface for the test runner printing output to the user.
+///
+/// It mainly exists to gracefully handle the inline progress indicator:
+///
+///     [00:08 | 100% | +  139 | -    3]
+///
+/// That does not print a newline at the end, but subsequent output should
+/// insert the newline before writing itself. This tracks whether that needs to
+/// be done.
+class Terminal {
+  static bool _needsNewline = false;
+
+  /// Prints [obj] to its own line.
+  ///
+  /// If this is called after a call to [writeLine], prints a newline first to
+  /// end that earlier line.
+  static void print(Object obj) {
+    finishLine();
+    stdout.writeln(obj);
+  }
+
+  /// Overwrites the current line with [obj].
+  ///
+  /// Does not output a newline at the end.
+  static void writeLine(Object obj) {
+    stdout.write('\r$obj');
+    _needsNewline = true;
+  }
+
+  /// If the last output was from [writeLine], finishes it by writing a newline.
+  static void finishLine() {
+    if (_needsNewline) stdout.writeln();
+    _needsNewline = false;
+  }
+}
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index cce2e8d..4a77be1 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -12,6 +12,7 @@
 import 'configuration.dart';
 import 'path.dart';
 import 'process_queue.dart';
+import 'terminal.dart';
 import 'test_progress.dart';
 import 'test_suite.dart';
 import 'utils.dart';
@@ -55,7 +56,7 @@
   // Extract global options from first configuration.
   var firstConf = configurations[0];
   var maxProcesses = firstConf.taskCount;
-  var progressIndicator = firstConf.progress;
+  var progress = firstConf.progress;
   BuildbotProgressIndicator.stepName = firstConf.stepName;
   var verbose = firstConf.isVerbose;
   var printTiming = firstConf.printTiming;
@@ -69,11 +70,13 @@
   // Print the configurations being run by this execution of
   // test.dart. However, don't do it if the silent progress indicator
   // is used.
-  if (progressIndicator != Progress.silent) {
-    print('Test configuration${configurations.length > 1 ? 's' : ''}:');
+  if (progress != Progress.silent) {
+    Terminal.print(
+        'Test configuration${configurations.length > 1 ? 's' : ''}:');
     for (var configuration in configurations) {
-      print("    ${configuration.configuration}");
-      print("Suites tested: ${configuration.selectors.keys.join(", ")}");
+      Terminal.print("    ${configuration.configuration}");
+      Terminal.print(
+          "Suites tested: ${configuration.selectors.keys.join(", ")}");
     }
   }
 
@@ -86,7 +89,8 @@
   if (configurations.length > 1 &&
       (configurations[0].testServerPort != 0 ||
           configurations[0].testServerCrossOriginPort != 0)) {
-    print("If the http server ports are specified, only one configuration"
+    Terminal.print(
+        "If the http server ports are specified, only one configuration"
         " may be run at a time");
     exit(1);
   }
@@ -154,9 +158,9 @@
   // we return from running here and just print.
   if (firstConf.listStatusFiles) {
     for (var suite in testSuites) {
-      print(suite.suiteName);
+      Terminal.print(suite.suiteName);
       for (var statusFile in suite.statusFilePaths.toSet()) {
-        print("\t$statusFile");
+        Terminal.print("\t$statusFile");
       }
     }
     return;
@@ -176,41 +180,41 @@
   var eventListener = <EventListener>[];
 
   // We don't print progress if we list tests.
-  if (progressIndicator != Progress.silent && !listTests) {
-    var printFailures = true;
+  if (progress != Progress.silent && !listTests) {
     var formatter = Formatter.normal;
-    if (progressIndicator == Progress.color) {
-      progressIndicator = Progress.compact;
+    if (progress == Progress.color) {
+      progress = Progress.compact;
       formatter = Formatter.color;
     }
-    if (progressIndicator == Progress.diff) {
-      progressIndicator = Progress.compact;
-      formatter = Formatter.color;
-      printFailures = false;
-      eventListener.add(StatusFileUpdatePrinter());
-    }
-    if (firstConf.silentFailures) {
-      printFailures = false;
-    }
+
     eventListener.add(SummaryPrinter());
-    if (printFailures) {
-      // The buildbot has it's own failure summary since it needs to wrap it
-      // into '@@@'-annotated sections.
-      var printFailureSummary = progressIndicator != Progress.buildbot;
-      eventListener.add(TestFailurePrinter(printFailureSummary, formatter));
+    if (!firstConf.silentFailures) {
+      eventListener.add(TestFailurePrinter(formatter));
     }
+
     if (firstConf.printPassingStdout) {
       eventListener.add(PassingStdoutPrinter(formatter));
     }
-    eventListener.add(ProgressIndicator.fromProgress(
-        progressIndicator, startTime, formatter));
+
+    var indicator =
+        ProgressIndicator.fromProgress(progress, startTime, formatter);
+    if (indicator != null) eventListener.add(indicator);
+
     if (printTiming) {
       eventListener.add(TimingPrinter(startTime));
     }
+
     eventListener.add(SkippedCompilationsPrinter());
-    if (progressIndicator == Progress.status) {
+
+    if (progress == Progress.status) {
       eventListener.add(TimedProgressPrinter());
     }
+
+    if (firstConf.reportFailures) {
+      eventListener.add(FailedTestsPrinter());
+    }
+
+    eventListener.add(ResultCountPrinter(formatter));
   }
 
   if (firstConf.writeResults) {
diff --git a/pkg/test_runner/lib/src/test_progress.dart b/pkg/test_runner/lib/src/test_progress.dart
index 8fbc394..7faf841 100644
--- a/pkg/test_runner/lib/src/test_progress.dart
+++ b/pkg/test_runner/lib/src/test_progress.dart
@@ -13,6 +13,7 @@
 import 'configuration.dart';
 import 'path.dart';
 import 'summary_report.dart';
+import 'terminal.dart';
 import 'test_case.dart';
 import 'utils.dart';
 
@@ -81,9 +82,10 @@
 
   void callback(Timer timer) {
     if (_allKnown) {
-      print('$_numCompleted out of $_numTests completed');
+      Terminal.print('$_numCompleted out of $_numTests completed');
     }
-    print("Tests running for ${(interval * timer.tick).inMinutes} minutes");
+    Terminal.print(
+        "Tests running for ${(interval * timer.tick).inMinutes} minutes");
   }
 
   void testAdded() => _numTests++;
@@ -104,10 +106,11 @@
     if (test.lastCommandOutput.result(test) == Expectation.ignore) {
       countIgnored++;
       if (countIgnored > maxIgnored) {
-        print("\nMore than $maxIgnored tests were ignored due to flakes in");
-        print("the test infrastructure. Notify dart-engprod@.");
-        print("Output of the last ignored test was:");
-        print(_buildFailureOutput(test));
+        Terminal.print(
+            "\nMore than $maxIgnored tests were ignored due to flakes in");
+        Terminal.print("the test infrastructure. Notify dart-engprod@.");
+        Terminal.print("Output of the last ignored test was:");
+        Terminal.print(_buildFailureOutput(test));
         exit(1);
       }
     }
@@ -115,7 +118,7 @@
 
   void allDone() {
     if (countIgnored > 0) {
-      print("Ignored $countIgnored tests due to flaky infrastructure");
+      Terminal.print("Ignored $countIgnored tests due to flaky infrastructure");
     }
   }
 }
@@ -184,14 +187,14 @@
           unexpectedCrashesFile.writeStringSync(
               "${test.displayName},$pid,${binaries.join(',')}\n");
         } catch (e) {
-          print('Failed to add crash to unexpected-crashes list: $e');
+          Terminal.print('Failed to add crash to unexpected-crashes list: $e');
         } finally {
           try {
             if (unexpectedCrashesFile != null) {
               unexpectedCrashesFile.closeSync();
             }
           } catch (e) {
-            print('Failed to close unexpected-crashes file: $e');
+            Terminal.print('Failed to close unexpected-crashes file: $e');
           }
         }
       }
@@ -206,8 +209,8 @@
 
   void allTestsKnown() {
     if (jsonOnly) {
-      print("JSON:");
-      print(jsonEncode(summaryReport.values));
+      Terminal.print("JSON:");
+      Terminal.print(jsonEncode(summaryReport.values));
     } else {
       summaryReport.printReport();
     }
@@ -232,7 +235,7 @@
 
   void allDone() {
     var d = DateTime.now().difference(_startTime);
-    print('\n--- Total time: ${_timeString(d)} ---');
+    Terminal.print('\n--- Total time: ${_timeString(d)} ---');
     var outputs = _commandOutputs.toList();
     outputs.sort((a, b) {
       return b.time.inMilliseconds - a.time.inMilliseconds;
@@ -246,75 +249,13 @@
         return "${testCase.configurationString}/${testCase.displayName}";
       }).join(', ');
 
-      print('${commandOutput.time} - '
+      Terminal.print('${commandOutput.time} - '
           '${command.displayName} - '
           '$testCasesDescription');
     }
   }
 }
 
-class StatusFileUpdatePrinter extends EventListener {
-  final Map<String, List<String>> statusToConfigs = {};
-
-  void done(TestCase test) {
-    if (test.unexpectedOutput) {
-      _printFailureOutput(test);
-    }
-  }
-
-  void allDone() {
-    _printFailureSummary();
-  }
-
-  void _printFailureOutput(TestCase test) {
-    var status = '${test.displayName}: ${test.result}';
-    var configs = statusToConfigs.putIfAbsent(status, () => <String>[]);
-    configs.add(test.configurationString);
-    if (test.lastCommandOutput.hasTimedOut) {
-      print('\n${test.displayName} timed out on ${test.configurationString}');
-    }
-  }
-
-  String _extractRuntime(String configuration) {
-    // Extract runtime from a configuration, for example,
-    // 'none-vm-checked release_ia32'.
-    var runtime = configuration.split(' ')[0].split('-');
-    return '${runtime[0]}-${runtime[1]}';
-  }
-
-  void _printFailureSummary() {
-    var groupedStatuses = <String, List<String>>{};
-    statusToConfigs.forEach((status, configs) {
-      var runtimeToConfiguration = <String, List<String>>{};
-      for (var config in configs) {
-        var runtime = _extractRuntime(config);
-        runtimeToConfiguration
-            .putIfAbsent(runtime, () => <String>[])
-            .add(config);
-      }
-
-      runtimeToConfiguration.forEach((runtime, runtimeConfigs) {
-        runtimeConfigs.sort((a, b) => a.compareTo(b));
-        var statuses = groupedStatuses.putIfAbsent(
-            '$runtime: $runtimeConfigs', () => <String>[]);
-        statuses.add(status);
-      });
-    });
-
-    if (groupedStatuses.isEmpty) return;
-
-    print('\n\nNecessary status file updates:');
-    groupedStatuses.forEach((String config, List<String> statuses) {
-      print('');
-      print('$config:');
-      statuses.sort((a, b) => a.compareTo(b));
-      for (var status in statuses) {
-        print('  $status');
-      }
-    });
-  }
-}
-
 class SkippedCompilationsPrinter extends EventListener {
   int _skippedCompilations = 0;
 
@@ -326,64 +267,84 @@
 
   void allDone() {
     if (_skippedCompilations > 0) {
-      print('\n$_skippedCompilations compilations were skipped because '
+      Terminal.print(
+          '\n$_skippedCompilations compilations were skipped because '
           'the previous output was already up to date.\n');
     }
   }
 }
 
-class LineProgressIndicator extends EventListener {
+class TestFailurePrinter extends EventListener {
+  final Formatter _formatter;
+
+  TestFailurePrinter([this._formatter = Formatter.normal]);
+
   void done(TestCase test) {
-    var status = 'pass';
-    if (test.unexpectedOutput) {
-      status = 'fail';
+    if (!test.unexpectedOutput) return;
+    for (var line in _buildFailureOutput(test, _formatter)) {
+      Terminal.print(line);
     }
-    print('Done ${test.configurationString} ${test.displayName}: $status');
   }
 }
 
-class TestFailurePrinter extends EventListener {
-  final bool _printSummary;
+/// Prints a one-line summary of passed and failed tests.
+class ResultCountPrinter extends EventListener {
   final Formatter _formatter;
-  final _failureSummary = <String>[];
   int _failedTests = 0;
   int _passedTests = 0;
 
-  TestFailurePrinter(this._printSummary, [this._formatter = Formatter.normal]);
+  ResultCountPrinter(this._formatter);
 
   void done(TestCase test) {
     if (test.unexpectedOutput) {
       _failedTests++;
-      var lines = _buildFailureOutput(test, _formatter);
-      for (var line in lines) {
-        print(line);
-      }
-      print('');
-      if (_printSummary) {
-        _failureSummary.addAll(lines);
-        _failureSummary.add('');
-      }
     } else {
       _passedTests++;
     }
   }
 
   void allDone() {
-    if (!_printSummary || _failureSummary.isEmpty) return;
+    var suffix = _passedTests != 1 ? 's' : '';
+    var passed =
+        '${_formatter.passed(_passedTests.toString())} test$suffix passed';
 
-    // Don't bother showing the summary if it's longer than the number of lines
-    // of successful test output. The benefit of the summary is that it saves
-    // you from scrolling past lots of passed tests to find the few failures.
-    // If most of the output *is* failures, showing them *twice* just makes it
-    // worse.
-    if (_passedTests <= _failureSummary.length) return;
-
-    print('\n=== Failure summary:\n');
-    for (var line in _failureSummary) {
-      print(line);
+    String summary;
+    if (_failedTests == 0) {
+      summary = 'All $passed';
+    } else {
+      summary = '$passed, ${_formatter.failed(_failedTests.toString())} failed';
     }
-    print('');
-    print(_buildSummaryEnd(_formatter, _failedTests));
+
+    var marker = _formatter.section('===');
+    Terminal.print('\n$marker $summary $marker');
+  }
+}
+
+/// Prints a list of the tests that failed.
+class FailedTestsPrinter extends EventListener {
+  final List<TestCase> _failedTests = [];
+
+  FailedTestsPrinter();
+
+  void done(TestCase test) {
+    if (test.unexpectedOutput) {
+      _failedTests.add(test);
+    }
+  }
+
+  void allDone() {
+    if (_failedTests.isEmpty) return;
+
+    Terminal.print('');
+    Terminal.print('=== Failed tests ===');
+    for (var test in _failedTests) {
+      var result = test.realResult.toString();
+      if (test.realExpected != Expectation.pass) {
+        result += ' (expected ${test.realExpected})';
+      }
+
+      Terminal.print('${test.displayName}: $result');
+    }
   }
 }
 
@@ -403,7 +364,7 @@
         commandOutput.describe(test, test.configuration.progress, output);
       }
       for (var line in lines) {
-        print(line);
+        Terminal.print(line);
       }
     }
   }
@@ -411,7 +372,7 @@
   void allDone() {}
 }
 
-class ProgressIndicator extends EventListener {
+abstract class ProgressIndicator extends EventListener {
   final DateTime _startTime;
   int _foundTests = 0;
   int _passedTests = 0;
@@ -426,11 +387,10 @@
       case Progress.compact:
         return CompactProgressIndicator(startTime, formatter);
       case Progress.line:
-        return LineProgressIndicator();
       case Progress.verbose:
-        return VerboseProgressIndicator(startTime);
+        return LineProgressIndicator(startTime);
       case Progress.status:
-        return ProgressIndicator(startTime);
+        return null;
       case Progress.buildbot:
         return BuildbotProgressIndicator(startTime);
     }
@@ -455,25 +415,13 @@
     _allTestsKnown = true;
   }
 
-  void _printDoneProgress(TestCase test) {}
+  void _printDoneProgress(TestCase test);
 
-  int _completedTests() => _passedTests + _failedTests;
+  int get _completedTests => _passedTests + _failedTests;
 }
 
 abstract class CompactIndicator extends ProgressIndicator {
   CompactIndicator(DateTime startTime) : super(startTime);
-
-  void allDone() {
-    if (_failedTests > 0) {
-      // We may have printed many failure logs, so reprint the summary data.
-      _printProgress();
-    }
-    print('');
-  }
-
-  void _printDoneProgress(TestCase test) => _printProgress();
-
-  void _printProgress();
 }
 
 class CompactProgressIndicator extends CompactIndicator {
@@ -482,8 +430,8 @@
   CompactProgressIndicator(DateTime startTime, this._formatter)
       : super(startTime);
 
-  void _printProgress() {
-    var percent = ((_completedTests() / _foundTests) * 100).toInt().toString();
+  void _printDoneProgress(TestCase testCase) {
+    var percent = ((_completedTests / _foundTests) * 100).toInt().toString();
     var progressPadded = (_allTestsKnown ? percent : '--').padLeft(3);
     var passedPadded = _passedTests.toString().padLeft(5);
     var failedPadded = _failedTests.toString().padLeft(5);
@@ -491,58 +439,48 @@
     var progressLine = '\r[${_timeString(elapsed)} | $progressPadded% | '
         '+${_formatter.passed(passedPadded)} | '
         '-${_formatter.failed(failedPadded)}]';
-    stdout.write(progressLine);
+    Terminal.writeLine(progressLine);
+  }
+
+  void allDone() {
+    Terminal.finishLine();
   }
 }
 
-class VerboseProgressIndicator extends ProgressIndicator {
-  VerboseProgressIndicator(DateTime startTime) : super(startTime);
+class LineProgressIndicator extends ProgressIndicator {
+  LineProgressIndicator(DateTime startTime) : super(startTime);
 
   void _printDoneProgress(TestCase test) {
     var status = 'pass';
     if (test.unexpectedOutput) {
       status = 'fail';
     }
-    print('Done ${test.configurationString} ${test.displayName}: $status');
+    Terminal.print(
+        'Done ${test.configurationString} ${test.displayName}: $status');
   }
 }
 
 class BuildbotProgressIndicator extends ProgressIndicator {
   static String stepName;
-  final _failureSummary = <String>[];
 
   BuildbotProgressIndicator(DateTime startTime) : super(startTime);
 
-  void done(TestCase test) {
-    super.done(test);
-    if (test.unexpectedOutput) {
-      _failureSummary.addAll(_buildFailureOutput(test));
-    }
-  }
-
   void _printDoneProgress(TestCase test) {
     var status = 'pass';
     if (test.unexpectedOutput) {
       status = 'fail';
     }
-    var percent = ((_completedTests() / _foundTests) * 100).toInt().toString();
-    print('Done ${test.configurationString} ${test.displayName}: $status');
-    print('@@@STEP_CLEAR@@@');
-    print('@@@STEP_TEXT@ $percent% +$_passedTests -$_failedTests @@@');
+    var percent = ((_completedTests / _foundTests) * 100).toInt().toString();
+    Terminal.print(
+        'Done ${test.configurationString} ${test.displayName}: $status');
+    Terminal.print('@@@STEP_CLEAR@@@');
+    Terminal.print('@@@STEP_TEXT@ $percent% +$_passedTests -$_failedTests @@@');
   }
 
   void allDone() {
-    if (!_failureSummary.isEmpty) {
-      print('@@@STEP_FAILURE@@@');
-      if (stepName != null) {
-        print('@@@BUILD_STEP $stepName failures@@@');
-      }
-      for (var line in _failureSummary) {
-        print(line);
-      }
-      print('');
-    }
-    print(_buildSummaryEnd(Formatter.normal, _failedTests));
+    if (_failedTests == 0) return;
+    Terminal.print('@@@STEP_FAILURE@@@');
+    if (stepName != null) Terminal.print('@@@BUILD_STEP $stepName failures@@@');
   }
 }
 
@@ -692,16 +630,6 @@
   output.write(arguments.map(escapeCommandLineArgument).join(' '));
 }
 
-String _buildSummaryEnd(Formatter formatter, int failedTests) {
-  if (failedTests == 0) {
-    return formatter.passed('\n===\n=== All tests succeeded\n===\n');
-  } else {
-    var pluralSuffix = failedTests != 1 ? 's' : '';
-    return formatter
-        .failed('\n===\n=== $failedTests test$pluralSuffix failed\n===\n');
-  }
-}
-
 /// Writes a results.json file with a line for each test.
 /// Each line is a json map with the test name and result and expected result.
 class ResultWriter extends EventListener {
diff --git a/pkg/test_runner/tool/update_static_error_tests.dart b/pkg/test_runner/tool/update_static_error_tests.dart
index 56ad830..fcdd01d 100644
--- a/pkg/test_runner/tool/update_static_error_tests.dart
+++ b/pkg/test_runner/tool/update_static_error_tests.dart
@@ -165,14 +165,24 @@
   var errors = <StaticError>[];
   if (insertAnalyzer) {
     stdout.write("\r${file.path} (Running analyzer...)");
-    errors.addAll(await runAnalyzer(file.absolute.path, options));
+    var fileErrors = await runAnalyzer(file.absolute.path, options);
+    if (fileErrors == null) {
+      print("Error: failed to update ${file.path}");
+    } else {
+      errors.addAll(fileErrors);
+    }
   }
 
   if (insertCfe) {
     // Clear the previous line.
     stdout.write("\r${file.path}                      ");
     stdout.write("\r${file.path} (Running CFE...)");
-    errors.addAll(await runCfe(file.absolute.path, options));
+    var fileErrors = await runCfe(file.absolute.path, options);
+    if (fileErrors == null) {
+      print("Error: failed to update ${file.path}");
+    } else {
+      errors.addAll(fileErrors);
+    }
   }
 
   errors = StaticError.simplify(errors);
@@ -203,6 +213,15 @@
         "--format=machine",
         path,
       ]);
+
+  // Analyzer returns 3 when it detects errors, 2 when it detects
+  // warnings and --fatal-warnings is enabled, 1 when it detects
+  // hints and --fatal-hints or --fatal-infos are enabled.
+  if (result.exitCode < 0 || result.exitCode > 3) {
+    print("Analyzer run failed: ${result.stdout}\n${result.stderr}");
+    return null;
+  }
+
   var errors = <StaticError>[];
   AnalysisCommandOutput.parseErrors(result.stderr as String, errors);
   return errors;
@@ -223,9 +242,16 @@
     path,
   ]);
 
-  // TODO(karlklose): handle exit codes != 0. This can happen if the dart
-  // executable is not compatible with the kernel package version.
-
+  // Running the above command may generate a dill file next to the test, which
+  // we don't want, so delete it if present.
+  var file = File("$path.dill");
+  if (await file.exists()) {
+    await file.delete();
+  }
+  if (result.exitCode != 0) {
+    print("CFE run failed: ${result.stdout}\n${result.stderr}");
+    return null;
+  }
   var errors = <StaticError>[];
   FastaCommandOutput.parseErrors(result.stdout as String, errors);
   return errors;
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index 10eeeaa..841f84b 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.dart
@@ -78,12 +78,14 @@
 
   _combinePendingDeltas(bool includePlatform) {
     Procedure mainMethod;
+    NonNullableByDefaultCompiledMode compilationMode;
     Map<Uri, Library> combined = <Uri, Library>{};
     Map<Uri, Source> uriToSource = new Map<Uri, Source>();
     for (Component delta in _pendingDeltas) {
       if (delta.mainMethod != null) {
         mainMethod = delta.mainMethod;
       }
+      compilationMode = delta.mode;
       uriToSource.addAll(delta.uriToSource);
       for (Library library in delta.libraries) {
         bool isPlatform =
@@ -96,7 +98,7 @@
     // TODO(vegorov) this needs to merge metadata repositories from deltas.
     return new Component(
         libraries: combined.values.toList(), uriToSource: uriToSource)
-      ..mainMethod = mainMethod;
+      ..setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
   }
 
   CoreTypes getCoreTypes() => _generator.getCoreTypes();
@@ -131,7 +133,8 @@
     _lastKnownGood = new Component(
       libraries: combined.values.toList(),
       uriToSource: uriToSource,
-    )..mainMethod = candidate.mainMethod;
+    )..setMainMethodAndMode(
+        candidate.mainMethod?.reference, true, candidate.mode);
     for (final repo in candidate.metadata.values) {
       _lastKnownGood.addMetadataRepository(repo);
     }
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index e9bb876..48605b1 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -78,6 +78,8 @@
   args.addOption('depfile', help: 'Path to output Ninja depfile');
   args.addFlag('link-platform',
       help: 'Include platform into resulting kernel file.', defaultsTo: true);
+  args.addFlag('minimal-kernel',
+      help: 'Produce minimal tree-shaken kernel file.', defaultsTo: false);
   args.addFlag('embed-sources',
       help: 'Embed source files in the generated kernel component',
       defaultsTo: true);
@@ -167,6 +169,7 @@
   final bool nullSafety = options['null-safety'];
   final bool useProtobufTreeShaker = options['protobuf-tree-shaker'];
   final bool splitOutputByPackages = options['split-output-by-packages'];
+  final bool minimalKernel = options['minimal-kernel'];
   final List<String> experimentalFlags = options['enable-experiment'];
   final Map<String, String> environmentDefines = {};
 
@@ -242,7 +245,8 @@
       genBytecode: genBytecode,
       bytecodeOptions: bytecodeOptions,
       dropAST: dropAST && !splitOutputByPackages,
-      useProtobufTreeShaker: useProtobufTreeShaker);
+      useProtobufTreeShaker: useProtobufTreeShaker,
+      minimalKernel: minimalKernel);
 
   errorPrinter.printCompilationMessages();
 
@@ -255,7 +259,10 @@
   }
 
   final IOSink sink = new File(outputFileName).openWrite();
-  final BinaryPrinter printer = new BinaryPrinter(sink);
+  final BinaryPrinter printer = new BinaryPrinter(sink,
+      libraryFilter: minimalKernel
+          ? ((lib) => !results.loadedLibraries.contains(lib))
+          : null);
   printer.writeComponentFile(results.component);
   await sink.close();
 
@@ -314,7 +321,8 @@
     bool genBytecode: false,
     BytecodeOptions bytecodeOptions,
     bool dropAST: false,
-    bool useProtobufTreeShaker: false}) async {
+    bool useProtobufTreeShaker: false,
+    bool minimalKernel: false}) async {
   // Replace error handler to detect if there are compilation errors.
   final errorDetector =
       new ErrorDetector(previousErrorHandler: options.onDiagnostic);
@@ -325,21 +333,32 @@
 
   CompilerResult compilerResult = await kernelForProgram(source, options);
   Component component = compilerResult?.component;
-  final compiledSources = component?.uriToSource?.keys;
+  Iterable<Uri> compiledSources = component?.uriToSource?.keys;
 
   Set<Library> loadedLibraries = createLoadedLibrariesSet(
       compilerResult?.loadedComponents, compilerResult?.sdkComponent,
       includePlatform: includePlatform);
 
   // Run global transformations only if component is correct.
-  if (aot && component != null) {
+  if ((aot || minimalKernel) && component != null) {
     await runGlobalTransformations(
         options.target,
         component,
         useGlobalTypeFlowAnalysis,
         enableAsserts,
         useProtobufTreeShaker,
-        errorDetector);
+        errorDetector,
+        minimalKernel: minimalKernel);
+
+    if (minimalKernel) {
+      // compiledSources is component.uriToSource.keys.
+      // Make a copy of compiledSources to detach it from
+      // component.uriToSource which is cleared below.
+      compiledSources = compiledSources.toList();
+
+      component.metadata.clear();
+      component.uriToSource.clear();
+    }
   }
 
   if (genBytecode && !errorDetector.hasCompilationErrors && component != null) {
@@ -404,7 +423,8 @@
     bool useGlobalTypeFlowAnalysis,
     bool enableAsserts,
     bool useProtobufTreeShaker,
-    ErrorDetector errorDetector) async {
+    ErrorDetector errorDetector,
+    {bool minimalKernel: false}) async {
   if (errorDetector.hasCompilationErrors) return;
 
   final coreTypes = new CoreTypes(component);
@@ -422,7 +442,8 @@
   unreachable_code_elimination.transformComponent(component, enableAsserts);
 
   if (useGlobalTypeFlowAnalysis) {
-    globalTypeFlow.transformComponent(target, coreTypes, component);
+    globalTypeFlow.transformComponent(target, coreTypes, component,
+        treeShakeSignatures: !minimalKernel);
   } else {
     devirtualization.transformComponent(coreTypes, component);
     no_dynamic_invocations_annotator.transformComponent(component);
@@ -436,7 +457,8 @@
     protobuf_tree_shaker.removeUnusedProtoReferences(
         component, coreTypes, null);
 
-    globalTypeFlow.transformComponent(target, coreTypes, component);
+    globalTypeFlow.transformComponent(target, coreTypes, component,
+        treeShakeSignatures: !minimalKernel);
   }
 
   // TODO(35069): avoid recomputing CSA by reading it from the platform files.
@@ -730,12 +752,13 @@
 
   final mainMethod = component.mainMethod;
   final problemsAsJson = component.problemsAsJson;
-  component.mainMethod = null;
+  final compilationMode = component.mode;
+  component.setMainMethodAndMode(null, true, compilationMode);
   component.problemsAsJson = null;
   for (String package in packages.keys) {
     await action(package, packages[package]);
   }
-  component.mainMethod = mainMethod;
+  component.setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
   component.problemsAsJson = problemsAsJson;
 
   if (!mainFirst) {
diff --git a/pkg/vm/lib/transformations/devirtualization.dart b/pkg/vm/lib/transformations/devirtualization.dart
index 43c9179..acbfa39 100644
--- a/pkg/vm/lib/transformations/devirtualization.dart
+++ b/pkg/vm/lib/transformations/devirtualization.dart
@@ -57,9 +57,14 @@
       return false;
     }
 
-    if (arguments.named.isNotEmpty) {
+    if (arguments.named.isNotEmpty || func.namedParameters.isNotEmpty) {
       final names = arguments.named.map((v) => v.name).toSet();
-      names.removeAll(func.namedParameters.map((v) => v.name));
+      for (var param in func.namedParameters) {
+        final passed = names.remove(param.name);
+        if (param.isRequired && !passed) {
+          return false;
+        }
+      }
       if (names.isNotEmpty) {
         return false;
       }
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index ee3028d..696b5f6 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -67,9 +67,15 @@
   final LibraryIndex index =
       LibraryIndex(component, const ["dart:ffi", "dart:core"]);
   if (!index.containsLibrary("dart:ffi")) {
+    // TODO: This check doesn't make sense: "dart:ffi" is always loaded/created
+    // for the VM target.
     // If dart:ffi is not loaded, do not do the transformation.
     return ReplacedMembers({}, {});
   }
+  if (index.tryGetClass('dart:ffi', 'NativeFunction') == null) {
+    // If dart:ffi is not loaded (for real): do not do the transformation.
+    return ReplacedMembers({}, {});
+  }
   final transformer = new _FfiDefinitionTransformer(index, coreTypes, hierarchy,
       diagnosticReporter, referenceFromIndex, changedStructureNotifier);
   libraries.forEach(transformer.visitLibrary);
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 9ac20c8..aec594f 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -38,9 +38,15 @@
     ReferenceFromIndex referenceFromIndex) {
   final index = new LibraryIndex(component, ["dart:ffi"]);
   if (!index.containsLibrary("dart:ffi")) {
+    // TODO: This check doesn't make sense: "dart:ffi" is always loaded/created
+    // for the VM target.
     // If dart:ffi is not loaded, do not do the transformation.
     return;
   }
+  if (index.tryGetClass('dart:ffi', 'NativeFunction') == null) {
+    // If dart:ffi is not loaded (for real): do not do the transformation.
+    return;
+  }
   final transformer = new _FfiUseSiteTransformer(
       index,
       coreTypes,
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 651e5f5..6d591f5 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -230,6 +230,9 @@
           // does not throw exception.
           initializerResult = new Type.nullable(initializerResult);
         }
+        if (kPrintTrace) {
+          tracePrint("Result of ${field} initializer: $initializerResult");
+        }
         fieldValue.setValue(initializerResult, typeFlowAnalysis,
             field.isStatic ? null : args.receiver);
         fieldValue.isInitialized = true;
@@ -989,7 +992,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 AnyType);
+      assertx(translated is RuntimeType || translated is UnknownType);
       result[i] = translated;
     }
     cachedFlattenedTypeArgsForNonGeneric[klass] = result;
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index 17f01c6..0b4ab0f 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -339,7 +339,7 @@
 
     void extractType(ConcreteType c) {
       if (c.typeArgs == null) {
-        extractedType = const AnyType();
+        extractedType = const UnknownType();
       } else {
         final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
             c.cls.classNode, referenceClass);
@@ -364,12 +364,12 @@
             }
           }
         } else {
-          assertx(typeArg is AnyType);
+          assertx(typeArg is UnknownType);
         }
         if (extractedType == null || extracted == extractedType) {
           extractedType = extracted;
         } else {
-          extractedType = const AnyType();
+          extractedType = const UnknownType();
         }
       }
     }
@@ -381,7 +381,7 @@
       argType.types.forEach(extractType);
     }
 
-    return extractedType ?? const AnyType();
+    return extractedType ?? const UnknownType();
   }
 }
 
@@ -414,7 +414,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 AnyType);
+      assertx(computed is RuntimeType || computed is UnknownType);
       if (computed is RuntimeType) hasRuntimeType = true;
       types[i] = computed;
     }
@@ -424,7 +424,7 @@
 
 // Similar to "CreateConcreteType", but creates a "RuntimeType" rather than a
 // "ConcreteType". Unlike a "ConcreteType", none of the type arguments can be
-// missing ("AnyType").
+// missing ("UnknownType").
 class CreateRuntimeType extends Statement {
   final Class klass;
   final Nullability nullability;
@@ -446,8 +446,8 @@
     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 AnyType);
-      if (computed is AnyType) return const AnyType();
+      assertx(computed is RuntimeType || computed is UnknownType);
+      if (computed is UnknownType) return const UnknownType();
       types[i] = computed;
     }
     return new RuntimeType(new InterfaceType(klass, nullability), types);
@@ -501,11 +501,11 @@
     Type argType = arg.getComputedType(computedTypes);
     Type checkType = type.getComputedType(computedTypes);
     // TODO(sjindel/tfa): Narrow the result if possible.
-    assertx(checkType is AnyType || checkType is RuntimeType);
+    assertx(checkType is UnknownType || checkType is RuntimeType);
 
     bool canSkip = true; // Can this check be skipped on this invocation.
 
-    if (checkType is AnyType) {
+    if (checkType is UnknownType) {
       // If we don't know what the RHS of the check is going to be, we can't
       // guarantee that it will pass.
       canSkip = false;
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index f0cf458..46a0e48 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -584,7 +584,8 @@
 
   Summary createSummary(Member member,
       {fieldSummaryType: FieldSummaryType.kInitializer}) {
-    debugPrint("===== ${member} =====");
+    debugPrint(
+        "===== ${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""} =====");
     assertx(!member.isAbstract);
 
     _staticTypeContext = new StaticTypeContext(member, _environment);
@@ -779,7 +780,7 @@
 
     final numTypeParameters = numTypeParams(member);
     for (int i = 0; i < numTypeParameters; ++i) {
-      args.add(const AnyType());
+      args.add(const UnknownType());
     }
 
     if (hasReceiverArg(member)) {
@@ -2175,16 +2176,16 @@
     final flattenedTypeExprs = new List<TypeExpr>(flattenedTypeArgs.length);
 
     bool createConcreteType = true;
-    bool allAnyType = true;
+    bool allUnknown = true;
     for (int i = 0; i < flattenedTypeArgs.length; ++i) {
       final typeExpr =
           translate(substitution.substituteType(flattenedTypeArgs[i]));
-      if (typeExpr != const AnyType()) allAnyType = false;
+      if (typeExpr is! UnknownType) allUnknown = false;
       if (typeExpr is Statement) createConcreteType = false;
       flattenedTypeExprs[i] = typeExpr;
     }
 
-    if (allAnyType) return type;
+    if (allUnknown) return type;
 
     if (createConcreteType) {
       return new ConcreteType(
@@ -2199,7 +2200,7 @@
   // Creates a TypeExpr representing the set of types which can flow through a
   // given DartType.
   //
-  // Will return AnyType, RuntimeType or Statement.
+  // Will return UnknownType, RuntimeType or Statement.
   TypeExpr translate(DartType type) {
     final cached = typesCache[type];
     if (cached != null) return cached;
@@ -2209,18 +2210,19 @@
     //   class A<T> extends Comparable<A<T>> {}
     //
     // Creating the factored type arguments of A will lead to an infinite loop.
-    // We break such loops by inserting an 'AnyType' in place of the currently
+    // We break such loops by inserting an 'UnknownType' in place of the currently
     // processed type, ensuring we try to build 'A<T>' in the process of
     // building 'A<T>'.
-    typesCache[type] = const AnyType();
+    typesCache[type] = const UnknownType();
     final result = type.accept(this);
-    assertx(result is AnyType || result is RuntimeType || result is Statement);
+    assertx(
+        result is UnknownType || result is RuntimeType || result is Statement);
     typesCache[type] = result;
     return result;
   }
 
   @override
-  TypeExpr defaultDartType(DartType node) => const AnyType();
+  TypeExpr defaultDartType(DartType node) => const UnknownType();
 
   @override
   TypeExpr visitDynamicType(DynamicType type) => new RuntimeType(type, null);
@@ -2248,7 +2250,7 @@
     for (var i = 0; i < flattenedTypeArgs.length; ++i) {
       final typeExpr =
           translate(substitution.substituteType(flattenedTypeArgs[i]));
-      if (typeExpr == const AnyType()) return const AnyType();
+      if (typeExpr == const UnknownType()) return const UnknownType();
       if (typeExpr is! RuntimeType) createRuntimeType = false;
       flattenedTypeExprs[i] = typeExpr;
     }
@@ -2271,7 +2273,7 @@
       final result = functionTypeVariables[type.parameter];
       if (result != null) return result;
     }
-    if (type.parameter.parent is! Class) return const AnyType();
+    if (type.parameter.parent is! Class) return const UnknownType();
     final interfaceClass = type.parameter.parent as Class;
     assertx(receiver != null);
     // Undetermined nullability is equivalent to nonNullable when
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 296bc42..3a3d400 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -190,7 +190,8 @@
     if (type is ConcreteType && type.typeArgs != null) {
       typeArgs = type.typeArgs
           .take(type.numImmediateTypeArgs)
-          .map((t) => t is AnyType ? null : (t as RuntimeType).representedType)
+          .map((t) =>
+              t is UnknownType ? null : (t as RuntimeType).representedType)
           .toList();
     }
 
@@ -256,7 +257,7 @@
 
     // If the call is not marked as 'isResultUsed', the 'resultType' will
     // not be observed (i.e., it will always be EmptyType). This is the
-    // case even if the result acutally might be used but is not used by
+    // case even if the result actually might be used but is not used by
     // the summary, e.g. if the result is an argument to a closure call.
     // Therefore, we need to pass in 'NullableType(AnyType)' as the
     // inferred result type here (since we don't know what it actually
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 771f18c..dceb628 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -93,7 +93,7 @@
       if (bound is TypeParameterType) {
         result = const AnyType();
       } else {
-        return fromStaticType(bound, canBeNull);
+        result = fromStaticType(bound, canBeNull);
       }
     } else {
       throw 'Unexpected type ${type.runtimeType} $type';
@@ -101,7 +101,7 @@
     if (nullSafety && type.nullability == Nullability.nonNullable) {
       canBeNull = false;
     }
-    if (canBeNull) {
+    if (canBeNull && result is! NullableType) {
       result = new Type.nullable(result);
     }
     return result;
@@ -186,6 +186,7 @@
 /// Order of precedence between types for evaluation of union/intersection.
 enum TypeOrder {
   RuntimeType,
+  Unknown,
   Empty,
   Nullable,
   Any,
@@ -293,7 +294,6 @@
 
 /// Type representing any instance except `null`.
 /// Semantically equivalent to ConeType of Object, but more efficient.
-/// Can also represent a set of types, the set of all types.
 class AnyType extends Type {
   const AnyType();
 
@@ -612,7 +612,7 @@
   int _hashCode;
 
   // May be null if there are no type arguments constraints. The type arguments
-  // should represent type sets, i.e. `AnyType` or `RuntimeType`. The type
+  // should represent type sets, i.e. `UnknownType` or `RuntimeType`. The type
   // arguments vector is factored against the generic interfaces implemented by
   // the class (see [TypeHierarchy.flattenedTypeArgumentsFor]).
   //
@@ -693,11 +693,13 @@
           runtimeType.numImmediateTypeArgs);
 
       for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
-        if (usableTypeArgs[i + interfaceOffset] == const AnyType())
+        final ta = usableTypeArgs[i + interfaceOffset];
+        if (ta is UnknownType) {
           return false;
-        assertx(usableTypeArgs[i + interfaceOffset] is RuntimeType);
-        if (!usableTypeArgs[i + interfaceOffset]
-            .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[i])) {
+        }
+        assertx(ta is RuntimeType);
+        if (!ta.isSubtypeOfRuntimeType(
+            typeHierarchy, runtimeType.typeArgs[i])) {
           return false;
         }
       }
@@ -864,7 +866,7 @@
 //   class A<T> extends Comparable<A<T>> {}
 //
 // To avoid these cycles, we approximate generic super-bounded types (the second
-// case), so the representation for 'A<String>' would be simply 'AnyType'.
+// case), so the representation for 'A<String>' would be simply 'UnknownType'.
 // However, approximating non-generic types like 'int' and 'num' (the first
 // case) would be too coarse, so we leave an null 'typeArgs' field for these
 // types. As a result, when doing an 'isSubtypeOfRuntimeType' against
@@ -963,11 +965,11 @@
   Type union(Type other, TypeHierarchy typeHierarchy) =>
       throw "ERROR: RuntimeType does not support union.";
 
-  // This only works between "type-set" representations ('AnyType' and
+  // This only works between "type-set" representations ('UnknownType' and
   // 'RuntimeType') and is used when merging type arguments.
   @override
   Type intersection(Type other, TypeHierarchy typeHierarchy) {
-    if (other is AnyType) {
+    if (other is UnknownType) {
       return this;
     } else if (other is RuntimeType) {
       return this == other ? this : const EmptyType();
@@ -1043,3 +1045,52 @@
     return true;
   }
 }
+
+/// Type which is not known at compile time.
+/// It is used as the right-hand-side of type tests.
+class UnknownType extends Type {
+  const UnknownType();
+
+  @override
+  int get hashCode => 1019;
+
+  @override
+  bool operator ==(other) => (other is UnknownType);
+
+  @override
+  String toString() => "UNKNOWN";
+
+  @override
+  int get order => TypeOrder.Unknown.index;
+
+  @override
+  bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
+      throw "ERROR: UnknownType does not support isSubtypeOf.";
+
+  @override
+  Type union(Type other, TypeHierarchy typeHierarchy) {
+    if (other is UnknownType || other is RuntimeType) {
+      return this;
+    }
+    throw "ERROR: UnknownType does not support union with ${other.runtimeType}";
+  }
+
+  // This only works between "type-set" representations ('UnknownType' and
+  // 'RuntimeType') and is used when merging type arguments.
+  @override
+  Type intersection(Type other, TypeHierarchy typeHierarchy) {
+    if (other is UnknownType || other is RuntimeType) {
+      return other;
+    }
+    throw "ERROR: UnknownType does not support intersection with ${other.runtimeType}";
+  }
+
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+    final rhs = other._type;
+    return (rhs is DynamicType) ||
+        (rhs is VoidType) ||
+        (rhs is InterfaceType &&
+            rhs.classNode == typeHierarchy.coreTypes.objectClass &&
+            rhs.nullability != Nullability.nonNullable);
+  }
+}
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index 4a7fb0c..6233aa5 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -145,11 +145,11 @@
 
 In order to re-generate expectations run tests with -D$kUpdateExpectations=true VM option:
 
-  tools/test.py -m release --vm-options -D$kUpdateExpectations=true pkg/vm
+  tools/test.py -m release --vm-options -D$kUpdateExpectations=true pkg/vm/
 
 In order to dump actual results into .actual files run tests with -D$kDumpActualResult=true VM option:
 
-  tools/test.py -m release --vm-options -D$kDumpActualResult=true pkg/vm
+  tools/test.py -m release --vm-options -D$kDumpActualResult=true pkg/vm/
 
 """);
     }
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index d015481..73d3434 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -61,7 +61,7 @@
   [27] = Reserved
   [28] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [29] = Reserved
-  [30] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [30] = InterfaceCall 'dart:async::_AsyncAwaitCompleter::start', ArgDesc num-args 2, num-type-args 0, names []
   [31] = Reserved
   [32] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
   [33] = Reserved
@@ -135,7 +135,7 @@
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          CP#30, 2
+  InterfaceCall        CP#30, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -284,7 +284,7 @@
   Push                 r0
   LoadContextVar       0, 1
   Push                 r6
-  DynamicCall          CP#24, 2
+  InterfaceCall        CP#24, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -316,7 +316,7 @@
   [21] = Reserved
   [22] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [23] = Reserved
-  [24] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [24] = InterfaceCall 'dart:async::_AsyncAwaitCompleter::start', ArgDesc num-args 2, num-type-args 0, names []
   [25] = Reserved
   [26] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
   [27] = Reserved
@@ -440,7 +440,7 @@
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          CP#26, 2
+  InterfaceCall        CP#26, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -474,7 +474,7 @@
   [23] = Reserved
   [24] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [25] = Reserved
-  [26] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [26] = InterfaceCall 'dart:async::_AsyncAwaitCompleter::start', ArgDesc num-args 2, num-type-args 0, names []
   [27] = Reserved
   [28] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
   [29] = Reserved
@@ -662,7 +662,7 @@
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          CP#34, 2
+  InterfaceCall        CP#34, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -704,7 +704,7 @@
   [31] = Reserved
   [32] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [33] = Reserved
-  [34] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [34] = InterfaceCall 'dart:async::_AsyncAwaitCompleter::start', ArgDesc num-args 2, num-type-args 0, names []
   [35] = Reserved
   [36] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
   [37] = Reserved
@@ -1014,7 +1014,7 @@
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 17
-  DynamicCall          CP#32, 2
+  InterfaceCall        CP#32, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -1054,7 +1054,7 @@
   [29] = Reserved
   [30] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [31] = Reserved
-  [32] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [32] = InterfaceCall 'dart:async::_AsyncAwaitCompleter::start', ArgDesc num-args 2, num-type-args 0, names []
   [33] = Reserved
   [34] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
   [35] = Reserved
@@ -1543,7 +1543,7 @@
   [27] = Reserved
   [28] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [29] = Reserved
-  [30] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [30] = InterfaceCall 'dart:async::_AsyncAwaitCompleter::start', ArgDesc num-args 2, num-type-args 0, names []
   [31] = Reserved
   [32] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
   [33] = Reserved
@@ -1609,7 +1609,7 @@
   LoadContextVar       1, 1
   Push                 r0
   LoadContextVar       1, 8
-  DynamicCall          CP#30, 2
+  InterfaceCall        CP#30, 2
   Drop1
   Push                 r0
   LoadContextVar       1, 1
@@ -1833,7 +1833,7 @@
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          CP#28, 2
+  InterfaceCall        CP#28, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -1869,7 +1869,7 @@
   [25] = Reserved
   [26] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [27] = Reserved
-  [28] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [28] = InterfaceCall 'dart:async::_AsyncAwaitCompleter::start', ArgDesc num-args 2, num-type-args 0, names []
   [29] = Reserved
   [30] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
   [31] = Reserved
@@ -2000,8 +2000,8 @@
     final dart.async::_AsyncAwaitCompleter<dart.core::Null?>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::Null?>();
     dart.async::FutureOr<dart.core::Null?>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -2015,21 +2015,21 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   };
   static method foo() → dart.async::Future<dart.core::int*>* /* originally async */ {
     final dart.async::_AsyncAwaitCompleter<dart.core::int*>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::int*>();
     dart.async::FutureOr<dart.core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
@@ -2042,21 +2042,21 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method simpleAsyncAwait(dart.async::Future<dart.core::int*>* a, dart.async::Future<dart.core::int*>* b) → dart.async::Future<dart.core::int*>* /* originally async */ {
     final dart.async::_AsyncAwaitCompleter<dart.core::int*>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::int*>();
     dart.async::FutureOr<dart.core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -2074,21 +2074,21 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method loops(dart.core::List<dart.core::int*>* list) → dart.async::Future<dart.core::int*>* /* originally async */ {
     final dart.async::_AsyncAwaitCompleter<dart.core::int*>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::int*>();
     dart.async::FutureOr<dart.core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -2101,7 +2101,7 @@
           dart.core::int* sum = 0;
           for (dart.core::int* i = 0; i.{dart.core::num::<}(10); i = i.{dart.core::num::+}(1)) {
             {
-              dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(list).{dart.core::Iterable::iterator};
+              dart.core::Iterator<dart.core::int*>* :sync-for-iterator = list.{dart.core::Iterable::iterator};
               for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
                 dart.core::int* j = :sync-for-iterator.{dart.core::Iterator::current};
                 {
@@ -2122,21 +2122,21 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method tryCatchRethrow(dart.async::Future<dart.core::int*>* a, dart.async::Future<dart.core::int*>* b, dart.async::Future<dart.core::int*>* c) → dart.async::Future<dart.core::int*>* /* originally async */ {
     final dart.async::_AsyncAwaitCompleter<dart.core::int*>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::int*>();
     dart.async::FutureOr<dart.core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -2180,13 +2180,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method closure(dart.async::Future<dart.core::int*>* a) → dynamic {
@@ -2195,8 +2195,8 @@
       final dart.async::_AsyncAwaitCompleter<dart.core::int*>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::int*>();
       dart.async::FutureOr<dart.core::int*>* :return_value;
       dynamic :async_stack_trace;
-      dynamic :async_op_then;
-      dynamic :async_op_error;
+      (dynamic) →* dynamic :async_op_then;
+      (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
       dart.core::int* :await_jump_var = 0;
       dynamic :await_ctx_var;
       dynamic :saved_try_context_var0;
@@ -2220,13 +2220,13 @@
           dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
           return;
         }
-        on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
           :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
         }
       :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
       :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
       :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-      :async_completer.start(:async_op);
+      :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
       return :async_completer.{dart.async::Completer::future};
     }
     return nested;
@@ -2235,8 +2235,8 @@
     final dart.async::_AsyncAwaitCompleter<dart.core::int*>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::int*>();
     dart.async::FutureOr<dart.core::int*>* :return_value;
     dynamic :async_stack_trace;
-    dynamic :async_op_then;
-    dynamic :async_op_error;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
@@ -2254,13 +2254,13 @@
         dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
       }
-      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      on dynamic catch(dynamic :exception, dart.core::StackTrace* :stack_trace) {
         :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
       }
     :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_completer.start(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{dart.async::Completer::future};
   }
   static method main() → dynamic {}
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index de90a1d..675d337d 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -1835,7 +1835,7 @@
     }
     method testForInLoop(dart.core::List<dart.core::int*>* list) → void {
       {
-        dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(list).{dart.core::Iterable::iterator};
+        dart.core::Iterator<dart.core::int*>* :sync-for-iterator = list.{dart.core::Iterable::iterator};
         for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
           dart.core::int* i = :sync-for-iterator.{dart.core::Iterator::current};
           {
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
index cb40ac2..524ae14 100644
--- a/pkg/vm/testcases/bytecode/loops.dart.expect
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -385,7 +385,7 @@
   static method test_for_in(dart.core::List<dart.core::int*>* list) → dart.core::int* {
     dart.core::int* sum = 0;
     {
-      dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(list).{dart.core::Iterable::iterator};
+      dart.core::Iterator<dart.core::int*>* :sync-for-iterator = list.{dart.core::Iterable::iterator};
       for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
         dart.core::int* e = :sync-for-iterator.{dart.core::Iterator::current};
         {
@@ -399,7 +399,7 @@
     dart.core::int* sum = 0;
     dart.core::int* e = 42;
     {
-      dart.core::Iterator<dart.core::int*>* :sync-for-iterator = dart._internal::unsafeCast<dart.core::Iterable<dart.core::int*>*>(list).{dart.core::Iterable::iterator};
+      dart.core::Iterator<dart.core::int*>* :sync-for-iterator = list.{dart.core::Iterable::iterator};
       for (; :sync-for-iterator.{dart.core::Iterator::moveNext}(); ) {
         final dart.core::int* #t3 = :sync-for-iterator.{dart.core::Iterator::current};
         {
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 b13924f..b840c08 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
@@ -191,14 +191,13 @@
 t0 = _Call direct [C1::] (_T (#lib::C1))
 t1 = _Call direct [C2::] (_T (#lib::C2))
 t2 = _Call direct [foo] (_T (#lib::C2))
-t3* = _Call direct [unsafeCast] (_T (dart.core::_GrowableList<DynamicType(dynamic)?>))
-t4* = _Call get [Iterable::iterator] (t3)
-t5* = _Call [Iterator::moveNext] (t4)
-t6 = _Narrow (t4 to _T ANY)
-t7 = _Call get [Iterator::current] (t6)
+t3* = _Call get [Iterable::iterator] (_T (dart.core::_GrowableList<DynamicType(dynamic)?>))
+t4* = _Call [Iterator::moveNext] (t3)
+t5 = _Narrow (t3 to _T ANY)
+t6 = _Call get [Iterator::current] (t5)
 x_0 = _Join [DynamicType(dynamic)] (_T (#lib::C2), _T (#lib::C3))
-t9 = _Call direct [foo] (x_0)
-t10 = _Call direct [C3::] (_T (#lib::C3))
+t8 = _Call direct [foo] (x_0)
+t9 = _Call direct [C3::] (_T (#lib::C3))
 RESULT: x_0
 ------------ loop5 ------------
 t0 = _Call direct [C1::] (_T (#lib::C1))
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
new file mode 100644
index 0000000..f2d7d4d
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/41452.
+// Tests handling of null initializer of covariant field.
+// This test requires non-nullable experiment and NNBD strong mode.
+
+// @dart = 2.9
+
+import "package:expect/expect.dart";
+
+class _SplayTreeNode<Node extends _SplayTreeNode<Node>> {
+  Node? left;
+  _SplayTreeNode();
+}
+
+class _SplayTreeMapNode<V> extends _SplayTreeNode<_SplayTreeMapNode<V>> {
+  _SplayTreeMapNode();
+}
+
+class _SplayTree<Node extends _SplayTreeNode<Node>> {
+  Node? _root;
+
+  add(Node n) {
+    Node? root = _root;
+    if (root == null) return;
+    print(root.left); // Should be inferred as nullable.
+  }
+}
+
+class SplayTreeMap<V> extends _SplayTree<_SplayTreeMapNode<V>> {
+  _SplayTreeMapNode<V>? _root = _SplayTreeMapNode<V>();
+}
+
+void main() {
+  SplayTreeMap().add(_SplayTreeMapNode());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
new file mode 100644
index 0000000..0285a9d
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
@@ -0,0 +1,38 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+abstract class _SplayTreeNode<Node extends self::_SplayTreeNode<self::_SplayTreeNode::Node> = self::_SplayTreeNode<dynamic>> extends core::Object {
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  generic-covariant-impl field self::_SplayTreeNode::Node? left = null;
+  constructor •() → self::_SplayTreeNode<self::_SplayTreeNode::Node>
+    : super core::Object::•()
+    ;
+}
+class _SplayTreeMapNode<V extends core::Object? = dynamic> extends self::_SplayTreeNode<self::_SplayTreeMapNode<self::_SplayTreeMapNode::V%>> {
+  constructor •() → self::_SplayTreeMapNode<self::_SplayTreeMapNode::V%>
+    : super self::_SplayTreeNode::•()
+    ;
+}
+abstract class _SplayTree<Node extends self::_SplayTreeNode<self::_SplayTree::Node> = self::_SplayTreeNode<dynamic>> extends core::Object {
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  generic-covariant-impl field self::_SplayTree::Node? _root = null;
+  synthetic constructor •() → self::_SplayTree<self::_SplayTree::Node>
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method add(generic-covariant-impl self::_SplayTree::Node n) → dynamic {
+    self::_SplayTree::Node? root = [@vm.direct-call.metadata=SplayTreeMap::_root] [@vm.inferred-type.metadata=#lib::_SplayTreeMapNode] this.{self::_SplayTree::_root};
+    if([@vm.direct-call.metadata=Object::==] [@vm.inferred-type.metadata=dart.core::bool (skip check) (receiver not int)] root.{core::Object::==}(null))
+      return;
+    core::print([@vm.direct-call.metadata=_SplayTreeNode::left] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] root{self::_SplayTree::Node}.{self::_SplayTreeNode::left});
+  }
+}
+class SplayTreeMap<V extends core::Object? = dynamic> extends self::_SplayTree<self::_SplayTreeMapNode<self::SplayTreeMap::V%>> {
+[@vm.inferred-type.metadata=#lib::_SplayTreeMapNode] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  generic-covariant-impl field self::_SplayTreeMapNode<self::SplayTreeMap::V%>? _root = new self::_SplayTreeMapNode::•<self::SplayTreeMap::V%>();
+  synthetic constructor •() → self::SplayTreeMap<self::SplayTreeMap::V%>
+    : super self::_SplayTree::•()
+    ;
+}
+static method main() → void {
+  [@vm.call-site-attributes.metadata=receiverType:InterfaceType(SplayTreeMap<dynamic>)] [@vm.direct-call.metadata=_SplayTree::add] new self::SplayTreeMap::•<dynamic>().{self::_SplayTree::add}(new self::_SplayTreeMapNode::•<dynamic>());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
index b39b249..00c3bcf 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
@@ -19,7 +19,7 @@
   synthetic constructor •() → self::A1*
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = #C1]) → void {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, [@vm.inferred-type.metadata=int?] dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = #C1]) → void {
     [@vm.direct-call.metadata=A1::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1*>(a5);
   }
 }
@@ -42,7 +42,7 @@
   synthetic constructor •() → self::A2*
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, [@vm.inferred-type.metadata=int?] dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
     [@vm.direct-call.metadata=A2::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A2::foo} = a6;
   }
 }
@@ -75,7 +75,7 @@
   synthetic constructor •() → self::A3*
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, [@vm.inferred-type.metadata=int?] dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
     [@vm.direct-call.metadata=A3::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A3::foo} = a7;
   }
 }
@@ -98,7 +98,7 @@
   synthetic constructor •() → self::A4*
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method call([dynamic a1 = #C1, dynamic a2 = #C1, [@vm.inferred-type.metadata=int?] dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
     [@vm.direct-call.metadata=A4::foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A4::foo} = a8;
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
index 4fd9f27..710cf8f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
@@ -5,7 +5,7 @@
 // Tests elimination of type casts.
 // This test requires non-nullable experiment.
 
-// @dart = 2.8
+// @dart = 2.9
 
 class A<T> {}
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
index 8855bf4..588f620 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
@@ -5,7 +5,7 @@
 // Tests elimination of type casts.
 // This test requires non-nullable experiment and NNBD strong mode.
 
-// @dart = 2.8
+// @dart = 2.9
 
 class A<T> {}
 
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
index acdab7a..04ae51a 100644
--- a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
@@ -1,7 +1,6 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
-import "dart:_internal" as _in;
 
 class TestAssertInitializer extends core::Object {
   constructor •() → self::TestAssertInitializer*
@@ -58,7 +57,7 @@
   for (; ; ) {
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(<core::int*>[1, 2]).{core::Iterable::iterator};
+    core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2].{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int* i = :sync-for-iterator.{core::Iterator::current};
     }
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index 326a854..b76c8bb 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -36,6 +36,9 @@
     --no-tfa | \
     --gen-bytecode | \
     --no-gen-bytecode | \
+    --bytecode-options=* | \
+    --minimal-kernel | \
+    --no-embed-sources | \
     -D* )
     GEN_KERNEL_OPTIONS+=("$arg")
     ;;
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index cbe9222..39645a7 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 4.0.1
+- Improved documentation.
+- Fixed analysis issues.
+
 ## 4.0.0
 - **breaking**: RPCs which can return a `Sentinel` will now throw a `SentinelException`
   if a `Sential` is received as a response.
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 366bd74..a454d5b 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: 4.0.0
+version: 4.0.1
 
 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 186e2e3..2851672 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -289,29 +289,34 @@
 
     final name = _getTestUri().pathSegments.last;
 
-    test(name, () async {
-      // Run vm tests.
-      if (vmTests != null) {
-        var testIndex = 1;
-        var totalTests = vmTests.length;
-        for (var t in vmTests) {
-          print('$name [$testIndex/$totalTests]');
-          await t(vm);
-          testIndex++;
+    test(
+      name,
+      () async {
+        // Run vm tests.
+        if (vmTests != null) {
+          var testIndex = 1;
+          var totalTests = vmTests.length;
+          for (var t in vmTests) {
+            print('$name [$testIndex/$totalTests]');
+            await t(vm);
+            testIndex++;
+          }
         }
-      }
 
-      // Run isolate tests.
-      if (isolateTests != null) {
-        var testIndex = 1;
-        var totalTests = isolateTests.length;
-        for (var t in isolateTests) {
-          print('$name [$testIndex/$totalTests]');
-          await t(vm, isolate);
-          testIndex++;
+        // Run isolate tests.
+        if (isolateTests != null) {
+          var testIndex = 1;
+          var totalTests = isolateTests.length;
+          for (var t in isolateTests) {
+            print('$name [$testIndex/$totalTests]');
+            await t(vm, isolate);
+            testIndex++;
+          }
         }
-      }
-    }, retry: 3);
+      },
+      retry: 0,
+      timeout: Timeout.none,
+    );
 
     tearDown(() {
       print('All service tests completed successfully.');
diff --git a/runtime/bin/dartdev_utils.cc b/runtime/bin/dartdev_utils.cc
index 88ac6f3..0314d6e 100644
--- a/runtime/bin/dartdev_utils.cc
+++ b/runtime/bin/dartdev_utils.cc
@@ -14,13 +14,10 @@
 namespace dart {
 namespace bin {
 
-// TODO(bkonyi): re-enable after 2.8 release.
-const bool kDartDevEnabled = false;
-
 bool DartDevUtils::ShouldParseCommand(const char* script_uri) {
   // If script_uri is not a file path or of a known URI scheme, we can assume
   // that this is a DartDev command.
-  return (kDartDevEnabled && !File::ExistsUri(nullptr, script_uri) &&
+  return (!File::ExistsUri(nullptr, script_uri) &&
           (strncmp(script_uri, "http://", 7) != 0) &&
           (strncmp(script_uri, "https://", 8) != 0) &&
           (strncmp(script_uri, "file://", 7) != 0) &&
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index be84119..71d0437 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -704,6 +704,10 @@
   return NewDartExceptionWithMessage(kCoreLibURL, "ArgumentError", message);
 }
 
+Dart_Handle DartUtils::NewDartFormatException(const char* message) {
+  return NewDartExceptionWithMessage(kCoreLibURL, "FormatException", message);
+}
+
 Dart_Handle DartUtils::NewDartUnsupportedError(const char* message) {
   return NewDartExceptionWithMessage(kCoreLibURL, "UnsupportedError", message);
 }
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index a0744ab..5a405f3 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -175,6 +175,7 @@
                                                  const char* exception_name,
                                                  const char* message);
   static Dart_Handle NewDartArgumentError(const char* message);
+  static Dart_Handle NewDartFormatException(const char* message);
   static Dart_Handle NewDartUnsupportedError(const char* message);
   static Dart_Handle NewDartIOException(const char* exception_name,
                                         const char* message,
diff --git a/runtime/bin/exe_utils.cc b/runtime/bin/exe_utils.cc
index 091f890..5361a9e 100644
--- a/runtime/bin/exe_utils.cc
+++ b/runtime/bin/exe_utils.cc
@@ -54,6 +54,7 @@
   if (name == nullptr) {
     name = Platform::GetExecutableName();
     target_size = strlen(name);
+    ASSERT(target_size < kTargetSize);
   }
   Namespace* namespc = Namespace::Create(Namespace::Default());
   if (File::GetType(namespc, name, false) == File::kIsLink) {
diff --git a/runtime/bin/filter.cc b/runtime/bin/filter.cc
index 292b978..c7eb4db 100644
--- a/runtime/bin/filter.cc
+++ b/runtime/bin/filter.cc
@@ -240,7 +240,8 @@
   intptr_t read = filter->Processed(
       filter->processed_buffer(), filter->processed_buffer_size(), flush, end);
   if (read < 0) {
-    Dart_ThrowException(DartUtils::NewInternalError("Filter error, bad data"));
+    Dart_ThrowException(
+        DartUtils::NewDartFormatException("Filter error, bad data"));
   } else if (read == 0) {
     Dart_SetReturnValue(args, Dart_Null());
   } else {
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 71a9b42..a1845c0 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -152,7 +152,7 @@
 "      --warn-on-pause-with-no-debugger\n"
 "  This set is subject to change.\n"
 "  Please see these options (--help --verbose) for further documentation.\n"
-"--write-service-info=<file_name>\n"
+"--write-service-info=<file_uri>\n"
 "  Outputs information necessary to connect to the VM service to the\n"
 "  specified file in JSON format. Useful for clients which are unable to\n"
 "  listen to stdout for the Observatory listening message.\n"
@@ -187,7 +187,7 @@
 "      --warn-on-pause-with-no-debugger\n"
 "  This set is subject to change.\n"
 "  Please see these options for further documentation.\n"
-"--write-service-info=<file_name>\n"
+"--write-service-info=<file_uri>\n"
 "  Outputs information necessary to connect to the VM service to the\n"
 "  specified file in JSON format. Useful for clients which are unable to\n"
 "  listen to stdout for the Observatory listening message.\n"
diff --git a/runtime/docs/gc.md b/runtime/docs/gc.md
index 70c58ea..8e6d463 100644
--- a/runtime/docs/gc.md
+++ b/runtime/docs/gc.md
@@ -27,6 +27,10 @@
 
 See [Cheney's algorithm](https://en.wikipedia.org/wiki/Cheney's_algorithm).
 
+## Parallel Scavenge
+
+FLAG_scavenger_tasks (default 2) workers are started on separate threads. Each worker competes to process parts of the root set (including the remembered set). When a worker copies an object to to-space, it allocates from a worker-local bump allocation region. The same worker will process the copied object. When a worker promotes an object to old-space, it allocates from a worker-local freelist, which uses bump allocation for large free blocks. The promoted object is added to a work list that implements work stealing, so some other worker may process the promoted object. After the object is evacuated, the worker using a compare-and-swap to install the forwarding pointer into the from-space object's header. If it loses the race, it un-allocates the to-space or old-space object it just allocated, and uses the winner's object to update the pointer it was processing. Workers run until all of the work set have been processed, and every worker have processed its to-space objects and local part of the promoted work list.
+
 ## Mark-Sweep
 
 All objects have a bit in their header called the mark bit. At the start of a collection cycle, all objects have this bit clear.
@@ -51,6 +55,8 @@
 
 Note that a mutator can be at a safepoint without being suspended. It might be performing a long task that doesn't access the heap. It will, however, need to wait for any safepoint operation to complete in order to leave its safepoint and resume accessing the heap.
 
+Because a safepoint operation excludes excution of Dart code, it is sometimes used for non-GC tasks that requires only this property. For example, when a background compilation has completed and wants to install its result, it uses a safepoint operation to ensure no Dart execution sees the intermediate states during installation.
+
 ## Concurrent Marking
 
 To reduce the time the mutator is paused for old-space GCs, we allow the mutator to continue running during most of the marking work. 
diff --git a/runtime/observatory/.packages b/runtime/observatory/.packages
deleted file mode 100644
index 29f9ce2..0000000
--- a/runtime/observatory/.packages
+++ /dev/null
@@ -1,37 +0,0 @@
-browser:../../third_party/observatory_pub_packages/packages/browser/lib
-charted:../../third_party/observatory_pub_packages/packages/charted/lib
-collection:../../third_party/observatory_pub_packages/packages/collection/lib
-intl:../../third_party/observatory_pub_packages/packages/intl/lib
-logging:../../third_party/observatory_pub_packages/packages/logging/lib
-meta:../../third_party/observatory_pub_packages/packages/meta/lib
-observable:../../third_party/observatory_pub_packages/packages/observable/lib
-path:../../third_party/observatory_pub_packages/packages/path/lib
-quiver:../../third_party/observatory_pub_packages/packages/quiver/lib
-stack_trace:../../third_party/observatory_pub_packages/packages/stack_trace/lib
-usage:../../third_party/observatory_pub_packages/packages/usage/lib
-observatory:lib
-
-# Testing only
-async:../../third_party/pkg/async/lib
-boolean_selector:../../third_party/pkg/boolean_selector/lib
-charcode:../../third_party/pkg/charcode/lib
-dart_internal:../../pkg/dart_internal/lib
-expect:../../pkg/expect/lib
-http:../../third_party/pkg/http/lib
-http_parser:../../third_party/pkg/http_parser/lib
-matcher:../../third_party/pkg/matcher/lib
-package_config:../../third_party/pkg_tested/package_config/lib
-pedantic:../../third_party/pkg/pedantic/lib
-pool:../../third_party/pkg/pool/lib
-pub_semver:../../third_party/pkg/pub_semver/lib
-source_map_stack_trace:../../third_party/pkg/source_map_stack_trace/lib
-source_maps:../../third_party/pkg/source_maps/lib
-source_span:../../third_party/pkg/source_span/lib
-stream_channel:../../third_party/pkg/stream_channel/lib
-string_scanner:../../third_party/pkg/string_scanner/lib
-term_glyph:../../third_party/pkg/term_glyph/lib
-test:../../third_party/pkg/test/pkgs/test/lib
-test_api:../../third_party/pkg/test/pkgs/test_api/lib
-test_core:../../third_party/pkg/test/pkgs/test_core/lib
-typed_data:../../third_party/pkg/typed_data/lib
-observatory_test_package:tests/service/observatory_test_package
diff --git a/runtime/observatory/BUILD.gn b/runtime/observatory/BUILD.gn
index b47dce6..1762e1a 100644
--- a/runtime/observatory/BUILD.gn
+++ b/runtime/observatory/BUILD.gn
@@ -13,7 +13,7 @@
 
   # 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
+  inputs = [ "../../.packages" ] + observatory_sources
 
   output = "$target_gen_dir/observatory/web/main.dart.js"
   outputs = [ output ]
@@ -36,7 +36,7 @@
     "-DOBS_VER=${version_string}",
     "-o",
     rebase_path(output),
-    "--packages=" + rebase_path(".packages"),
+    "--packages=" + rebase_path("../../.packages"),
   ]
   if (is_debug) {
     args += [ "--enable-asserts" ]
@@ -113,42 +113,6 @@
   },
 ]
 
-# All the contents of third_party/observatory_pub_packages should be
-# accounted for here. Uncommented entries are those packages that have
-# files that pass the observatory_ignore_patterns filters.
-observatory_pub_packages = [
-  "browser",
-  "charted",
-  "intl",
-
-  # Dependent packages that have no files that pass the above filter.
-  # "collection",
-  # "logging",
-  # "matcher",
-  # "meta",
-  # "observable",
-  # "path",
-  # "quiver",
-  # "stack_trace",
-  # "usage",
-
-  # Only needed for testing.
-  # "unittest",
-]
-
-foreach(package, observatory_pub_packages) {
-  copy_tree_specs += [
-    {
-      target = "copy_${package}_package"
-      visibility = [ ":deploy_observatory" ]
-      source =
-          "../../third_party/observatory_pub_packages/packages/$package/lib"
-      dest = "$target_out_dir/observatory/deployed/web/packages/$package"
-      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") {
@@ -167,9 +131,6 @@
 
 group("deploy_observatory") {
   deps = [
-    ":copy_browser_package",
-    ":copy_charted_package",
-    ":copy_intl_package",
     ":copy_main_dart_js",
     ":copy_observatory_package",
     ":copy_web_package",
diff --git a/runtime/observatory/lib/src/elements/allocation_profile.dart b/runtime/observatory/lib/src/elements/allocation_profile.dart
index d589289..7770d15 100644
--- a/runtime/observatory/lib/src/elements/allocation_profile.dart
+++ b/runtime/observatory/lib/src/elements/allocation_profile.dart
@@ -4,8 +4,6 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:charted/charted.dart';
-import "package:charted/charts/charts.dart";
 import 'package:observatory/models.dart' as M;
 import 'package:observatory/src/elements/class_ref.dart';
 import 'package:observatory/src/elements/containers/virtual_collection.dart';
@@ -159,12 +157,6 @@
           ..children = <Element>[new HeadingElement.h2()..text = 'Loading...']
       ]);
     } else {
-      final newChartHost = new DivElement()..classes = ['host'];
-      final newChartLegend = new DivElement()..classes = ['legend'];
-      final oldChartHost = new DivElement()..classes = ['host'];
-      final oldChartLegend = new DivElement()..classes = ['legend'];
-      final totalChartHost = new DivElement()..classes = ['host'];
-      final totalChartLegend = new DivElement()..classes = ['legend'];
       children.addAll([
         new DivElement()
           ..classes = ['content-centered-big']
@@ -206,10 +198,6 @@
                       new DivElement()
                         ..classes = ['memberList']
                         ..children = _createSpaceMembers(_profile.newSpace),
-                      new BRElement(),
-                      new DivElement()
-                        ..classes = ['chart']
-                        ..children = <Element>[newChartLegend, newChartHost]
                     ],
             new DivElement()
               ..classes = ['heap-space', 'left']
@@ -225,10 +213,6 @@
                       new DivElement()
                         ..classes = ['memberList']
                         ..children = _createSpaceMembers(_profile.oldSpace),
-                      new BRElement(),
-                      new DivElement()
-                        ..classes = ['chart']
-                        ..children = <Element>[oldChartLegend, oldChartHost]
                     ],
             new DivElement()
               ..classes = ['heap-space', 'left']
@@ -244,10 +228,6 @@
                       new DivElement()
                         ..classes = ['memberList']
                         ..children = _createSpaceMembers(_profile.totalSpace),
-                      new BRElement(),
-                      new DivElement()
-                        ..classes = ['chart']
-                        ..children = <Element>[totalChartLegend, totalChartHost]
                     ],
             new ButtonElement()
               ..classes = ['compact']
@@ -270,9 +250,6 @@
                 .element
           ]
       ]);
-      _renderGraph(newChartHost, newChartLegend, _profile.newSpace);
-      _renderGraph(oldChartHost, oldChartLegend, _profile.oldSpace);
-      _renderGraph(totalChartHost, totalChartLegend, _profile.totalSpace);
     }
   }
 
@@ -544,31 +521,6 @@
     ];
   }
 
-  static final _columns = [
-    new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING),
-    new ChartColumnSpec(label: 'Size', formatter: (v) => v.toString())
-  ];
-
-  static void _renderGraph(Element host, Element legend, M.HeapSpace space) {
-    final series = [
-      new ChartSeries("Work", [1], new PieChartRenderer(sortDataByValue: false))
-    ];
-    final rect = host.getBoundingClientRect();
-    final minSize = new Rect.size(rect.width, rect.height);
-    final config = new ChartConfig(series, [0])
-      ..minimumSize = minSize
-      ..legend = new ChartLegend(legend, showValues: true);
-    final data = new ChartData(_columns, <List>[
-      ['Used', space.used],
-      ['Free', space.capacity - space.used],
-      ['External', space.external]
-    ]);
-
-    new LayoutArea(host, data, config,
-        state: new ChartState(), autoUpdate: true)
-      ..draw();
-  }
-
   Future _refresh({bool gc: false, bool reset: false}) async {
     _profile = null;
     _r.dirty();
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart
index 83c3182..30c51f8 100644
--- a/runtime/observatory/lib/src/elements/class_tree.dart
+++ b/runtime/observatory/lib/src/elements/class_tree.dart
@@ -29,7 +29,7 @@
     VirtualTreeElement.tag
   ]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<ClassTreeElement> _r;
 
   Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index 255ea65..f8c0756 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -479,11 +479,7 @@
 }
 
 .allocation-profile .collection {
-  position: absolute;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  top: 560px;
+  height: 100%;
 }
 
 .allocation-profile .collection.expanded {
@@ -1535,7 +1531,7 @@
 }
 
 .isolate-shared-summary > .summary {
-  height: 300px;
+  height: 350px;
   position: relative;
 }
 .isolate-shared-summary .menu {
diff --git a/runtime/observatory/lib/src/elements/error_view.dart b/runtime/observatory/lib/src/elements/error_view.dart
index 010f4cc..71114f4 100644
--- a/runtime/observatory/lib/src/elements/error_view.dart
+++ b/runtime/observatory/lib/src/elements/error_view.dart
@@ -22,7 +22,7 @@
         ViewFooterElement.tag
       ]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<ErrorViewElement> _r;
 
   Stream<RenderedEvent<ErrorViewElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/flag_list.dart b/runtime/observatory/lib/src/elements/flag_list.dart
index 7aa02fd..0d0e090 100644
--- a/runtime/observatory/lib/src/elements/flag_list.dart
+++ b/runtime/observatory/lib/src/elements/flag_list.dart
@@ -28,7 +28,7 @@
     ViewFooterElement.tag,
   ]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<FlagListElement> _r;
 
   Stream<RenderedEvent<FlagListElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/general_error.dart b/runtime/observatory/lib/src/elements/general_error.dart
index f94872b..bc07f6a 100644
--- a/runtime/observatory/lib/src/elements/general_error.dart
+++ b/runtime/observatory/lib/src/elements/general_error.dart
@@ -17,7 +17,7 @@
   static const tag = const Tag<GeneralErrorElement>('general-error',
       dependencies: const [NavTopMenuElement.tag, NavNotifyElement.tag]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<GeneralErrorElement> _r;
 
   Stream<RenderedEvent<GeneralErrorElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/isolate/counter_chart.dart b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
index 8cdd325..3c68990 100644
--- a/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
+++ b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
@@ -4,8 +4,6 @@
 
 import 'dart:html';
 import 'dart:async';
-import 'package:charted/charted.dart';
-import "package:charted/charts/charts.dart";
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
@@ -46,34 +44,25 @@
     _subscription.cancel();
   }
 
-  static final _columns = [
-    new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING),
-    new ChartColumnSpec(label: 'Percent', formatter: (v) => v.toString())
-  ];
-
   void render() {
-    final _series = [
-      new ChartSeries(
-          "Work", const [1], new PieChartRenderer(sortDataByValue: false))
-    ];
-    final areaHost = new DivElement()..classes = ['host'];
-    final legendHost = new DivElement()..classes = ['legend'];
-    children = <Element>[areaHost, legendHost];
-    final rect = areaHost.getBoundingClientRect();
-    final minSize = new Rect.size(rect.width, rect.height);
-    final config = new ChartConfig(_series, const [0])
-      ..minimumSize = minSize
-      ..legend = new ChartLegend(legendHost, showValues: true);
-    final data = new ChartData(
-        _columns,
-        _counters.keys
-            .map((key) => [key, double.parse(_counters[key].split('%')[0])])
-            .toList());
+    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,
+        ]);
+    });
 
-    new LayoutArea(areaHost, data, config,
-        state: new ChartState(), autoUpdate: false)
-      ..addChartBehavior(new Hovercard())
-      ..addChartBehavior(new AxisLabelTooltip())
-      ..draw();
+    children = <Element>[
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = members
+    ];
   }
 }
diff --git a/runtime/observatory/lib/src/elements/isolate_reconnect.dart b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
index bf72f2f..8031aa3 100644
--- a/runtime/observatory/lib/src/elements/isolate_reconnect.dart
+++ b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
@@ -23,7 +23,7 @@
         ViewFooterElement.tag
       ]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<IsolateReconnectElement> _r;
 
   Stream<RenderedEvent<IsolateReconnectElement>> get onRendered =>
       _r.onRendered;
diff --git a/runtime/observatory/lib/src/elements/metric/graph.dart b/runtime/observatory/lib/src/elements/metric/graph.dart
index 24406a2..b143895 100644
--- a/runtime/observatory/lib/src/elements/metric/graph.dart
+++ b/runtime/observatory/lib/src/elements/metric/graph.dart
@@ -5,7 +5,6 @@
 import 'dart:html';
 import 'dart:async';
 import 'package:observatory/models.dart' as M;
-import 'package:charted/charted.dart';
 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 import 'package:observatory/src/elements/helpers/tag.dart';
 
@@ -55,11 +54,6 @@
     _timer.cancel();
   }
 
-  final _columns = [
-    new ChartColumnSpec(label: 'Time', type: ChartColumnSpec.TYPE_TIMESTAMP),
-    new ChartColumnSpec(label: 'Value', formatter: (v) => v.toString())
-  ];
-
   void render() {
     final min = _metrics.getMinValue(_isolate, _metric);
     final max = _metrics.getMaxValue(_isolate, _metric);
@@ -117,18 +111,9 @@
                       ..text = '$max'
                   ]
         ],
-      new DivElement()
-        ..classes = ['graph']
-        ..children = <Element>[host]
     ];
     if (rows.length <= 1) {
       return;
     }
-    final rect = host.getBoundingClientRect();
-    var series = new ChartSeries("one", [1], new LineChartRenderer());
-    var config = new ChartConfig([series], [0]);
-    config.minimumSize = new Rect(rect.width, rect.height);
-    final data = new ChartData(_columns, rows);
-    new CartesianArea(host, data, config, state: new ChartState()).draw();
   }
 }
diff --git a/runtime/observatory/lib/src/elements/nav/class_menu.dart b/runtime/observatory/lib/src/elements/nav/class_menu.dart
index c388eb3..f0dd55d 100644
--- a/runtime/observatory/lib/src/elements/nav/class_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/class_menu.dart
@@ -13,7 +13,7 @@
 class NavClassMenuElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavClassMenuElement>('nav-class-menu');
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavClassMenuElement> _r;
 
   Stream<RenderedEvent<NavClassMenuElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/isolate_menu.dart b/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
index 9b94daf..65cbca9 100644
--- a/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
@@ -15,7 +15,7 @@
   static const tag = const Tag<NavIsolateMenuElement>('nav-isolate-menu',
       dependencies: const [NavMenuItemElement.tag]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavIsolateMenuElement> _r;
 
   Stream<RenderedEvent<NavIsolateMenuElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/library_menu.dart b/runtime/observatory/lib/src/elements/nav/library_menu.dart
index 2ef6f15..e5705d4 100644
--- a/runtime/observatory/lib/src/elements/nav/library_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/library_menu.dart
@@ -13,7 +13,7 @@
 class NavLibraryMenuElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavLibraryMenuElement>('nav-library-menu');
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavLibraryMenuElement> _r;
 
   Stream<RenderedEvent<NavLibraryMenuElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/menu_item.dart b/runtime/observatory/lib/src/elements/nav/menu_item.dart
index 5df68a9..5de1b94 100644
--- a/runtime/observatory/lib/src/elements/nav/menu_item.dart
+++ b/runtime/observatory/lib/src/elements/nav/menu_item.dart
@@ -10,7 +10,7 @@
 class NavMenuItemElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavMenuItemElement>('nav-menu-item');
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavMenuItemElement> _r;
 
   Stream<RenderedEvent<NavMenuItemElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/notify.dart b/runtime/observatory/lib/src/elements/nav/notify.dart
index a33d800..07ba4e0 100644
--- a/runtime/observatory/lib/src/elements/nav/notify.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify.dart
@@ -17,7 +17,7 @@
         NavNotifyExceptionElement.tag
       ]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavNotifyElement> _r;
 
   Stream<RenderedEvent<NavNotifyElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/notify_event.dart b/runtime/observatory/lib/src/elements/nav/notify_event.dart
index fc9defc..5fa52d6 100644
--- a/runtime/observatory/lib/src/elements/nav/notify_event.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify_event.dart
@@ -17,7 +17,7 @@
 class NavNotifyEventElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavNotifyEventElement>('nav-event');
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavNotifyEventElement> _r;
 
   Stream<RenderedEvent<NavNotifyEventElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/notify_exception.dart b/runtime/observatory/lib/src/elements/nav/notify_exception.dart
index 9a746f0..4100ef6 100644
--- a/runtime/observatory/lib/src/elements/nav/notify_exception.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify_exception.dart
@@ -19,7 +19,7 @@
 class NavNotifyExceptionElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavNotifyExceptionElement>('nav-exception');
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavNotifyExceptionElement> _r;
 
   Stream<RenderedEvent<NavNotifyExceptionElement>> get onRendered =>
       _r.onRendered;
diff --git a/runtime/observatory/lib/src/elements/nav/refresh.dart b/runtime/observatory/lib/src/elements/nav/refresh.dart
index 1d918fb..445d53b 100644
--- a/runtime/observatory/lib/src/elements/nav/refresh.dart
+++ b/runtime/observatory/lib/src/elements/nav/refresh.dart
@@ -15,7 +15,7 @@
 class NavRefreshElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavRefreshElement>('nav-refresh');
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavRefreshElement> _r;
 
   Stream<RenderedEvent<NavRefreshElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/reload.dart b/runtime/observatory/lib/src/elements/nav/reload.dart
index b6d1a5c..da6813b 100644
--- a/runtime/observatory/lib/src/elements/nav/reload.dart
+++ b/runtime/observatory/lib/src/elements/nav/reload.dart
@@ -18,7 +18,7 @@
 class NavReloadElement extends CustomElement implements Renderable {
   static const tag = const Tag<NavReloadElement>('nav-reload');
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavReloadElement> _r;
 
   Stream<RenderedEvent<NavReloadElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/top_menu.dart b/runtime/observatory/lib/src/elements/nav/top_menu.dart
index eb8cf97..3415fde 100644
--- a/runtime/observatory/lib/src/elements/nav/top_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/top_menu.dart
@@ -14,7 +14,7 @@
   static const tag = const Tag<NavTopMenuElement>('nav-top-menu',
       dependencies: const [NavMenuItemElement.tag]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavTopMenuElement> _r;
 
   Stream<RenderedEvent<NavTopMenuElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/nav/vm_menu.dart b/runtime/observatory/lib/src/elements/nav/vm_menu.dart
index 38fbdf7..0216a01 100644
--- a/runtime/observatory/lib/src/elements/nav/vm_menu.dart
+++ b/runtime/observatory/lib/src/elements/nav/vm_menu.dart
@@ -15,7 +15,7 @@
   static const tag = const Tag<NavVMMenuElement>('nav-vm-menu',
       dependencies: const [NavMenuItemElement.tag]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<NavVMMenuElement> _r;
 
   Stream<RenderedEvent<NavVMMenuElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 9c5ca8f..032072b 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -19,7 +19,7 @@
 class ScriptInsetElement extends CustomElement implements Renderable {
   static const tag = const Tag<ScriptInsetElement>('script-inset');
 
-  RenderingScheduler _r;
+  RenderingScheduler<ScriptInsetElement> _r;
 
   Stream<RenderedEvent<ScriptInsetElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/script_ref.dart b/runtime/observatory/lib/src/elements/script_ref.dart
index f5acf04..91f8e68 100644
--- a/runtime/observatory/lib/src/elements/script_ref.dart
+++ b/runtime/observatory/lib/src/elements/script_ref.dart
@@ -14,7 +14,7 @@
 class ScriptRefElement extends CustomElement implements Renderable {
   static const tag = const Tag<ScriptRefElement>('script-ref');
 
-  RenderingScheduler _r;
+  RenderingScheduler<ScriptRefElement> _r;
 
   Stream<RenderedEvent<ScriptRefElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/source_inset.dart b/runtime/observatory/lib/src/elements/source_inset.dart
index 42d3d2b..9e3b78d 100644
--- a/runtime/observatory/lib/src/elements/source_inset.dart
+++ b/runtime/observatory/lib/src/elements/source_inset.dart
@@ -14,7 +14,7 @@
 class SourceInsetElement extends CustomElement implements Renderable {
   static const tag = const Tag<SourceInsetElement>('source-inset');
 
-  RenderingScheduler _r;
+  RenderingScheduler<SourceInsetElement> _r;
 
   Stream<RenderedEvent<SourceInsetElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/source_link.dart b/runtime/observatory/lib/src/elements/source_link.dart
index d19c726..b05ac57 100644
--- a/runtime/observatory/lib/src/elements/source_link.dart
+++ b/runtime/observatory/lib/src/elements/source_link.dart
@@ -16,7 +16,7 @@
 class SourceLinkElement extends CustomElement implements Renderable {
   static const tag = const Tag<SourceLinkElement>('source-link');
 
-  RenderingScheduler _r;
+  RenderingScheduler<SourceLinkElement> _r;
 
   Stream<RenderedEvent<SourceLinkElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/view_footer.dart b/runtime/observatory/lib/src/elements/view_footer.dart
index d401bde..2115632 100644
--- a/runtime/observatory/lib/src/elements/view_footer.dart
+++ b/runtime/observatory/lib/src/elements/view_footer.dart
@@ -12,7 +12,7 @@
 class ViewFooterElement extends CustomElement implements Renderable {
   static const tag = const Tag<ViewFooterElement>('view-footer');
 
-  RenderingScheduler _r;
+  RenderingScheduler<ViewFooterElement> _r;
 
   Stream<RenderedEvent<ViewFooterElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/lib/src/elements/vm_connect.dart b/runtime/observatory/lib/src/elements/vm_connect.dart
index 576aa76..926b2c9 100644
--- a/runtime/observatory/lib/src/elements/vm_connect.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect.dart
@@ -25,7 +25,7 @@
     VMConnectTargetElement.tag
   ]);
 
-  RenderingScheduler _r;
+  RenderingScheduler<VMConnectElement> _r;
 
   Stream<RenderedEvent<VMConnectElement>> get onRendered => _r.onRendered;
 
diff --git a/runtime/observatory/tests/service/invoke_test.dart b/runtime/observatory/tests/service/invoke_test.dart
index 8a9ebb7..4d198a7 100644
--- a/runtime/observatory/tests/service/invoke_test.dart
+++ b/runtime/observatory/tests/service/invoke_test.dart
@@ -11,13 +11,17 @@
 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() {
@@ -27,11 +31,22 @@
   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");
@@ -66,30 +81,43 @@
     expect(result.valueAsString, equals('foobar3applebanana'));
 
     // Wrong arity.
-    await expectError(() => isolate.invokeRpc("invoke", {
-          "targetId": instance.id,
-          "selector": "instanceFunction",
-          "argumentIds": [apple.id]
-        }));
+    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]
-        }));
+    await expectError(
+        () => isolate.invokeRpc("invoke", {
+              "targetId": instance.id,
+              "selector": "functionDoesNotExist",
+              "argumentIds": [apple.id]
+            }),
+        ServerRpcException.kExpressionCompilationError);
   },
   resumeIsolate,
 ];
 
-expectError(func) async {
+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, equals(ServerRpcException.kExpressionCompilationError));
+    expect(e.code, code);
     gotException = true;
   }
   if (result?.type != 'Error') {
diff --git a/runtime/observatory/tests/service/process_service_test.dart b/runtime/observatory/tests/service/process_service_test.dart
index 02e71fc..ced9326 100644
--- a/runtime/observatory/tests/service/process_service_test.dart
+++ b/runtime/observatory/tests/service/process_service_test.dart
@@ -19,7 +19,11 @@
 Future setupProcesses() async {
   var dir = await io.Directory.systemTemp.createTemp('file_service');
 
-  var args = ['--pause_isolates_on_start', io.Platform.script.toFilePath()];
+  var args = [
+    ...io.Platform.executableArguments,
+    '--pause_isolates_on_start',
+    io.Platform.script.toFilePath(),
+  ];
   var process1;
   var process2;
   var process3;
@@ -57,7 +61,8 @@
             await stdin.drain();
           }
           ''');
-      process3 = await io.Process.start(dartJITBinary, [codeFilePath]);
+      process3 = await io.Process.start(
+          dartJITBinary, [...io.Platform.executableArguments, codeFilePath]);
     } catch (e) {
       closeDown();
       throw e;
diff --git a/runtime/observatory/web/index.html b/runtime/observatory/web/index.html
index 6369746..161e866 100644
--- a/runtime/observatory/web/index.html
+++ b/runtime/observatory/web/index.html
@@ -3,7 +3,6 @@
 <head>
   <meta charset="utf-8">
   <title>Dart VM Observatory</title>
-  <link rel="stylesheet" href="packages/charted/charts/themes/quantum_theme.css">
   <link rel="stylesheet" href="packages/observatory/src/elements/css/shared.css">
   <script defer src="main.dart.js"></script>
 </head>
diff --git a/runtime/observatory/web/third_party/trace_viewer_full.html b/runtime/observatory/web/third_party/trace_viewer_full.html
index a6966b4..d815ec5 100644
--- a/runtime/observatory/web/third_party/trace_viewer_full.html
+++ b/runtime/observatory/web/third_party/trace_viewer_full.html
@@ -3,6 +3,8 @@
   <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 {
@@ -4832,7 +4834,7 @@
 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 POSTTASK_FLOW_EVENT='disabled-by-default-toplevel.flow';const IPC_FLOW_EVENT='disabled-by-default-ipc.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_();}}
+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;}}
@@ -4844,14 +4846,14 @@
 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];if(flow.category!==POSTTASK_FLOW_EVENT||!flow.endSlice){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===POSTTASK_FLOW_EVENT||outflow.category===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;}
+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;}}}
@@ -5173,7 +5175,7 @@
 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);},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;}
+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');}
@@ -8291,7 +8293,7 @@
 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.BrowserMessageLoopStartTimeFromMainEntry3';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);}}}
+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;}}}
@@ -8385,28 +8387,32 @@
 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;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});}}
+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_TOP_UNIFIED_GC_MARKING_EVENTS={'BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8'};const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=Object.assign({'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.AtomicPauseMarkTransitiveClosure':'blink-gc-atomic-pause-mark-transitive-closure','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step',},BLINK_TOP_UNIFIED_GC_MARKING_EVENTS);const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS={'BlinkGC.ConcurrentMarkingStep':'blink-gc-mark-task-background'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS={'BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation'};const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS={'BlinkGC.ConcurrentSweepingStep':'blink-gc-sweep-task-background'};const BLINK_TOP_GC_EVENTS=Object.assign({'BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact',},BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS,BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_TOP_GC_EVENTS[event.title];}
-function blinkGarbageCollectionEventNames(){return Object.values(BLINK_TOP_GC_EVENTS);}
+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 event.title in BLINK_TOP_GC_EVENTS&&isNonForcedEvent(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 isNonForcedBlinkGarbageCollectionForegroundMarkingEvent(event){return event.title in BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS&&isNonForcedEvent(event);}
-function isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent(event){return event.title in BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS&&isNonForcedEvent(event);}
-function isNonForcedBlinkGarbageCollectionForegroundSweepingEvent(event){return event.title in BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS&&isNonForcedEvent(event);}
-function isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent(event){return event.title in BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS&&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);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfRootsMarking(histograms,model);addTotalDurationOfMarkingTransitiveClosure(histograms,model);addTotalDurationOfForegroundMarking(histograms,model);addTotalDurationOfBackgroundMarking(histograms,model);addTotalDurationOfForegroundSweeping(histograms,model);addTotalDurationOfBackgroundSweeping(histograms,model);}
+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,isNonForcedBlinkGarbageCollectionEvent,blinkGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForTopEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+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);}
@@ -8493,13 +8499,13 @@
 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,shouldNormalize,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);}
+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){let value=categoryValues.get(category)||0;if(shouldNormalize)value/=segment.duration;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);}}}
+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)+
@@ -8526,8 +8532,9 @@
 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_',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,false,(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,false,(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);}
+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);}}
@@ -8575,7 +8582,7 @@
 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;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);}}
+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);}}}
@@ -8683,7 +8690,7 @@
 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);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 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);}
@@ -8836,7 +8843,7 @@
 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.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});}}
+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);}
@@ -9008,13 +9015,11 @@
 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];navigationInfos.push({navigationStart:expectation.navigationStart,rendererHelper,url:expectation.url});}
+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 getRendererHelpers(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=[];for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;rendererHelpers.push(rendererHelper);}
-return rendererHelpers;}
 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 rendererHelpers=getRendererHelpers(model);const navigationInfos=getNavigationInfos(model);if(navigationInfos.length===0){return;}
+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);});});}
@@ -9817,27 +9822,27 @@
 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];for(const idx in typesToDraw){for(let i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.ui.tracks.Track)){continue;}
-this.children[i].drawTrack(typesToDraw[idx]);}}
+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){for(let i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.ui.tracks.Track)){continue;}
-const trackClientRect=this.children[i].getBoundingClientRect();const a=Math.max(loY,trackClientRect.top);const b=Math.min(hiY,trackClientRect.bottom);if(a<=b){this.children[i].addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);}}
-tr.ui.tracks.Track.prototype.addClosestEventToSelection.apply(this,arguments);},addEventsToTrackMap(eventToTrackMap){for(let i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.ui.tracks.Track)){continue;}
-this.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);}
+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=[];for(let i=0;i<this.children.length;i++){if(this.children[i]instanceof tr.ui.tracks.Track){tracks.push(this.children[i]);}}
-return tracks;},drawTrack(type){this.tracks_.forEach(function(track){track.drawTrack(type);});},addIntersectingEventsInRangeToSelection(loVX,hiVX,loY,hiY,selection){for(let i=0;i<this.tracks_.length;i++){const trackClientRect=this.tracks_[i].getBoundingClientRect();const a=Math.max(loY,trackClientRect.top);const b=Math.min(hiY,trackClientRect.bottom);if(a<=b){this.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){for(let i=0;i<this.tracks_.length;i++){this.tracks_[i].addAllEventsMatchingFilterToSelection(filter,selection);}},addAllEventsMatchingFilterToSelectionAsTask(filter,selection){const task=new Task();for(let i=0;i<this.tracks_.length;i++){task.subTask(function(i){return function(){this.tracks_[i].addAllEventsMatchingFilterToSelection(filter,selection);};}(i),this);}
-return task;},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){for(let i=0;i<this.tracks_.length;i++){const trackClientRect=this.tracks_[i].getBoundingClientRect();const a=Math.max(loY,trackClientRect.top);const b=Math.min(hiY,trackClientRect.bottom);if(a<=b){this.tracks_[i].addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);}}
+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
@@ -9946,9 +9951,9 @@
 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 minH=Math.max(2,Math.ceil(18/this.children.length));const h=(this.expanded_?18:minH)+'px';for(let i=0;i<this.children.length;i++){this.children[i].height=h;if(i===0){this.children[i].arrowVisible=true;}
-this.children[i].expanded=this.expanded;}
-if(this.children.length===1){this.children[0].expanded=true;this.children[0].arrowVisible=false;}},updateContents_(){tr.ui.tracks.ContainerTrack.prototype.updateContents_.call(this);this.detach();if(this.currentSubRowsWithHeadings_===undefined){if(this.itemsToGroup_===undefined){return;}
+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;}
@@ -10001,8 +10006,8 @@
 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;let draw=false;ctx.fillStyle='#eee';for(let i=0;i<this.children.length;++i){if(!(this.children[i]instanceof tr.ui.tracks.Track)||(this.children[i]instanceof tr.ui.tracks.SpacingTrack)){continue;}
-draw=!draw;if(!draw)continue;const bounds=this.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);}
+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);}
@@ -10108,7 +10113,7 @@
 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;this.polyfillWarnedOnce_=true;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;}
+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();}
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 22e85f4..e2a35ca 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -252,14 +252,6 @@
 #endif
 
 #ifdef _MSC_VER
-#define DART_FLATTEN
-#elif __GNUC__
-#define DART_FLATTEN __attribute__((flatten))
-#else
-#error Automatic compiler detection failed.
-#endif
-
-#ifdef _MSC_VER
 #elif __GNUC__
 #define DART_HAS_COMPUTED_GOTO 1
 #else
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 93a5a23..6635fc3 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -364,6 +364,7 @@
 
   template <typename T>
   DART_FORCE_INLINE static bool TestBit(T mask, intptr_t position) {
+    ASSERT(position < static_cast<intptr_t>(sizeof(T) * kBitsPerByte));
     return ((mask >> position) & 1) != 0;
   }
 
diff --git a/runtime/tests/vm/dart/minimal_kernel_bytecode_test.dart b/runtime/tests/vm/dart/minimal_kernel_bytecode_test.dart
new file mode 100644
index 0000000..417f129
--- /dev/null
+++ b/runtime/tests/vm/dart/minimal_kernel_bytecode_test.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.
+
+// 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/minimal_kernel_script.dart b/runtime/tests/vm/dart/minimal_kernel_script.dart
new file mode 100644
index 0000000..ea3070c
--- /dev/null
+++ b/runtime/tests/vm/dart/minimal_kernel_script.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.
+
+import "dart:convert";
+
+main(List<String> args) {
+  final String encoded = base64.encode(args[0].codeUnits);
+  print(String.fromCharCodes(base64.decode(encoded)));
+}
diff --git a/runtime/tests/vm/dart/minimal_kernel_test.dart b/runtime/tests/vm/dart/minimal_kernel_test.dart
new file mode 100644
index 0000000..0c7722c
--- /dev/null
+++ b/runtime/tests/vm/dart/minimal_kernel_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.
+
+// OtherResources=minimal_kernel_script.dart
+
+// Tests that dill file produced with --minimal-kernel option
+// works as expected.
+
+import 'dart:io' show Platform;
+
+import 'package:path/path.dart' as path;
+import 'snapshot_test_helper.dart';
+
+compileAndRunMinimalDillTest(List<String> extraCompilationArgs) async {
+  final testScriptUri = Platform.script.resolve('minimal_kernel_script.dart');
+  final message = 'Round_trip_message';
+
+  await withTempDir((String temp) async {
+    final minimalDillPath = path.join(temp, 'minimal.dill');
+    await runGenKernel('BUILD MINIMAL DILL FILE', [
+      '--minimal-kernel',
+      '--no-link-platform',
+      ...extraCompilationArgs,
+      '--output=$minimalDillPath',
+      testScriptUri.toFilePath(),
+    ]);
+
+    final result =
+        await runDart('RUN FROM MINIMAL DILL FILE', [minimalDillPath, message]);
+    expectOutput(message, result);
+  });
+}
+
+main() async {
+  await compileAndRunMinimalDillTest([]);
+}
diff --git a/runtime/tests/vm/dart/non_smi_receiver_assert_assignable_test.dart b/runtime/tests/vm/dart/non_smi_receiver_assert_assignable_test.dart
new file mode 100644
index 0000000..b6b5814
--- /dev/null
+++ b/runtime/tests/vm/dart/non_smi_receiver_assert_assignable_test.dart
@@ -0,0 +1,22 @@
+class A {}
+
+class B extends A {}
+
+final bool kTrue = int.parse('1') == 1;
+
+final dynamic smiValue = kTrue == 1 ? 1 : 'a';
+final A barValue = kTrue ? B() : A();
+
+main() {
+  // Inlined AssertAssignable has to perform Smi check on LoadClassId.
+  smiValue as String;
+
+  // Inlined AssertAssignable can omit Smi check on LoadClassId.
+  barValue as B;
+
+  foo<int>(1);
+  foo<String>('a');
+}
+
+@pragma('vm:never-inline')
+T foo<T>(dynamic arg) => arg as T;
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 8ffd309..a66c247 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -14,6 +14,8 @@
   final ProcessResult processResult;
 
   Result(this.cmdline, this.processResult);
+
+  String get output => processResult.stdout.trim();
 }
 
 void reportError(Result result, String msg) {
@@ -36,7 +38,7 @@
 }
 
 void expectOutput(String what, Result result) {
-  if (result.processResult.stdout.trim() != what) {
+  if (result.output != what) {
     reportError(result, 'Expected test to print \'${what}\' to stdout');
   }
 }
diff --git a/runtime/tests/vm/dart/splay_test.dart b/runtime/tests/vm/dart/splay_test.dart
index a91c853..eae1cbb 100644
--- a/runtime/tests/vm/dart/splay_test.dart
+++ b/runtime/tests/vm/dart/splay_test.dart
@@ -19,6 +19,10 @@
 // VMOptions=--concurrent_mark --concurrent_sweep
 // VMOptions=--concurrent_mark --use_compactor
 // VMOptions=--concurrent_mark --use_compactor --force_evacuation
+// VMOptions=--scavenger_tasks=0
+// VMOptions=--scavenger_tasks=1
+// VMOptions=--scavenger_tasks=2
+// VMOptions=--scavenger_tasks=3
 // VMOptions=--verify_before_gc
 // VMOptions=--verify_after_gc
 // VMOptions=--verify_before_gc --verify_after_gc
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 6b115e1..5f260b4 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
@@ -70,18 +70,16 @@
     ]);
 
     // Run the resulting Dwarf-AOT compiled script.
-    final dwarfOut1 = await runError(aotRuntime, <String>[
+    final dwarfTrace1 = await runError(aotRuntime, <String>[
       '--dwarf-stack-traces',
       scriptDwarfSnapshot,
       scriptDill,
     ]);
-    final dwarfTrace1 = cleanStacktrace(dwarfOut1);
-    final dwarfOut2 = await runError(aotRuntime, <String>[
+    final dwarfTrace2 = await runError(aotRuntime, <String>[
       '--no-dwarf-stack-traces',
       scriptDwarfSnapshot,
       scriptDill,
     ]);
-    final dwarfTrace2 = cleanStacktrace(dwarfOut2);
 
     // Run the resulting non-Dwarf-AOT compiled script.
     final nonDwarfTrace1 = await runError(aotRuntime, <String>[
@@ -104,10 +102,37 @@
     // out of the stack trace, those should be equal.
     Expect.deepEquals(
         collectPCOffsets(dwarfTrace1), collectPCOffsets(dwarfTrace2));
+
+    // Check that translating the DWARF stack trace (without internal frames)
+    // matches the symbolic stack trace.
+    final dwarf = Dwarf.fromFile(scriptDwarfSnapshot);
+    // We are generating unstripped snapshots, so the snapshot should include
+    // the appropriate DWARF information.
+    assert(dwarf != null);
+    final translatedDwarfTrace1 = await Stream.fromIterable(dwarfTrace1)
+        .transform(DwarfStackTraceDecoder(dwarf))
+        .toList();
+
+    final translatedStackFrames = onlySymbolicFrameLines(translatedDwarfTrace1);
+    final originalStackFrames = onlySymbolicFrameLines(nonDwarfTrace1);
+
+    print('Stack frames from translated non-symbolic stack trace:');
+    translatedStackFrames.forEach(print);
+    print('');
+
+    print('Stack frames from original symbolic stack trace:');
+    originalStackFrames.forEach(print);
+    print('');
+
+    Expect.isTrue(translatedStackFrames.length > 0);
+    Expect.isTrue(originalStackFrames.length > 0);
+
+    Expect.deepEquals(translatedStackFrames, originalStackFrames);
   });
 }
 
-Iterable<String> cleanStacktrace(Iterable<String> lines) {
-  // For DWARF stack traces, the pid/tid, if output, will vary over runs.
-  return lines.where((line) => !line.startsWith('pid'));
+final _symbolicFrameRE = RegExp(r'^#\d+\s+');
+
+Iterable<String> onlySymbolicFrameLines(Iterable<String> lines) {
+  return lines.where((line) => _symbolicFrameRE.hasMatch(line));
 }
diff --git a/runtime/tests/vm/dart/use_flag_test_helper.dart b/runtime/tests/vm/dart/use_flag_test_helper.dart
index c6fa872..fe9c511 100644
--- a/runtime/tests/vm/dart/use_flag_test_helper.dart
+++ b/runtime/tests/vm/dart/use_flag_test_helper.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:io';
 
 import 'package:expect/expect.dart';
@@ -152,7 +153,9 @@
   Expect.isTrue(result.stdout.isNotEmpty);
   Expect.isTrue(result.stderr.isEmpty);
 
-  return result.stdout.split(RegExp(r'[\r\n]'));
+  return await Stream.value(result.stdout as String)
+      .transform(const LineSplitter())
+      .toList();
 }
 
 Future<Iterable<String>> runError(String executable, List<String> args) async {
@@ -164,7 +167,9 @@
   Expect.isTrue(result.stdout.isEmpty);
   Expect.isTrue(result.stderr.isNotEmpty);
 
-  return result.stderr.split(RegExp(r'[\r\n]'));
+  return await Stream.value(result.stderr as String)
+      .transform(const LineSplitter())
+      .toList();
 }
 
 const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES';
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 b46d695..e098c5a 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
@@ -110,20 +110,20 @@
     // Stripped output should not change when --save-debugging-info is used.
     compareSnapshots(scriptStrippedOnlySnapshot, scriptStrippedSnapshot);
 
-    final stackTraceWithTerminators = strippedTrace.map((String s) => s + "\n");
-    print("\nOriginal stack trace:");
-    print(stackTraceWithTerminators.join());
+    print('');
+    print("Original stack trace:");
+    strippedTrace.forEach(print);
 
     final debugDwarf = Dwarf.fromFile(scriptDebuggingInfo);
     final wholeDwarf = Dwarf.fromFile(scriptWholeSnapshot);
 
-    final fromDebug = await Stream.fromIterable(stackTraceWithTerminators)
+    final fromDebug = await Stream.fromIterable(strippedTrace)
         .transform(DwarfStackTraceDecoder(debugDwarf))
         .toList();
     print("\nStack trace converted using separate debugging info:");
     print(fromDebug.join());
 
-    final fromWhole = await Stream.fromIterable(stackTraceWithTerminators)
+    final fromWhole = await Stream.fromIterable(strippedTrace)
         .transform(DwarfStackTraceDecoder(wholeDwarf))
         .toList();
     print("\nStack trace converted using unstripped ELF file:");
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index c22bccd..010b5c7 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -13,6 +13,8 @@
 cc/IsolateReload_PendingUnqualifiedCall_StaticToInstance: Fail # Issue 32981
 dart/data_uri_import_test/none: SkipByDesign
 dart/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
+dart/minimal_kernel_bytecode_test: Pass, Slow # Spawns several subprocesses
+dart/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 dart/snapshot_version_test: Skip # This test is a Dart1 test (script snapshot)
 dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -32,6 +34,8 @@
 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
 
 [ $builder_tag == tsan ]
 dart/appjit_cha_deopt_test: SkipSlow
@@ -57,6 +61,8 @@
 cc/VerifyExplicit_Crash: Crash # Negative tests of VerifiedMemory should crash iff in DEBUG mode. TODO(koda): Improve support for negative tests.
 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/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/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
 
 [ $mode == product ]
@@ -117,6 +123,8 @@
 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/snapshot_depfile_test: SkipByDesign # Test needs to run from source
 
 [ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
@@ -176,6 +184,8 @@
 [ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
 dart/appjit*: SkipSlow # DFE too slow
 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/snapshot_version_test: RuntimeError # Please triage.
 
 [ $hot_reload || $hot_reload_rollback ]
@@ -274,6 +284,8 @@
 dart/compilation_trace_test: Pass, Slow
 dart/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses
 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/print_flow_graph_determinism_test: SkipSlow
 dart/slow_path_shared_stub_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled.
 dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 857e1f4..cefcf0b 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1699,8 +1699,27 @@
     }
   }
 
-  class ClearCodeFunctionVisitor : public FunctionVisitor {
-    void Visit(const Function& function) {
+  auto const thread = Thread::Current();
+  auto const isolate = thread->isolate();
+  StackZone stack_zone(thread);
+  HANDLESCOPE(thread);
+  auto const zone = thread->zone();
+
+  class ClearCodeVisitor : public FunctionVisitor {
+   public:
+    ClearCodeVisitor(Zone* zone, bool force)
+        : force_(force),
+          bytecode_(Bytecode::Handle(zone)),
+          pool_(ObjectPool::Handle(zone)),
+          entry_(Object::Handle(zone)) {}
+
+    void VisitClass(const Class& cls) {
+      if (force_ || cls.id() >= kNumPredefinedCids) {
+        cls.DisableAllocationStub();
+      }
+    }
+
+    void VisitFunction(const Function& function) {
       bytecode_ = function.bytecode();
       if (!bytecode_.IsNull()) {
         pool_ = bytecode_.object_pool();
@@ -1720,41 +1739,27 @@
       function.ClearICDataArray();
     }
 
-    Bytecode& bytecode_ = Bytecode::Handle();
-    ObjectPool& pool_ = ObjectPool::Handle();
-    Object& entry_ = Object::Handle();
-  };
-  ClearCodeFunctionVisitor function_visitor;
-  ProgramVisitor::VisitFunctions(&function_visitor);
-
-  class ClearCodeClassVisitor : public ClassVisitor {
-   public:
-    explicit ClearCodeClassVisitor(bool force) : force_(force) {}
-
-    void Visit(const Class& cls) {
-      if (force_ || cls.id() >= kNumPredefinedCids) {
-        cls.DisableAllocationStub();
-      }
-    }
-
    private:
-    bool force_;
+    const bool force_;
+    Bytecode& bytecode_;
+    ObjectPool& pool_;
+    Object& entry_;
   };
-  ClearCodeClassVisitor class_visitor(including_nonchanging_cids);
-  ProgramVisitor::VisitClasses(&class_visitor);
+
+  ClearCodeVisitor visitor(zone, including_nonchanging_cids);
+  ProgramVisitor::WalkProgram(zone, isolate, &visitor);
 
   // Apart from normal function code and allocation stubs we have two global
   // code objects to clear.
   if (including_nonchanging_cids) {
-    auto thread = Thread::Current();
-    auto object_store = thread->isolate()->object_store();
-    auto& null_code = Code::Handle(thread->zone());
+    auto object_store = isolate->object_store();
+    auto& null_code = Code::Handle(zone);
     object_store->set_build_method_extractor_code(null_code);
 
-    auto& miss_function = Function::Handle(
-        thread->zone(), object_store->megamorphic_miss_function());
+    auto& miss_function =
+        Function::Handle(zone, object_store->megamorphic_call_miss_function());
     miss_function.ClearCode();
-    object_store->SetMegamorphicMissHandler(null_code, miss_function);
+    object_store->SetMegamorphicCallMissHandler(null_code, miss_function);
   }
 #endif  // !DART_PRECOMPILED_RUNTIME
 }
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index a5d003c..3078643 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -41,6 +41,7 @@
   V(SingleTargetCache)                                                         \
   V(UnlinkedCall)                                                              \
   V(MonomorphicSmiableCall)                                                    \
+  V(CallSiteData)                                                              \
   V(ICData)                                                                    \
   V(MegamorphicCache)                                                          \
   V(SubtypeTestCache)                                                          \
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index d19460a..c08e1c6 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -214,9 +214,17 @@
   auto old_table = table_.load();
   auto new_table = static_cast<RawClass**>(
       malloc(new_capacity * sizeof(RawClass*)));  // NOLINT
-  memmove(new_table, old_table, capacity_ * sizeof(RawClass*));
-  memset(new_table + capacity_, 0,
-         (new_capacity - capacity_) * sizeof(RawClass*));
+  intptr_t i;
+  for (i = 0; i < capacity_; i++) {
+    // Don't use memmove, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_table[i] = old_table[i];
+  }
+  for (; i < new_capacity; i++) {
+    // Don't use memset, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_table[i] = 0;
+  }
   old_class_tables_->Add(old_table);
   table_.store(new_table);
 
@@ -246,17 +254,32 @@
       reinterpret_cast<RelaxedAtomic<intptr_t>*>(
           malloc(new_capacity * sizeof(RelaxedAtomic<intptr_t>)));  // NOLINT
 
-  memmove(new_table, old_table, capacity_ * sizeof(intptr_t));
-  memset(new_table + capacity_, 0,
-         (new_capacity - capacity_) * sizeof(intptr_t));
+  intptr_t i;
+  for (i = 0; i < capacity_; i++) {
+    // Don't use memmove, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_table[i] = old_table[i];
+  }
+  for (; i < new_capacity; i++) {
+    // Don't use memset, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_table[i] = 0;
+  }
 
 #if !defined(PRODUCT)
   auto old_trace_table = trace_allocation_table_.load();
   auto new_trace_table =
       static_cast<uint8_t*>(malloc(new_capacity * sizeof(uint8_t)));  // NOLINT
-  memmove(new_trace_table, old_trace_table, capacity_ * sizeof(uint8_t));
-  memset(new_trace_table + capacity_, 0,
-         (new_capacity - capacity_) * sizeof(uint8_t));
+  for (i = 0; i < capacity_; i++) {
+    // Don't use memmove, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_trace_table[i] = old_trace_table[i];
+  }
+  for (; i < new_capacity; i++) {
+    // Don't use memset, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_trace_table[i] = 0;
+  }
 #endif
 
   old_tables_->Add(old_table);
@@ -265,13 +288,20 @@
   NOT_IN_PRODUCT(trace_allocation_table_.store(new_trace_table));
 
 #if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
+  auto old_unboxed_fields_map = unboxed_fields_map_;
   auto new_unboxed_fields_map = static_cast<UnboxedFieldBitmap*>(
       malloc(new_capacity * sizeof(UnboxedFieldBitmap)));
-  memmove(new_unboxed_fields_map, unboxed_fields_map_,
-          capacity_ * sizeof(UnboxedFieldBitmap));
-  memset(new_unboxed_fields_map + capacity_, 0,
-         (new_capacity - capacity_) * sizeof(UnboxedFieldBitmap));
-  old_tables_->Add(unboxed_fields_map_);
+  for (i = 0; i < capacity_; i++) {
+    // Don't use memmove, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_unboxed_fields_map[i] = old_unboxed_fields_map[i];
+  }
+  for (; i < new_capacity; i++) {
+    // Don't use memset, which changes this from a relaxed atomic operation
+    // to a non-atomic operation.
+    new_unboxed_fields_map[i] = UnboxedFieldBitmap(0);
+  }
+  old_tables_->Add(old_unboxed_fields_map);
   unboxed_fields_map_ = new_unboxed_fields_map;
 #endif  // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
 
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index eb5a431..a21dd51 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -42,9 +42,11 @@
   UnboxedFieldBitmap& operator=(const UnboxedFieldBitmap&) = default;
 
   DART_FORCE_INLINE bool Get(intptr_t position) const {
+    if (position >= Length()) return false;
     return Utils::TestBit(bitmap_, position);
   }
   DART_FORCE_INLINE void Set(intptr_t position) {
+    ASSERT(position < Length());
     bitmap_ |= Utils::Bit<decltype(bitmap_)>(position);
   }
   DART_FORCE_INLINE uint64_t Value() const { return bitmap_; }
@@ -134,14 +136,24 @@
     const intptr_t num_cids = NumCids();
     const intptr_t bytes = sizeof(intptr_t) * num_cids;
     auto size_table = static_cast<intptr_t*>(malloc(bytes));
-    memmove(size_table, table_.load(), sizeof(intptr_t) * num_cids);
+    auto table = table_.load();
+    for (intptr_t i = 0; i < num_cids; i++) {
+      // Don't use memmove, which changes this from a relaxed atomic operation
+      // to a non-atomic operation.
+      size_table[i] = table[i];
+    }
     *copy_num_cids = num_cids;
     *copy = size_table;
   }
 
   void ResetBeforeHotReload() {
     // The [IsolateReloadContext] is now source-of-truth for GC.
-    memset(table_.load(), 0, sizeof(intptr_t) * top_);
+    auto table = table_.load();
+    for (intptr_t i = 0; i < top_; i++) {
+      // Don't use memset, which changes this from a relaxed atomic operation
+      // to a non-atomic operation.
+      table[i] = 0;
+    }
   }
 
   void ResetAfterHotReload(intptr_t* old_table,
@@ -151,7 +163,12 @@
     // return, so we restore size information for all classes.
     if (is_rollback) {
       SetNumCids(num_old_cids);
-      memmove(table_.load(), old_table, sizeof(intptr_t) * num_old_cids);
+      auto table = table_.load();
+      for (intptr_t i = 0; i < num_old_cids; i++) {
+        // Don't use memmove, which changes this from a relaxed atomic operation
+        // to a non-atomic operation.
+        table[i] = old_table[i];
+      }
     }
 
     // Can't free this table immediately as another thread (e.g., concurrent
@@ -247,7 +264,12 @@
     const intptr_t num_cids = NumCids();
     const intptr_t bytes = sizeof(RawClass*) * num_cids;
     auto class_table = static_cast<RawClass**>(malloc(bytes));
-    memmove(class_table, table_.load(), sizeof(RawClass*) * num_cids);
+    auto table = table_.load();
+    for (intptr_t i = 0; i < num_cids; i++) {
+      // Don't use memmove, which changes this from a relaxed atomic operation
+      // to a non-atomic operation.
+      class_table[i] = table[i];
+    }
     *copy_num_cids = num_cids;
     *copy = class_table;
   }
@@ -267,7 +289,12 @@
     // return, so we restore size information for all classes.
     if (is_rollback) {
       SetNumCids(num_old_cids);
-      memmove(table_.load(), old_table, sizeof(RawClass*) * num_old_cids);
+      auto table = table_.load();
+      for (intptr_t i = 0; i < num_old_cids; i++) {
+        // Don't use memmove, which changes this from a relaxed atomic operation
+        // to a non-atomic operation.
+        table[i] = old_table[i];
+      }
     } else {
       CopySizesFromClassObjects();
     }
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 063d5dd..25a37ad 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -150,6 +150,8 @@
     RawClass* cls = Class::RawCast(object);
     intptr_t class_id = cls->ptr()->id_;
 
+    // Classes expected to be dropped by the precompiler should not be traced.
+    ASSERT(class_id != kIllegalCid);
     if (class_id < kNumPredefinedCids) {
       // These classes are allocated by Object::Init or Object::InitOnce, so the
       // deserializer must find them in the class table instead of allocating
@@ -200,6 +202,9 @@
       s->UnexpectedObject(cls, "Class with illegal cid");
     }
     s->WriteCid(class_id);
+    if (s->kind() == Snapshot::kFull && RequireLegacyErasureOfConstants(cls)) {
+      s->UnexpectedObject(cls, "Class with non mode agnostic constants");
+    }
     if (s->kind() != Snapshot::kFullAOT) {
       s->Write<uint32_t>(cls->ptr()->binary_declaration_);
     }
@@ -254,6 +259,20 @@
 
     return unboxed_fields_bitmap;
   }
+
+  bool RequireLegacyErasureOfConstants(RawClass* 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()) {
+      return false;
+    }
+    Zone* zone = Thread::Current()->zone();
+    const Class& clazz = Class::Handle(zone, cls);
+    return clazz.RequireLegacyErasureOfConstants(zone);
+  }
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
@@ -2050,7 +2069,7 @@
   // the object ID from the heap directly.
   bool ShouldDrop(RawWeakSerializationReference* ref) const {
     auto const target = WeakSerializationReference::TargetOf(ref);
-    return Serializer::IsAllocatedReference(heap_->GetObjectId(target));
+    return Serializer::IsReachableReference(heap_->GetObjectId(target));
   }
 
   Heap* const heap_;
@@ -5440,8 +5459,8 @@
 
   ClassTable* table = isolate()->class_table();
   for (intptr_t cid = kClassCid; cid < kInstanceCid; cid++) {
-    // Error has no class object.
-    if (cid != kErrorCid) {
+    // Error, CallSiteData has no class object.
+    if (cid != kErrorCid && cid != kCallSiteDataCid) {
       ASSERT(table->HasValidClassAt(cid));
       AddBaseObject(table->At(cid), "Class");
     }
@@ -6056,13 +6075,16 @@
 class HeapLocker : public StackResource {
  public:
   HeapLocker(Thread* thread, PageSpace* page_space)
-      : StackResource(thread), page_space_(page_space) {
-    page_space_->AcquireDataLock();
+      : StackResource(thread),
+        page_space_(page_space),
+        freelist_(page_space->DataFreeList()) {
+    page_space_->AcquireLock(freelist_);
   }
-  ~HeapLocker() { page_space_->ReleaseDataLock(); }
+  ~HeapLocker() { page_space_->ReleaseLock(freelist_); }
 
  private:
   PageSpace* page_space_;
+  FreeList* freelist_;
 };
 
 void Deserializer::AddVMIsolateBaseObjects() {
@@ -6107,8 +6129,8 @@
 
   ClassTable* table = isolate()->class_table();
   for (intptr_t cid = kClassCid; cid <= kUnwindErrorCid; cid++) {
-    // Error has no class object.
-    if (cid != kErrorCid) {
+    // Error, CallSiteData has no class object.
+    if (cid != kErrorCid && cid != kCallSiteDataCid) {
       ASSERT(table->HasValidClassAt(cid));
       AddBaseObject(table->At(cid));
     }
@@ -6548,7 +6570,7 @@
   if (FLAG_use_bare_instructions) {
     // By default, every switchable call site will put (ic_data, code) into the
     // object pool.  The [code] is initialized (at AOT compile-time) to be a
-    // [StubCode::UnlinkedCall].
+    // [StubCode::SwitchableCallMiss].
     //
     // In --use-bare-instruction we reduce the extra indirection via the [code]
     // object and store instead (ic_data, entrypoint) in the object pool.
@@ -6563,9 +6585,15 @@
     for (intptr_t i = 0; i < pool.Length(); i++) {
       if (pool.TypeAt(i) == ObjectPool::EntryType::kTaggedObject) {
         entry = pool.ObjectAt(i);
-        if (entry.raw() == StubCode::UnlinkedCall().raw()) {
+        if (entry.raw() == StubCode::SwitchableCallMiss().raw()) {
           smi = Smi::FromAlignedAddress(
-              StubCode::UnlinkedCall().MonomorphicEntryPoint());
+              StubCode::SwitchableCallMiss().MonomorphicEntryPoint());
+          pool.SetTypeAt(i, ObjectPool::EntryType::kImmediate,
+                         ObjectPool::Patchability::kPatchable);
+          pool.SetObjectAt(i, smi);
+        } else if (entry.raw() == StubCode::MegamorphicCall().raw()) {
+          smi = Smi::FromAlignedAddress(
+              StubCode::MegamorphicCall().MonomorphicEntryPoint());
           pool.SetTypeAt(i, ObjectPool::EntryType::kImmediate,
                          ObjectPool::Patchability::kPatchable);
           pool.SetObjectAt(i, smi);
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index 28ad54a..1846638 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -27,7 +27,7 @@
       lib_(Library::Handle(zone)),
       uri_(String::Handle(zone)) {}
 
-void CompilationTraceSaver::Visit(const Function& function) {
+void CompilationTraceSaver::VisitFunction(const Function& function) {
   if (!function.HasCode()) {
     return;  // Not compiled.
   }
@@ -505,7 +505,7 @@
   }
 }
 
-void TypeFeedbackSaver::Visit(const Function& function) {
+void TypeFeedbackSaver::VisitFunction(const Function& function) {
   if (!function.HasCode()) {
     return;  // Not compiled.
   }
diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h
index e3a8fbd..d7fed08 100644
--- a/runtime/vm/compilation_trace.h
+++ b/runtime/vm/compilation_trace.h
@@ -15,7 +15,7 @@
 class CompilationTraceSaver : public FunctionVisitor {
  public:
   explicit CompilationTraceSaver(Zone* zone);
-  void Visit(const Function& function);
+  void VisitFunction(const Function& function);
 
   void StealBuffer(uint8_t** buffer, intptr_t* buffer_length) {
     *buffer = reinterpret_cast<uint8_t*>(buf_.buffer());
@@ -72,7 +72,7 @@
   void WriteHeader();
   void SaveClasses();
   void SaveFields();
-  void Visit(const Function& function);
+  void VisitFunction(const Function& function);
 
  private:
   void WriteClassByName(const Class& cls);
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 2bf294a..ec30d5d 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -282,73 +282,22 @@
         global_object_pool_builder()->Reset();
         stub_pool.CopyInto(global_object_pool_builder());
 
-        // We have two global code objects we need to re-generate with the new
-        // global object pool, namely the
-        //   - megamorphic miss handler code and the
-        //   - build method extractor code
-        MegamorphicCacheTable::ReInitMissHandlerCode(
-            isolate_, global_object_pool_builder());
-
+        // We have various stubs we would like to generate inside the isolate,
+        // to ensure the rest of the AOT compilation will use the
+        // isolate-specific stubs (callable via pc-relative calls).
         auto& stub_code = Code::Handle();
-
+#define DO(member, name)                                                       \
+  stub_code = StubCode::BuildIsolateSpecific##name##Stub(                      \
+      global_object_pool_builder());                                           \
+  I->object_store()->set_##member(stub_code);
+        OBJECT_STORE_STUB_CODE_LIST(DO)
+#undef DO
         stub_code =
             StubCode::GetBuildMethodExtractorStub(global_object_pool_builder());
         I->object_store()->set_build_method_extractor_code(stub_code);
 
-        stub_code = StubCode::BuildIsolateSpecificDispatchTableNullErrorStub(
-            global_object_pool_builder());
-        I->object_store()->set_dispatch_table_null_error_stub(stub_code);
-
-        stub_code =
-            StubCode::BuildIsolateSpecificNullErrorSharedWithFPURegsStub(
-                global_object_pool_builder());
-        I->object_store()->set_null_error_stub_with_fpu_regs_stub(stub_code);
-
-        stub_code =
-            StubCode::BuildIsolateSpecificNullErrorSharedWithoutFPURegsStub(
-                global_object_pool_builder());
-        I->object_store()->set_null_error_stub_without_fpu_regs_stub(stub_code);
-
-        stub_code =
-            StubCode::BuildIsolateSpecificNullArgErrorSharedWithFPURegsStub(
-                global_object_pool_builder());
-        I->object_store()->set_null_arg_error_stub_with_fpu_regs_stub(
-            stub_code);
-
-        stub_code =
-            StubCode::BuildIsolateSpecificNullArgErrorSharedWithoutFPURegsStub(
-                global_object_pool_builder());
-        I->object_store()->set_null_arg_error_stub_without_fpu_regs_stub(
-            stub_code);
-
-        stub_code = StubCode::BuildIsolateSpecificAllocateMintWithFPURegsStub(
-            global_object_pool_builder());
-        I->object_store()->set_allocate_mint_with_fpu_regs_stub(stub_code);
-
-        stub_code =
-            StubCode::BuildIsolateSpecificAllocateMintWithoutFPURegsStub(
-                global_object_pool_builder());
-        I->object_store()->set_allocate_mint_without_fpu_regs_stub(stub_code);
-
-        stub_code =
-            StubCode::BuildIsolateSpecificStackOverflowSharedWithFPURegsStub(
-                global_object_pool_builder());
-        I->object_store()->set_stack_overflow_stub_with_fpu_regs_stub(
-            stub_code);
-
-        stub_code =
-            StubCode::BuildIsolateSpecificStackOverflowSharedWithoutFPURegsStub(
-                global_object_pool_builder());
-        I->object_store()->set_stack_overflow_stub_without_fpu_regs_stub(
-            stub_code);
-
-        stub_code = StubCode::BuildIsolateSpecificWriteBarrierWrappersStub(
-            global_object_pool_builder());
-        I->object_store()->set_write_barrier_wrappers_stub(stub_code);
-
-        stub_code = StubCode::BuildIsolateSpecificArrayWriteBarrierStub(
-            global_object_pool_builder());
-        I->object_store()->set_array_write_barrier_stub(stub_code);
+        MegamorphicCacheTable::ReInitMissHandlerCode(
+            isolate_, global_object_pool_builder());
       }
 
       CollectDynamicFunctionNames();
@@ -484,7 +433,7 @@
              non_visited.ToFullyQualifiedCString());
     }
 #endif
-    ProgramVisitor::Dedup();
+    ProgramVisitor::Dedup(T);
 
     zone_ = NULL;
   }
@@ -519,7 +468,7 @@
    public:
     explicit ConstructorVisitor(Precompiler* precompiler, Zone* zone)
         : precompiler_(precompiler), zone_(zone) {}
-    void Visit(const Function& function) {
+    void VisitFunction(const Function& function) {
       if (!function.IsGenerativeConstructor()) return;
       if (function.HasCode()) {
         // Const constructors may have been visited before. Recompile them here
@@ -538,8 +487,8 @@
   };
 
   HANDLESCOPE(T);
-  ConstructorVisitor visitor(this, zone_);
-  ProgramVisitor::VisitFunctions(&visitor);
+  ConstructorVisitor visitor(this, Z);
+  ProgramVisitor::WalkProgram(Z, I, &visitor);
 }
 
 void Precompiler::AddRoots() {
@@ -917,6 +866,9 @@
     const AbstractType& type =
         AbstractType::Handle(Z, TypeParameter::Cast(abstype).bound());
     AddType(type);
+    const auto& function = Function::Handle(
+        Z, TypeParameter::Cast(abstype).parameterized_function());
+    AddTypesOf(function);
     const Class& cls =
         Class::Handle(Z, TypeParameter::Cast(abstype).parameterized_class());
     AddTypesOf(cls);
@@ -2182,14 +2134,14 @@
 
     const CodeSet& visited() const { return visited_code_; }
 
-    void Visit(const Code& code) { visited_code_.Insert(code); }
+    void VisitCode(const Code& code) { visited_code_.Insert(code); }
 
    private:
     CodeSet visited_code_;
   };
 
   CodeChecker visitor;
-  ProgramVisitor::VisitCode(&visitor);
+  ProgramVisitor::WalkProgram(Z, I, &visitor);
   const CodeSet& visited = visitor.visited();
 
   FunctionSet::Iterator it(&functions_to_retain_);
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index a6ba5bd..9c0caf9 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -1592,7 +1592,6 @@
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
   ASSERT(IsOriginalObject(object));
-  ASSERT(!target::CanLoadFromThread(object));
   if (!constant_pool_allowed()) {
     return false;
   }
@@ -1608,24 +1607,31 @@
                                  bool is_unique,
                                  Register pp) {
   ASSERT(IsOriginalObject(object));
-  intptr_t offset = 0;
-  if (target::CanLoadFromThread(object, &offset)) {
-    // Load common VM constants from the thread. This works also in places where
-    // no constant pool is set up (e.g. intrinsic code).
-    ldr(rd, Address(THR, offset), cond);
-  } else if (target::IsSmi(object)) {
-    // Relocation doesn't apply to Smis.
-    LoadImmediate(rd, target::ToRawSmi(object), cond);
-  } else if (CanLoadFromObjectPool(object)) {
-    // Make sure that class CallPattern is able to decode this load from the
-    // object pool.
-    const auto index = is_unique ? object_pool_builder().AddObject(object)
-                                 : object_pool_builder().FindObject(object);
-    const int32_t offset = target::ObjectPool::element_offset(index);
-    LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, pp, cond);
-  } else {
-    UNREACHABLE();
+  // `is_unique == true` effectively means object has to be patchable.
+  if (!is_unique) {
+    intptr_t offset = 0;
+    if (target::CanLoadFromThread(object, &offset)) {
+      // Load common VM constants from the thread. This works also in places
+      // where no constant pool is set up (e.g. intrinsic code).
+      ldr(rd, Address(THR, offset), cond);
+      return;
+    }
+    if (target::IsSmi(object)) {
+      // Relocation doesn't apply to Smis.
+      LoadImmediate(rd, target::ToRawSmi(object), cond);
+      return;
+    }
   }
+  if (!CanLoadFromObjectPool(object)) {
+    UNREACHABLE();
+    return;
+  }
+  // Make sure that class CallPattern is able to decode this load from the
+  // object pool.
+  const auto index = is_unique ? object_pool_builder().AddObject(object)
+                               : object_pool_builder().FindObject(object);
+  const int32_t offset = target::ObjectPool::element_offset(index);
+  LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, pp, cond);
 }
 
 void Assembler::LoadObject(Register rd, const Object& object, Condition cond) {
@@ -1967,6 +1973,25 @@
   str(value, dest);
 }
 
+void Assembler::ExtractClassIdFromTags(Register result, Register tags) {
+  ASSERT(target::RawObject::kClassIdTagPos == 16);
+  ASSERT(target::RawObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(classid_t) == sizeof(uint16_t));
+  Lsr(result, tags, Operand(target::RawObject::kClassIdTagPos), AL);
+}
+
+void Assembler::ExtractInstanceSizeFromTags(Register result, Register tags) {
+  ASSERT(target::RawObject::kSizeTagPos == 8);
+  ASSERT(target::RawObject::kSizeTagSize == 8);
+  Lsr(result, tags,
+      Operand(target::RawObject::kSizeTagPos -
+              target::ObjectAlignment::kObjectAlignmentLog2),
+      AL);
+  AndImmediate(result, result,
+               (Utils::NBitMask(target::RawObject::kSizeTagSize)
+                << target::ObjectAlignment::kObjectAlignmentLog2));
+}
+
 void Assembler::LoadClassId(Register result, Register object, Condition cond) {
   ASSERT(target::RawObject::kClassIdTagPos == 16);
   ASSERT(target::RawObject::kClassIdTagSize == 16);
@@ -2727,27 +2752,6 @@
   blx(IP);
 }
 
-void Assembler::CallNullErrorShared(bool save_fpu_registers) {
-  uword entry_point_offset =
-      save_fpu_registers
-          ? target::Thread::null_error_shared_with_fpu_regs_entry_point_offset()
-          : target::Thread::
-                null_error_shared_without_fpu_regs_entry_point_offset();
-  ldr(LR, Address(THR, entry_point_offset));
-  blx(LR);
-}
-
-void Assembler::CallNullArgErrorShared(bool save_fpu_registers) {
-  const uword entry_point_offset =
-      save_fpu_registers
-          ? target::Thread::
-                null_arg_error_shared_with_fpu_regs_entry_point_offset()
-          : target::Thread::
-                null_arg_error_shared_without_fpu_regs_entry_point_offset();
-  ldr(LR, Address(THR, entry_point_offset));
-  blx(LR);
-}
-
 void Assembler::BranchLinkWithEquivalence(const Code& target,
                                           const Object& equivalence,
                                           CodeEntryKind entry_kind) {
@@ -3459,7 +3463,7 @@
   LoadClassIdMayBeSmi(IP, R0);
   add(R2, R2, Operand(target::ToRawSmi(1)));
   cmp(R1, Operand(IP, LSL, 1));
-  Branch(Address(THR, target::Thread::monomorphic_miss_entry_offset()), NE);
+  Branch(Address(THR, target::Thread::switchable_call_miss_entry_offset()), NE);
   str(R2, FieldAddress(R9, count_offset));
   LoadImmediate(R4, 0);  // GC-safe for OptimizeInvokedFunction.
 
@@ -3488,7 +3492,7 @@
 
   LoadClassId(IP, R0);
   cmp(R9, Operand(IP, LSL, 1));
-  Branch(Address(THR, target::Thread::monomorphic_miss_entry_offset()), NE);
+  Branch(Address(THR, target::Thread::switchable_call_miss_entry_offset()), NE);
 
   // Fall through to unchecked entry.
   ASSERT_EQUAL(CodeSize() - start,
@@ -3636,6 +3640,17 @@
   pattern.set_distance(offset_into_target);
 }
 
+void Assembler::GenerateUnRelocatedPcRelativeTailCall(
+    Condition cond,
+    intptr_t offset_into_target) {
+  // Emit "b <offset>".
+  EmitType5(cond, 0x686868, /*link=*/false);
+
+  PcRelativeTailCallPattern pattern(buffer_.contents() + buffer_.Size() -
+                                    PcRelativeTailCallPattern::kLengthInBytes);
+  pattern.set_distance(offset_into_target);
+}
+
 Address Assembler::ElementAddressForIntIndex(bool is_load,
                                              bool is_external,
                                              intptr_t cid,
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 5f8ee9c..bd79c03 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -735,10 +735,6 @@
                   CodeEntryKind entry_kind = CodeEntryKind::kNormal);
   void BranchLinkToRuntime();
 
-  void CallNullErrorShared(bool save_fpu_registers);
-
-  void CallNullArgErrorShared(bool save_fpu_registers);
-
   // Branch and link to an entry address. Call sequence can be patched.
   void BranchLinkPatchable(const Code& code,
                            CodeEntryKind entry_kind = CodeEntryKind::kNormal);
@@ -900,6 +896,9 @@
   // Stores a Smi value into a heap object field that always contains a Smi.
   void StoreIntoSmiField(const Address& dest, Register value);
 
+  void ExtractClassIdFromTags(Register result, Register tags);
+  void ExtractInstanceSizeFromTags(Register result, Register tags);
+
   void LoadClassId(Register result, Register object, Condition cond = AL);
   void LoadClassById(Register result, Register class_id);
   void CompareClassId(Register object, intptr_t class_id, Register scratch);
@@ -1192,9 +1191,9 @@
                         Register temp1,
                         Register temp2);
 
-  // This emits an PC-relative call of the form "blr <offset>".  The offset
-  // is not yet known and needs therefore relocation to the right place before
-  // the code can be used.
+  // This emits an PC-relative call of the form "blr.<cond> <offset>".  The
+  // offset is not yet known and needs therefore relocation to the right place
+  // before the code can be used.
   //
   // The neccessary information for the "linker" (i.e. the relocation
   // information) is stored in [RawCode::static_calls_target_table_]: an entry
@@ -1210,6 +1209,12 @@
   void GenerateUnRelocatedPcRelativeCall(Condition cond = AL,
                                          intptr_t offset_into_target = 0);
 
+  // This emits an PC-relative tail call of the form "b.<cond> <offset>".
+  //
+  // See also above for the pc-relative call.
+  void GenerateUnRelocatedPcRelativeTailCall(Condition cond = AL,
+                                             intptr_t offset_into_target = 0);
+
   // Emit data (e.g encoded instruction or immediate) in instruction stream.
   void Emit(int32_t value);
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index ddfa229..422ba5a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -430,7 +430,6 @@
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
   ASSERT(IsOriginalObject(object));
-  ASSERT(!target::CanLoadFromThread(object));
   if (!constant_pool_allowed()) {
     return false;
   }
@@ -464,20 +463,36 @@
                                  const Object& object,
                                  bool is_unique) {
   ASSERT(IsOriginalObject(object));
-  word offset = 0;
-  if (IsSameObject(compiler::NullObject(), object)) {
-    mov(dst, NULL_REG);
-  } else if (target::CanLoadFromThread(object, &offset)) {
-    ldr(dst, Address(THR, offset));
-  } else if (CanLoadFromObjectPool(object)) {
+  // `is_unique == true` effectively means object has to be patchable.
+  // (even if the object is null)
+  if (!is_unique) {
+    if (IsSameObject(compiler::NullObject(), object)) {
+      mov(dst, NULL_REG);
+      return;
+    }
+    if (IsSameObject(CastHandle<Object>(compiler::TrueObject()), object)) {
+      AddImmediate(dst, NULL_REG, kTrueOffsetFromNull);
+      return;
+    }
+    if (IsSameObject(CastHandle<Object>(compiler::FalseObject()), object)) {
+      AddImmediate(dst, NULL_REG, kFalseOffsetFromNull);
+      return;
+    }
+    word offset = 0;
+    if (target::CanLoadFromThread(object, &offset)) {
+      ldr(dst, Address(THR, offset));
+      return;
+    }
+  }
+  if (CanLoadFromObjectPool(object)) {
     const int32_t offset = target::ObjectPool::element_offset(
         is_unique ? object_pool_builder().AddObject(object)
                   : object_pool_builder().FindObject(object));
     LoadWordFromPoolOffset(dst, offset);
-  } else {
-    ASSERT(target::IsSmi(object));
-    LoadImmediate(dst, target::ToRawSmi(object));
+    return;
   }
+  ASSERT(target::IsSmi(object));
+  LoadImmediate(dst, target::ToRawSmi(object));
 }
 
 void Assembler::LoadObject(Register dst, const Object& object) {
@@ -636,27 +651,6 @@
   blr(TMP);
 }
 
-void Assembler::CallNullErrorShared(bool save_fpu_registers) {
-  uword entry_point_offset =
-      save_fpu_registers
-          ? target::Thread::null_error_shared_with_fpu_regs_entry_point_offset()
-          : target::Thread::
-                null_error_shared_without_fpu_regs_entry_point_offset();
-  ldr(LR, Address(THR, entry_point_offset));
-  blr(LR);
-}
-
-void Assembler::CallNullArgErrorShared(bool save_fpu_registers) {
-  const uword entry_point_offset =
-      save_fpu_registers
-          ? target::Thread::
-                null_arg_error_shared_with_fpu_regs_entry_point_offset()
-          : target::Thread::
-                null_arg_error_shared_without_fpu_regs_entry_point_offset();
-  ldr(LR, Address(THR, entry_point_offset));
-  blr(LR);
-}
-
 void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) {
   Operand op;
   if (imm == 0) {
@@ -1133,6 +1127,21 @@
   str(value, dest);
 }
 
+void Assembler::ExtractClassIdFromTags(Register result, Register tags) {
+  ASSERT(target::RawObject::kClassIdTagPos == 16);
+  ASSERT(target::RawObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(classid_t) == sizeof(uint16_t));
+  LsrImmediate(result, tags, target::RawObject::kClassIdTagPos, kWord);
+}
+
+void Assembler::ExtractInstanceSizeFromTags(Register result, Register tags) {
+  ASSERT(target::RawObject::kSizeTagPos == 8);
+  ASSERT(target::RawObject::kSizeTagSize == 8);
+  ubfx(result, tags, target::RawObject::kSizeTagPos,
+       target::RawObject::kSizeTagSize);
+  LslImmediate(result, result, target::ObjectAlignment::kObjectAlignmentLog2);
+}
+
 void Assembler::LoadClassId(Register result, Register object) {
   ASSERT(target::RawObject::kClassIdTagPos == 16);
   ASSERT(target::RawObject::kClassIdTagSize == 16);
@@ -1549,7 +1558,7 @@
 
   Label immediate, miss;
   Bind(&miss);
-  ldr(IP0, Address(THR, target::Thread::monomorphic_miss_entry_offset()));
+  ldr(IP0, Address(THR, target::Thread::switchable_call_miss_entry_offset()));
   br(IP0);
 
   Comment("MonomorphicCheckedEntry");
@@ -1567,7 +1576,7 @@
   cmp(R1, Operand(IP0, LSL, 1));
   b(&miss, NE);
   str(R2, FieldAddress(R5, count_offset));
-  LoadImmediate(R4, 0);  // GC-safe for OptimizeInvokedFunction.
+  LoadImmediate(R4, 0);  // GC-safe for OptimizeInvokedFunction
 
   // Fall through to unchecked entry.
   ASSERT_EQUAL(CodeSize() - start,
@@ -1587,7 +1596,7 @@
 
   Label immediate, miss;
   Bind(&miss);
-  ldr(IP0, Address(THR, target::Thread::monomorphic_miss_entry_offset()));
+  ldr(IP0, Address(THR, target::Thread::switchable_call_miss_entry_offset()));
   br(IP0);
 
   Comment("MonomorphicCheckedEntry");
@@ -1737,6 +1746,15 @@
   pattern.set_distance(offset_into_target);
 }
 
+void Assembler::GenerateUnRelocatedPcRelativeTailCall(
+    intptr_t offset_into_target) {
+  // Emit "b <offset>".
+  EmitUnconditionalBranchOp(B, 0);
+  PcRelativeTailCallPattern pattern(buffer_.contents() + buffer_.Size() -
+                                    PcRelativeTailCallPattern::kLengthInBytes);
+  pattern.set_distance(offset_into_target);
+}
+
 Address Assembler::ElementAddressForIntIndex(bool is_external,
                                              intptr_t cid,
                                              intptr_t index_scale,
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index d83aa8e..26ab378 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1406,10 +1406,6 @@
   }
   void BranchLinkToRuntime();
 
-  void CallNullErrorShared(bool save_fpu_registers);
-
-  void CallNullArgErrorShared(bool save_fpu_registers);
-
   // Emit a call that shares its object pool entries with other calls
   // that have the same equivalence marker.
   void BranchLinkWithEquivalence(
@@ -1571,6 +1567,9 @@
   }
   void CompareObject(Register reg, const Object& object);
 
+  void ExtractClassIdFromTags(Register result, Register tags);
+  void ExtractInstanceSizeFromTags(Register result, Register tags);
+
   void LoadClassId(Register result, Register object);
   void LoadClassById(Register result, Register class_id);
   void CompareClassId(Register object,
@@ -1669,6 +1668,11 @@
   // function.
   void GenerateUnRelocatedPcRelativeCall(intptr_t offset_into_target = 0);
 
+  // This emits an PC-relative tail call of the form "b <offset>".
+  //
+  // See also above for the pc-relative call.
+  void GenerateUnRelocatedPcRelativeTailCall(intptr_t offset_into_target = 0);
+
   Address ElementAddressForIntIndex(bool is_external,
                                     intptr_t cid,
                                     intptr_t index_scale,
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 3f5872f..74d3316 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2123,7 +2123,7 @@
   intptr_t start = CodeSize();
   Label have_cid, miss;
   Bind(&miss);
-  jmp(Address(THR, target::Thread::monomorphic_miss_entry_offset()));
+  jmp(Address(THR, target::Thread::switchable_call_miss_entry_offset()));
 
   Comment("MonomorphicCheckedEntry");
   ASSERT(CodeSize() - start ==
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index cf87f74..c60968e 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -602,6 +602,10 @@
 
   void LoadIsolate(Register dst);
 
+  void LoadUniqueObject(Register dst, const Object& object) {
+    LoadObject(dst, object, /*movable_referent=*/true);
+  }
+
   void LoadObject(Register dst,
                   const Object& object,
                   bool movable_referent = false);
@@ -705,10 +709,6 @@
             CodeEntryKind entry_kind = CodeEntryKind::kNormal);
   void CallToRuntime();
 
-  void CallNullErrorShared(bool save_fpu_registers) { UNREACHABLE(); }
-
-  void CallNullArgErrorShared(bool save_fpu_registers) { UNREACHABLE(); }
-
   void Jmp(const Code& code);
   void J(Condition condition, const Code& code);
 
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 604fcc3..60802f9 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -100,25 +100,6 @@
   call(Address(THR, target::Thread::call_to_runtime_entry_point_offset()));
 }
 
-void Assembler::CallNullErrorShared(bool save_fpu_registers) {
-  uword entry_point_offset =
-      save_fpu_registers
-          ? target::Thread::null_error_shared_with_fpu_regs_entry_point_offset()
-          : target::Thread::
-                null_error_shared_without_fpu_regs_entry_point_offset();
-  call(Address(THR, entry_point_offset));
-}
-
-void Assembler::CallNullArgErrorShared(bool save_fpu_registers) {
-  const uword entry_point_offset =
-      save_fpu_registers
-          ? target::Thread::
-                null_arg_error_shared_with_fpu_regs_entry_point_offset()
-          : target::Thread::
-                null_arg_error_shared_without_fpu_regs_entry_point_offset();
-  call(Address(THR, entry_point_offset));
-}
-
 void Assembler::pushq(Register reg) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitRegisterREX(reg, REX_NONE);
@@ -1208,7 +1189,6 @@
 
 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
   ASSERT(IsOriginalObject(object));
-  ASSERT(!target::CanLoadFromThread(object));
   if (!constant_pool_allowed()) {
     return false;
   }
@@ -1243,18 +1223,23 @@
                                  bool is_unique) {
   ASSERT(IsOriginalObject(object));
 
-  intptr_t offset_from_thread;
-  if (target::CanLoadFromThread(object, &offset_from_thread)) {
-    movq(dst, Address(THR, offset_from_thread));
-  } else if (CanLoadFromObjectPool(object)) {
-    const intptr_t idx = is_unique ? object_pool_builder().AddObject(object)
-                                   : object_pool_builder().FindObject(object);
-    const int32_t offset = target::ObjectPool::element_offset(idx);
-    LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
-  } else {
-    ASSERT(target::IsSmi(object));
-    LoadImmediate(dst, Immediate(target::ToRawSmi(object)));
+  // `is_unique == true` effectively means object has to be patchable.
+  if (!is_unique) {
+    intptr_t offset;
+    if (target::CanLoadFromThread(object, &offset)) {
+      movq(dst, Address(THR, offset));
+      return;
+    }
   }
+  if (CanLoadFromObjectPool(object)) {
+    const int32_t offset = target::ObjectPool::element_offset(
+        is_unique ? object_pool_builder().AddObject(object)
+                  : object_pool_builder().FindObject(object));
+    LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
+    return;
+  }
+  ASSERT(target::IsSmi(object));
+  LoadImmediate(dst, Immediate(target::ToRawSmi(object)));
 }
 
 void Assembler::LoadObject(Register dst, const Object& object) {
@@ -1801,7 +1786,7 @@
   intptr_t start = CodeSize();
   Label have_cid, miss;
   Bind(&miss);
-  jmp(Address(THR, target::Thread::monomorphic_miss_entry_offset()));
+  jmp(Address(THR, target::Thread::switchable_call_miss_entry_offset()));
 
   // Ensure the monomorphic entry is 2-byte aligned (so GC can see them if we
   // store them in ICData / MegamorphicCache arrays)
@@ -1829,12 +1814,14 @@
   ASSERT(((CodeSize() - start) & kSmiTagMask) == kSmiTag);
 }
 
+// RBX - input: class id smi
+// RDX - input: receiver object
 void Assembler::MonomorphicCheckedEntryAOT() {
   has_monomorphic_entry_ = true;
   intptr_t start = CodeSize();
   Label have_cid, miss;
   Bind(&miss);
-  jmp(Address(THR, target::Thread::monomorphic_miss_entry_offset()));
+  jmp(Address(THR, target::Thread::switchable_call_miss_entry_offset()));
 
   // Ensure the monomorphic entry is 2-byte aligned (so GC can see them if we
   // store them in ICData / MegamorphicCache arrays)
@@ -1983,6 +1970,17 @@
   pattern.set_distance(offset_into_target);
 }
 
+void Assembler::GenerateUnRelocatedPcRelativeTailCall(
+    intptr_t offset_into_target) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  buffer_.Emit<uint8_t>(0xe9);
+  buffer_.Emit<int32_t>(0);
+
+  PcRelativeCallPattern pattern(buffer_.contents() + buffer_.Size() -
+                                PcRelativeCallPattern::kLengthInBytes);
+  pattern.set_distance(offset_into_target);
+}
+
 void Assembler::Align(int alignment, intptr_t offset) {
   ASSERT(Utils::IsPowerOfTwo(alignment));
   intptr_t pos = offset + buffer_.GetPosition();
@@ -2110,6 +2108,25 @@
   EmitOperand(rm, Operand(operand));
 }
 
+void Assembler::ExtractClassIdFromTags(Register result, Register tags) {
+  ASSERT(target::RawObject::kClassIdTagPos == 16);
+  ASSERT(target::RawObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(classid_t) == sizeof(uint16_t));
+  movl(result, tags);
+  shrl(result, Immediate(target::RawObject::kClassIdTagPos));
+}
+
+void Assembler::ExtractInstanceSizeFromTags(Register result, Register tags) {
+  ASSERT(target::RawObject::kSizeTagPos == 8);
+  ASSERT(target::RawObject::kSizeTagSize == 8);
+  movzxw(result, tags);
+  shrl(result, Immediate(target::RawObject::kSizeTagPos -
+                         target::ObjectAlignment::kObjectAlignmentLog2));
+  AndImmediate(result,
+               Immediate(Utils::NBitMask(target::RawObject::kSizeTagSize)
+                         << target::ObjectAlignment::kObjectAlignmentLog2));
+}
+
 void Assembler::LoadClassId(Register result, Register object) {
   ASSERT(target::RawObject::kClassIdTagPos == 16);
   ASSERT(target::RawObject::kClassIdTagSize == 16);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 4508fd9..0c281ca 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -725,10 +725,6 @@
   void Call(const Code& stub_entry);
   void CallToRuntime();
 
-  void CallNullErrorShared(bool save_fpu_registers);
-
-  void CallNullArgErrorShared(bool save_fpu_registers);
-
   // Emit a call that shares its object pool entries with other calls
   // that have the same equivalence marker.
   void CallWithEquivalence(const Code& code,
@@ -819,6 +815,9 @@
   // if platform ABI requires that. Does not restore RSP after the call itself.
   void CallCFunction(Register reg);
 
+  void ExtractClassIdFromTags(Register result, Register tags);
+  void ExtractInstanceSizeFromTags(Register result, Register tags);
+
   // Loading and comparing classes of objects.
   void LoadClassId(Register result, Register object);
   void LoadClassById(Register result, Register class_id);
@@ -956,6 +955,11 @@
   // function.
   void GenerateUnRelocatedPcRelativeCall(intptr_t offset_into_target = 0);
 
+  // This emits an PC-relative tail call of the form "jmp *[rip+<offset>]".
+  //
+  // See also above for the pc-relative call.
+  void GenerateUnRelocatedPcRelativeTailCall(intptr_t offset_into_target = 0);
+
   // Debugging and bringup support.
   void Breakpoint() override { int3(); }
 
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index e43229b..37c3743 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -388,6 +388,9 @@
           case Code::kPcRelativeCall:
             skind = "pc-relative-call";
             break;
+          case Code::kPcRelativeTailCall:
+            skind = "pc-relative-tail-call";
+            break;
           case Code::kCallViaCode:
             skind = "call-via-code";
             break;
diff --git a/runtime/vm/compiler/backend/compile_type.h b/runtime/vm/compiler/backend/compile_type.h
index f068bf0..d6477b1 100644
--- a/runtime/vm/compiler/backend/compile_type.h
+++ b/runtime/vm/compiler/backend/compile_type.h
@@ -106,8 +106,10 @@
     return CompileType(is_nullable, cid, nullptr);
   }
 
-  // Create a new CompileType representing given abstract type. By default
-  // values as assumed to be nullable.
+  // Create a new CompileType representing given abstract type.
+  // By default nullability of values is determined by type.
+  // CompileType can be further constrained to non-nullable values by
+  // passing kNonNullable as an optional parameter.
   static CompileType FromAbstractType(const AbstractType& type,
                                       bool is_nullable = kNullable);
 
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 266cb14..5cde585 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1621,6 +1621,12 @@
       } else if (auto check = instruction->AsCheckNull()) {
         check->ReplaceUsesWith(check->value()->definition());
         check->ClearSSATempIndex();
+      } else if (auto check = instruction->AsAssertAssignable()) {
+        check->ReplaceUsesWith(check->value()->definition());
+        check->ClearSSATempIndex();
+      } else if (auto check = instruction->AsAssertBoolean()) {
+        check->ReplaceUsesWith(check->value()->definition());
+        check->ClearSSATempIndex();
       }
     }
   }
@@ -2378,10 +2384,18 @@
        block_it.Advance()) {
     for (ForwardInstructionIterator instr_it(block_it.Current());
          !instr_it.Done(); instr_it.Advance()) {
-      RedefinitionInstr* redefinition = instr_it.Current()->AsRedefinition();
-      if (redefinition != NULL) {
-        Definition* original = redefinition->value()->definition();
-        RenameDominatedUses(original, redefinition, redefinition);
+      Definition* definition = instr_it.Current()->AsDefinition();
+      // CheckArrayBound instructions have their own mechanism for ensuring
+      // proper dependencies, so we don't rewrite those here.
+      if (definition != nullptr && !definition->IsCheckArrayBound()) {
+        Value* redefined = definition->RedefinedValue();
+        if (redefined != nullptr) {
+          if (!definition->HasSSATemp()) {
+            AllocateSSAIndexes(definition);
+          }
+          Definition* original = redefined->definition();
+          RenameDominatedUses(original, definition, definition);
+        }
       }
     }
   }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index ef80744..92c0a64 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -788,6 +788,14 @@
       &stub_code));
 }
 
+void FlowGraphCompiler::AddPcRelativeTailCallStubTarget(const Code& stub_code) {
+  ASSERT(stub_code.IsZoneHandle() || stub_code.IsReadOnlyHandle());
+  ASSERT(!stub_code.IsNull());
+  static_calls_target_table_.Add(new (zone()) StaticCallsStruct(
+      Code::kPcRelativeTailCall, Code::kDefaultEntry, assembler()->CodeSize(),
+      nullptr, &stub_code));
+}
+
 void FlowGraphCompiler::AddStaticCallTarget(const Function& func,
                                             Code::EntryKind entry_kind) {
   ASSERT(func.IsZoneHandle());
@@ -1346,22 +1354,14 @@
   return complete;
 }
 
-void FlowGraphCompiler::GenerateCallWithDeopt(TokenPosition token_pos,
-                                              intptr_t deopt_id,
-                                              const Code& stub,
-                                              RawPcDescriptors::Kind kind,
-                                              LocationSummary* locs) {
-  GenerateCall(token_pos, stub, kind, locs);
-  if (!FLAG_precompiled_mode) {
-    const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
-    if (is_optimizing()) {
-      AddDeoptIndexAtCall(deopt_id_after);
-    } else {
-      // Add deoptimization continuation point after the call and before the
-      // arguments are removed.
-      AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
-    }
-  }
+void FlowGraphCompiler::GenerateStubCall(TokenPosition token_pos,
+                                         const Code& stub,
+                                         RawPcDescriptors::Kind kind,
+                                         LocationSummary* locs,
+                                         intptr_t deopt_id,
+                                         Environment* env) {
+  EmitCallToStub(stub);
+  EmitCallsiteMetadata(token_pos, deopt_id, kind, locs, env);
 }
 
 static const Code& StubEntryFor(const ICData& ic_data, bool optimized) {
@@ -2333,6 +2333,7 @@
 }
 
 void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
+    CompileType* receiver_type,
     const AbstractType& dst_type,
     const String& dst_name,
     const Register dst_type_reg_to_call,
@@ -2351,6 +2352,8 @@
   if (int_type.IsSubtypeOf(dst_type, Heap::kOld)) {
     __ BranchIfSmi(TypeTestABI::kInstanceReg, done);
     is_non_smi = true;
+  } else if (receiver_type->IsNotSmi()) {
+    is_non_smi = true;
   }
 
   // We use two type registers iff the dst type is a type parameter.
@@ -2519,25 +2522,22 @@
       instruction()->UseSharedSlowPathStub(compiler->is_optimizing());
   const bool live_fpu_registers =
       instruction()->locs()->live_registers()->FpuRegisterCount() > 0;
-  ASSERT(!use_shared_stub || num_args_ == 0);
   __ Bind(entry_label());
   EmitCodeAtSlowPathEntry(compiler);
   LocationSummary* locs = instruction()->locs();
   // Save registers as they are needed for lazy deopt / exception handling.
-  if (!use_shared_stub) {
-    compiler->SaveLiveRegisters(locs);
-  }
-  intptr_t i = 0;
-  if (num_args_ % 2 != 0) {
-    __ PushRegister(locs->in(i).reg());
-    ++i;
-  }
-  for (; i < num_args_; i += 2) {
-    __ PushRegisterPair(locs->in(i + 1).reg(), locs->in(i).reg());
-  }
   if (use_shared_stub) {
     EmitSharedStubCall(compiler, live_fpu_registers);
   } else {
+    compiler->SaveLiveRegisters(locs);
+    intptr_t i = 0;
+    if (num_args_ % 2 != 0) {
+      __ PushRegister(locs->in(i).reg());
+      ++i;
+    }
+    for (; i < num_args_; i += 2) {
+      __ PushRegisterPair(locs->in(i + 1).reg(), locs->in(i).reg());
+    }
     __ CallRuntime(runtime_entry_, num_args_);
   }
   const intptr_t deopt_id = instruction()->deopt_id();
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 0c16478..0097fcd 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -348,6 +348,21 @@
   }
 };
 
+class RangeErrorSlowPath : public ThrowErrorSlowPathCode {
+ public:
+  static const intptr_t kNumberOfArguments = 0;
+
+  RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
+      : ThrowErrorSlowPathCode(instruction,
+                               kRangeErrorRuntimeEntry,
+                               kNumberOfArguments,
+                               try_index) {}
+  virtual const char* name() { return "check bound"; }
+
+  virtual void EmitSharedStubCall(FlowGraphCompiler* compielr,
+                                  bool save_fpu_registers);
+};
+
 class FlowGraphCompiler : public ValueObject {
  private:
   class BlockInfo : public ZoneAllocated {
@@ -548,7 +563,8 @@
                      Representation src_type,
                      TemporaryRegisterAllocator* temp);
 
-  void GenerateAssertAssignable(TokenPosition token_pos,
+  void GenerateAssertAssignable(CompileType* receiver_type,
+                                TokenPosition token_pos,
                                 intptr_t deopt_id,
                                 const AbstractType& dst_type,
                                 const String& dst_name,
@@ -559,13 +575,15 @@
   static bool ShouldUseTypeTestingStubFor(bool optimizing,
                                           const AbstractType& type);
 
-  void GenerateAssertAssignableViaTypeTestingStub(TokenPosition token_pos,
+  void GenerateAssertAssignableViaTypeTestingStub(CompileType* receiver_type,
+                                                  TokenPosition token_pos,
                                                   intptr_t deopt_id,
                                                   const AbstractType& dst_type,
                                                   const String& dst_name,
                                                   LocationSummary* locs);
 
   void GenerateAssertAssignableViaTypeTestingStub(
+      CompileType* receiver_type,
       const AbstractType& dst_type,
       const String& dst_name,
       const Register dst_type_reg_to_call,
@@ -578,16 +596,12 @@
                            intptr_t argument_count,
                            LocationSummary* locs);
 
-  void GenerateCall(TokenPosition token_pos,
-                    const Code& stub,
-                    RawPcDescriptors::Kind kind,
-                    LocationSummary* locs);
-
-  void GenerateCallWithDeopt(TokenPosition token_pos,
-                             intptr_t deopt_id,
-                             const Code& stub,
-                             RawPcDescriptors::Kind kind,
-                             LocationSummary* locs);
+  void GenerateStubCall(TokenPosition token_pos,
+                        const Code& stub,
+                        RawPcDescriptors::Kind kind,
+                        LocationSummary* locs,
+                        intptr_t deopt_id = DeoptId::kNone,
+                        Environment* env = nullptr);
 
   void GeneratePatchableCall(TokenPosition token_pos,
                              const Code& stub,
@@ -744,6 +758,7 @@
                                       bool needs_number_check,
                                       TokenPosition token_pos,
                                       intptr_t deopt_id);
+  Condition EmitBoolTest(Register value, BranchLabels labels, bool invert);
 
   bool NeedsEdgeCounter(BlockEntryInstr* block);
 
@@ -752,6 +767,9 @@
   void RecordCatchEntryMoves(Environment* env = NULL,
                              intptr_t try_index = kInvalidTryIndex);
 
+  void EmitCallToStub(const Code& stub);
+  void EmitTailCallToStub(const Code& stub);
+
   // Emits the following metadata for the current PC:
   //
   //   * Attaches current try index
@@ -954,6 +972,7 @@
   void AddPcRelativeCallTarget(const Function& function,
                                Code::EntryKind entry_kind);
   void AddPcRelativeCallStubTarget(const Code& stub_code);
+  void AddPcRelativeTailCallStubTarget(const Code& stub_code);
   void AddStaticCallTarget(const Function& function,
                            Code::EntryKind entry_kind);
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index c32f5d1..2a45dcb 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -214,8 +214,11 @@
   compiler::Label fall_through;
   __ CompareObject(bool_register, Object::null_object());
   __ b(&fall_through, EQ);
-  __ CompareObject(bool_register, Bool::True());
-  __ b(is_true, EQ);
+  BranchLabels labels = {is_true, is_false, &fall_through};
+  Condition true_condition =
+      EmitBoolTest(bool_register, labels, /*invert=*/false);
+  ASSERT(true_condition != kInvalidCondition);
+  __ b(is_true, true_condition);
   __ b(is_false);
   __ Bind(&fall_through);
 }
@@ -428,13 +431,17 @@
   __ LoadClassId(R2, TypeTestABI::kInstanceReg);
   __ LoadClassById(R1, R2);
   // R1: instance class.
-  // Check immediate superclass equality.
-  __ ldr(R2, compiler::FieldAddress(
-                 R1, compiler::target::Class::super_type_offset()));
-  __ ldr(R2, compiler::FieldAddress(
-                 R2, compiler::target::Type::type_class_id_offset()));
-  __ CompareImmediate(R2, Smi::RawValue(type_class.id()));
-  __ b(is_instance_lbl, EQ);
+  // Check immediate superclass equality. If type_class is Object, then testing
+  // supertype may yield a wrong result for Null in NNBD strong mode (because
+  // Null also extends Object).
+  if (!type_class.IsObjectClass() || !Isolate::Current()->null_safety()) {
+    __ ldr(R2, compiler::FieldAddress(
+                   R1, compiler::target::Class::super_type_offset()));
+    __ ldr(R2, compiler::FieldAddress(
+                   R2, compiler::target::Type::type_class_id_offset()));
+    __ CompareImmediate(R2, Smi::RawValue(type_class.id()));
+    __ b(is_instance_lbl, EQ);
+  }
 
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
@@ -657,18 +664,10 @@
     __ ldm(IA, SP,
            (1 << TypeTestABI::kFunctionTypeArgumentsReg) |
                (1 << TypeTestABI::kInstantiatorTypeArgumentsReg));
-    __ PushObject(Object::null_object());  // Make room for the result.
-    __ Push(TypeTestABI::kInstanceReg);    // Push the instance.
-    __ PushObject(type);                   // Push the type.
-    __ PushList((1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
-                (1 << TypeTestABI::kFunctionTypeArgumentsReg));
-    __ LoadUniqueObject(R0, test_cache);
-    __ Push(R0);
-    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
-    // Pop the parameters supplied to the runtime entry. The result of the
-    // instanceof runtime call will be left as the result of the operation.
-    __ Drop(5);
-    __ Pop(R0);
+    __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
+    __ LoadUniqueObject(TypeTestABI::kSubtypeTestCacheReg, test_cache);
+    GenerateStubCall(token_pos, StubCode::InstanceOf(),
+                     /*kind=*/RawPcDescriptors::kOther, locs, deopt_id);
     __ b(&done);
   }
   __ Bind(&is_not_instance);
@@ -694,7 +693,8 @@
 // - object in R0 for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
 // as they throw an exception.
-void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateAssertAssignable(CompileType* receiver_type,
+                                                 TokenPosition token_pos,
                                                  intptr_t deopt_id,
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
@@ -706,8 +706,8 @@
   ASSERT(!dst_type.IsTopTypeForAssignability());
 
   if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
-    GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
-                                               dst_name, locs);
+    GenerateAssertAssignableViaTypeTestingStub(
+        receiver_type, token_pos, deopt_id, dst_type, dst_name, locs);
   } else {
     compiler::Label is_assignable_fast, is_assignable, runtime_call;
 
@@ -756,6 +756,7 @@
 }
 
 void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
+    CompileType* receiver_type,
     TokenPosition token_pos,
     intptr_t deopt_id,
     const AbstractType& dst_type,
@@ -767,8 +768,8 @@
 
   compiler::Label done;
 
-  GenerateAssertAssignableViaTypeTestingStub(dst_type, dst_name, kRegToCall,
-                                             kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(receiver_type, dst_type, dst_name,
+                                             kRegToCall, kScratchReg, &done);
 
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
@@ -968,19 +969,33 @@
   }
 }
 
-void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const Code& stub,
-                                     RawPcDescriptors::Kind kind,
-                                     LocationSummary* locs) {
+void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
       !stub.InVMIsolateHeap()) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallStubTarget(stub);
-    EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
   } else {
-    ASSERT(!stub.IsNull());
     __ BranchLink(stub);
-    EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
+    AddStubCallTarget(stub);
+  }
+}
+
+void FlowGraphCompiler::EmitTailCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
+      !stub.InVMIsolateHeap()) {
+    __ LeaveDartFrame();
+    __ GenerateUnRelocatedPcRelativeTailCall();
+    AddPcRelativeTailCallStubTarget(stub);
+#if defined(DEBUG)
+    __ Breakpoint();
+#endif
+  } else {
+    __ LoadObject(CODE_REG, stub);
+    __ LeaveDartFrame();
+    __ ldr(PC, compiler::FieldAddress(
+                   CODE_REG, compiler::target::Code::entry_point_offset()));
     AddStubCallTarget(stub);
   }
 }
@@ -1128,13 +1143,29 @@
   // Load receiver into R0.
   __ LoadFromOffset(kWord, R0, SP,
                     (args_desc.Count() - 1) * compiler::target::kWordSize);
-  __ LoadObject(R9, cache);
-  __ ldr(
-      LR,
-      compiler::Address(
-          THR,
-          compiler::target::Thread::megamorphic_call_checked_entry_offset()));
-  __ blx(LR);
+  // Use same code pattern as instance call so it can be parsed by code patcher.
+  if (FLAG_precompiled_mode) {
+    if (FLAG_use_bare_instructions) {
+      // The AOT runtime will replace the slot in the object pool with the
+      // entrypoint address - see clustered_snapshot.cc.
+      __ LoadUniqueObject(LR, StubCode::MegamorphicCall());
+    } else {
+      __ LoadUniqueObject(CODE_REG, StubCode::MegamorphicCall());
+      __ ldr(LR, compiler::FieldAddress(
+                     CODE_REG, compiler::target::Code::entry_point_offset(
+                                   Code::EntryKind::kMonomorphic)));
+    }
+    __ LoadUniqueObject(R9, cache);
+    __ blx(LR);
+
+  } else {
+    __ LoadUniqueObject(R9, cache);
+    __ LoadUniqueObject(CODE_REG, StubCode::MegamorphicCall());
+    __ ldr(LR, compiler::FieldAddress(
+                   CODE_REG,
+                   Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+    __ blx(LR);
+  }
 
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
@@ -1169,7 +1200,7 @@
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(ic_data.NumArgsTested() == 1);
-  const Code& initial_stub = StubCode::UnlinkedCall();
+  const Code& initial_stub = StubCode::SwitchableCallMiss();
   const char* switchable_call_mode = "smiable";
   if (!receiver_can_be_smi) {
     switchable_call_mode = "non-smi";
@@ -1318,6 +1349,15 @@
   return EQ;
 }
 
+Condition FlowGraphCompiler::EmitBoolTest(Register value,
+                                          BranchLabels labels,
+                                          bool invert) {
+  __ Comment("BoolTest");
+  __ tst(value,
+         compiler::Operand(compiler::target::ObjectAlignment::kBoolValueMask));
+  return invert ? NE : EQ;
+}
+
 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and
 // FlowGraphCompiler::SlowPathEnvironmentFor.
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 20cc37d..353cc31 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -206,9 +206,10 @@
   compiler::Label fall_through;
   __ CompareObject(bool_register, Object::null_object());
   __ b(&fall_through, EQ);
-  __ CompareObject(bool_register, Bool::True());
-  __ b(is_true, EQ);
-  __ b(is_false);
+  BranchLabels labels = {is_true, is_false, &fall_through};
+  Condition true_condition =
+      EmitBoolTest(bool_register, labels, /*invert=*/false);
+  ASSERT(true_condition == kInvalidCondition);
   __ Bind(&fall_through);
 }
 
@@ -414,11 +415,15 @@
   __ LoadClassId(TMP, TypeTestABI::kInstanceReg);
   __ LoadClassById(R1, TMP);
   // R1: instance class.
-  // Check immediate superclass equality.
-  __ LoadFieldFromOffset(R2, R1, Class::super_type_offset());
-  __ LoadFieldFromOffset(R2, R2, Type::type_class_id_offset());
-  __ CompareImmediate(R2, Smi::RawValue(type_class.id()));
-  __ b(is_instance_lbl, EQ);
+  // Check immediate superclass equality. If type_class is Object, then testing
+  // supertype may yield a wrong result for Null in NNBD strong mode (because
+  // Null also extends Object).
+  if (!type_class.IsObjectClass() || !Isolate::Current()->null_safety()) {
+    __ LoadFieldFromOffset(R2, R1, Class::super_type_offset());
+    __ LoadFieldFromOffset(R2, R2, Type::type_class_id_offset());
+    __ CompareImmediate(R2, Smi::RawValue(type_class.id()));
+    __ b(is_instance_lbl, EQ);
+  }
 
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
@@ -625,19 +630,10 @@
     __ ldp(TypeTestABI::kFunctionTypeArgumentsReg,
            TypeTestABI::kInstantiatorTypeArgumentsReg,
            compiler::Address(SP, 0 * kWordSize, compiler::Address::PairOffset));
-    __ PushPair(TypeTestABI::kInstanceReg,
-                NULL_REG);      // Make room for the result and
-                                // push the instance.
-    __ LoadObject(TMP, type);   // Push the type.
-
-    __ PushPair(TypeTestABI::kInstantiatorTypeArgumentsReg, TMP);
-    __ LoadUniqueObject(R0, test_cache);
-    __ PushPair(R0, TypeTestABI::kFunctionTypeArgumentsReg);
-    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
-    // Pop the parameters supplied to the runtime entry. The result of the
-    // instanceof runtime call will be left as the result of the operation.
-    __ Drop(5);
-    __ Pop(R0);
+    __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
+    __ LoadUniqueObject(TypeTestABI::kSubtypeTestCacheReg, test_cache);
+    GenerateStubCall(token_pos, StubCode::InstanceOf(),
+                     /*kind=*/RawPcDescriptors::kOther, locs, deopt_id);
     __ b(&done);
   }
   __ Bind(&is_not_instance);
@@ -663,7 +659,8 @@
 // - object in R0 for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
 // as they throw an exception.
-void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateAssertAssignable(CompileType* receiver_type,
+                                                 TokenPosition token_pos,
                                                  intptr_t deopt_id,
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
@@ -675,8 +672,8 @@
   ASSERT(!dst_type.IsTopTypeForAssignability());
 
   if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
-    GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
-                                               dst_name, locs);
+    GenerateAssertAssignableViaTypeTestingStub(
+        receiver_type, token_pos, deopt_id, dst_type, dst_name, locs);
   } else {
     compiler::Label is_assignable_fast, is_assignable, runtime_call;
 
@@ -721,6 +718,7 @@
 }
 
 void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
+    CompileType* receiver_type,
     TokenPosition token_pos,
     intptr_t deopt_id,
     const AbstractType& dst_type,
@@ -732,8 +730,8 @@
 
   compiler::Label done;
 
-  GenerateAssertAssignableViaTypeTestingStub(dst_type, dst_name, kRegToCall,
-                                             kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(receiver_type, dst_type, dst_name,
+                                             kRegToCall, kScratchReg, &done);
 
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
@@ -929,19 +927,34 @@
   }
 }
 
-void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const Code& stub,
-                                     RawPcDescriptors::Kind kind,
-                                     LocationSummary* locs) {
+void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
       !stub.InVMIsolateHeap()) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallStubTarget(stub);
-    EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
   } else {
-    ASSERT(!stub.IsNull());
     __ BranchLink(stub);
-    EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
+    AddStubCallTarget(stub);
+  }
+}
+
+void FlowGraphCompiler::EmitTailCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
+      !stub.InVMIsolateHeap()) {
+    __ LeaveDartFrame();
+    __ GenerateUnRelocatedPcRelativeTailCall();
+    AddPcRelativeTailCallStubTarget(stub);
+#if defined(DEBUG)
+    __ Breakpoint();
+#endif
+  } else {
+    __ LoadObject(CODE_REG, stub);
+    __ LeaveDartFrame();
+    __ ldr(TMP, compiler::FieldAddress(
+                    CODE_REG, compiler::target::Code::entry_point_offset()));
+    __ br(TMP);
     AddStubCallTarget(stub);
   }
 }
@@ -1085,9 +1098,25 @@
   // Load receiver into R0.
   __ LoadFromOffset(R0, SP, (args_desc.Count() - 1) * kWordSize);
 
-  __ LoadObject(R5, cache);
-  __ ldr(LR, compiler::Address(
-                 THR, Thread::megamorphic_call_checked_entry_offset()));
+  // Use same code pattern as instance call so it can be parsed by code patcher.
+  compiler::ObjectPoolBuilder& op = __ object_pool_builder();
+  const intptr_t data_index =
+      op.AddObject(cache, ObjectPool::Patchability::kPatchable);
+  const intptr_t stub_index = op.AddObject(
+      StubCode::MegamorphicCall(), ObjectPool::Patchability::kPatchable);
+  ASSERT((data_index + 1) == stub_index);
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    // The AOT runtime will replace the slot in the object pool with the
+    // entrypoint address - see clustered_snapshot.cc.
+    __ LoadDoubleWordFromPoolOffset(R5, LR,
+                                    ObjectPool::element_offset(data_index));
+  } else {
+    __ LoadDoubleWordFromPoolOffset(R5, CODE_REG,
+                                    ObjectPool::element_offset(data_index));
+    __ ldr(LR, compiler::FieldAddress(
+                   CODE_REG,
+                   Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+  }
   __ blr(LR);
 
   RecordSafepoint(locs, slow_path_argument_count);
@@ -1121,7 +1150,7 @@
                                             bool receiver_can_be_smi) {
   ASSERT(CanCallDart());
   ASSERT(ic_data.NumArgsTested() == 1);
-  const Code& initial_stub = StubCode::UnlinkedCall();
+  const Code& initial_stub = StubCode::SwitchableCallMiss();
   const char* switchable_call_mode = "smiable";
   if (!receiver_can_be_smi) {
     switchable_call_mode = "non-smi";
@@ -1133,6 +1162,9 @@
   compiler::ObjectPoolBuilder& op = __ object_pool_builder();
 
   __ Comment("InstanceCallAOT (%s)", switchable_call_mode);
+  // Clear argument descriptor to keep gc happy when it gets pushed on to
+  // the stack.
+  __ LoadImmediate(R4, 0);
   __ LoadFromOffset(R0, SP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize);
 
   const intptr_t data_index =
@@ -1266,6 +1298,36 @@
   return EQ;
 }
 
+Condition FlowGraphCompiler::EmitBoolTest(Register value,
+                                          BranchLabels labels,
+                                          bool invert) {
+  __ Comment("BoolTest");
+  if (labels.true_label == nullptr || labels.false_label == nullptr) {
+    __ tsti(value, compiler::Immediate(
+                       compiler::target::ObjectAlignment::kBoolValueMask));
+    return invert ? NE : EQ;
+  }
+  const intptr_t bool_bit =
+      compiler::target::ObjectAlignment::kBoolValueBitPosition;
+  if (labels.fall_through == labels.false_label) {
+    if (invert) {
+      __ tbnz(labels.true_label, value, bool_bit);
+    } else {
+      __ tbz(labels.true_label, value, bool_bit);
+    }
+  } else {
+    if (invert) {
+      __ tbz(labels.false_label, value, bool_bit);
+    } else {
+      __ tbnz(labels.false_label, value, bool_bit);
+    }
+    if (labels.fall_through != labels.true_label) {
+      __ b(labels.true_label);
+    }
+  }
+  return kInvalidCondition;
+}
+
 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and
 // FlowGraphCompiler::SlowPathEnvironmentFor.
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index d362feb..086ea4d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -185,8 +185,11 @@
   compiler::Label fall_through;
   __ cmpl(bool_register, raw_null);
   __ j(EQUAL, &fall_through, compiler::Assembler::kNearJump);
-  __ CompareObject(bool_register, Bool::True());
-  __ j(EQUAL, is_true);
+  BranchLabels labels = {is_true, is_false, &fall_through};
+  Condition true_condition =
+      EmitBoolTest(bool_register, labels, /*invert=*/false);
+  ASSERT(true_condition != kInvalidCondition);
+  __ j(true_condition, is_true);
   __ jmp(is_false);
   __ Bind(&fall_through);
 }
@@ -401,11 +404,15 @@
   __ LoadClassId(EDI, TypeTestABI::kInstanceReg);
   __ LoadClassById(ECX, EDI);
   // ECX: instance class.
-  // Check immediate superclass equality.
-  __ movl(EDI, compiler::FieldAddress(ECX, Class::super_type_offset()));
-  __ movl(EDI, compiler::FieldAddress(EDI, Type::type_class_id_offset()));
-  __ cmpl(EDI, compiler::Immediate(Smi::RawValue(type_class.id())));
-  __ j(EQUAL, is_instance_lbl);
+  // Check immediate superclass equality. If type_class is Object, then testing
+  // supertype may yield a wrong result for Null in NNBD strong mode (because
+  // Null also extends Object).
+  if (!type_class.IsObjectClass() || !Isolate::Current()->null_safety()) {
+    __ movl(EDI, compiler::FieldAddress(ECX, Class::super_type_offset()));
+    __ movl(EDI, compiler::FieldAddress(EDI, Type::type_class_id_offset()));
+    __ cmpl(EDI, compiler::Immediate(Smi::RawValue(type_class.id())));
+    __ j(EQUAL, is_instance_lbl);
+  }
 
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
@@ -662,7 +669,8 @@
 // - object in EAX for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
 // as they throw an exception.
-void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateAssertAssignable(CompileType* receiver_type,
+                                                 TokenPosition token_pos,
                                                  intptr_t deopt_id,
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
@@ -842,12 +850,8 @@
   }
 }
 
-void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const Code& stub,
-                                     RawPcDescriptors::Kind kind,
-                                     LocationSummary* locs) {
+void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
   __ Call(stub);
-  EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
   AddStubCallTarget(stub);
 }
 
@@ -978,9 +982,10 @@
   __ Comment("MegamorphicCall");
   // Load receiver into EBX.
   __ movl(EBX, compiler::Address(ESP, (args_desc.Count() - 1) * kWordSize));
-  __ LoadObject(ECX, cache);
-  __ call(
-      compiler::Address(THR, Thread::megamorphic_call_checked_entry_offset()));
+  __ LoadObject(ECX, cache, true);
+  __ LoadObject(CODE_REG, StubCode::MegamorphicCall(), true);
+  __ call(compiler::FieldAddress(
+      CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
 
   AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, token_pos);
   RecordSafepoint(locs, slow_path_argument_count);
@@ -1092,6 +1097,15 @@
   return EQUAL;
 }
 
+Condition FlowGraphCompiler::EmitBoolTest(Register value,
+                                          BranchLabels labels,
+                                          bool invert) {
+  __ Comment("BoolTest");
+  __ testl(value, compiler::Immediate(
+                      compiler::target::ObjectAlignment::kBoolValueMask));
+  return invert ? NOT_EQUAL : EQUAL;
+}
+
 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and
 // FlowGraphCompiler::SlowPathEnvironmentFor.
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index f1f0c6b..e9e7b22 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -207,8 +207,11 @@
   compiler::Label fall_through;
   __ CompareObject(bool_register, Object::null_object());
   __ j(EQUAL, &fall_through, compiler::Assembler::kNearJump);
-  __ CompareObject(bool_register, Bool::True());
-  __ j(EQUAL, is_true);
+  BranchLabels labels = {is_true, is_false, &fall_through};
+  Condition true_condition =
+      EmitBoolTest(bool_register, labels, /*invert=*/false);
+  ASSERT(true_condition != kInvalidCondition);
+  __ j(true_condition, is_true);
   __ jmp(is_false);
   __ Bind(&fall_through);
 }
@@ -433,11 +436,16 @@
   __ LoadClassId(TMP, TypeTestABI::kInstanceReg);
   __ LoadClassById(R10, TMP);
   // R10: instance class.
-  // Check immediate superclass equality.
-  __ movq(R13, compiler::FieldAddress(R10, Class::super_type_offset()));
-  __ movq(R13, compiler::FieldAddress(R13, Type::type_class_id_offset()));
-  __ CompareImmediate(R13, compiler::Immediate(Smi::RawValue(type_class.id())));
-  __ j(EQUAL, is_instance_lbl);
+  // Check immediate superclass equality. If type_class is Object, then testing
+  // supertype may yield a wrong result for Null in NNBD strong mode (because
+  // Null also extends Object).
+  if (!type_class.IsObjectClass() || !Isolate::Current()->null_safety()) {
+    __ movq(R13, compiler::FieldAddress(R10, Class::super_type_offset()));
+    __ movq(R13, compiler::FieldAddress(R13, Type::type_class_id_offset()));
+    __ CompareImmediate(R13,
+                        compiler::Immediate(Smi::RawValue(type_class.id())));
+    __ j(EQUAL, is_instance_lbl);
+  }
 
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
@@ -638,19 +646,11 @@
   // test_cache is null if there is no fall-through.
   compiler::Label done;
   if (!test_cache.IsNull()) {
-    // Generate runtime call.
-    __ PushObject(Object::null_object());  // Make room for the result.
-    __ pushq(TypeTestABI::kInstanceReg);   // Push the instance.
-    __ PushObject(type);                   // Push the type.
-    __ pushq(TypeTestABI::kInstantiatorTypeArgumentsReg);
-    __ pushq(TypeTestABI::kFunctionTypeArgumentsReg);
-    __ LoadUniqueObject(RAX, test_cache);
-    __ pushq(RAX);
-    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
-    // Pop the parameters supplied to the runtime entry. The result of the
-    // instanceof runtime call will be left as the result of the operation.
-    __ Drop(5);
-    __ popq(RAX);
+    // Generate Runtime call.
+    __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
+    __ LoadUniqueObject(TypeTestABI::kSubtypeTestCacheReg, test_cache);
+    GenerateStubCall(token_pos, StubCode::InstanceOf(),
+                     /*kind=*/RawPcDescriptors::kOther, locs, deopt_id);
     __ jmp(&done, compiler::Assembler::kNearJump);
   }
   __ Bind(&is_not_instance);
@@ -674,7 +674,8 @@
 // - object in RAX for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
 // as they throw an exception.
-void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateAssertAssignable(CompileType* receiver_type,
+                                                 TokenPosition token_pos,
                                                  intptr_t deopt_id,
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
@@ -686,8 +687,8 @@
   ASSERT(!dst_type.IsTopTypeForAssignability());
 
   if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
-    GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
-                                               dst_name, locs);
+    GenerateAssertAssignableViaTypeTestingStub(
+        receiver_type, token_pos, deopt_id, dst_type, dst_name, locs);
   } else {
     compiler::Label is_assignable, runtime_call;
 
@@ -722,6 +723,7 @@
 }
 
 void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
+    CompileType* receiver_type,
     TokenPosition token_pos,
     intptr_t deopt_id,
     const AbstractType& dst_type,
@@ -733,8 +735,8 @@
       dst_type.IsTypeParameter() ? RSI : TypeTestABI::kDstTypeReg;
   const Register kScratchReg = kRegToCall;
 
-  GenerateAssertAssignableViaTypeTestingStub(dst_type, dst_name, kRegToCall,
-                                             kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(receiver_type, dst_type, dst_name,
+                                             kRegToCall, kScratchReg, &done);
 
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
@@ -931,19 +933,33 @@
   }
 }
 
-void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
-                                     const Code& stub,
-                                     RawPcDescriptors::Kind kind,
-                                     LocationSummary* locs) {
+void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
       !stub.InVMIsolateHeap()) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallStubTarget(stub);
-    EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
   } else {
-    ASSERT(!stub.IsNull());
     __ Call(stub);
-    EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
+    AddStubCallTarget(stub);
+  }
+}
+
+void FlowGraphCompiler::EmitTailCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
+      !stub.InVMIsolateHeap()) {
+    __ LeaveDartFrame();
+    __ GenerateUnRelocatedPcRelativeTailCall();
+    AddPcRelativeTailCallStubTarget(stub);
+#if defined(DEBUG)
+    __ Breakpoint();
+#endif
+  } else {
+    __ LoadObject(CODE_REG, stub);
+    __ LeaveDartFrame();
+    __ jmp(compiler::FieldAddress(
+        CODE_REG, compiler::target::Code::entry_point_offset()));
     AddStubCallTarget(stub);
   }
 }
@@ -1094,9 +1110,27 @@
   __ Comment("MegamorphicCall");
   // Load receiver into RDX.
   __ movq(RDX, compiler::Address(RSP, (args_desc.Count() - 1) * kWordSize));
-  __ LoadObject(RBX, cache);
-  __ call(
-      compiler::Address(THR, Thread::megamorphic_call_checked_entry_offset()));
+
+  // Use same code pattern as instance call so it can be parsed by code patcher.
+  if (FLAG_precompiled_mode) {
+    if (FLAG_use_bare_instructions) {
+      // The AOT runtime will replace the slot in the object pool with the
+      // entrypoint address - see clustered_snapshot.cc.
+      __ LoadUniqueObject(RCX, StubCode::MegamorphicCall());
+    } else {
+      __ LoadUniqueObject(CODE_REG, StubCode::MegamorphicCall());
+      __ movq(RCX, compiler::FieldAddress(CODE_REG,
+                                          Code::entry_point_offset(
+                                              Code::EntryKind::kMonomorphic)));
+    }
+    __ LoadUniqueObject(RBX, cache);
+    __ call(RCX);
+  } else {
+    __ LoadUniqueObject(RBX, cache);
+    __ LoadUniqueObject(CODE_REG, StubCode::MegamorphicCall());
+    __ call(compiler::FieldAddress(
+        CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+  }
 
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
@@ -1131,7 +1165,7 @@
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(ic_data.NumArgsTested() == 1);
-  const Code& initial_stub = StubCode::UnlinkedCall();
+  const Code& initial_stub = StubCode::SwitchableCallMiss();
   const char* switchable_call_mode = "smiable";
   if (!receiver_can_be_smi) {
     switchable_call_mode = "non-smi";
@@ -1258,6 +1292,15 @@
   return EQUAL;
 }
 
+Condition FlowGraphCompiler::EmitBoolTest(Register value,
+                                          BranchLabels labels,
+                                          bool invert) {
+  __ Comment("BoolTest");
+  __ testq(value, compiler::Immediate(
+                      compiler::target::ObjectAlignment::kBoolValueMask));
+  return invert ? NOT_EQUAL : EQUAL;
+}
+
 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and
 // FlowGraphCompiler::SlowPathEnvironmentFor.
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 80958c4..eca6a6c 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -515,6 +515,10 @@
   return value();
 }
 
+Value* AssertBooleanInstr::RedefinedValue() const {
+  return value();
+}
+
 Value* CheckBoundBase::RedefinedValue() const {
   return index();
 }
@@ -4059,26 +4063,144 @@
       compiler::target::Thread::field_table_values_offset();
   const intptr_t field_offset = compiler::target::FieldTable::OffsetOf(field());
 
+  auto object_store = compiler->isolate()->object_store();
+  const auto& init_static_field_stub = Code::ZoneHandle(
+      compiler->zone(), object_store->init_static_field_stub());
+
   const Register temp = InitStaticFieldABI::kFieldReg;
   __ LoadMemoryValue(temp, THR, static_cast<int32_t>(field_table_offset));
   __ LoadMemoryValue(temp, temp, static_cast<int32_t>(field_offset));
 
   compiler::Label call_runtime, no_call;
   __ CompareObject(temp, Object::sentinel());
-  __ BranchIf(EQUAL, &call_runtime);
 
-  __ CompareObject(temp, Object::transition_sentinel());
+  if (!field().is_late()) {
+    __ BranchIf(EQUAL, &call_runtime);
+    __ CompareObject(temp, Object::transition_sentinel());
+  }
+
   __ BranchIf(NOT_EQUAL, &no_call);
 
   __ Bind(&call_runtime);
   __ LoadObject(InitStaticFieldABI::kFieldReg,
                 Field::ZoneHandle(field().Original()));
-  compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  StubCode::InitStaticField(),
-                                  /*kind=*/RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), init_static_field_stub,
+                             /*kind=*/RawPcDescriptors::kOther, locs(),
+                             deopt_id());
   __ Bind(&no_call);
 }
 
+LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  auto const locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0,
+               Location::RegisterLocation(InitInstanceFieldABI::kInstanceReg));
+  return locs;
+}
+
+void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register temp = InitInstanceFieldABI::kFieldReg;
+
+  __ LoadField(temp, compiler::FieldAddress(InitInstanceFieldABI::kInstanceReg,
+                                            field().TargetOffset()));
+
+  compiler::Label no_call;
+  __ CompareObject(temp, Object::sentinel());
+  __ BranchIf(NOT_EQUAL, &no_call);
+
+  __ LoadObject(InitInstanceFieldABI::kFieldReg,
+                Field::ZoneHandle(field().Original()));
+  compiler->GenerateStubCall(token_pos(), StubCode::InitInstanceField(),
+                             /*kind=*/RawPcDescriptors::kOther, locs(),
+                             deopt_id());
+  __ Bind(&no_call);
+}
+
+LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  summary->set_in(0, Location::RegisterLocation(ThrowABI::kExceptionReg));
+  return summary;
+}
+
+void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  auto object_store = compiler->isolate()->object_store();
+  const auto& throw_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->throw_stub());
+
+  compiler->GenerateStubCall(token_pos(), throw_stub,
+                             /*kind=*/RawPcDescriptors::kOther, locs(),
+                             deopt_id());
+  // Issue(dartbug.com/41353): Right now we have to emit an extra breakpoint
+  // instruction: The ThrowInstr will terminate the current block. The very
+  // next machine code instruction might get a pc descriptor attached with a
+  // different try-index. If we removed this breakpoint instruction, the
+  // runtime might associated this call with the try-index of the next
+  // instruction.
+  __ Breakpoint();
+}
+
+LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  summary->set_in(0, Location::RegisterLocation(ReThrowABI::kExceptionReg));
+  summary->set_in(1, Location::RegisterLocation(ReThrowABI::kStackTraceReg));
+  return summary;
+}
+
+void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  auto object_store = compiler->isolate()->object_store();
+  const auto& re_throw_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->re_throw_stub());
+
+  compiler->SetNeedsStackTrace(catch_try_index());
+  compiler->GenerateStubCall(token_pos(), re_throw_stub,
+                             /*kind=*/RawPcDescriptors::kOther, locs(),
+                             deopt_id());
+  // Issue(dartbug.com/41353): Right now we have to emit an extra breakpoint
+  // instruction: The ThrowInstr will terminate the current block. The very
+  // next machine code instruction might get a pc descriptor attached with a
+  // different try-index. If we removed this breakpoint instruction, the
+  // runtime might associated this call with the try-index of the next
+  // instruction.
+  __ Breakpoint();
+}
+
+LocationSummary* AssertBooleanInstr::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(0, Location::RegisterLocation(AssertBooleanABI::kObjectReg));
+  locs->set_out(0, Location::RegisterLocation(AssertBooleanABI::kObjectReg));
+  return locs;
+}
+
+void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Check that the type of the value is allowed in conditional context.
+  ASSERT(locs()->always_calls());
+
+  auto object_store = compiler->isolate()->object_store();
+  const auto& assert_boolean_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
+
+  compiler::Label done;
+  __ CompareObject(AssertBooleanABI::kObjectReg, Object::null_instance());
+  __ BranchIf(NOT_EQUAL, &done);
+  compiler->GenerateStubCall(token_pos(), assert_boolean_stub,
+                             /*kind=*/RawPcDescriptors::kOther, locs(),
+                             deopt_id());
+  __ Bind(&done);
+}
+
 LocationSummary* PhiInstr::MakeLocationSummary(Zone* zone,
                                                bool optimizing) const {
   UNREACHABLE();
@@ -4290,6 +4412,50 @@
   SetInputAt(1, right);
 }
 
+Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                                 BranchLabels labels) {
+  Location left = locs()->in(0);
+  Location right = locs()->in(1);
+  ASSERT(!left.IsConstant() || !right.IsConstant());
+  Condition true_condition;
+  if (left.IsConstant()) {
+    if (TryEmitBoolTest(compiler, labels, 1, left.constant(),
+                        &true_condition)) {
+      return true_condition;
+    }
+    true_condition = EmitComparisonCodeRegConstant(
+        compiler, labels, right.reg(), left.constant());
+  } else if (right.IsConstant()) {
+    if (TryEmitBoolTest(compiler, labels, 0, right.constant(),
+                        &true_condition)) {
+      return true_condition;
+    }
+    true_condition = EmitComparisonCodeRegConstant(compiler, labels, left.reg(),
+                                                   right.constant());
+  } else {
+    true_condition = compiler->EmitEqualityRegRegCompare(
+        left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id());
+  }
+  return true_condition != kInvalidCondition && (kind() != Token::kEQ_STRICT)
+             ? InvertCondition(true_condition)
+             : true_condition;
+}
+
+bool StrictCompareInstr::TryEmitBoolTest(FlowGraphCompiler* compiler,
+                                         BranchLabels labels,
+                                         intptr_t input_index,
+                                         const Object& obj,
+                                         Condition* true_condition_out) {
+  CompileType* input_type = InputAt(input_index)->Type();
+  if (input_type->ToCid() == kBoolCid && obj.GetClassId() == kBoolCid) {
+    bool invert = (kind() != Token::kEQ_STRICT) ^ !Bool::Cast(obj).value();
+    *true_condition_out =
+        compiler->EmitBoolTest(locs()->in(input_index).reg(), labels, invert);
+    return true;
+  }
+  return false;
+}
+
 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -4859,8 +5025,8 @@
 }
 
 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  compiler->GenerateAssertAssignable(token_pos(), deopt_id(), dst_type(),
-                                     dst_name(), locs());
+  compiler->GenerateAssertAssignable(value()->Type(), token_pos(), deopt_id(),
+                                     dst_type(), dst_name(), locs());
   ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
 }
 
@@ -4939,25 +5105,13 @@
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone) LocationSummary(
-      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
-  locs->set_in(kLengthPos, Location::RequiresRegister());
-  locs->set_in(kIndexPos, Location::RequiresRegister());
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSharedSlowPath);
+  locs->set_in(kLengthPos,
+               Location::RegisterLocation(RangeErrorABI::kLengthReg));
+  locs->set_in(kIndexPos, Location::RegisterLocation(RangeErrorABI::kIndexReg));
   return locs;
 }
 
-class RangeErrorSlowPath : public ThrowErrorSlowPathCode {
- public:
-  static const intptr_t kNumberOfArguments = 2;
-
-  RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
-      : ThrowErrorSlowPathCode(instruction,
-                               kRangeErrorRuntimeEntry,
-                               kNumberOfArguments,
-                               try_index) {}
-
-  virtual const char* name() { return "check bound"; }
-};
-
 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   RangeErrorSlowPath* slow_path =
       new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
@@ -4991,6 +5145,51 @@
   compiler->AddNullCheck(check_null->token_pos(), check_null->function_name());
 }
 
+void NullErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
+                                           bool save_fpu_registers) {
+#if defined(TARGET_ARCH_IA32)
+  UNREACHABLE();
+#else
+  auto object_store = compiler->isolate()->object_store();
+  const auto& stub = Code::ZoneHandle(
+      compiler->zone(),
+      save_fpu_registers
+          ? object_store->null_error_stub_with_fpu_regs_stub()
+          : object_store->null_error_stub_without_fpu_regs_stub());
+  compiler->EmitCallToStub(stub);
+#endif
+}
+
+void NullArgErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
+                                              bool save_fpu_registers) {
+#if defined(TARGET_ARCH_IA32)
+  UNREACHABLE();
+#else
+  auto object_store = compiler->isolate()->object_store();
+  const auto& stub = Code::ZoneHandle(
+      compiler->zone(),
+      save_fpu_registers
+          ? object_store->null_arg_error_stub_with_fpu_regs_stub()
+          : object_store->null_arg_error_stub_without_fpu_regs_stub());
+  compiler->EmitCallToStub(stub);
+#endif
+}
+
+void RangeErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
+                                            bool save_fpu_registers) {
+#if defined(TARGET_ARCH_IA32)
+  UNREACHABLE();
+#else
+  auto object_store = compiler->isolate()->object_store();
+  const auto& stub = Code::ZoneHandle(
+      compiler->zone(),
+      save_fpu_registers
+          ? object_store->range_error_stub_with_fpu_regs_stub()
+          : object_store->range_error_stub_without_fpu_regs_stub());
+  compiler->EmitCallToStub(stub);
+#endif
+}
+
 void UnboxInstr::EmitLoadFromBoxWithDeopt(FlowGraphCompiler* compiler) {
   const intptr_t box_cid = BoxCid();
   const Register box = locs()->in(0).reg();
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 1139d7c..c727de1 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -3587,6 +3587,8 @@
 
   virtual bool AttributesEqual(Instruction* other) const { return true; }
 
+  virtual Value* RedefinedValue() const;
+
   PRINT_OPERANDS_TO_SUPPORT
 
  private:
@@ -4226,6 +4228,16 @@
   ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT;
 
  private:
+  Condition EmitComparisonCodeRegConstant(FlowGraphCompiler* compiler,
+                                          BranchLabels labels,
+                                          Register reg,
+                                          const Object& obj);
+  bool TryEmitBoolTest(FlowGraphCompiler* compiler,
+                       BranchLabels labels,
+                       intptr_t input_index,
+                       const Object& obj,
+                       Condition* condition_out);
+
   // True if the comparison must check for double or Mint and
   // use value comparison instead.
   bool needs_number_check_;
@@ -6340,6 +6352,13 @@
   virtual bool HasUnknownSideEffects() const { return true; }
   virtual Instruction* Canonicalize(FlowGraph* flow_graph);
 
+  // Two InitStaticField instructions can be canonicalized into one
+  // instruction if both are initializing the same field.
+  virtual bool AllowsCSE() const { return true; }
+  virtual bool AttributesEqual(Instruction* other) const {
+    return other->AsInitStaticField()->field().raw() == field().raw();
+  }
+
  private:
   const Field& field_;
 
@@ -8314,7 +8333,7 @@
   bool IsArgumentCheck() const { return exception_type_ == kArgumentError; }
   ExceptionType exception_type() const { return exception_type_; }
 
-  bool UseSharedSlowPathStub(bool is_optimizing) const {
+  virtual bool UseSharedSlowPathStub(bool is_optimizing) const {
     return SlowPathSharingSupported(is_optimizing);
   }
 
@@ -8474,6 +8493,10 @@
 
   virtual bool MayThrow() const { return true; }
 
+  virtual bool UseSharedSlowPathStub(bool is_optimizing) const {
+    return SlowPathSharingSupported(is_optimizing);
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(GenericCheckBoundInstr);
 };
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index a765a18..5e3faea 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -145,10 +145,7 @@
                (NoLocation,
                 Fixed<Register, ARGS_DESC_REG>,
                 Temp<Register> temp)) {
-  __ LoadObject(CODE_REG, instr->code());
-  __ LeaveDartFrame();  // The arguments are still on the stack.
-  __ Branch(compiler::FieldAddress(
-      CODE_REG, compiler::target::Code::entry_point_offset()));
+  compiler->EmitTailCallToStub(instr->code());
 
   // Even though the TailCallInstr will be the last instruction in a basic
   // block, the flow graph compiler will emit native code for other blocks after
@@ -395,38 +392,6 @@
   __ set_constant_pool_allowed(true);
 }
 
-static Condition NegateCondition(Condition condition) {
-  switch (condition) {
-    case EQ:
-      return NE;
-    case NE:
-      return EQ;
-    case LT:
-      return GE;
-    case LE:
-      return GT;
-    case GT:
-      return LE;
-    case GE:
-      return LT;
-    case CC:
-      return CS;
-    case LS:
-      return HI;
-    case HI:
-      return LS;
-    case CS:
-      return CC;
-    case VC:
-      return VS;
-    case VS:
-      return VC;
-    default:
-      UNREACHABLE();
-      return EQ;
-  }
-}
-
 // Detect pattern when one value is zero and another is a power of 2.
 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
   return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
@@ -464,7 +429,7 @@
   if (is_power_of_two_kind) {
     if (true_value == 0) {
       // We need to have zero in result on true_condition.
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   } else {
     if (true_value == 0) {
@@ -473,7 +438,7 @@
       true_value = false_value;
       false_value = temp;
     } else {
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   }
 
@@ -741,48 +706,6 @@
   return summary;
 }
 
-LocationSummary* AssertBooleanInstr::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(0, Location::RegisterLocation(R0));
-  locs->set_out(0, Location::RegisterLocation(R0));
-  return locs;
-}
-
-static void EmitAssertBoolean(Register reg,
-                              TokenPosition token_pos,
-                              intptr_t deopt_id,
-                              LocationSummary* locs,
-                              FlowGraphCompiler* compiler) {
-  // Check that the type of the value is allowed in conditional context.
-  // Call the runtime if the object is not bool::true or bool::false.
-  ASSERT(locs->always_calls());
-  compiler::Label done;
-
-  __ CompareObject(reg, Object::null_instance());
-  __ b(&done, NE);
-
-  __ Push(reg);  // Push the source object.
-  compiler->GenerateRuntimeCall(token_pos, deopt_id,
-                                kNonBoolTypeErrorRuntimeEntry, 1, locs);
-  // We should never return here.
-#if defined(DEBUG)
-  __ bkpt(0);
-#endif
-  __ Bind(&done);
-}
-
-void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register obj = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-
-  EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
-  ASSERT(obj == result);
-}
-
 static Condition TokenKindToSmiCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ:
@@ -895,7 +818,7 @@
     __ b(labels.true_label, true_condition);
   } else {
     // If the next block is not the false successor we will branch to it.
-    Condition false_condition = NegateCondition(true_condition);
+    Condition false_condition = InvertCondition(true_condition);
     __ b(labels.false_label, false_condition);
 
     // Fall through or jump to the true successor.
@@ -1233,8 +1156,8 @@
     compiler->GeneratePatchableCall(token_pos(), *stub,
                                     RawPcDescriptors::kOther, locs());
   } else {
-    compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther,
-                           locs());
+    compiler->GenerateStubCall(token_pos(), *stub, RawPcDescriptors::kOther,
+                               locs());
   }
   __ Pop(result);
 
@@ -2394,9 +2317,12 @@
         }
       }
       __ b(fail, NE);
+    } else if (value_cid == field_cid) {
+      // This would normaly be caught by Canonicalize, but RemoveRedefinitions
+      // may sometimes produce the situation after the last Canonicalize pass.
     } else {
       // Both value's and field's class id is known.
-      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      ASSERT(value_cid != nullability);
       __ b(fail);
     }
   }
@@ -2523,8 +2449,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(TokenPosition::kNoSource,  // No token position.
-                           stub, RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(TokenPosition::kNoSource,  // No token position.
+                               stub, RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -3124,9 +3050,12 @@
       return;
     }
   }
-  compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  StubCode::AllocateArray(),
-                                  RawPcDescriptors::kOther, locs());
+
+  auto object_store = compiler->isolate()->object_store();
+  const auto& allocate_array_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
+  compiler->GenerateStubCall(token_pos(), allocate_array_stub,
+                             RawPcDescriptors::kOther, locs(), deopt_id());
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
 
@@ -3389,8 +3318,8 @@
   // Lookup cache in stub before calling runtime.
   __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
                 type_arguments());
-  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateStubCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -3425,10 +3354,13 @@
 
     compiler->SaveLiveRegisters(locs);
 
+    auto object_store = compiler->isolate()->object_store();
+    const auto& allocate_context_stub = Code::ZoneHandle(
+        compiler->zone(), object_store->allocate_context_stub());
     __ LoadImmediate(R1, instruction()->num_context_variables());
-    compiler->GenerateCall(instruction()->token_pos(),
-                           StubCode::AllocateContext(),
-                           RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(instruction()->token_pos(),
+                               allocate_context_stub, RawPcDescriptors::kOther,
+                               locs);
     ASSERT(instruction()->locs()->out(0).reg() == R0);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ b(exit_label());
@@ -3473,38 +3405,12 @@
   ASSERT(locs()->temp(0).reg() == R1);
   ASSERT(locs()->out(0).reg() == R0);
 
+  auto object_store = compiler->isolate()->object_store();
+  const auto& allocate_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
   __ LoadImmediate(R1, num_context_variables());
-  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
-                         RawPcDescriptors::kOther, locs());
-}
-
-LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
-                                                             bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 1;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(R0));
-  locs->set_temp(0, Location::RegisterLocation(R1));
-  return locs;
-}
-
-void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register instance = locs()->in(0).reg();
-  Register temp = locs()->temp(0).reg();
-  compiler::Label no_call;
-
-  __ ldr(temp, compiler::FieldAddress(instance, field().TargetOffset()));
-  __ CompareObject(temp, Object::sentinel());
-  __ b(&no_call, NE);
-
-  __ PushObject(Object::null_object());  // Make room for (unused) result.
-  __ Push(instance);
-  __ PushObject(Field::ZoneHandle(field().Original()));
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInitInstanceFieldRuntimeEntry, 2, locs());
-  __ Drop(3);  // Remove arguments and result placeholder.
-  __ Bind(&no_call);
+  compiler->GenerateStubCall(token_pos(), allocate_context_stub,
+                             RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -3522,8 +3428,11 @@
   ASSERT(locs()->in(0).reg() == R4);
   ASSERT(locs()->out(0).reg() == R0);
 
-  compiler->GenerateCall(token_pos(), StubCode::CloneContext(),
-                         /*kind=*/RawPcDescriptors::kOther, locs());
+  auto object_store = compiler->isolate()->object_store();
+  const auto& clone_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
+  compiler->GenerateStubCall(token_pos(), clone_context_stub,
+                             /*kind=*/RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -4086,7 +3995,7 @@
   ASSERT(true_condition != kInvalidCondition);
   Register result = locs()->out(0).reg();
   __ LoadObject(result, Bool::True(), true_condition);
-  __ LoadObject(result, Bool::False(), NegateCondition(true_condition));
+  __ LoadObject(result, Bool::False(), InvertCondition(true_condition));
   __ Bind(slow_path->exit_label());
 }
 #undef EMIT_SMI_CHECK
@@ -4907,7 +4816,7 @@
   if (compiler->intrinsic_mode()) {
     __ TryAllocate(compiler->mint_class(),
                    compiler->intrinsic_slow_path_label(), out_reg, tmp);
-  } else {
+  } else if (locs()->call_on_shared_slow_path()) {
     auto object_store = compiler->isolate()->object_store();
     const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
     const auto& stub = Code::ZoneHandle(
@@ -4915,24 +4824,13 @@
         live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
                       : object_store->allocate_mint_without_fpu_regs_stub());
 
-    if (locs()->call_on_shared_slow_path()) {
-      // BoxInt64Instr uses shared slow path only if stub can be reached
-      // via PC-relative call.
-      ASSERT(FLAG_use_bare_instructions);
-      ASSERT(!stub.InVMIsolateHeap());
-      __ GenerateUnRelocatedPcRelativeCall();
-      compiler->AddPcRelativeCallStubTarget(stub);
-
       ASSERT(!locs()->live_registers()->ContainsRegister(R0));
-
       auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
-      compiler->EmitCallsiteMetadata(token_pos(), DeoptId::kNone,
-                                     RawPcDescriptors::kOther, locs(),
-                                     extended_env);
-    } else {
-      BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
-                                      out_reg, tmp);
-    }
+      compiler->GenerateStubCall(token_pos(), stub, RawPcDescriptors::kOther,
+                                 locs(), DeoptId::kNone, extended_env);
+  } else {
+    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
+                                    out_reg, tmp);
   }
 
   __ StoreToOffset(kWord, value_lo, out_reg,
@@ -6511,16 +6409,6 @@
   __ BranchIf(EQUAL, slow_path->entry_label());
 }
 
-void NullErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                           bool save_fpu_registers) {
-  compiler->assembler()->CallNullErrorShared(save_fpu_registers);
-}
-
-void NullArgErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                              bool save_fpu_registers) {
-  compiler->assembler()->CallNullArgErrorShared(save_fpu_registers);
-}
-
 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -7379,44 +7267,6 @@
   }
 }
 
-LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R0));
-  return summary;
-}
-
-void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  __ Push(exception_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1,
-                                locs());
-  __ bkpt(0);
-}
-
-LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R0));
-  summary->set_in(1, Location::RegisterLocation(R1));
-  return summary;
-}
-
-void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  const Register stacktrace_reg = locs()->in(1).reg();
-  compiler->SetNeedsStackTrace(catch_try_index());
-  __ Push(exception_reg);
-  __ Push(stacktrace_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry,
-                                2, locs());
-  __ bkpt(0);
-}
-
 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
 }
@@ -7535,29 +7385,13 @@
   return locs;
 }
 
-Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                 BranchLabels labels) {
-  Location left = locs()->in(0);
-  Location right = locs()->in(1);
-  ASSERT(!left.IsConstant() || !right.IsConstant());
-  Condition true_condition;
-  if (left.IsConstant()) {
-    true_condition = compiler->EmitEqualityRegConstCompare(
-        right.reg(), left.constant(), needs_number_check(), token_pos(),
-        deopt_id_);
-  } else if (right.IsConstant()) {
-    true_condition = compiler->EmitEqualityRegConstCompare(
-        left.reg(), right.constant(), needs_number_check(), token_pos(),
-        deopt_id_);
-  } else {
-    true_condition = compiler->EmitEqualityRegRegCompare(
-        left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_);
-  }
-  if (kind() != Token::kEQ_STRICT) {
-    ASSERT(kind() == Token::kNE_STRICT);
-    true_condition = NegateCondition(true_condition);
-  }
-  return true_condition;
+Condition StrictCompareInstr::EmitComparisonCodeRegConstant(
+    FlowGraphCompiler* compiler,
+    BranchLabels labels,
+    Register reg,
+    const Object& obj) {
+  return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
+                                               token_pos(), deopt_id());
 }
 
 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -7582,7 +7416,7 @@
     // a condition we can avoid the branch and use conditional loads.
     ASSERT(true_condition != kInvalidCondition);
     __ LoadObject(result, Bool::True(), true_condition);
-    __ LoadObject(result, Bool::False(), NegateCondition(true_condition));
+    __ LoadObject(result, Bool::False(), InvertCondition(true_condition));
   }
 }
 
@@ -7602,12 +7436,18 @@
 }
 
 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register value = locs()->in(0).reg();
+  const Register input = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
 
-  __ LoadObject(result, Bool::True());
-  __ cmp(result, compiler::Operand(value));
-  __ LoadObject(result, Bool::False(), EQ);
+  if (value()->Type()->ToCid() == kBoolCid) {
+    __ eor(
+        result, input,
+        compiler::Operand(compiler::target::ObjectAlignment::kBoolValueMask));
+  } else {
+    __ LoadObject(result, Bool::True());
+    __ cmp(result, compiler::Operand(input));
+    __ LoadObject(result, Bool::False(), EQ);
+  }
 }
 
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
@@ -7634,7 +7474,8 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), stub, RawPcDescriptors::kOther,
+                             locs());
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 2c73987..7393059 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -125,10 +125,7 @@
                (NoLocation,
                 Fixed<Register, ARGS_DESC_REG>,
                 Temp<Register> temp)) {
-  __ LoadObject(CODE_REG, instr->code());
-  __ LeaveDartFrame();  // The arguments are still on the stack.
-  __ ldr(temp, compiler::FieldAddress(CODE_REG, Code::entry_point_offset()));
-  __ br(temp);
+  compiler->EmitTailCallToStub(instr->code());
 
   // Even though the TailCallInstr will be the last instruction in a basic
   // block, the flow graph compiler will emit native code for other blocks after
@@ -296,38 +293,6 @@
   __ set_constant_pool_allowed(true);
 }
 
-static Condition NegateCondition(Condition condition) {
-  switch (condition) {
-    case EQ:
-      return NE;
-    case NE:
-      return EQ;
-    case LT:
-      return GE;
-    case LE:
-      return GT;
-    case GT:
-      return LE;
-    case GE:
-      return LT;
-    case CC:
-      return CS;
-    case LS:
-      return HI;
-    case HI:
-      return LS;
-    case CS:
-      return CC;
-    case VS:
-      return VC;
-    case VC:
-      return VS;
-    default:
-      UNREACHABLE();
-      return EQ;
-  }
-}
-
 // Detect pattern when one value is zero and another is a power of 2.
 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
   return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
@@ -362,7 +327,7 @@
   if (is_power_of_two_kind) {
     if (true_value == 0) {
       // We need to have zero in result on true_condition.
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   } else {
     if (true_value == 0) {
@@ -371,7 +336,7 @@
       true_value = false_value;
       false_value = temp;
     } else {
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   }
 
@@ -632,48 +597,6 @@
   return summary;
 }
 
-LocationSummary* AssertBooleanInstr::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(0, Location::RegisterLocation(R0));
-  locs->set_out(0, Location::RegisterLocation(R0));
-  return locs;
-}
-
-static void EmitAssertBoolean(Register reg,
-                              TokenPosition token_pos,
-                              intptr_t deopt_id,
-                              LocationSummary* locs,
-                              FlowGraphCompiler* compiler) {
-  // Check that the type of the value is allowed in conditional context.
-  // Call the runtime if the object is not bool::true or bool::false.
-  ASSERT(locs->always_calls());
-  compiler::Label done;
-
-  __ CompareObject(reg, Object::null_instance());
-  __ b(&done, NE);
-
-  __ Push(reg);  // Push the source object.
-  compiler->GenerateRuntimeCall(token_pos, deopt_id,
-                                kNonBoolTypeErrorRuntimeEntry, 1, locs);
-  // We should never return here.
-#if defined(DEBUG)
-  __ brk(0);
-#endif
-  __ Bind(&done);
-}
-
-void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register obj = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-
-  EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
-  ASSERT(obj == result);
-}
-
 static Condition TokenKindToSmiCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ:
@@ -730,7 +653,7 @@
     __ b(labels.true_label, true_condition);
   } else {
     // If the next block is not the false successor we will branch to it.
-    Condition false_condition = NegateCondition(true_condition);
+    Condition false_condition = InvertCondition(true_condition);
     __ b(labels.false_label, false_condition);
 
     // Fall through or jump to the true successor.
@@ -762,7 +685,7 @@
     __ GenerateXCbzTbz(reg, true_condition, labels.true_label);
   } else {
     // If the next block is not the false successor we will branch to it.
-    Condition false_condition = NegateCondition(true_condition);
+    Condition false_condition = InvertCondition(true_condition);
     __ GenerateXCbzTbz(reg, false_condition, labels.false_label);
 
     // Fall through or jump to the true successor.
@@ -1059,8 +982,8 @@
     compiler->GeneratePatchableCall(token_pos(), *stub,
                                     RawPcDescriptors::kOther, locs());
   } else {
-    compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther,
-                           locs());
+    compiler->GenerateStubCall(token_pos(), *stub, RawPcDescriptors::kOther,
+                               locs());
   }
   __ Pop(result);
 
@@ -2066,9 +1989,12 @@
       }
 
       __ b(fail, NE);
+    } else if (value_cid == field_cid) {
+      // This would normaly be caught by Canonicalize, but RemoveRedefinitions
+      // may sometimes produce the situation after the last Canonicalize pass.
     } else {
       // Both value's and field's class id is known.
-      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      ASSERT(value_cid != nullability);
       __ b(fail);
     }
   }
@@ -2181,8 +2107,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(TokenPosition::kNoSource,  // No token position.
-                           stub, RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(TokenPosition::kNoSource,  // No token position.
+                               stub, RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -2636,9 +2562,11 @@
       return;
     }
   }
-  compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  StubCode::AllocateArray(),
-                                  RawPcDescriptors::kOther, locs());
+  auto object_store = compiler->isolate()->object_store();
+  const auto& allocate_array_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
+  compiler->GenerateStubCall(token_pos(), allocate_array_stub,
+                             RawPcDescriptors::kOther, locs(), deopt_id());
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
 
@@ -2879,8 +2807,8 @@
   // Lookup cache in stub before calling runtime.
   __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
                 type_arguments());
-  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateStubCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -2915,10 +2843,14 @@
 
     compiler->SaveLiveRegisters(locs);
 
+    auto object_store = compiler->isolate()->object_store();
+    const auto& allocate_context_stub = Code::ZoneHandle(
+        compiler->zone(), object_store->allocate_context_stub());
+
     __ LoadImmediate(R1, instruction()->num_context_variables());
-    compiler->GenerateCall(instruction()->token_pos(),
-                           StubCode::AllocateContext(),
-                           RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(instruction()->token_pos(),
+                               allocate_context_stub, RawPcDescriptors::kOther,
+                               locs);
     ASSERT(instruction()->locs()->out(0).reg() == R0);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ b(exit_label());
@@ -2963,37 +2895,12 @@
   ASSERT(locs()->temp(0).reg() == R1);
   ASSERT(locs()->out(0).reg() == R0);
 
+  auto object_store = compiler->isolate()->object_store();
+  const auto& allocate_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
   __ LoadImmediate(R1, num_context_variables());
-  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
-                         RawPcDescriptors::kOther, locs());
-}
-
-LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
-                                                             bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 1;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(R0));
-  locs->set_temp(0, Location::RegisterLocation(R1));
-  return locs;
-}
-
-void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register instance = locs()->in(0).reg();
-  Register temp = locs()->temp(0).reg();
-  compiler::Label no_call;
-
-  __ ldr(temp, compiler::FieldAddress(instance, field().TargetOffset()));
-  __ CompareObject(temp, Object::sentinel());
-  __ b(&no_call, NE);
-
-  __ PushPair(instance, ZR);  // Make room for (unused) result.
-  __ PushObject(Field::ZoneHandle(field().Original()));
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInitInstanceFieldRuntimeEntry, 2, locs());
-  __ Drop(3);  // Remove arguments and result placeholder.
-  __ Bind(&no_call);
+  compiler->GenerateStubCall(token_pos(), allocate_context_stub,
+                             RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -3011,8 +2918,11 @@
   ASSERT(locs()->in(0).reg() == R5);
   ASSERT(locs()->out(0).reg() == R0);
 
-  compiler->GenerateCall(token_pos(), StubCode::CloneContext(),
-                         /*kind=*/RawPcDescriptors::kOther, locs());
+  auto object_store = compiler->isolate()->object_store();
+  const auto& clone_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
+  compiler->GenerateStubCall(token_pos(), clone_context_stub,
+                             /*kind=*/RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -4117,19 +4027,11 @@
           compiler->zone(),
           live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
                         : object_store->allocate_mint_without_fpu_regs_stub());
-      // BoxInt64Instr uses shared slow path only if stub can be reached
-      // via PC-relative call.
-      ASSERT(FLAG_use_bare_instructions);
-      ASSERT(!stub.InVMIsolateHeap());
-      __ GenerateUnRelocatedPcRelativeCall();
-      compiler->AddPcRelativeCallStubTarget(stub);
 
       ASSERT(!locs()->live_registers()->ContainsRegister(R0));
-
       auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
-      compiler->EmitCallsiteMetadata(token_pos(), DeoptId::kNone,
-                                     RawPcDescriptors::kOther, locs(),
-                                     extended_env);
+      compiler->GenerateStubCall(token_pos(), stub, RawPcDescriptors::kOther,
+                                 locs(), DeoptId::kNone, extended_env);
     } else {
       BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
                                       out, temp);
@@ -5466,50 +5368,6 @@
   __ BranchIf(EQUAL, slow_path->entry_label());
 }
 
-void NullErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                           bool save_fpu_registers) {
-  auto check_null = instruction()->AsCheckNull();
-  auto locs = check_null->locs();
-  const bool using_shared_stub = locs->call_on_shared_slow_path();
-
-  const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
-  auto object_store = compiler->isolate()->object_store();
-  const auto& stub = Code::ZoneHandle(
-      compiler->zone(),
-      live_fpu_regs ? object_store->null_error_stub_with_fpu_regs_stub()
-                    : object_store->null_error_stub_without_fpu_regs_stub());
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
-      using_shared_stub && !stub.InVMIsolateHeap()) {
-    compiler->assembler()->GenerateUnRelocatedPcRelativeCall();
-    compiler->AddPcRelativeCallStubTarget(stub);
-    return;
-  }
-
-  compiler->assembler()->CallNullErrorShared(save_fpu_registers);
-}
-
-void NullArgErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                              bool save_fpu_registers) {
-  auto check_null = instruction()->AsCheckNull();
-  auto locs = check_null->locs();
-
-  const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
-  auto object_store = compiler->isolate()->object_store();
-  const auto& stub = Code::ZoneHandle(
-      compiler->zone(),
-      live_fpu_regs
-          ? object_store->null_arg_error_stub_with_fpu_regs_stub()
-          : object_store->null_arg_error_stub_without_fpu_regs_stub());
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions &&
-      !stub.InVMIsolateHeap()) {
-    compiler->assembler()->GenerateUnRelocatedPcRelativeCall();
-    compiler->AddPcRelativeCallStubTarget(stub);
-    return;
-  }
-
-  compiler->assembler()->CallNullArgErrorShared(save_fpu_registers);
-}
-
 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -6359,44 +6217,6 @@
   }
 }
 
-LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R0));
-  return summary;
-}
-
-void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  __ Push(exception_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1,
-                                locs());
-  __ brk(0);
-}
-
-LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R0));
-  summary->set_in(1, Location::RegisterLocation(R1));
-  return summary;
-}
-
-void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  const Register stacktrace_reg = locs()->in(1).reg();
-  compiler->SetNeedsStackTrace(catch_try_index());
-  __ Push(exception_reg);
-  __ Push(stacktrace_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry,
-                                2, locs());
-  __ brk(0);
-}
-
 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
 }
@@ -6506,47 +6326,20 @@
   return locs;
 }
 
-static Condition EmitComparisonCodeRegConstant(FlowGraphCompiler* compiler,
-                                               Token::Kind kind,
-                                               BranchLabels labels,
-                                               Register reg,
-                                               const Object& obj,
-                                               bool needs_number_check,
-                                               TokenPosition token_pos,
-                                               intptr_t deopt_id) {
-  Condition orig_cond = (kind == Token::kEQ_STRICT) ? EQ : NE;
-  if (!needs_number_check && compiler::target::IsSmi(obj) &&
+Condition StrictCompareInstr::EmitComparisonCodeRegConstant(
+    FlowGraphCompiler* compiler,
+    BranchLabels labels,
+    Register reg,
+    const Object& obj) {
+  Condition orig_cond = (kind() == Token::kEQ_STRICT) ? EQ : NE;
+  if (!needs_number_check() && compiler::target::IsSmi(obj) &&
       compiler::target::ToRawSmi(obj) == 0 &&
       CanUseCbzTbzForComparison(compiler, reg, orig_cond, labels)) {
     EmitCbzTbz(reg, compiler, orig_cond, labels);
     return kInvalidCondition;
   } else {
-    Condition true_condition = compiler->EmitEqualityRegConstCompare(
-        reg, obj, needs_number_check, token_pos, deopt_id);
-    return (kind != Token::kEQ_STRICT) ? NegateCondition(true_condition)
-                                       : true_condition;
-  }
-}
-
-Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                 BranchLabels labels) {
-  Location left = locs()->in(0);
-  Location right = locs()->in(1);
-  ASSERT(!left.IsConstant() || !right.IsConstant());
-  Condition true_condition;
-  if (left.IsConstant()) {
-    return EmitComparisonCodeRegConstant(compiler, kind(), labels, right.reg(),
-                                         left.constant(), needs_number_check(),
-                                         token_pos(), deopt_id_);
-  } else if (right.IsConstant()) {
-    return EmitComparisonCodeRegConstant(compiler, kind(), labels, left.reg(),
-                                         right.constant(), needs_number_check(),
-                                         token_pos(), deopt_id_);
-  } else {
-    true_condition = compiler->EmitEqualityRegRegCompare(
-        left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_);
-    return (kind() != Token::kEQ_STRICT) ? NegateCondition(true_condition)
-                                         : true_condition;
+    return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
+                                                 token_pos(), deopt_id());
   }
 }
 
@@ -6585,13 +6378,19 @@
 }
 
 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register value = locs()->in(0).reg();
+  const Register input = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
 
-  __ LoadObject(result, Bool::True());
-  __ LoadObject(TMP, Bool::False());
-  __ CompareRegisters(result, value);
-  __ csel(result, TMP, result, EQ);
+  if (value()->Type()->ToCid() == kBoolCid) {
+    __ eori(
+        result, input,
+        compiler::Immediate(compiler::target::ObjectAlignment::kBoolValueMask));
+  } else {
+    __ LoadObject(result, Bool::True());
+    __ LoadObject(TMP, Bool::False());
+    __ CompareRegisters(result, input);
+    __ csel(result, TMP, result, EQ);
+  }
 }
 
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
@@ -6618,7 +6417,8 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), stub, RawPcDescriptors::kOther,
+                             locs());
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 07851c4..745c44ea 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -387,48 +387,6 @@
   return summary;
 }
 
-LocationSummary* AssertBooleanInstr::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(0, Location::RegisterLocation(EAX));
-  locs->set_out(0, Location::RegisterLocation(EAX));
-  return locs;
-}
-
-static void EmitAssertBoolean(Register reg,
-                              TokenPosition token_pos,
-                              intptr_t deopt_id,
-                              LocationSummary* locs,
-                              FlowGraphCompiler* compiler) {
-  // Check that the type of the value is allowed in conditional context.
-  // Call the runtime if the object is not bool::true or bool::false.
-  ASSERT(locs->always_calls());
-  compiler::Label done;
-
-  __ CompareObject(reg, Object::null_instance());
-  __ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
-
-  __ pushl(reg);  // Push the source object.
-  compiler->GenerateRuntimeCall(token_pos, deopt_id,
-                                kNonBoolTypeErrorRuntimeEntry, 1, locs);
-  // We should never return here.
-#if defined(DEBUG)
-  __ int3();
-#endif
-  __ Bind(&done);
-}
-
-void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register obj = locs()->in(0).reg();
-  Register result = locs()->out(0).reg();
-
-  EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
-  ASSERT(obj == result);
-}
-
 static Condition TokenKindToSmiCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ:
@@ -536,38 +494,6 @@
   }
 }
 
-static Condition NegateCondition(Condition condition) {
-  switch (condition) {
-    case EQUAL:
-      return NOT_EQUAL;
-    case NOT_EQUAL:
-      return EQUAL;
-    case LESS:
-      return GREATER_EQUAL;
-    case LESS_EQUAL:
-      return GREATER;
-    case GREATER:
-      return LESS_EQUAL;
-    case GREATER_EQUAL:
-      return LESS;
-    case BELOW:
-      return ABOVE_EQUAL;
-    case BELOW_EQUAL:
-      return ABOVE;
-    case ABOVE:
-      return BELOW_EQUAL;
-    case ABOVE_EQUAL:
-      return BELOW;
-    case PARITY_ODD:
-      return PARITY_EVEN;
-    case PARITY_EVEN:
-      return PARITY_ODD;
-    default:
-      UNIMPLEMENTED();
-      return EQUAL;
-  }
-}
-
 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
                                   Condition true_condition,
                                   BranchLabels labels) {
@@ -576,7 +502,7 @@
     __ j(true_condition, labels.true_label);
   } else {
     // If the next block is not the false successor, branch to it.
-    Condition false_condition = NegateCondition(true_condition);
+    Condition false_condition = InvertCondition(true_condition);
     __ j(false_condition, labels.false_label);
 
     // Fall through or jump to the true successor.
@@ -746,7 +672,7 @@
   compiler::Label is_true, is_false;
   BranchLabels labels = {&is_true, &is_false, &is_false};
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  if (true_condition != INVALID_CONDITION) {
+  if (true_condition != kInvalidCondition) {
     EmitBranchOnCondition(compiler, true_condition, labels);
   }
 
@@ -764,7 +690,7 @@
                                      BranchInstr* branch) {
   BranchLabels labels = compiler->CreateBranchLabels(branch);
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  if (true_condition != INVALID_CONDITION) {
+  if (true_condition != kInvalidCondition) {
     EmitBranchOnCondition(compiler, true_condition, labels);
   }
 }
@@ -848,7 +774,7 @@
   }
   // Dummy result as this method already did the jump, there's no need
   // for the caller to branch on a condition.
-  return INVALID_CONDITION;
+  return kInvalidCondition;
 }
 
 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone,
@@ -930,7 +856,8 @@
   const compiler::ExternalLabel label(
       reinterpret_cast<uword>(native_c_function()));
   __ movl(ECX, compiler::Immediate(label.address()));
-  compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), *stub, RawPcDescriptors::kOther,
+                             locs());
 
   __ popl(result);
 
@@ -1807,9 +1734,12 @@
         }
       }
       __ j(NOT_EQUAL, fail);
+    } else if (value_cid == field_cid) {
+      // This would normaly be caught by Canonicalize, but RemoveRedefinitions
+      // may sometimes produce the situation after the last Canonicalize pass.
     } else {
       // Both value's and field's class id is known.
-      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      ASSERT(value_cid != nullability);
       __ jmp(fail);
     }
   }
@@ -1922,8 +1852,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(TokenPosition::kNoSource, stub,
-                           RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(TokenPosition::kNoSource, stub,
+                               RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, EAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -2351,9 +2281,8 @@
   }
 
   __ Bind(&slow_path);
-  compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  StubCode::AllocateArray(),
-                                  RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), StubCode::AllocateArray(),
+                             RawPcDescriptors::kOther, locs(), deopt_id());
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2564,8 +2493,8 @@
   // Lookup cache in stub before calling runtime.
   __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
                 type_arguments());
-  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateStubCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -2600,9 +2529,9 @@
     compiler->SaveLiveRegisters(locs);
 
     __ movl(EDX, compiler::Immediate(instruction()->num_context_variables()));
-    compiler->GenerateCall(instruction()->token_pos(),
-                           StubCode::AllocateContext(),
-                           RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(instruction()->token_pos(),
+                               StubCode::AllocateContext(),
+                               RawPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == EAX);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ jmp(exit_label());
@@ -2649,38 +2578,8 @@
   ASSERT(locs()->out(0).reg() == EAX);
 
   __ movl(EDX, compiler::Immediate(num_context_variables()));
-  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
-                         RawPcDescriptors::kOther, locs());
-}
-
-LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
-                                                             bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 1;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(EAX));
-  locs->set_temp(0, Location::RegisterLocation(ECX));
-  return locs;
-}
-
-void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register instance = locs()->in(0).reg();
-  Register temp = locs()->temp(0).reg();
-
-  compiler::Label no_call;
-
-  __ movl(temp, compiler::FieldAddress(instance, field().TargetOffset()));
-  __ CompareObject(temp, Object::sentinel());
-  __ j(NOT_EQUAL, &no_call, compiler::Assembler::kNearJump);
-
-  __ pushl(compiler::Immediate(0));  // Make room for (unused) result.
-  __ pushl(instance);
-  __ PushObject(Field::ZoneHandle(field().Original()));
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInitInstanceFieldRuntimeEntry, 2, locs());
-  __ Drop(3);  // Remove arguments and unused result.
-  __ Bind(&no_call);
+  compiler->GenerateStubCall(token_pos(), StubCode::AllocateContext(),
+                             RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -2698,8 +2597,8 @@
   ASSERT(locs()->in(0).reg() == ECX);
   ASSERT(locs()->out(0).reg() == EAX);
 
-  compiler->GenerateCall(token_pos(), StubCode::CloneContext(),
-                         /*kind=*/RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), StubCode::CloneContext(),
+                             /*kind=*/RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -5353,18 +5252,6 @@
   __ BranchIf(EQUAL, slow_path->entry_label());
 }
 
-void NullErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                           bool save_fpu_registers) {
-  // We only generate shared spilling stub calls for AOT configurations.
-  UNREACHABLE();
-}
-
-void NullArgErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                              bool save_fpu_registers) {
-  // We only generate shared spilling stub calls for AOT configurations.
-  UNREACHABLE();
-}
-
 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -6164,44 +6051,6 @@
   }
 }
 
-LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(EAX));
-  return summary;
-}
-
-void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  __ pushl(exception_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1,
-                                locs());
-  __ int3();
-}
-
-LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(EAX));
-  summary->set_in(1, Location::RegisterLocation(EDX));
-  return summary;
-}
-
-void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  const Register stacktrace_reg = locs()->in(1).reg();
-  compiler->SetNeedsStackTrace(catch_try_index());
-  __ pushl(exception_reg);
-  __ pushl(stacktrace_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry,
-                                2, locs());
-  __ int3();
-}
-
 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
 }
@@ -6312,29 +6161,13 @@
   return locs;
 }
 
-Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                 BranchLabels labels) {
-  Location left = locs()->in(0);
-  Location right = locs()->in(1);
-  ASSERT(!left.IsConstant() || !right.IsConstant());
-  Condition true_condition;
-  if (left.IsConstant()) {
-    true_condition = compiler->EmitEqualityRegConstCompare(
-        right.reg(), left.constant(), needs_number_check(), token_pos(),
-        deopt_id_);
-  } else if (right.IsConstant()) {
-    true_condition = compiler->EmitEqualityRegConstCompare(
-        left.reg(), right.constant(), needs_number_check(), token_pos(),
-        deopt_id_);
-  } else {
-    true_condition = compiler->EmitEqualityRegRegCompare(
-        left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_);
-  }
-  if (kind() != Token::kEQ_STRICT) {
-    ASSERT(kind() == Token::kNE_STRICT);
-    true_condition = NegateCondition(true_condition);
-  }
-  return true_condition;
+Condition StrictCompareInstr::EmitComparisonCodeRegConstant(
+    FlowGraphCompiler* compiler,
+    BranchLabels labels,
+    Register reg,
+    const Object& obj) {
+  return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
+                                               token_pos(), deopt_id());
 }
 
 // Detect pattern when one value is zero and another is a power of 2.
@@ -6364,7 +6197,7 @@
   // the labels or returning an invalid condition.
   BranchLabels labels = {NULL, NULL, NULL};
   Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
-  ASSERT(true_condition != INVALID_CONDITION);
+  ASSERT(true_condition != kInvalidCondition);
 
   const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
 
@@ -6374,7 +6207,7 @@
   if (is_power_of_two_kind) {
     if (true_value == 0) {
       // We need to have zero in EDX on true_condition.
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   } else {
     if (true_value == 0) {
@@ -6383,7 +6216,7 @@
       true_value = false_value;
       false_value = temp;
     } else {
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   }
 
@@ -6445,20 +6278,30 @@
 
 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
-  return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
+  return LocationSummary::Make(zone, 1,
+                               value()->Type()->ToCid() == kBoolCid
+                                   ? Location::SameAsFirstInput()
+                                   : Location::RequiresRegister(),
                                LocationSummary::kNoCall);
 }
 
 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register value = locs()->in(0).reg();
+  Register input = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
 
-  compiler::Label done;
-  __ LoadObject(result, Bool::True());
-  __ CompareRegisters(result, value);
-  __ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
-  __ LoadObject(result, Bool::False());
-  __ Bind(&done);
+  if (value()->Type()->ToCid() == kBoolCid) {
+    ASSERT(input == result);
+    __ xorl(result, compiler::Immediate(
+                        compiler::target::ObjectAlignment::kBoolValueMask));
+  } else {
+    ASSERT(input != result);
+    compiler::Label done;
+    __ LoadObject(result, Bool::True());
+    __ CompareRegisters(result, input);
+    __ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
+    __ LoadObject(result, Bool::False());
+    __ Bind(&done);
+  }
 }
 
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
@@ -6478,7 +6321,8 @@
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), stub, RawPcDescriptors::kOther,
+                             locs());
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index ddb0a2f..0ab1b74 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -118,9 +118,7 @@
 }
 
 DEFINE_BACKEND(TailCall, (NoLocation, Fixed<Register, ARGS_DESC_REG>)) {
-  __ LoadObject(CODE_REG, instr->code());
-  __ LeaveDartFrame();  // The arguments are still on the stack.
-  __ jmp(compiler::FieldAddress(CODE_REG, Code::entry_point_offset()));
+  compiler->EmitTailCallToStub(instr->code());
 
   // Even though the TailCallInstr will be the last instruction in a basic
   // block, the flow graph compiler will emit native code for other blocks after
@@ -280,38 +278,6 @@
   __ set_constant_pool_allowed(true);
 }
 
-static Condition NegateCondition(Condition condition) {
-  switch (condition) {
-    case EQUAL:
-      return NOT_EQUAL;
-    case NOT_EQUAL:
-      return EQUAL;
-    case LESS:
-      return GREATER_EQUAL;
-    case LESS_EQUAL:
-      return GREATER;
-    case GREATER:
-      return LESS_EQUAL;
-    case GREATER_EQUAL:
-      return LESS;
-    case BELOW:
-      return ABOVE_EQUAL;
-    case BELOW_EQUAL:
-      return ABOVE;
-    case ABOVE:
-      return BELOW_EQUAL;
-    case ABOVE_EQUAL:
-      return BELOW;
-    case PARITY_EVEN:
-      return PARITY_ODD;
-    case PARITY_ODD:
-      return PARITY_EVEN;
-    default:
-      UNIMPLEMENTED();
-      return EQUAL;
-  }
-}
-
 // Detect pattern when one value is zero and another is a power of 2.
 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
   return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
@@ -339,7 +305,7 @@
   // the labels or returning an invalid condition.
   BranchLabels labels = {NULL, NULL, NULL};
   Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
-  ASSERT(true_condition != INVALID_CONDITION);
+  ASSERT(true_condition != kInvalidCondition);
 
   const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
 
@@ -349,7 +315,7 @@
   if (is_power_of_two_kind) {
     if (true_value == 0) {
       // We need to have zero in RDX on true_condition.
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   } else {
     if (true_value == 0) {
@@ -358,7 +324,7 @@
       true_value = false_value;
       false_value = temp;
     } else {
-      true_condition = NegateCondition(true_condition);
+      true_condition = InvertCondition(true_condition);
     }
   }
 
@@ -587,48 +553,6 @@
   return summary;
 }
 
-LocationSummary* AssertBooleanInstr::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(0, Location::RegisterLocation(RAX));
-  locs->set_out(0, Location::RegisterLocation(RAX));
-  return locs;
-}
-
-static void EmitAssertBoolean(Register reg,
-                              TokenPosition token_pos,
-                              intptr_t deopt_id,
-                              LocationSummary* locs,
-                              FlowGraphCompiler* compiler) {
-  // Check that the type of the value is allowed in conditional context.
-  // Call the runtime if the object is not bool::true or bool::false.
-  ASSERT(locs->always_calls());
-  compiler::Label done;
-
-  __ CompareObject(reg, Object::null_instance());
-  __ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
-
-  __ pushq(reg);  // Push the source object.
-  compiler->GenerateRuntimeCall(token_pos, deopt_id,
-                                kNonBoolTypeErrorRuntimeEntry, 1, locs);
-  // We should never return here.
-#if defined(DEBUG)
-  __ int3();
-#endif
-  __ Bind(&done);
-}
-
-void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register obj = locs()->in(0).reg();
-  Register result = locs()->out(0).reg();
-
-  EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
-  ASSERT(obj == result);
-}
-
 static Condition TokenKindToIntCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ:
@@ -733,7 +657,7 @@
     __ j(true_condition, labels.true_label);
   } else {
     // If the next block is not the false successor, branch to it.
-    Condition false_condition = NegateCondition(true_condition);
+    Condition false_condition = InvertCondition(true_condition);
     __ j(false_condition, labels.false_label);
 
     // Fall through or jump to the true successor.
@@ -830,7 +754,7 @@
   compiler::Label is_true, is_false;
   BranchLabels labels = {&is_true, &is_false, &is_false};
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  if (true_condition != INVALID_CONDITION) {
+  if (true_condition != kInvalidCondition) {
     EmitBranchOnCondition(compiler, true_condition, labels);
   }
 
@@ -848,7 +772,7 @@
                                      BranchInstr* branch) {
   BranchLabels labels = compiler->CreateBranchLabels(branch);
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  if (true_condition != INVALID_CONDITION) {
+  if (true_condition != kInvalidCondition) {
     EmitBranchOnCondition(compiler, true_condition, labels);
   }
 }
@@ -932,7 +856,7 @@
   }
   // Dummy result as this method already did the jump, there's no need
   // for the caller to branch on a condition.
-  return INVALID_CONDITION;
+  return kInvalidCondition;
 }
 
 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone,
@@ -1009,8 +933,8 @@
         reinterpret_cast<uword>(native_c_function()));
     __ LoadNativeEntry(RBX, &label,
                        compiler::ObjectPoolBuilderEntry::kNotPatchable);
-    compiler->GenerateCall(token_pos(), *stub, RawPcDescriptors::kOther,
-                           locs());
+    compiler->GenerateStubCall(token_pos(), *stub, RawPcDescriptors::kOther,
+                               locs());
   }
   __ popq(result);
 
@@ -1376,8 +1300,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(TokenPosition::kNoSource,  // No token position.
-                           stub, RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(TokenPosition::kNoSource,  // No token position.
+                               stub, RawPcDescriptors::kOther, locs);
     __ MoveRegister(result_, RAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -2004,9 +1928,12 @@
       }
 
       __ j(NOT_EQUAL, fail);
+    } else if (value_cid == field_cid) {
+      // This would normaly be caught by Canonicalize, but RemoveRedefinitions
+      // may sometimes produce the situation after the last Canonicalize pass.
     } else {
       // Both value's and field's class id is known.
-      ASSERT((value_cid != field_cid) && (value_cid != nullability));
+      ASSERT(value_cid != nullability);
       __ jmp(fail);
     }
   }
@@ -2618,9 +2545,11 @@
   }
 
   __ Bind(&slow_path);
-  compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
-                                  StubCode::AllocateArray(),
-                                  RawPcDescriptors::kOther, locs());
+  auto object_store = compiler->isolate()->object_store();
+  const auto& allocate_array_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
+  compiler->GenerateStubCall(token_pos(), allocate_array_stub,
+                             RawPcDescriptors::kOther, locs(), deopt_id());
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2871,8 +2800,8 @@
   }
   __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
                 type_arguments());
-  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
-                         locs());
+  compiler->GenerateStubCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -2906,11 +2835,15 @@
 
     compiler->SaveLiveRegisters(locs);
 
+    auto object_store = compiler->isolate()->object_store();
+    const auto& allocate_context_stub = Code::ZoneHandle(
+        compiler->zone(), object_store->allocate_context_stub());
+
     __ LoadImmediate(
         R10, compiler::Immediate(instruction()->num_context_variables()));
-    compiler->GenerateCall(instruction()->token_pos(),
-                           StubCode::AllocateContext(),
-                           RawPcDescriptors::kOther, locs);
+    compiler->GenerateStubCall(instruction()->token_pos(),
+                               allocate_context_stub, RawPcDescriptors::kOther,
+                               locs);
     ASSERT(instruction()->locs()->out(0).reg() == RAX);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ jmp(exit_label());
@@ -2955,39 +2888,13 @@
   ASSERT(locs()->temp(0).reg() == R10);
   ASSERT(locs()->out(0).reg() == RAX);
 
+  auto object_store = compiler->isolate()->object_store();
+  const auto& allocate_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
+
   __ LoadImmediate(R10, compiler::Immediate(num_context_variables()));
-  compiler->GenerateCall(token_pos(), StubCode::AllocateContext(),
-                         RawPcDescriptors::kOther, locs());
-}
-
-LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
-                                                             bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 1;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(RAX));
-  locs->set_temp(0, Location::RegisterLocation(RCX));
-  return locs;
-}
-
-void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register instance = locs()->in(0).reg();
-  Register temp = locs()->temp(0).reg();
-
-  compiler::Label no_call;
-
-  __ movq(temp, compiler::FieldAddress(instance, field().TargetOffset()));
-  __ CompareObject(temp, Object::sentinel());
-  __ j(NOT_EQUAL, &no_call, compiler::Assembler::kNearJump);
-
-  __ pushq(compiler::Immediate(0));  // Make room for (unused) result.
-  __ pushq(instance);
-  __ PushObject(Field::ZoneHandle(field().Original()));
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInitInstanceFieldRuntimeEntry, 2, locs());
-  __ Drop(3);  // Remove arguments and unused result.
-  __ Bind(&no_call);
+  compiler->GenerateStubCall(token_pos(), allocate_context_stub,
+                             RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -3005,8 +2912,11 @@
   ASSERT(locs()->in(0).reg() == R9);
   ASSERT(locs()->out(0).reg() == RAX);
 
-  compiler->GenerateCall(token_pos(), StubCode::CloneContext(),
-                         /*kind=*/RawPcDescriptors::kOther, locs());
+  auto object_store = compiler->isolate()->object_store();
+  const auto& clone_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
+  compiler->GenerateStubCall(token_pos(), clone_context_stub,
+                             /*kind=*/RawPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -3561,7 +3471,7 @@
   compiler->AddSlowPathCode(slow_path);
   EMIT_SMI_CHECK;
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  ASSERT(true_condition != INVALID_CONDITION);
+  ASSERT(true_condition != kInvalidCondition);
   EmitBranchOnCondition(compiler, true_condition, labels);
   // No need to bind slow_path->exit_label() as slow path exits through
   // true/false branch labels.
@@ -3582,7 +3492,7 @@
   compiler->AddSlowPathCode(slow_path);
   EMIT_SMI_CHECK;
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  ASSERT(true_condition != INVALID_CONDITION);
+  ASSERT(true_condition != kInvalidCondition);
   EmitBranchOnCondition(compiler, true_condition, labels);
   Register result = locs()->out(0).reg();
   __ Bind(false_label);
@@ -5626,16 +5536,6 @@
   __ BranchIf(EQUAL, slow_path->entry_label());
 }
 
-void NullErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                           bool save_fpu_registers) {
-  compiler->assembler()->CallNullErrorShared(save_fpu_registers);
-}
-
-void NullArgErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
-                                              bool save_fpu_registers) {
-  compiler->assembler()->CallNullArgErrorShared(save_fpu_registers);
-}
-
 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -5676,8 +5576,8 @@
       compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnknown);
   BranchLabels labels = {&if_true, if_false, &if_true};
   Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
-  if (true_condition != INVALID_CONDITION) {
-    __ j(NegateCondition(true_condition), if_false);
+  if (true_condition != kInvalidCondition) {
+    __ j(InvertCondition(true_condition), if_false);
   }
   __ Bind(&if_true);
 }
@@ -6581,44 +6481,6 @@
   }
 }
 
-LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(RAX));
-  return summary;
-}
-
-void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  __ pushq(exception_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1,
-                                locs());
-  __ int3();
-}
-
-LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(RAX));
-  summary->set_in(1, Location::RegisterLocation(RDX));
-  return summary;
-}
-
-void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register exception_reg = locs()->in(0).reg();
-  const Register stacktrace_reg = locs()->in(1).reg();
-  compiler->SetNeedsStackTrace(catch_try_index());
-  __ pushq(exception_reg);
-  __ pushq(stacktrace_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry,
-                                2, locs());
-  __ int3();
-}
-
 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
 }
@@ -6728,29 +6590,13 @@
   return locs;
 }
 
-Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                 BranchLabels labels) {
-  Location left = locs()->in(0);
-  Location right = locs()->in(1);
-  ASSERT(!left.IsConstant() || !right.IsConstant());
-  Condition true_condition;
-  if (left.IsConstant()) {
-    true_condition = compiler->EmitEqualityRegConstCompare(
-        right.reg(), left.constant(), needs_number_check(), token_pos(),
-        deopt_id_);
-  } else if (right.IsConstant()) {
-    true_condition = compiler->EmitEqualityRegConstCompare(
-        left.reg(), right.constant(), needs_number_check(), token_pos(),
-        deopt_id_);
-  } else {
-    true_condition = compiler->EmitEqualityRegRegCompare(
-        left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_);
-  }
-  if (kind() != Token::kEQ_STRICT) {
-    ASSERT(kind() == Token::kNE_STRICT);
-    true_condition = NegateCondition(true_condition);
-  }
-  return true_condition;
+Condition StrictCompareInstr::EmitComparisonCodeRegConstant(
+    FlowGraphCompiler* compiler,
+    BranchLabels labels,
+    Register reg,
+    const Object& obj) {
+  return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
+                                               token_pos(), deopt_id());
 }
 
 LocationSummary* DispatchTableCallInstr::MakeLocationSummary(Zone* zone,
@@ -6805,20 +6651,30 @@
 
 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
-  return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
+  return LocationSummary::Make(zone, 1,
+                               value()->Type()->ToCid() == kBoolCid
+                                   ? Location::SameAsFirstInput()
+                                   : Location::RequiresRegister(),
                                LocationSummary::kNoCall);
 }
 
 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register value = locs()->in(0).reg();
+  Register input = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
 
-  compiler::Label done;
-  __ LoadObject(result, Bool::True());
-  __ CompareRegisters(result, value);
-  __ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
-  __ LoadObject(result, Bool::False());
-  __ Bind(&done);
+  if (value()->Type()->ToCid() == kBoolCid) {
+    ASSERT(input == result);
+    __ xorq(result, compiler::Immediate(
+                        compiler::target::ObjectAlignment::kBoolValueMask));
+  } else {
+    ASSERT(input != result);
+    compiler::Label done;
+    __ LoadObject(result, Bool::True());
+    __ CompareRegisters(result, input);
+    __ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
+    __ LoadObject(result, Bool::False());
+    __ Bind(&done);
+  }
 }
 
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
@@ -6845,7 +6701,8 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateCall(token_pos(), stub, RawPcDescriptors::kOther, locs());
+  compiler->GenerateStubCall(token_pos(), stub, RawPcDescriptors::kOther,
+                             locs());
 }
 
 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index 7164e20..2fb3b16 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -954,4 +954,44 @@
   EXPECT_EQ(1, aft_stores);
 }
 
+ISOLATE_UNIT_TEST_CASE(CSE_RedundantInitStaticField) {
+  const char* kScript = R"(
+    int getX() => 2;
+    int x = getX();
+
+    foo() => x + x;
+
+    main() {
+      foo();
+    }
+  )";
+
+  // Make sure InitStaticField is not removed because
+  // field is already initialized.
+  SetFlagScope<bool> sfs(&FLAG_fields_may_be_reset, true);
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  Invoke(root_library, "main");
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+  ASSERT(flow_graph != nullptr);
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  ILMatcher cursor(flow_graph, entry);
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMatchAndMoveFunctionEntry,
+      kMatchAndMoveCheckStackOverflow,
+      kMatchAndMoveInitStaticField,
+      kMatchAndMoveLoadStaticField,
+      kMatchAndMoveCheckSmi,
+      kMoveParallelMoves,
+      kMatchAndMoveBinarySmiOp,
+      kMoveParallelMoves,
+      kMatchReturn,
+  }));
+}
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 43d3989..3ebb148 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -195,6 +195,11 @@
     }
   }
 
+  AbstractType& type = AbstractType::ZoneHandle(zone, field.type());
+  if (type.IsStrictlyNonNullable()) {
+    is_nullable = false;
+  }
+
   bool used_guarded_state = false;
   if (field.guarded_cid() != kIllegalCid &&
       field.guarded_cid() != kDynamicCid) {
@@ -210,8 +215,6 @@
     }
   }
 
-  AbstractType& type = AbstractType::ZoneHandle(zone, field.type());
-
   if (field.needs_load_guard()) {
     // Should be kept in sync with LoadStaticFieldInstr::ComputeType.
     type = Type::DynamicType();
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 629c9b0..39e92e5 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -370,6 +370,11 @@
             new (zone()) CompileType(instr->ComputeType()));
 }
 
+void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
+  SetTypeOf(instr->value()->definition(),
+            new (zone()) CompileType(CompileType::Bool()));
+}
+
 void FlowGraphTypePropagator::VisitAssertSubtype(AssertSubtypeInstr* instr) {}
 
 void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) {
@@ -640,7 +645,8 @@
 
 CompileType CompileType::FromAbstractType(const AbstractType& type,
                                           bool is_nullable) {
-  return CompileType(is_nullable, kIllegalCid, &type);
+  return CompileType(is_nullable && !type.IsStrictlyNonNullable(), kIllegalCid,
+                     &type);
 }
 
 CompileType CompileType::FromCid(intptr_t cid) {
@@ -672,7 +678,7 @@
 }
 
 CompileType CompileType::NullableInt() {
-  return FromAbstractType(Type::ZoneHandle(Type::IntType()), kNullable);
+  return FromAbstractType(Type::ZoneHandle(Type::NullableIntType()), kNullable);
 }
 
 CompileType CompileType::Smi() {
@@ -684,7 +690,7 @@
 }
 
 CompileType CompileType::NullableDouble() {
-  return FromAbstractType(Type::ZoneHandle(Type::Double()), kNullable);
+  return FromAbstractType(Type::ZoneHandle(Type::NullableDouble()), kNullable);
 }
 
 CompileType CompileType::String() {
@@ -1053,7 +1059,7 @@
         graph_entry->parsed_function().RawParameterVariable(0)->type();
     if (type.IsObjectType() || type.IsNullType()) {
       // Receiver can be null.
-      return CompileType::FromAbstractType(type, CompileType::kNullable);
+      return CompileType::FromAbstractType(type);
     }
 
     // Receiver can't be null but can be an instance of a subclass.
@@ -1391,10 +1397,10 @@
     TraceStrongModeType(this, *abstract_type);
   }
   ASSERT(field.is_static());
-  if (field.is_final() && !FLAG_fields_may_be_reset) {
+  const bool is_initialized = IsFieldInitialized() && !FLAG_fields_may_be_reset;
+  if (field.is_final() && is_initialized) {
     const Instance& obj = Instance::Handle(field.StaticValue());
-    if ((obj.raw() != Object::sentinel().raw()) &&
-        (obj.raw() != Object::transition_sentinel().raw()) && !obj.IsNull()) {
+    if (!obj.IsNull()) {
       is_nullable = CompileType::kNonNullable;
       cid = obj.GetClassId();
       abstract_type = nullptr;  // Cid is known, calculate abstract type lazily.
@@ -1411,10 +1417,6 @@
     DEBUG_ASSERT(Isolate::Current()->HasAttemptedReload());
     return CompileType::Dynamic();
   }
-  if (field.is_late()) {
-    // TODO(dartbug.com/40796): Extend CompileType to handle lateness.
-    is_nullable = CompileType::kNullable;
-  }
   return CompileType(is_nullable, cid, abstract_type);
 }
 
diff --git a/runtime/vm/compiler/backend/type_propagator.h b/runtime/vm/compiler/backend/type_propagator.h
index d59acf7..65ef9f4 100644
--- a/runtime/vm/compiler/backend/type_propagator.h
+++ b/runtime/vm/compiler/backend/type_propagator.h
@@ -33,6 +33,7 @@
   virtual void VisitCheckNull(CheckNullInstr* instr);
   virtual void VisitGuardFieldClass(GuardFieldClassInstr* instr);
   virtual void VisitAssertAssignable(AssertAssignableInstr* instr);
+  virtual void VisitAssertBoolean(AssertBooleanInstr* instr);
   virtual void VisitAssertSubtype(AssertSubtypeInstr* instr);
   virtual void VisitInstanceCall(InstanceCallInstr* instr);
   virtual void VisitPolymorphicInstanceCall(
diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc
index 5b0a62d..fd0870f 100644
--- a/runtime/vm/compiler/backend/typed_data_aot_test.cc
+++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc
@@ -191,11 +191,8 @@
   char function_name[1024];
   auto& lib = Library::Handle();
   auto& function = Function::Handle();
-  auto& view = TypedDataView::Handle();
-  auto& arguments = Array::Handle();
-  auto& result = Object::Handle();
 
-  auto run_reverse_list = [&](const char* name, const TypedDataBase& data) {
+  auto check_il = [&](const char* name) {
     // Fill in the template with the [name].
     Utils::SNPrint(script_buffer, sizeof(script_buffer), kTemplate, name, name);
     Utils::SNPrint(uri_buffer, sizeof(uri_buffer), "file:///reverse-%s.dart",
@@ -213,98 +210,19 @@
     // Ensure the IL matches what we expect.
     ILMatcher cursor(flow_graph, entry);
     EXPECT(cursor.TryMatch(expected_il));
-
-    // Compile the graph and attach the code.
-    pipeline.CompileGraphAndAttachFunction();
-
-    // Class ids are numbered from internal/view/external.
-    const classid_t view_cid = data.GetClassId() + 1;
-    ASSERT(RawObject::IsTypedDataViewClassId(view_cid));
-
-    // First and last element are not in the view, i.e.
-    //    view[0:view.length()-1] = data[1:data.length()-2]
-    const intptr_t length_in_bytes =
-        (data.LengthInBytes() - 2 * data.ElementSizeInBytes());
-    view = TypedDataView::New(view_cid, data, data.ElementSizeInBytes(),
-                              length_in_bytes / data.ElementSizeInBytes());
-    ASSERT(data.ElementType() == view.ElementType());
-
-    arguments = Array::New(1);
-    arguments.SetAt(0, view);
-    result = DartEntry::InvokeFunction(function, arguments);
-    EXPECT(result.IsNull());
-
-    // Ensure we didn't deoptimize to unoptimized code.
-    EXPECT(function.unoptimized_code() == Code::null());
   };
 
-  const auto& uint8_list =
-      TypedData::Handle(TypedData::New(kTypedDataUint8ArrayCid, 16));
-  const auto& uint8c_list =
-      TypedData::Handle(TypedData::New(kTypedDataUint8ClampedArrayCid, 16));
-  const auto& int16_list =
-      TypedData::Handle(TypedData::New(kTypedDataInt16ArrayCid, 16));
-  const auto& uint16_list =
-      TypedData::Handle(TypedData::New(kTypedDataUint16ArrayCid, 16));
-  const auto& int32_list =
-      TypedData::Handle(TypedData::New(kTypedDataInt32ArrayCid, 16));
-  const auto& uint32_list =
-      TypedData::Handle(TypedData::New(kTypedDataUint32ArrayCid, 16));
-  const auto& int64_list =
-      TypedData::Handle(TypedData::New(kTypedDataInt64ArrayCid, 16));
-  const auto& uint64_list =
-      TypedData::Handle(TypedData::New(kTypedDataUint64ArrayCid, 16));
-  const auto& float32_list =
-      TypedData::Handle(TypedData::New(kTypedDataFloat32ArrayCid, 16));
-  const auto& float64_list =
-      TypedData::Handle(TypedData::New(kTypedDataFloat64ArrayCid, 16));
-  const auto& int8_list =
-      TypedData::Handle(TypedData::New(kTypedDataInt8ArrayCid, 16));
-  for (intptr_t i = 0; i < 16; ++i) {
-    int8_list.SetInt8(i, i);
-    uint8_list.SetUint8(i, i);
-    uint8c_list.SetUint8(i, i);
-    int16_list.SetInt16(2 * i, i);
-    uint16_list.SetUint16(2 * i, i);
-    int32_list.SetInt32(4 * i, i);
-    uint32_list.SetUint32(4 * i, i);
-    int64_list.SetInt64(8 * i, i);
-    uint64_list.SetUint64(8 * i, i);
-    float32_list.SetFloat32(4 * i, i + 0.5);
-    float64_list.SetFloat64(8 * i, i + 0.7);
-  }
-  run_reverse_list("Uint8List", int8_list);
-  run_reverse_list("Int8List", uint8_list);
-  run_reverse_list("Uint8ClampedList", uint8c_list);
-  run_reverse_list("Int16List", int16_list);
-  run_reverse_list("Uint16List", uint16_list);
-  run_reverse_list("Int32List", int32_list);
-  run_reverse_list("Uint32List", uint32_list);
-  run_reverse_list("Int64List", int64_list);
-  run_reverse_list("Uint64List", uint64_list);
-  run_reverse_list("Float32List", float32_list);
-  run_reverse_list("Float64List", float64_list);
-  for (intptr_t i = 0; i < 16; ++i) {
-    // Only the values in the view are reversed.
-    const bool in_view = i >= 1 && i < 15;
-
-    const int64_t expected_value = in_view ? (16 - i - 1) : i;
-    const uint64_t expected_uvalue = in_view ? (16 - i - 1) : i;
-    const float expected_fvalue = (in_view ? (16 - i - 1) : i) + 0.5;
-    const double expected_dvalue = (in_view ? (16 - i - 1) : i) + 0.7;
-
-    EXPECT(int8_list.GetInt8(i) == expected_value);
-    EXPECT(uint8_list.GetUint8(i) == expected_uvalue);
-    EXPECT(uint8c_list.GetUint8(i) == expected_uvalue);
-    EXPECT(int16_list.GetInt16(2 * i) == expected_value);
-    EXPECT(uint16_list.GetUint16(2 * i) == expected_uvalue);
-    EXPECT(int32_list.GetInt32(4 * i) == expected_value);
-    EXPECT(uint32_list.GetUint32(4 * i) == expected_uvalue);
-    EXPECT(int64_list.GetInt64(8 * i) == expected_value);
-    EXPECT(uint64_list.GetUint64(8 * i) == expected_uvalue);
-    EXPECT(float32_list.GetFloat32(4 * i) == expected_fvalue);
-    EXPECT(float64_list.GetFloat64(8 * i) == expected_dvalue);
-  }
+  check_il("Uint8List");
+  check_il("Int8List");
+  check_il("Uint8ClampedList");
+  check_il("Int16List");
+  check_il("Uint16List");
+  check_il("Int32List");
+  check_il("Uint32List");
+  check_il("Int64List");
+  check_il("Uint64List");
+  check_il("Float32List");
+  check_il("Float64List");
 }
 
 // This test asserts that we get errors if receiver, index or value are null.
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index c306430..53a60de 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -823,7 +823,8 @@
   JoinEntryInstr* nsm = BuildJoinEntry();
 
   Fragment failing(nsm);
-  const Code& nsm_handler = StubCode::CallClosureNoSuchMethod();
+  const Code& nsm_handler = Code::ZoneHandle(
+      Z, I->object_store()->call_closure_no_such_method_stub());
   failing += LoadArgDescriptor();
   failing += TailCall(nsm_handler);
 
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index d0381e0..fbc1a7e 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -2055,7 +2055,7 @@
     field.set_has_initializer(has_initializer);
 
     if (has_nontrivial_initializer) {
-      if (field.is_late()) {
+      if (field.is_late() && !is_static) {
         // Late fields are initialized to Object::sentinel, which is a flavor of
         // null. So we need to record that store so that the field guard doesn't
         // prematurely optimise out the late field's sentinel checking logic.
diff --git a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
index bd0b3ec..e7283f6 100644
--- a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc
@@ -117,12 +117,6 @@
     }
     case RawFunction::kImplicitStaticGetter: {
       ASSERT(!IsStaticFieldGetterGeneratedAsInitializer(function, Z));
-      const Field& field = Field::Handle(Z, function.accessor_field());
-      const bool lib_is_nnbd = function.nnbd_mode() == NNBDMode::kOptedInLib;
-      if (field.is_late() || lib_is_nnbd) {
-        // LoadLateField uses expression_temp_var.
-        needs_expr_temp = true;
-      }
       break;
     }
     case RawFunction::kDynamicInvocationForwarder: {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 4e4df30..b0dd414 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1716,10 +1716,26 @@
                                         clear_the_temp);
 }
 
+static void BadArity() {
+#ifndef PRODUCT
+  // TODO(https://github.com/dart-lang/sdk/issues/37517): Should emit code to
+  // throw a NoSuchMethodError.
+  ASSERT(Isolate::Current()->HasAttemptedReload());
+  Report::LongJump(LanguageError::Handle(LanguageError::New(String::Handle(
+      String::New("Unimplemented handling of static target arity change")))));
+#else
+  UNREACHABLE();
+#endif
+}
+
 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
                                                const Function& target,
                                                intptr_t argument_count,
                                                ICData::RebindRule rebind_rule) {
+  String& error_message = String::Handle();
+  if (!target.AreValidArgumentCounts(0, argument_count, 0, &error_message)) {
+    BadArity();
+  }
   return flow_graph_builder_->StaticCall(position, target, argument_count,
                                          rebind_rule);
 }
@@ -1733,6 +1749,11 @@
     const InferredTypeMetadata* result_type,
     intptr_t type_args_count,
     bool use_unchecked_entry) {
+  String& error_message = String::Handle();
+  if (!target.AreValidArguments(type_args_count, argument_count, argument_names,
+                                &error_message)) {
+    BadArity();
+  }
   return flow_graph_builder_->StaticCall(
       position, target, argument_count, argument_names, rebind_rule,
       result_type, type_args_count, use_unchecked_entry);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 375dc2f..138d13d 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -441,15 +441,11 @@
   Fragment instructions;
   TargetEntryInstr *is_uninitialized, *is_initialized;
   const TokenPosition position = field.token_pos();
-  const bool is_static = field.is_static();
+  ASSERT(!field.is_static());
 
   // Check whether the field has been initialized already.
-  if (is_static) {
-    instructions += LoadStaticField(field);
-  } else {
-    instructions += LoadLocal(instance);
-    instructions += LoadField(field);
-  }
+  instructions += LoadLocal(instance);
+  instructions += LoadField(field);
 
   LocalVariable* temp = parsed_function_->expression_temp_var();
   instructions += StoreLocal(position, temp);
@@ -467,14 +463,9 @@
     Function& init_function =
         Function::ZoneHandle(Z, field.EnsureInitializerFunction());
     Fragment initialize(is_uninitialized);
-    if (is_static) {
-      initialize += StaticCall(position, init_function,
-                               /* argument_count = */ 0, ICData::kNoRebind);
-    } else {
-      initialize += LoadLocal(instance);
-      initialize += StaticCall(position, init_function,
-                               /* argument_count = */ 1, ICData::kNoRebind);
-    }
+    initialize += LoadLocal(instance);
+    initialize += StaticCall(position, init_function,
+                             /* argument_count = */ 1, ICData::kNoRebind);
     initialize += StoreLocal(position, temp);
     initialize += Drop();
     initialize += StoreLateField(field, instance, temp);
@@ -2586,9 +2577,6 @@
     field = function.accessor_field();
   }
 
-  const Class& owner = Class::ZoneHandle(Z, field.Owner());
-  const bool lib_is_nnbd = Library::ZoneHandle(Z, owner.library()).is_nnbd();
-
   graph_entry_ =
       new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
 
@@ -2659,18 +2647,17 @@
     ASSERT(!field.IsUninitialized());
     body += Constant(Instance::ZoneHandle(Z, field.StaticValue()));
   } else {
-    // The field always has an initializer because static fields without
-    // initializers are initialized eagerly and do not have implicit getters.
-    if (lib_is_nnbd) {
-      // In NNBD mode, static fields act like late fields regardless of whether
-      // they're marked late. The only behavioural difference is in compile
-      // errors that are handled by the front end.
-      body += LoadLateField(field, /* instance = */ nullptr);
-    } else {
-      ASSERT(field.has_nontrivial_initializer());
-      body += InitStaticField(field);
-      body += LoadStaticField(field);
-    }
+    // Static fields
+    //  - with trivial initializer
+    //  - without initializer if they are not late
+    // are initialized eagerly and do not have implicit getters.
+    // Static fields with non-trivial initializer need getter to perform
+    // lazy initialization. Late fields without initializer need getter
+    // to make sure they are already initialized.
+    ASSERT(field.has_nontrivial_initializer() ||
+           (field.is_late() && !field.has_initializer()));
+    body += InitStaticField(field);
+    body += LoadStaticField(field);
     if (field.needs_load_guard()) {
 #if defined(PRODUCT)
       UNREACHABLE();
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 6b311fb..c56e34a 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2654,14 +2654,33 @@
   return position;
 }
 
+intptr_t KernelReaderHelper::SourceTableFieldCountFromFirstLibraryOffset() {
+  // translation_helper_.info() might not be initialized at this point so we
+  // can't use translation_helper_.info().kernel_binary_version().
+  SetOffset(KernelFormatVersionOffset);
+  uint32_t formatVersion = reader_.ReadUInt32();
+  intptr_t count_from_first_library_offset =
+      SourceTableFieldCountFromFirstLibraryOffsetPre41;
+  static_assert(kMinSupportedKernelFormatVersion < 41, "cleanup this code");
+  if (formatVersion >= 41) {
+    count_from_first_library_offset =
+        SourceTableFieldCountFromFirstLibraryOffset41Plus;
+  }
+  return count_from_first_library_offset;
+}
+
 intptr_t KernelReaderHelper::SourceTableSize() {
   AlternativeReadingScope alt(&reader_);
   intptr_t library_count = reader_.ReadFromIndexNoReset(
       reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);
+
+  const intptr_t count_from_first_library_offset =
+      SourceTableFieldCountFromFirstLibraryOffset();
+
   intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
       reader_.size(),
       LibraryCountFieldCountFromEnd + 1 + library_count + 1 +
-          SourceTableFieldCountFromFirstLibraryOffset,
+          count_from_first_library_offset,
       1, 0);
   SetOffset(source_table_offset);  // read source table offset.
   return reader_.ReadUInt32();     // read source table size.
@@ -2671,10 +2690,14 @@
   AlternativeReadingScope alt(&reader_);
   intptr_t library_count = reader_.ReadFromIndexNoReset(
       reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);
+
+  const intptr_t count_from_first_library_offset =
+      SourceTableFieldCountFromFirstLibraryOffset();
+
   intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
       reader_.size(),
       LibraryCountFieldCountFromEnd + 1 + library_count + 1 +
-          SourceTableFieldCountFromFirstLibraryOffset,
+          count_from_first_library_offset,
       1, 0);
   intptr_t next_field_offset = reader_.ReadUInt32();
   SetOffset(source_table_offset);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 4597fb6..9fb8301 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -958,7 +958,9 @@
   CompileType ToCompileType(Zone* zone) const {
     if (IsInt() && cid == kDynamicCid) {
       return CompileType::FromAbstractType(
-          Type::ZoneHandle(zone, Type::IntType()), IsNullable());
+          Type::ZoneHandle(
+              zone, (IsNullable() ? Type::NullableIntType() : Type::IntType())),
+          IsNullable());
     } else {
       return CompileType::CreateNullable(IsNullable(), cid);
     }
@@ -1218,6 +1220,7 @@
   Nullability ReadNullability();
   Variance ReadVariance();
 
+  intptr_t SourceTableFieldCountFromFirstLibraryOffset();
   intptr_t SourceTableSize();
   intptr_t GetOffsetForSourceInfo(intptr_t index);
   String& SourceTableUriFor(intptr_t index);
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 1d7e9c8..81157c7 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -328,18 +328,12 @@
     case RawFunction::kImplicitStaticGetter: {
       ASSERT(helper_.PeekTag() == kField);
       ASSERT(function.IsStaticFunction());
-      const auto& field = Field::Handle(Z, function.accessor_field());
       // In addition to static field initializers, scopes/local variables
       // are needed for implicit getters of static const fields, in order to
       // be able to evaluate their initializers in constant evaluator.
       if (Field::Handle(Z, function.accessor_field()).is_const()) {
         VisitNode();
       }
-      const bool lib_is_nnbd = function.nnbd_mode() == NNBDMode::kOptedInLib;
-      if (field.is_late() || lib_is_nnbd) {
-        // LoadLateField uses expression_temp_var.
-        needs_expr_temp_ = true;
-      }
       break;
     }
     case RawFunction::kFieldInitializer: {
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index 48bf5a7..2f56864 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -148,13 +148,21 @@
         // A call site can decide to jump not to the beginning of a function but
         // rather jump into it at a certain (positive) offset.
         int32_t offset_into_target = 0;
-        const intptr_t call_instruction_offset =
-            return_pc_offset - PcRelativeCallPattern::kLengthInBytes;
-        {
+        if (kind == Code::kPcRelativeCall) {
+          const intptr_t call_instruction_offset =
+              return_pc_offset - PcRelativeCallPattern::kLengthInBytes;
           PcRelativeCallPattern call(current_caller.PayloadStart() +
                                      call_instruction_offset);
           ASSERT(call.IsValid());
           offset_into_target = call.distance();
+        } else {
+          ASSERT(kind == Code::kPcRelativeTailCall);
+          const intptr_t call_instruction_offset =
+              return_pc_offset - PcRelativeTailCallPattern::kLengthInBytes;
+          PcRelativeTailCallPattern call(current_caller.PayloadStart() +
+                                         call_instruction_offset);
+          ASSERT(call.IsValid());
+          offset_into_target = call.distance();
         }
 
         const uword destination_payload = destination_.PayloadStart();
@@ -263,12 +271,24 @@
     // A call site can decide to jump not to the beginning of a function but
     // rather jump into it at a certain offset.
     int32_t offset_into_target = 0;
-    const intptr_t call_instruction_offset =
-        return_pc_offset - PcRelativeCallPattern::kLengthInBytes;
-    {
+    bool is_tail_call;
+    intptr_t call_instruction_offset;
+    if (kind == Code::kPcRelativeCall) {
+      call_instruction_offset =
+          return_pc_offset - PcRelativeCallPattern::kLengthInBytes;
       PcRelativeCallPattern call(code.PayloadStart() + call_instruction_offset);
       ASSERT(call.IsValid());
       offset_into_target = call.distance();
+      is_tail_call = false;
+    } else {
+      ASSERT(kind == Code::kPcRelativeTailCall);
+      call_instruction_offset =
+          return_pc_offset - PcRelativeTailCallPattern::kLengthInBytes;
+      PcRelativeTailCallPattern call(code.PayloadStart() +
+                                     call_instruction_offset);
+      ASSERT(call.IsValid());
+      offset_into_target = call.distance();
+      is_tail_call = true;
     }
 
     const uword destination_payload = destination_.PayloadStart();
@@ -283,7 +303,7 @@
 
     UnresolvedCall unresolved_call(code.raw(), call_instruction_offset,
                                    text_offset, destination_.raw(),
-                                   offset_into_target);
+                                   offset_into_target, is_tail_call);
     if (!TryResolveBackwardsCall(&unresolved_call)) {
       EnqueueUnresolvedCall(new UnresolvedCall(unresolved_call));
     }
@@ -373,10 +393,17 @@
     if (FLAG_write_protect_code) {
       addr -= HeapPage::Of(Code::InstructionsOf(caller))->AliasOffset();
     }
-    PcRelativeCallPattern call(addr);
-    ASSERT(call.IsValid());
-    call.set_distance(static_cast<int32_t>(distance));
-    ASSERT(call.distance() == distance);
+    if (unresolved_call->is_tail_call) {
+      PcRelativeTailCallPattern call(addr);
+      ASSERT(call.IsValid());
+      call.set_distance(static_cast<int32_t>(distance));
+      ASSERT(call.distance() == distance);
+    } else {
+      PcRelativeCallPattern call(addr);
+      ASSERT(call.IsValid());
+      call.set_distance(static_cast<int32_t>(distance));
+      ASSERT(call.distance() == distance);
+    }
   }
 
   unresolved_call->caller = nullptr;
@@ -405,8 +432,13 @@
                                        intptr_t target_text_offset) {
   const auto forward_distance =
       target_text_offset - unresolved_call->text_offset;
-  return PcRelativeCallPattern::kLowerCallingRange < forward_distance &&
-         forward_distance < PcRelativeCallPattern::kUpperCallingRange;
+  if (unresolved_call->is_tail_call) {
+    return PcRelativeTailCallPattern::kLowerCallingRange < forward_distance &&
+           forward_distance < PcRelativeTailCallPattern::kUpperCallingRange;
+  } else {
+    return PcRelativeCallPattern::kLowerCallingRange < forward_distance &&
+           forward_distance < PcRelativeCallPattern::kUpperCallingRange;
+  }
 }
 
 static void MarkAsFreeListElement(uint8_t* trampoline_bytes,
diff --git a/runtime/vm/compiler/relocation.h b/runtime/vm/compiler/relocation.h
index 2022f81..b373989 100644
--- a/runtime/vm/compiler/relocation.h
+++ b/runtime/vm/compiler/relocation.h
@@ -25,12 +25,14 @@
                  intptr_t call_offset,
                  intptr_t text_offset,
                  RawCode* callee,
-                 intptr_t offset_into_target)
+                 intptr_t offset_into_target,
+                 bool is_tail_call)
       : caller(caller),
         call_offset(call_offset),
         text_offset(text_offset),
         callee(callee),
-        offset_into_target(offset_into_target) {}
+        offset_into_target(offset_into_target),
+        is_tail_call(is_tail_call) {}
 
   UnresolvedCall(const UnresolvedCall& other)
       : IntrusiveDListEntry<UnresolvedCall>(),
@@ -39,18 +41,22 @@
         call_offset(other.call_offset),
         text_offset(other.text_offset),
         callee(other.callee),
-        offset_into_target(other.offset_into_target) {}
+        offset_into_target(other.offset_into_target),
+        is_tail_call(other.is_tail_call) {}
 
-  // The caller which has an unresolved call.
+  // The caller which has an unresolved call (will be null'ed out when
+  // resolved).
   RawCode* caller;
   // The offset from the payload of the calling code which performs the call.
-  intptr_t call_offset;
+  const intptr_t call_offset;
   // The offset in the .text segment where the call happens.
-  intptr_t text_offset;
-  // The target of the forward call.
+  const intptr_t text_offset;
+  // The target of the forward call (will be null'ed out when resolved).
   RawCode* callee;
   // The extra offset into the target.
-  intptr_t offset_into_target;
+  const intptr_t offset_into_target;
+  // Whether this is a tail call.
+  const bool is_tail_call;
 };
 
 // A list of all unresolved calls.
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 0fe7674..7f92b3b 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -252,6 +252,11 @@
   return (offset / kWordSize) * dart::kWordSize;
 }
 
+bool SizeFitsInSizeTag(uword instance_size) {
+  return dart::RawObject::SizeTag::SizeFits(
+      TranslateOffsetInWordsToHost(instance_size));
+}
+
 uint32_t MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size) {
   return dart::RawObject::SizeTag::encode(
              TranslateOffsetInWordsToHost(instance_size)) |
@@ -271,6 +276,10 @@
 const word RawObject::kOldAndNotMarkedBit =
     dart::RawObject::kOldAndNotMarkedBit;
 
+const word RawObject::kSizeTagPos = dart::RawObject::kSizeTagPos;
+
+const word RawObject::kSizeTagSize = dart::RawObject::kSizeTagSize;
+
 const word RawObject::kClassIdTagPos = dart::RawObject::kClassIdTagPos;
 
 const word RawObject::kClassIdTagSize = dart::RawObject::kClassIdTagSize;
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 1ac43ce..5966425 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -313,6 +313,9 @@
   return frame_layout.FrameSlotForVariable(variable) * kWordSize;
 }
 
+// Check whether instance_size is small enough to be encoded in the size tag.
+bool SizeFitsInSizeTag(uword instance_size);
+
 // Encode tag word for a heap allocated object with the given class id and
 // size.
 //
@@ -370,6 +373,8 @@
   static const word kCardRememberedBit;
   static const word kOldAndNotRememberedBit;
   static const word kOldAndNotMarkedBit;
+  static const word kSizeTagPos;
+  static const word kSizeTagSize;
   static const word kClassIdTagPos;
   static const word kClassIdTagSize;
   static const word kSizeTagMaxSizeTag;
@@ -457,10 +462,14 @@
   static word NextFieldOffset();
 };
 
+class CallSiteData : public AllStatic {
+ public:
+  static word arguments_descriptor_offset();
+};
+
 class ICData : public AllStatic {
  public:
   static word owner_offset();
-  static word arguments_descriptor_offset();
   static word entries_offset();
   static word receivers_static_type_offset();
   static word state_bits_offset();
@@ -482,7 +491,6 @@
   static const word kSpreadFactor;
   static word mask_offset();
   static word buckets_offset();
-  static word arguments_descriptor_offset();
   static word InstanceSize();
   static word NextFieldOffset();
 };
@@ -952,16 +960,15 @@
   static word field_table_values_offset();
   static word store_buffer_block_offset();
   static word call_to_runtime_entry_point_offset();
-  static word null_error_shared_with_fpu_regs_entry_point_offset();
-  static word null_error_shared_without_fpu_regs_entry_point_offset();
-  static word null_arg_error_shared_with_fpu_regs_entry_point_offset();
-  static word null_arg_error_shared_without_fpu_regs_entry_point_offset();
   static word write_barrier_mask_offset();
-  static word monomorphic_miss_entry_offset();
+  static word switchable_call_miss_entry_offset();
   static word write_barrier_wrappers_thread_offset(Register regno);
   static word array_write_barrier_entry_point_offset();
   static word allocate_mint_with_fpu_regs_entry_point_offset();
   static word allocate_mint_without_fpu_regs_entry_point_offset();
+  static word allocate_object_entry_point_offset();
+  static word allocate_object_parameterized_entry_point_offset();
+  static word allocate_object_slow_entry_point_offset();
   static word write_barrier_entry_point_offset();
   static word vm_tag_offset();
   static uword vm_tag_compiled_id();
@@ -989,7 +996,7 @@
   static word fix_callers_target_code_offset();
   static word fix_allocation_stub_code_offset();
 
-  static word monomorphic_miss_stub_offset();
+  static word switchable_call_miss_stub_offset();
   static word lazy_specialize_type_test_stub_offset();
   static word slow_type_test_stub_offset();
   static word call_to_runtime_stub_offset();
@@ -1000,6 +1007,8 @@
   static word null_error_shared_with_fpu_regs_stub_offset();
   static word null_arg_error_shared_without_fpu_regs_stub_offset();
   static word null_arg_error_shared_with_fpu_regs_stub_offset();
+  static word range_error_shared_without_fpu_regs_stub_offset();
+  static word range_error_shared_with_fpu_regs_stub_offset();
   static word stack_overflow_shared_without_fpu_regs_entry_point_offset();
   static word stack_overflow_shared_without_fpu_regs_stub_offset();
   static word stack_overflow_shared_with_fpu_regs_entry_point_offset();
@@ -1008,6 +1017,9 @@
   static word lazy_deopt_from_throw_stub_offset();
   static word allocate_mint_with_fpu_regs_stub_offset();
   static word allocate_mint_without_fpu_regs_stub_offset();
+  static word allocate_object_stub_offset();
+  static word allocate_object_parameterized_stub_offset();
+  static word allocate_object_slow_stub_offset();
   static word optimize_stub_offset();
   static word deoptimize_stub_offset();
   static word enter_safepoint_stub_offset();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index c825f44..295a04b 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -128,11 +128,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 8;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 12;
-static constexpr dart::compiler::target::word ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word ICData_entries_offset = 12;
 static constexpr dart::compiler::target::word ICData_owner_offset = 20;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
 static constexpr dart::compiler::target::word
@@ -157,11 +157,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    4;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
+    12;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     4;
@@ -170,10 +168,10 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 60;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    140;
+    148;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -192,76 +190,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 336;
+    Thread_AllocateArray_entry_point_offset = 364;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    668;
+    684;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    672;
+    688;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 228;
+    Thread_array_write_barrier_entry_point_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 252;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 168;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 256;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 172;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 192;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 296;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 324;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 288;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 316;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 232;
+    Thread_call_to_runtime_entry_point_offset = 264;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 704;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 720;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    276;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 188;
+    304;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 220;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    280;
+    308;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    192;
+    224;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    316;
+    344;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 312;
+    Thread_double_negate_address_offset = 340;
 static constexpr dart::compiler::target::word Thread_end_offset = 56;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 212;
+    Thread_enter_safepoint_stub_offset = 244;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    688;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 216;
+    Thread_exit_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 220;
+    Thread_call_native_through_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 284;
+    Thread_call_native_through_safepoint_entry_point_offset = 312;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 328;
+    Thread_float_absolute_address_offset = 356;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 324;
+    Thread_float_negate_address_offset = 352;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    320;
+    348;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 332;
+    Thread_float_zerow_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    676;
+    692;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 300;
+    Thread_interpret_call_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 144;
 static constexpr dart::compiler::target::word
@@ -270,60 +280,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 196;
+    Thread_lazy_deopt_from_return_stub_offset = 228;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 200;
+    Thread_lazy_deopt_from_throw_stub_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 208;
+    Thread_lazy_specialize_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 84;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 268;
+    Thread_megamorphic_call_checked_entry_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 272;
+    Thread_switchable_call_miss_entry_offset = 300;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 184;
+    Thread_switchable_call_miss_stub_offset = 204;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 292;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 240;
+    Thread_no_scope_native_wrapper_entry_point_offset = 320;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 248;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 164;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 236;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 172;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 244;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 168;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 304;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 680;
+    Thread_predefined_symbols_address_offset = 332;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 696;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 684;
+    Thread_saved_shadow_call_stack_offset = 700;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    692;
+    708;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 204;
+    Thread_slow_type_test_stub_offset = 236;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     60;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 64;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 264;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 180;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 260;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 176;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 196;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     80;
 static constexpr dart::compiler::target::word
@@ -336,10 +342,10 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 224;
+    Thread_write_barrier_entry_point_offset = 256;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 696;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 712;
 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;
@@ -377,7 +383,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        636, 640, 644, 648, 652, -1, 656, -1, 660, 664, -1, -1, -1, -1, -1, -1};
+        652, 656, 660, 664, 668, -1, 672, -1, 676, 680, -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;
@@ -596,11 +602,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word ICData_owner_offset = 40;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
 static constexpr dart::compiler::target::word
@@ -625,11 +631,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 32;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    8;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+    24;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 32;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     8;
@@ -638,10 +642,10 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    280;
+    296;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -661,76 +665,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 656;
+    Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1344;
+    1376;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1352;
+    1384;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 440;
+    Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 224;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 448;
+    Thread_call_to_runtime_entry_point_offset = 512;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1416;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1448;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    536;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 360;
+    592;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    544;
+    600;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    368;
+    432;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    616;
+    672;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 608;
+    Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 408;
+    Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1384;
+    1416;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 416;
+    Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 424;
+    Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 552;
+    Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 640;
+    Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 632;
+    Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    624;
+    680;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 648;
+    Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1360;
+    1392;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 584;
+    Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -739,60 +755,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 376;
+    Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 384;
+    Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 400;
+    Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 520;
+    Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 528;
+    Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 352;
+    Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 592;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1368;
+    Thread_predefined_symbols_address_offset = 648;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1400;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1376;
+    Thread_saved_shadow_call_stack_offset = 1408;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1392;
+    1424;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 392;
+    Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     120;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     160;
 static constexpr dart::compiler::target::word
@@ -805,11 +817,11 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     232;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 432;
+    Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1400;
+    1432;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -848,8 +860,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, -1,   -1,   1288, 1296,
-        1304, 1312, 1320, -1,   1328, 1336, -1,   -1};
+        1288, 1296, 1304, 1312, -1,   -1,   1320, 1328,
+        1336, 1344, 1352, -1,   1360, 1368, -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;
@@ -1067,11 +1079,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 8;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 12;
-static constexpr dart::compiler::target::word ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word ICData_entries_offset = 12;
 static constexpr dart::compiler::target::word ICData_owner_offset = 20;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
 static constexpr dart::compiler::target::word
@@ -1096,11 +1108,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    4;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
+    12;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     4;
@@ -1109,10 +1119,10 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 60;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    140;
+    148;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -1131,76 +1141,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 336;
+    Thread_AllocateArray_entry_point_offset = 364;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    636;
+    652;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    640;
+    656;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 228;
+    Thread_array_write_barrier_entry_point_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 252;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 168;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 256;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 172;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 192;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 296;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 324;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 288;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 316;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 232;
+    Thread_call_to_runtime_entry_point_offset = 264;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 672;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 688;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    276;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 188;
+    304;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 220;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    280;
+    308;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    192;
+    224;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    316;
+    344;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 312;
+    Thread_double_negate_address_offset = 340;
 static constexpr dart::compiler::target::word Thread_end_offset = 56;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 212;
+    Thread_enter_safepoint_stub_offset = 244;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    656;
+    672;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 216;
+    Thread_exit_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 220;
+    Thread_call_native_through_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 284;
+    Thread_call_native_through_safepoint_entry_point_offset = 312;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 328;
+    Thread_float_absolute_address_offset = 356;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 324;
+    Thread_float_negate_address_offset = 352;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    320;
+    348;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 332;
+    Thread_float_zerow_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    644;
+    660;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 300;
+    Thread_interpret_call_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 144;
 static constexpr dart::compiler::target::word
@@ -1209,60 +1231,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 196;
+    Thread_lazy_deopt_from_return_stub_offset = 228;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 200;
+    Thread_lazy_deopt_from_throw_stub_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 208;
+    Thread_lazy_specialize_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 84;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 268;
+    Thread_megamorphic_call_checked_entry_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 272;
+    Thread_switchable_call_miss_entry_offset = 300;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 184;
+    Thread_switchable_call_miss_stub_offset = 204;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 292;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 240;
+    Thread_no_scope_native_wrapper_entry_point_offset = 320;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 248;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 164;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 236;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 172;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 244;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 168;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 304;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 648;
+    Thread_predefined_symbols_address_offset = 332;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 664;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 652;
+    Thread_saved_shadow_call_stack_offset = 668;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    660;
+    676;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 204;
+    Thread_slow_type_test_stub_offset = 236;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     60;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 64;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 264;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 180;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 260;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 176;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 196;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     80;
 static constexpr dart::compiler::target::word
@@ -1275,10 +1293,10 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 224;
+    Thread_write_barrier_entry_point_offset = 256;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 664;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 680;
 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;
@@ -1532,11 +1550,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word ICData_owner_offset = 40;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
 static constexpr dart::compiler::target::word
@@ -1561,11 +1579,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 32;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    8;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+    24;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 32;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     8;
@@ -1574,10 +1590,10 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    280;
+    296;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -1597,76 +1613,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 656;
+    Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1416;
+    1448;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1424;
+    1456;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 440;
+    Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 224;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 448;
+    Thread_call_to_runtime_entry_point_offset = 512;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1488;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1520;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    536;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 360;
+    592;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    544;
+    600;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    368;
+    432;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    616;
+    672;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 608;
+    Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 408;
+    Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1456;
+    1488;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 416;
+    Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 424;
+    Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 552;
+    Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 640;
+    Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 632;
+    Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    624;
+    680;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 648;
+    Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1432;
+    1464;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 584;
+    Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -1675,60 +1703,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 376;
+    Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 384;
+    Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 400;
+    Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 520;
+    Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 528;
+    Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 352;
+    Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 592;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1440;
+    Thread_predefined_symbols_address_offset = 648;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1472;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1448;
+    Thread_saved_shadow_call_stack_offset = 1480;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1464;
+    1496;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 392;
+    Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     120;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     160;
 static constexpr dart::compiler::target::word
@@ -1741,11 +1765,11 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     232;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 432;
+    Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1472;
+    1504;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -1784,9 +1808,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, 1288, 1296, 1304, 1312, 1320, 1328, 1336,
-        1344, 1352, 1360, 1368, -1,   -1,   -1,   -1,   1376, 1384, -1,
-        -1,   1392, 1400, 1408, -1,   -1,   -1,   -1,   -1,   -1};
+        1288, 1296, 1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368,
+        1376, 1384, 1392, 1400, -1,   -1,   -1,   -1,   1408, 1416, -1,
+        -1,   1424, 1432, 1440, -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;
@@ -2004,11 +2028,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 8;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 12;
-static constexpr dart::compiler::target::word ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word ICData_entries_offset = 12;
 static constexpr dart::compiler::target::word ICData_owner_offset = 20;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
 static constexpr dart::compiler::target::word
@@ -2032,11 +2056,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    4;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
+    12;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     4;
@@ -2045,10 +2067,10 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 60;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    140;
+    148;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -2067,76 +2089,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 336;
+    Thread_AllocateArray_entry_point_offset = 364;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    668;
+    684;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    672;
+    688;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 228;
+    Thread_array_write_barrier_entry_point_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 252;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 168;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 256;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 172;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 192;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 296;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 324;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 288;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 316;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 232;
+    Thread_call_to_runtime_entry_point_offset = 264;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 704;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 720;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    276;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 188;
+    304;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 220;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    280;
+    308;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    192;
+    224;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    316;
+    344;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 312;
+    Thread_double_negate_address_offset = 340;
 static constexpr dart::compiler::target::word Thread_end_offset = 56;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 212;
+    Thread_enter_safepoint_stub_offset = 244;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    688;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 216;
+    Thread_exit_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 220;
+    Thread_call_native_through_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 284;
+    Thread_call_native_through_safepoint_entry_point_offset = 312;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 328;
+    Thread_float_absolute_address_offset = 356;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 324;
+    Thread_float_negate_address_offset = 352;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    320;
+    348;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 332;
+    Thread_float_zerow_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    676;
+    692;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 300;
+    Thread_interpret_call_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 144;
 static constexpr dart::compiler::target::word
@@ -2145,60 +2179,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 196;
+    Thread_lazy_deopt_from_return_stub_offset = 228;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 200;
+    Thread_lazy_deopt_from_throw_stub_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 208;
+    Thread_lazy_specialize_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 84;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 268;
+    Thread_megamorphic_call_checked_entry_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 272;
+    Thread_switchable_call_miss_entry_offset = 300;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 184;
+    Thread_switchable_call_miss_stub_offset = 204;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 292;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 240;
+    Thread_no_scope_native_wrapper_entry_point_offset = 320;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 248;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 164;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 236;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 172;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 244;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 168;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 304;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 680;
+    Thread_predefined_symbols_address_offset = 332;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 696;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 684;
+    Thread_saved_shadow_call_stack_offset = 700;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    692;
+    708;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 204;
+    Thread_slow_type_test_stub_offset = 236;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     60;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 64;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 264;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 180;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 260;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 176;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 196;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     80;
 static constexpr dart::compiler::target::word
@@ -2211,10 +2241,10 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 224;
+    Thread_write_barrier_entry_point_offset = 256;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 696;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 712;
 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;
@@ -2249,7 +2279,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        636, 640, 644, 648, 652, -1, 656, -1, 660, 664, -1, -1, -1, -1, -1, -1};
+        652, 656, 660, 664, 668, -1, 672, -1, 676, 680, -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;
@@ -2466,11 +2496,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word ICData_owner_offset = 40;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
 static constexpr dart::compiler::target::word
@@ -2494,11 +2524,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 32;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    8;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+    24;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 32;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     8;
@@ -2507,10 +2535,10 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    280;
+    296;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -2530,76 +2558,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 656;
+    Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1344;
+    1376;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1352;
+    1384;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 440;
+    Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 224;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 448;
+    Thread_call_to_runtime_entry_point_offset = 512;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1416;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1448;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    536;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 360;
+    592;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    544;
+    600;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    368;
+    432;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    616;
+    672;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 608;
+    Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 408;
+    Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1384;
+    1416;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 416;
+    Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 424;
+    Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 552;
+    Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 640;
+    Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 632;
+    Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    624;
+    680;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 648;
+    Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1360;
+    1392;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 584;
+    Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -2608,60 +2648,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 376;
+    Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 384;
+    Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 400;
+    Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 520;
+    Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 528;
+    Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 352;
+    Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 592;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1368;
+    Thread_predefined_symbols_address_offset = 648;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1400;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1376;
+    Thread_saved_shadow_call_stack_offset = 1408;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1392;
+    1424;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 392;
+    Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     120;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     160;
 static constexpr dart::compiler::target::word
@@ -2674,11 +2710,11 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     232;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 432;
+    Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1400;
+    1432;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -2714,8 +2750,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, -1,   -1,   1288, 1296,
-        1304, 1312, 1320, -1,   1328, 1336, -1,   -1};
+        1288, 1296, 1304, 1312, -1,   -1,   1320, 1328,
+        1336, 1344, 1352, -1,   1360, 1368, -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;
@@ -2931,11 +2967,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 8;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 12;
-static constexpr dart::compiler::target::word ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word ICData_entries_offset = 12;
 static constexpr dart::compiler::target::word ICData_owner_offset = 20;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
 static constexpr dart::compiler::target::word
@@ -2959,11 +2995,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    4;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
+    12;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     4;
@@ -2972,10 +3006,10 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 60;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    140;
+    148;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -2994,76 +3028,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 336;
+    Thread_AllocateArray_entry_point_offset = 364;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    636;
+    652;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    640;
+    656;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 228;
+    Thread_array_write_barrier_entry_point_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 252;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 168;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 256;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 172;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 192;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 296;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 324;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 288;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 316;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 232;
+    Thread_call_to_runtime_entry_point_offset = 264;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 672;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 688;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    276;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 188;
+    304;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 220;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    280;
+    308;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    192;
+    224;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    316;
+    344;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 312;
+    Thread_double_negate_address_offset = 340;
 static constexpr dart::compiler::target::word Thread_end_offset = 56;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 212;
+    Thread_enter_safepoint_stub_offset = 244;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    656;
+    672;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 216;
+    Thread_exit_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 220;
+    Thread_call_native_through_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 284;
+    Thread_call_native_through_safepoint_entry_point_offset = 312;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 328;
+    Thread_float_absolute_address_offset = 356;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 324;
+    Thread_float_negate_address_offset = 352;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    320;
+    348;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 332;
+    Thread_float_zerow_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    644;
+    660;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 300;
+    Thread_interpret_call_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 144;
 static constexpr dart::compiler::target::word
@@ -3072,60 +3118,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 196;
+    Thread_lazy_deopt_from_return_stub_offset = 228;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 200;
+    Thread_lazy_deopt_from_throw_stub_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 208;
+    Thread_lazy_specialize_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 84;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 268;
+    Thread_megamorphic_call_checked_entry_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 272;
+    Thread_switchable_call_miss_entry_offset = 300;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 184;
+    Thread_switchable_call_miss_stub_offset = 204;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 292;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 240;
+    Thread_no_scope_native_wrapper_entry_point_offset = 320;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 248;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 164;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 236;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 172;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 244;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 168;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 304;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 648;
+    Thread_predefined_symbols_address_offset = 332;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 664;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 652;
+    Thread_saved_shadow_call_stack_offset = 668;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    660;
+    676;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 204;
+    Thread_slow_type_test_stub_offset = 236;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     60;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 64;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 264;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 180;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 260;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 176;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 196;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     80;
 static constexpr dart::compiler::target::word
@@ -3138,10 +3180,10 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 224;
+    Thread_write_barrier_entry_point_offset = 256;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 664;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 680;
 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;
@@ -3390,11 +3432,11 @@
 static constexpr dart::compiler::target::word
     GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word ICData_owner_offset = 40;
 static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
 static constexpr dart::compiler::target::word
@@ -3418,11 +3460,9 @@
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 32;
 static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    8;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+    24;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 32;
 static constexpr dart::compiler::target::word Mint_value_offset = 8;
 static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
     8;
@@ -3431,10 +3471,10 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    280;
+    296;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -3454,76 +3494,88 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 656;
+    Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1416;
+    1448;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1424;
+    1456;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 440;
+    Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 224;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 448;
+    Thread_call_to_runtime_entry_point_offset = 512;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1488;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1520;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    536;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 360;
+    592;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 424;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    544;
+    600;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    368;
+    432;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    616;
+    672;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 608;
+    Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 408;
+    Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1456;
+    1488;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 416;
+    Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 424;
+    Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 552;
+    Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 640;
+    Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 632;
+    Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    624;
+    680;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 648;
+    Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1432;
+    1464;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 584;
+    Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -3532,60 +3584,56 @@
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 376;
+    Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 384;
+    Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 400;
+    Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 520;
+    Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 528;
+    Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 352;
+    Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 592;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1440;
+    Thread_predefined_symbols_address_offset = 648;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1472;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1448;
+    Thread_saved_shadow_call_stack_offset = 1480;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1464;
+    1496;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 392;
+    Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     120;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
     160;
 static constexpr dart::compiler::target::word
@@ -3598,11 +3646,11 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     232;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 432;
+    Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1472;
+    1504;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -3638,9 +3686,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, 1288, 1296, 1304, 1312, 1320, 1328, 1336,
-        1344, 1352, 1360, 1368, -1,   -1,   -1,   -1,   1376, 1384, -1,
-        -1,   1392, 1400, 1408, -1,   -1,   -1,   -1,   -1,   -1};
+        1288, 1296, 1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368,
+        1376, 1384, 1392, 1400, -1,   -1,   -1,   -1,   1408, 1416, -1,
+        -1,   1424, 1432, 1440, -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;
@@ -3860,11 +3908,11 @@
     AOT_GrowableObjectArray_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word AOT_HeapPage_card_table_offset =
     20;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 8;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    AOT_ICData_arguments_descriptor_offset = 12;
-static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 12;
 static constexpr dart::compiler::target::word AOT_Isolate_class_table_offset =
     36;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
@@ -3895,11 +3943,9 @@
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
     4;
 static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_arguments_descriptor_offset = 16;
-static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_buckets_offset = 4;
+    AOT_MegamorphicCache_buckets_offset = 12;
 static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
-    8;
+    16;
 static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_argc_tag_offset = 4;
@@ -3910,11 +3956,11 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 116;
+    AOT_ObjectStore_double_type_offset = 120;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
     60;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 140;
+    AOT_ObjectStore_string_type_offset = 148;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -3938,79 +3984,91 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 336;
+    AOT_Thread_AllocateArray_entry_point_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 668;
+    AOT_Thread_active_exception_offset = 684;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 672;
+    AOT_Thread_active_stacktrace_offset = 688;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 228;
+    AOT_Thread_array_write_barrier_entry_point_offset = 260;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 252;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 168;
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 256;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 172;
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 192;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 96;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 296;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 324;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     120;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 288;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 316;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 232;
+    AOT_Thread_call_to_runtime_entry_point_offset = 264;
 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 =
-    704;
+    720;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    276;
+    304;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
-    188;
+    220;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 280;
+    AOT_Thread_deoptimize_entry_offset = 308;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_stub_offset = 192;
+    AOT_Thread_deoptimize_stub_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 316;
+    AOT_Thread_double_abs_address_offset = 344;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 312;
+    AOT_Thread_double_negate_address_offset = 340;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 56;
 static constexpr dart::compiler::target::word
-    AOT_Thread_enter_safepoint_stub_offset = 212;
+    AOT_Thread_enter_safepoint_stub_offset = 244;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 688;
+    AOT_Thread_execution_state_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_safepoint_stub_offset = 216;
+    AOT_Thread_exit_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 220;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 284;
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 312;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 328;
+    AOT_Thread_float_absolute_address_offset = 356;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 324;
+    AOT_Thread_float_negate_address_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 320;
+    AOT_Thread_float_not_address_offset = 348;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 332;
+    AOT_Thread_float_zerow_address_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 676;
+    AOT_Thread_global_object_pool_offset = 692;
 static constexpr dart::compiler::target::word
-    AOT_Thread_interpret_call_entry_point_offset = 300;
+    AOT_Thread_interpret_call_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_from_bytecode_stub_offset = 144;
 static constexpr dart::compiler::target::word
@@ -4019,48 +4077,44 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_return_stub_offset = 196;
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 228;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_throw_stub_offset = 200;
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_specialize_type_test_stub_offset = 208;
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 84;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 268;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 296;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_entry_offset = 272;
+    AOT_Thread_switchable_call_miss_entry_offset = 300;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_stub_offset = 184;
+    AOT_Thread_switchable_call_miss_stub_offset = 204;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 292;
-static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_with_fpu_regs_entry_point_offset = 240;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 320;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 248;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 164;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_without_fpu_regs_entry_point_offset = 236;
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 172;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 244;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 168;
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 304;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 680;
+    AOT_Thread_predefined_symbols_address_offset = 332;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 696;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 684;
+    AOT_Thread_saved_shadow_call_stack_offset = 700;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 692;
+    AOT_Thread_safepoint_state_offset = 708;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_stub_offset = 204;
+    AOT_Thread_slow_type_test_stub_offset = 236;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     36;
 static constexpr dart::compiler::target::word
@@ -4068,13 +4122,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 64;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 264;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 180;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 260;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 176;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 196;
 static constexpr dart::compiler::target::word
     AOT_Thread_store_buffer_block_offset = 80;
 static constexpr dart::compiler::target::word
@@ -4088,11 +4142,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 124;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 224;
+    AOT_Thread_write_barrier_entry_point_offset = 256;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    696;
+    712;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -4137,7 +4191,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        636, 640, 644, 648, 652, -1, 656, -1, 660, 664, -1, -1, -1, -1, -1, -1};
+        652, 656, 660, 664, 668, -1, 672, -1, 676, 680, -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;
@@ -4372,11 +4426,11 @@
     AOT_GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word AOT_HeapPage_card_table_offset =
     40;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    AOT_ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word AOT_Isolate_class_table_offset =
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
@@ -4407,11 +4461,9 @@
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_arguments_descriptor_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_buckets_offset = 8;
+    AOT_MegamorphicCache_buckets_offset = 24;
 static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
-    16;
+    32;
 static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_argc_tag_offset = 8;
@@ -4422,11 +4474,11 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 232;
+    AOT_ObjectStore_double_type_offset = 240;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
     120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 280;
+    AOT_ObjectStore_string_type_offset = 296;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -4450,79 +4502,91 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 656;
+    AOT_Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1344;
+    AOT_Thread_active_exception_offset = 1376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1352;
+    AOT_Thread_active_stacktrace_offset = 1384;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 440;
+    AOT_Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     224;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 448;
+    AOT_Thread_call_to_runtime_entry_point_offset = 512;
 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 =
-    1416;
+    1448;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    536;
+    592;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
-    360;
+    424;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 544;
+    AOT_Thread_deoptimize_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_stub_offset = 368;
+    AOT_Thread_deoptimize_stub_offset = 432;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 616;
+    AOT_Thread_double_abs_address_offset = 672;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 608;
+    AOT_Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_enter_safepoint_stub_offset = 408;
+    AOT_Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1384;
+    AOT_Thread_execution_state_offset = 1416;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_safepoint_stub_offset = 416;
+    AOT_Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 424;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 552;
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 640;
+    AOT_Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 632;
+    AOT_Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 624;
+    AOT_Thread_float_not_address_offset = 680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 648;
+    AOT_Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1360;
+    AOT_Thread_global_object_pool_offset = 1392;
 static constexpr dart::compiler::target::word
-    AOT_Thread_interpret_call_entry_point_offset = 584;
+    AOT_Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -4531,49 +4595,45 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_return_stub_offset = 376;
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_throw_stub_offset = 384;
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_specialize_type_test_stub_offset = 400;
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 520;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_entry_offset = 528;
+    AOT_Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_stub_offset = 352;
+    AOT_Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 592;
+    AOT_Thread_predefined_symbols_address_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1368;
+    1400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1376;
+    AOT_Thread_saved_shadow_call_stack_offset = 1408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1392;
+    AOT_Thread_safepoint_state_offset = 1424;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_stub_offset = 392;
+    AOT_Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     72;
 static constexpr dart::compiler::target::word
@@ -4581,13 +4641,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word
     AOT_Thread_store_buffer_block_offset = 160;
 static constexpr dart::compiler::target::word
@@ -4601,11 +4661,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 432;
+    AOT_Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1400;
+    1432;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -4650,8 +4710,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, -1,   -1,   1288, 1296,
-        1304, 1312, 1320, -1,   1328, 1336, -1,   -1};
+        1288, 1296, 1304, 1312, -1,   -1,   1320, 1328,
+        1336, 1344, 1352, -1,   1360, 1368, -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;
@@ -4890,11 +4950,11 @@
     AOT_GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word AOT_HeapPage_card_table_offset =
     40;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    AOT_ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word AOT_Isolate_class_table_offset =
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
@@ -4925,11 +4985,9 @@
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_arguments_descriptor_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_buckets_offset = 8;
+    AOT_MegamorphicCache_buckets_offset = 24;
 static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
-    16;
+    32;
 static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_argc_tag_offset = 8;
@@ -4940,11 +4998,11 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 232;
+    AOT_ObjectStore_double_type_offset = 240;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
     120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 280;
+    AOT_ObjectStore_string_type_offset = 296;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -4968,79 +5026,91 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 656;
+    AOT_Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1416;
+    AOT_Thread_active_exception_offset = 1448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1424;
+    AOT_Thread_active_stacktrace_offset = 1456;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 440;
+    AOT_Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     224;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 448;
+    AOT_Thread_call_to_runtime_entry_point_offset = 512;
 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 =
-    1488;
+    1520;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    536;
+    592;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
-    360;
+    424;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 544;
+    AOT_Thread_deoptimize_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_stub_offset = 368;
+    AOT_Thread_deoptimize_stub_offset = 432;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 616;
+    AOT_Thread_double_abs_address_offset = 672;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 608;
+    AOT_Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_enter_safepoint_stub_offset = 408;
+    AOT_Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1456;
+    AOT_Thread_execution_state_offset = 1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_safepoint_stub_offset = 416;
+    AOT_Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 424;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 552;
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 640;
+    AOT_Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 632;
+    AOT_Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 624;
+    AOT_Thread_float_not_address_offset = 680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 648;
+    AOT_Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1432;
+    AOT_Thread_global_object_pool_offset = 1464;
 static constexpr dart::compiler::target::word
-    AOT_Thread_interpret_call_entry_point_offset = 584;
+    AOT_Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -5049,49 +5119,45 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_return_stub_offset = 376;
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_throw_stub_offset = 384;
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_specialize_type_test_stub_offset = 400;
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 520;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_entry_offset = 528;
+    AOT_Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_stub_offset = 352;
+    AOT_Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 592;
+    AOT_Thread_predefined_symbols_address_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1440;
+    1472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1448;
+    AOT_Thread_saved_shadow_call_stack_offset = 1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1464;
+    AOT_Thread_safepoint_state_offset = 1496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_stub_offset = 392;
+    AOT_Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     72;
 static constexpr dart::compiler::target::word
@@ -5099,13 +5165,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word
     AOT_Thread_store_buffer_block_offset = 160;
 static constexpr dart::compiler::target::word
@@ -5119,11 +5185,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 432;
+    AOT_Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1472;
+    1504;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -5168,9 +5234,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, 1288, 1296, 1304, 1312, 1320, 1328, 1336,
-        1344, 1352, 1360, 1368, -1,   -1,   -1,   -1,   1376, 1384, -1,
-        -1,   1392, 1400, 1408, -1,   -1,   -1,   -1,   -1,   -1};
+        1288, 1296, 1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368,
+        1376, 1384, 1392, 1400, -1,   -1,   -1,   -1,   1408, 1416, -1,
+        -1,   1424, 1432, 1440, -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;
@@ -5406,11 +5472,11 @@
     AOT_GrowableObjectArray_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word AOT_HeapPage_card_table_offset =
     20;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 8;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    AOT_ICData_arguments_descriptor_offset = 12;
-static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 4;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 12;
 static constexpr dart::compiler::target::word AOT_Isolate_class_table_offset =
     36;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
@@ -5439,11 +5505,9 @@
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
     4;
 static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_arguments_descriptor_offset = 16;
-static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_buckets_offset = 4;
+    AOT_MegamorphicCache_buckets_offset = 12;
 static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
-    8;
+    16;
 static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_argc_tag_offset = 4;
@@ -5454,11 +5518,11 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 116;
+    AOT_ObjectStore_double_type_offset = 120;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
     60;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 140;
+    AOT_ObjectStore_string_type_offset = 148;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -5482,79 +5546,91 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 336;
+    AOT_Thread_AllocateArray_entry_point_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 668;
+    AOT_Thread_active_exception_offset = 684;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 672;
+    AOT_Thread_active_stacktrace_offset = 688;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 228;
+    AOT_Thread_array_write_barrier_entry_point_offset = 260;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 252;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 168;
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 256;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 172;
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 192;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 96;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 296;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 324;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     120;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 288;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 316;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 232;
+    AOT_Thread_call_to_runtime_entry_point_offset = 264;
 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 =
-    704;
+    720;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    276;
+    304;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
-    188;
+    220;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 280;
+    AOT_Thread_deoptimize_entry_offset = 308;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_stub_offset = 192;
+    AOT_Thread_deoptimize_stub_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 316;
+    AOT_Thread_double_abs_address_offset = 344;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 312;
+    AOT_Thread_double_negate_address_offset = 340;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 56;
 static constexpr dart::compiler::target::word
-    AOT_Thread_enter_safepoint_stub_offset = 212;
+    AOT_Thread_enter_safepoint_stub_offset = 244;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 688;
+    AOT_Thread_execution_state_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_safepoint_stub_offset = 216;
+    AOT_Thread_exit_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 220;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 284;
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 312;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 328;
+    AOT_Thread_float_absolute_address_offset = 356;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 324;
+    AOT_Thread_float_negate_address_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 320;
+    AOT_Thread_float_not_address_offset = 348;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 332;
+    AOT_Thread_float_zerow_address_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 676;
+    AOT_Thread_global_object_pool_offset = 692;
 static constexpr dart::compiler::target::word
-    AOT_Thread_interpret_call_entry_point_offset = 300;
+    AOT_Thread_interpret_call_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_from_bytecode_stub_offset = 144;
 static constexpr dart::compiler::target::word
@@ -5563,48 +5639,44 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_return_stub_offset = 196;
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 228;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_throw_stub_offset = 200;
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_specialize_type_test_stub_offset = 208;
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 84;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 268;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 296;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_entry_offset = 272;
+    AOT_Thread_switchable_call_miss_entry_offset = 300;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_stub_offset = 184;
+    AOT_Thread_switchable_call_miss_stub_offset = 204;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 292;
-static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_with_fpu_regs_entry_point_offset = 240;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 320;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 248;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 164;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_without_fpu_regs_entry_point_offset = 236;
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 172;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 244;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 168;
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 304;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 680;
+    AOT_Thread_predefined_symbols_address_offset = 332;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 696;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 684;
+    AOT_Thread_saved_shadow_call_stack_offset = 700;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 692;
+    AOT_Thread_safepoint_state_offset = 708;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_stub_offset = 204;
+    AOT_Thread_slow_type_test_stub_offset = 236;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     36;
 static constexpr dart::compiler::target::word
@@ -5612,13 +5684,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 64;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 264;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 180;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 260;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 176;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 196;
 static constexpr dart::compiler::target::word
     AOT_Thread_store_buffer_block_offset = 80;
 static constexpr dart::compiler::target::word
@@ -5632,11 +5704,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 124;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 224;
+    AOT_Thread_write_barrier_entry_point_offset = 256;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    696;
+    712;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -5678,7 +5750,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        636, 640, 644, 648, 652, -1, 656, -1, 660, 664, -1, -1, -1, -1, -1, -1};
+        652, 656, 660, 664, 668, -1, 672, -1, 676, 680, -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;
@@ -5911,11 +5983,11 @@
     AOT_GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word AOT_HeapPage_card_table_offset =
     40;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    AOT_ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word AOT_Isolate_class_table_offset =
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
@@ -5944,11 +6016,9 @@
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_arguments_descriptor_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_buckets_offset = 8;
+    AOT_MegamorphicCache_buckets_offset = 24;
 static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
-    16;
+    32;
 static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_argc_tag_offset = 8;
@@ -5959,11 +6029,11 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 232;
+    AOT_ObjectStore_double_type_offset = 240;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
     120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 280;
+    AOT_ObjectStore_string_type_offset = 296;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -5987,79 +6057,91 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 656;
+    AOT_Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1344;
+    AOT_Thread_active_exception_offset = 1376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1352;
+    AOT_Thread_active_stacktrace_offset = 1384;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 440;
+    AOT_Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     224;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 448;
+    AOT_Thread_call_to_runtime_entry_point_offset = 512;
 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 =
-    1416;
+    1448;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    536;
+    592;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
-    360;
+    424;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 544;
+    AOT_Thread_deoptimize_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_stub_offset = 368;
+    AOT_Thread_deoptimize_stub_offset = 432;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 616;
+    AOT_Thread_double_abs_address_offset = 672;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 608;
+    AOT_Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_enter_safepoint_stub_offset = 408;
+    AOT_Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1384;
+    AOT_Thread_execution_state_offset = 1416;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_safepoint_stub_offset = 416;
+    AOT_Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 424;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 552;
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 640;
+    AOT_Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 632;
+    AOT_Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 624;
+    AOT_Thread_float_not_address_offset = 680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 648;
+    AOT_Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1360;
+    AOT_Thread_global_object_pool_offset = 1392;
 static constexpr dart::compiler::target::word
-    AOT_Thread_interpret_call_entry_point_offset = 584;
+    AOT_Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -6068,49 +6150,45 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_return_stub_offset = 376;
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_throw_stub_offset = 384;
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_specialize_type_test_stub_offset = 400;
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 520;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_entry_offset = 528;
+    AOT_Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_stub_offset = 352;
+    AOT_Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 592;
+    AOT_Thread_predefined_symbols_address_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1368;
+    1400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1376;
+    AOT_Thread_saved_shadow_call_stack_offset = 1408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1392;
+    AOT_Thread_safepoint_state_offset = 1424;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_stub_offset = 392;
+    AOT_Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     72;
 static constexpr dart::compiler::target::word
@@ -6118,13 +6196,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word
     AOT_Thread_store_buffer_block_offset = 160;
 static constexpr dart::compiler::target::word
@@ -6138,11 +6216,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 432;
+    AOT_Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1400;
+    1432;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -6184,8 +6262,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, -1,   -1,   1288, 1296,
-        1304, 1312, 1320, -1,   1328, 1336, -1,   -1};
+        1288, 1296, 1304, 1312, -1,   -1,   1320, 1328,
+        1336, 1344, 1352, -1,   1360, 1368, -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;
@@ -6422,11 +6500,11 @@
     AOT_GrowableObjectArray_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word AOT_HeapPage_card_table_offset =
     40;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 16;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
 static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    AOT_ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 8;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24;
 static constexpr dart::compiler::target::word AOT_Isolate_class_table_offset =
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
@@ -6455,11 +6533,9 @@
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_arguments_descriptor_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_MegamorphicCache_buckets_offset = 8;
+    AOT_MegamorphicCache_buckets_offset = 24;
 static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
-    16;
+    32;
 static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_argc_tag_offset = 8;
@@ -6470,11 +6546,11 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 232;
+    AOT_ObjectStore_double_type_offset = 240;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
     120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 280;
+    AOT_ObjectStore_string_type_offset = 296;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -6498,79 +6574,91 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 656;
+    AOT_Thread_AllocateArray_entry_point_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1416;
+    AOT_Thread_active_exception_offset = 1448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1424;
+    AOT_Thread_active_stacktrace_offset = 1456;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 440;
+    AOT_Thread_array_write_barrier_entry_point_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 488;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 320;
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 496;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 328;
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 368;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 576;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 632;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     224;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 216;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 560;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 448;
+    AOT_Thread_call_to_runtime_entry_point_offset = 512;
 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 =
-    1488;
+    1520;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    536;
+    592;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
-    360;
+    424;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 544;
+    AOT_Thread_deoptimize_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_stub_offset = 368;
+    AOT_Thread_deoptimize_stub_offset = 432;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 616;
+    AOT_Thread_double_abs_address_offset = 672;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 608;
+    AOT_Thread_double_negate_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_enter_safepoint_stub_offset = 408;
+    AOT_Thread_enter_safepoint_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1456;
+    AOT_Thread_execution_state_offset = 1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_safepoint_stub_offset = 416;
+    AOT_Thread_exit_safepoint_stub_offset = 480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 424;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 552;
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 256;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 640;
+    AOT_Thread_float_absolute_address_offset = 696;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 632;
+    AOT_Thread_float_negate_address_offset = 688;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 624;
+    AOT_Thread_float_not_address_offset = 680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 648;
+    AOT_Thread_float_zerow_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1432;
+    AOT_Thread_global_object_pool_offset = 1464;
 static constexpr dart::compiler::target::word
-    AOT_Thread_interpret_call_entry_point_offset = 584;
+    AOT_Thread_interpret_call_entry_point_offset = 640;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_from_bytecode_stub_offset = 272;
 static constexpr dart::compiler::target::word
@@ -6579,49 +6667,45 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_return_stub_offset = 376;
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_deopt_from_throw_stub_offset = 384;
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_lazy_specialize_type_test_stub_offset = 400;
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 464;
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 168;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 520;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_entry_offset = 528;
+    AOT_Thread_switchable_call_miss_entry_offset = 584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_monomorphic_miss_stub_offset = 352;
+    AOT_Thread_switchable_call_miss_stub_offset = 392;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 568;
-static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_with_fpu_regs_entry_point_offset = 464;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_with_fpu_regs_entry_point_offset = 480;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_error_shared_without_fpu_regs_entry_point_offset = 456;
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word
-    AOT_Thread_null_arg_error_shared_without_fpu_regs_entry_point_offset = 472;
-static constexpr dart::compiler::target::word
     AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 320;
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 592;
+    AOT_Thread_predefined_symbols_address_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1440;
+    1472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1448;
+    AOT_Thread_saved_shadow_call_stack_offset = 1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1464;
+    AOT_Thread_safepoint_state_offset = 1496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_stub_offset = 392;
+    AOT_Thread_slow_type_test_stub_offset = 456;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     72;
 static constexpr dart::compiler::target::word
@@ -6629,13 +6713,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 512;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 344;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 384;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 504;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 336;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 376;
 static constexpr dart::compiler::target::word
     AOT_Thread_store_buffer_block_offset = 160;
 static constexpr dart::compiler::target::word
@@ -6649,11 +6733,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 432;
+    AOT_Thread_write_barrier_entry_point_offset = 496;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1472;
+    1504;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -6695,9 +6779,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1256, 1264, 1272, 1280, 1288, 1296, 1304, 1312, 1320, 1328, 1336,
-        1344, 1352, 1360, 1368, -1,   -1,   -1,   -1,   1376, 1384, -1,
-        -1,   1392, 1400, 1408, -1,   -1,   -1,   -1,   -1,   -1};
+        1288, 1296, 1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368,
+        1376, 1384, 1392, 1400, -1,   -1,   -1,   -1,   1408, 1416, -1,
+        -1,   1424, 1432, 1440, -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;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 0ec3d1f..229ff56 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -99,9 +99,9 @@
   FIELD(GrowableObjectArray, length_offset)                                    \
   FIELD(GrowableObjectArray, type_arguments_offset)                            \
   FIELD(HeapPage, card_table_offset)                                           \
+  FIELD(CallSiteData, arguments_descriptor_offset)                             \
   FIELD(ICData, NumArgsTestedMask)                                             \
   FIELD(ICData, NumArgsTestedShift)                                            \
-  FIELD(ICData, arguments_descriptor_offset)                                   \
   FIELD(ICData, entries_offset)                                                \
   PRECOMP_NO_CHECK(FIELD(ICData, owner_offset))                                \
   PRECOMP_NO_CHECK(FIELD(ICData, state_bits_offset))                           \
@@ -121,7 +121,6 @@
   FIELD(LinkedHashMap, used_data_offset)                                       \
   FIELD(MarkingStackBlock, pointers_offset)                                    \
   FIELD(MarkingStackBlock, top_offset)                                         \
-  FIELD(MegamorphicCache, arguments_descriptor_offset)                         \
   FIELD(MegamorphicCache, buckets_offset)                                      \
   FIELD(MegamorphicCache, mask_offset)                                         \
   FIELD(Mint, value_offset)                                                    \
@@ -153,6 +152,12 @@
   FIELD(Thread, allocate_mint_with_fpu_regs_stub_offset)                       \
   FIELD(Thread, allocate_mint_without_fpu_regs_entry_point_offset)             \
   FIELD(Thread, allocate_mint_without_fpu_regs_stub_offset)                    \
+  FIELD(Thread, allocate_object_entry_point_offset)                            \
+  FIELD(Thread, allocate_object_stub_offset)                                   \
+  FIELD(Thread, allocate_object_parameterized_entry_point_offset)              \
+  FIELD(Thread, allocate_object_parameterized_stub_offset)                     \
+  FIELD(Thread, allocate_object_slow_entry_point_offset)                       \
+  FIELD(Thread, allocate_object_slow_stub_offset)                              \
   FIELD(Thread, async_stack_trace_offset)                                      \
   FIELD(Thread, auto_scope_native_wrapper_entry_point_offset)                  \
   FIELD(Thread, bool_false_offset)                                             \
@@ -191,18 +196,16 @@
   FIELD(Thread, lazy_specialize_type_test_stub_offset)                         \
   FIELD(Thread, marking_stack_block_offset)                                    \
   FIELD(Thread, megamorphic_call_checked_entry_offset)                         \
-  FIELD(Thread, monomorphic_miss_entry_offset)                                 \
-  FIELD(Thread, monomorphic_miss_stub_offset)                                  \
+  FIELD(Thread, switchable_call_miss_entry_offset)                             \
+  FIELD(Thread, switchable_call_miss_stub_offset)                              \
   FIELD(Thread, no_scope_native_wrapper_entry_point_offset)                    \
-  FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset)            \
   FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset)                   \
-  FIELD(Thread, null_arg_error_shared_with_fpu_regs_entry_point_offset)        \
   FIELD(Thread, null_arg_error_shared_with_fpu_regs_stub_offset)               \
+  FIELD(Thread, range_error_shared_with_fpu_regs_stub_offset)                  \
                                                                                \
-  FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset)         \
   FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset)                \
-  FIELD(Thread, null_arg_error_shared_without_fpu_regs_entry_point_offset)     \
   FIELD(Thread, null_arg_error_shared_without_fpu_regs_stub_offset)            \
+  FIELD(Thread, range_error_shared_without_fpu_regs_stub_offset)               \
   FIELD(Thread, object_null_offset)                                            \
   FIELD(Thread, predefined_symbols_address_offset)                             \
   FIELD(Thread, resume_pc_offset)                                              \
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 3e6c845..bd3fdc4 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -29,6 +29,57 @@
   __ Ret();
 }
 
+void StubCodeCompiler::GenerateInitInstanceFieldStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ PushObject(NullObject());  // Make room for (unused) result.
+  __ PushRegister(InitInstanceFieldABI::kInstanceReg);
+  __ PushRegister(InitInstanceFieldABI::kFieldReg);
+  __ CallRuntime(kInitInstanceFieldRuntimeEntry, /*argument_count=*/2);
+  __ Drop(3);
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
+void StubCodeCompiler::GenerateThrowStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ PushObject(NullObject());  // Make room for (unused) result.
+  __ PushRegister(ThrowABI::kExceptionReg);
+  __ CallRuntime(kThrowRuntimeEntry, /*argument_count=*/1);
+  __ Breakpoint();
+}
+
+void StubCodeCompiler::GenerateReThrowStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ PushObject(NullObject());  // Make room for (unused) result.
+  __ PushRegister(ReThrowABI::kExceptionReg);
+  __ PushRegister(ReThrowABI::kStackTraceReg);
+  __ CallRuntime(kReThrowRuntimeEntry, /*argument_count=*/2);
+  __ Breakpoint();
+}
+
+void StubCodeCompiler::GenerateAssertBooleanStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ PushObject(NullObject());  // Make room for (unused) result.
+  __ PushRegister(AssertBooleanABI::kObjectReg);
+  __ CallRuntime(kNonBoolTypeErrorRuntimeEntry, /*argument_count=*/1);
+  __ Breakpoint();
+}
+
+void StubCodeCompiler::GenerateInstanceOfStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ PushObject(NullObject());  // Make room for the result.
+  __ PushRegister(TypeTestABI::kInstanceReg);
+  __ PushRegister(TypeTestABI::kDstTypeReg);
+  __ PushRegister(TypeTestABI::kInstantiatorTypeArgumentsReg);
+  __ PushRegister(TypeTestABI::kFunctionTypeArgumentsReg);
+  __ PushRegister(TypeTestABI::kSubtypeTestCacheReg);
+  __ CallRuntime(kInstanceofRuntimeEntry, /*argument_count=*/5);
+  __ Drop(5);
+  __ PopRegister(TypeTestABI::kResultReg);
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index a856c0d..e4a9429 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -8,15 +8,39 @@
 #include "vm/allocation.h"
 #include "vm/compiler/runtime_api.h"
 #include "vm/constants.h"
+#include "vm/growable_array.h"
 #include "vm/stub_code_list.h"
 
 namespace dart {
 
+// Forward declarations.
+class Code;
+
 namespace compiler {
 
 // Forward declarations.
 class Assembler;
 
+// Represents an unresolved PC-relative Call/TailCall.
+class UnresolvedPcRelativeCall : public ZoneAllocated {
+ public:
+  UnresolvedPcRelativeCall(intptr_t offset,
+                           const dart::Code& target,
+                           bool is_tail_call)
+      : offset_(offset), target_(target), is_tail_call_(is_tail_call) {}
+
+  intptr_t offset() const { return offset_; }
+  const dart::Code& target() const { return target_; }
+  bool is_tail_call() const { return is_tail_call_; }
+
+ private:
+  const intptr_t offset_;
+  const dart::Code& target_;
+  const bool is_tail_call_;
+};
+
+using UnresolvedPcRelativeCalls = GrowableArray<UnresolvedPcRelativeCall*>;
+
 class StubCodeCompiler : public AllStatic {
  public:
 #if !defined(TARGET_ARCH_IA32)
@@ -27,14 +51,22 @@
 #endif
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  static RawArray* BuildStaticCallsTable(
+      Zone* zone,
+      compiler::UnresolvedPcRelativeCalls* unresolved_calls);
+
 #define STUB_CODE_GENERATE(name)                                               \
   static void Generate##name##Stub(Assembler* assembler);
   VM_STUB_CODE_LIST(STUB_CODE_GENERATE)
 #undef STUB_CODE_GENERATE
 
-  static void GenerateMegamorphicMissStub(Assembler* assembler);
-  static void GenerateAllocationStubForClass(Assembler* assembler,
-                                             const Class& cls);
+  static void GenerateMegamorphicCallMissStub(Assembler* assembler);
+  static void GenerateAllocationStubForClass(
+      Assembler* assembler,
+      UnresolvedPcRelativeCalls* unresolved_calls,
+      const Class& cls,
+      const dart::Code& allocate_object,
+      const dart::Code& allocat_object_parametrized);
 
   enum Optimized {
     kUnoptimized,
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 490f4c1..1e817e7 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -156,12 +156,14 @@
   __ Ret();
 }
 
-void GenerateSharedStub(Assembler* assembler,
-                        bool save_fpu_registers,
-                        const RuntimeEntry* target,
-                        intptr_t self_code_stub_offset_from_thread,
-                        bool allow_return,
-                        bool store_runtime_result_in_r0 = false) {
+void GenerateSharedStub(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    const RuntimeEntry* target,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return,
+    bool store_runtime_result_in_r0 = false,
+    std::initializer_list<Register> runtime_call_arguments = {}) {
   // If the target CPU does not support VFP the caller should always use the
   // non-FPU stub.
   if (save_fpu_registers && !TargetCPUFeatures::vfp_supported()) {
@@ -190,16 +192,19 @@
     __ Push(LR);
   }
 
-  __ CallRuntime(*target, /*argument_count=*/0);
-
-  if (store_runtime_result_in_r0) {
-    __ Pop(R0);
+  for (Register argument_reg : runtime_call_arguments) {
+    __ PushRegister(argument_reg);
   }
-
+  __ CallRuntime(*target, /*argument_count=*/runtime_call_arguments.size());
   if (!allow_return) {
     __ Breakpoint();
     return;
   }
+
+  __ Drop(runtime_call_arguments.size());
+  if (store_runtime_result_in_r0) {
+    __ Pop(R0);
+  }
   __ LeaveStubFrame();
   if (store_runtime_result_in_r0) {
     // Stores the runtime result in stack where R0 was pushed ( R0 is the very
@@ -483,7 +488,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
@@ -491,7 +496,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithoutFPURegsStub(
@@ -499,7 +504,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithFPURegsStub(
@@ -507,7 +512,27 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
+}
+
+void StubCodeCompiler::GenerateRangeErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/false, &kRangeErrorRuntimeEntry,
+      target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false,
+      /*store_runtime_result_in_r0=*/false,
+      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+}
+
+void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kRangeErrorRuntimeEntry,
+      target::Thread::range_error_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/false,
+      /*store_runtime_result_in_r0=*/false,
+      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
@@ -515,7 +540,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/true);
+      /*allow_return=*/true, {});
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
@@ -523,7 +548,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/true);
+      /*allow_return=*/true, {});
 }
 
 // Input parameters:
@@ -964,14 +989,13 @@
   __ Ret();
 }
 
-static void GenerateDispatcherCode(Assembler* assembler,
-                                   Label* call_target_function) {
-  __ Comment("NoSuchMethodDispatch");
-  // When lazily generated invocation dispatchers are disabled, the
-  // miss-handler may return null.
-  __ CompareObject(R0, NullObject());
-  __ b(call_target_function, NE);
+// R9: ICData/MegamorphicCache
+static void GenerateNoSuchMethodDispatcherBody(Assembler* assembler) {
   __ EnterStubFrame();
+
+  __ ldr(R4,
+         FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
+
   // Load the receiver.
   __ ldr(R2, FieldAddress(R4, target::ArgumentsDescriptor::size_offset()));
   __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
@@ -1000,43 +1024,23 @@
   __ Ret();
 }
 
-void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
-  __ EnterStubFrame();
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  __ CompareObject(R0, NullObject());
+  __ b(call_target_function, NE);
 
-  // Load the receiver.
-  __ ldr(R2, FieldAddress(R4, target::ArgumentsDescriptor::size_offset()));
-  __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
-  __ ldr(R8, Address(IP, target::frame_layout.param_end_from_fp *
-                             target::kWordSize));
+  GenerateNoSuchMethodDispatcherBody(assembler);
+}
 
-  // Preserve IC data and arguments descriptor.
-  __ PushList((1 << R4) | (1 << R9));
-
-  __ LoadImmediate(IP, 0);
-  __ Push(IP);  // result slot
-  __ Push(R8);  // receiver
-  __ Push(R9);  // ICData
-  __ Push(R4);  // arguments descriptor
-  __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
-  // Remove arguments.
-  __ Drop(3);
-  __ Pop(R0);  // Get result into R0 (target function).
-
-  // Restore IC data and arguments descriptor.
-  __ PopList((1 << R4) | (1 << R9));
-
-  __ RestoreCodePointer();
-  __ LeaveStubFrame();
-
-  if (!FLAG_lazy_dispatchers) {
-    Label call_target_function;
-    GenerateDispatcherCode(assembler, &call_target_function);
-    __ Bind(&call_target_function);
-  }
-
-  // Tail-call to target function.
-  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
-  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
+// Input:
+//   R4 - arguments descriptor
+//   R9 - icdata/megamorphic_cache
+void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
+    Assembler* assembler) {
+  GenerateNoSuchMethodDispatcherBody(assembler);
 }
 
 // Called for inline allocation of arrays.
@@ -1169,7 +1173,7 @@
 }
 
 // Called for allocation of Mint.
-void StubCodeCompiler::GenerateAllocateMintWithFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithFPURegsStub(
     Assembler* assembler) {
   // For test purpose call allocation stub without inline allocation attempt.
   if (!FLAG_use_slow_path) {
@@ -1184,11 +1188,11 @@
                      &kAllocateMintRuntimeEntry,
                      target::Thread::allocate_mint_with_fpu_regs_stub_offset(),
                      /*allow_return=*/true,
-                     /*store_runtime_result_in_r0=*/true);
+                     /*store_runtime_result_in_r0=*/true, {});
 }
 
 // Called for allocation of Mint.
-void StubCodeCompiler::GenerateAllocateMintWithoutFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub(
     Assembler* assembler) {
   // For test purpose call allocation stub without inline allocation attempt.
   if (!FLAG_use_slow_path) {
@@ -1203,7 +1207,7 @@
       assembler, /*save_fpu_registers=*/false, &kAllocateMintRuntimeEntry,
       target::Thread::allocate_mint_without_fpu_regs_stub_offset(),
       /*allow_return=*/true,
-      /*store_runtime_result_in_r0=*/true);
+      /*store_runtime_result_in_r0=*/true, {});
 }
 
 // Called when invoking Dart code from C++ (VM code).
@@ -1883,109 +1887,224 @@
       Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
+static void GenerateAllocateObjectHelper(Assembler* assembler,
+                                         bool is_cls_parameterized) {
+  const Register kInstanceReg = R0;
+  // R1
+  const Register kTagsReg = R2;
+  // kAllocationStubTypeArgumentsReg = R3
+
+  {
+    Label slow_case;
+
+    const Register kNewTopReg = R8;
+
+    // Bump allocation.
+    {
+      const Register kEndReg = R1;
+      const Register kInstanceSizeReg = R9;
+
+      __ ExtractInstanceSizeFromTags(kInstanceSizeReg, kTagsReg);
+
+      // Load two words from Thread::top: top and end.
+      // kInstanceReg: potential next object start.
+      __ ldrd(kInstanceReg, kEndReg, THR, target::Thread::top_offset());
+
+      __ add(kNewTopReg, kInstanceReg, Operand(kInstanceSizeReg));
+
+      __ CompareRegisters(kEndReg, kNewTopReg);
+      __ b(&slow_case, UNSIGNED_LESS_EQUAL);
+
+      // Successfully allocated the object, now update top to point to
+      // next object start and store the class in the class field of object.
+      __ str(kNewTopReg, Address(THR, target::Thread::top_offset()));
+    }  //  kEndReg = R1, kInstanceSizeReg = R9
+
+    // Tags.
+    __ str(kTagsReg, Address(kInstanceReg, target::Object::tags_offset()));
+
+    // Initialize the remaining words of the object.
+    {
+      const Register kFieldReg = R1;
+      const Register kNullReg = R9;
+
+      __ LoadObject(kNullReg, NullObject());
+
+      __ AddImmediate(kFieldReg, kInstanceReg,
+                      target::Instance::first_field_offset());
+      Label done, init_loop;
+      __ Bind(&init_loop);
+      __ CompareRegisters(kFieldReg, kNewTopReg);
+      __ b(&done, UNSIGNED_GREATER_EQUAL);
+      __ str(kNullReg,
+             Address(kFieldReg, target::kWordSize, Address::PostIndex));
+      __ b(&init_loop);
+
+      __ Bind(&done);
+    }  // kFieldReg = R1, kNullReg = R9
+
+    // Store parameterized type.
+    if (is_cls_parameterized) {
+      Label not_parameterized_case;
+
+      const Register kClsIdReg = R2;
+      const Register kTypeOffestReg = R9;
+
+      __ ExtractClassIdFromTags(kClsIdReg, kTagsReg);
+
+      // Load class' type_arguments_field offset in words.
+      __ LoadClassById(kTypeOffestReg, kClsIdReg);
+      __ ldr(
+          kTypeOffestReg,
+          FieldAddress(kTypeOffestReg,
+                       target::Class::
+                           host_type_arguments_field_offset_in_words_offset()));
+
+      // Set the type arguments in the new object.
+      __ StoreIntoObjectNoBarrier(
+          kInstanceReg,
+          Address(kInstanceReg, kTypeOffestReg, LSL, target::kWordSizeLog2),
+          kAllocationStubTypeArgumentsReg);
+
+      __ Bind(&not_parameterized_case);
+    }  // kClsIdReg = R1, kTypeOffestReg = R9
+
+    __ AddImmediate(kInstanceReg, kInstanceReg, kHeapObjectTag);
+
+    __ Ret();
+
+    __ Bind(&slow_case);
+  }  // kNewTopReg = R8
+
+  // Fall back on slow case:
+  {
+    const Register kStubReg = R8;
+
+    if (!is_cls_parameterized) {
+      __ LoadObject(kAllocationStubTypeArgumentsReg, NullObject());
+    }
+
+    // Tail call to generic allocation stub.
+    __ ldr(kStubReg,
+           Address(THR,
+                   target::Thread::allocate_object_slow_entry_point_offset()));
+    __ bx(kStubReg);
+  }  // kStubReg = R8
+}
+
+// Called for inline allocation of objects (any class).
+void StubCodeCompiler::GenerateAllocateObjectStub(Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/false);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectParameterizedStub(
+    Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/true);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectSlowStub(Assembler* assembler) {
+  const Register kInstanceReg = R0;
+  const Register kClsReg = R1;
+  const Register kTagsReg = R2;
+  // kAllocationStubTypeArgumentsReg = R3
+
+  if (!FLAG_use_bare_instructions) {
+    __ ldr(CODE_REG,
+           Address(THR, target::Thread::call_to_runtime_stub_offset()));
+  }
+
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
+  __ EnterStubFrame();
+
+  __ ExtractClassIdFromTags(kInstanceReg, kTagsReg);
+  __ LoadClassById(kClsReg, kInstanceReg);
+
+  __ LoadObject(kInstanceReg, NullObject());
+
+  // Pushes result slot, then parameter class.
+  __ PushRegisterPair(kClsReg, kInstanceReg);
+
+  // Should be Object::null() if class is non-parameterized.
+  __ Push(kAllocationStubTypeArgumentsReg);
+
+  __ CallRuntime(kAllocateObjectRuntimeEntry, 2);
+
+  // Load result off the stack into result register.
+  __ ldr(kInstanceReg, Address(SP, 2 * target::kWordSize));
+
+  // Write-barrier elimination is enabled for [cls] and we therefore need to
+  // ensure that the object is in new-space or has remembered bit set.
+  EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
+
+  __ LeaveDartFrameAndReturn();
+}
+
 // Called for inline allocation of objects.
-// Input parameters:
-//   LR : return address.
-//   kAllocationStubTypeArgumentsReg (R3): type arguments object
-//                                         (only if class is parameterized).
-void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
-                                                      const Class& cls) {
+void StubCodeCompiler::GenerateAllocationStubForClass(
+    Assembler* assembler,
+    UnresolvedPcRelativeCalls* unresolved_calls,
+    const Class& cls,
+    const Code& allocate_object,
+    const Code& allocat_object_parametrized) {
+  classid_t cls_id = target::Class::GetId(cls);
+  ASSERT(cls_id != kIllegalCid);
+
+  RELEASE_ASSERT(AllocateObjectInstr::WillAllocateNewOrRemembered(cls));
+
   // The generated code is different if the class is parameterized.
   const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
   ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
                                       cls) != target::Class::kNoTypeArguments);
 
-  const Register kNullReg = R8;
-  const Register kOtherNullReg = R9;
-  const Register kTypeArgumentsReg = kAllocationStubTypeArgumentsReg;
-  const Register kInstanceReg = R0;
-  const Register kEndReg = R1;
-  const Register kEndOfInstanceReg = R2;
-  static_assert(kAllocationStubTypeArgumentsReg == R3,
-                "Adjust register allocation in the AllocationStub");
-
-  // kInlineInstanceSize is a constant used as a threshold for determining
-  // when the object initialization should be done as a loop or as
-  // straight line code.
-  const int kInlineInstanceSize = 12;
   const intptr_t instance_size = target::Class::GetInstanceSize(cls);
   ASSERT(instance_size > 0);
-  ASSERT(instance_size % target::ObjectAlignment::kObjectAlignment == 0);
+  RELEASE_ASSERT(target::Heap::IsAllocatableInNewSpace(instance_size));
 
-  __ LoadObject(kNullReg, NullObject());
+  const uint32_t tags =
+      target::MakeTagWordForNewSpaceObject(cls_id, instance_size);
+
+  // Note: Keep in sync with helper function.
+  // kInstanceReg = R0
+  const Register kTagsReg = R2;
+  // kAllocationStubTypeArgumentsReg = R3
+
+  __ LoadImmediate(kTagsReg, tags);
+
   if (!FLAG_use_slow_path && FLAG_inline_alloc &&
-      target::Heap::IsAllocatableInNewSpace(instance_size) &&
-      !target::Class::TraceAllocation(cls)) {
-    Label slow_case;
-
-    // Allocate the object and update top to point to
-    // next object start and initialize the allocated object.
-
-    RELEASE_ASSERT((target::Thread::top_offset() + target::kWordSize) ==
-                   target::Thread::end_offset());
-    __ ldrd(kInstanceReg, kEndReg, THR, target::Thread::top_offset());
-    __ AddImmediate(kEndOfInstanceReg, kInstanceReg, instance_size);
-    __ cmp(kEndOfInstanceReg, Operand(kEndReg));
-    __ b(&slow_case, CS);  // Unsigned higher or equal.
-
-    __ str(kEndOfInstanceReg, Address(THR, target::Thread::top_offset()));
-
-    // Set the tags.
-    ASSERT(target::Class::GetId(cls) != kIllegalCid);
-    const uint32_t tags = target::MakeTagWordForNewSpaceObject(
-        target::Class::GetId(cls), instance_size);
-
-    __ LoadImmediate(R1, tags);
-    __ str(R1, Address(kInstanceReg, target::Object::tags_offset()));
-    __ add(kInstanceReg, kInstanceReg, Operand(kHeapObjectTag));
-
-    // First try inlining the initialization without a loop.
-    if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
-      intptr_t begin_offset =
-          target::Instance::first_field_offset() - kHeapObjectTag;
-      intptr_t end_offset = instance_size - kHeapObjectTag;
-      if ((end_offset - begin_offset) >= (2 * target::kWordSize)) {
-        __ mov(kOtherNullReg, Operand(kNullReg));
-      }
-      __ InitializeFieldsNoBarrierUnrolled(kInstanceReg, kInstanceReg,
-                                           begin_offset, end_offset, kNullReg,
-                                           kOtherNullReg);
-    } else {
-      __ add(R1, kInstanceReg,
-             Operand(target::Instance::first_field_offset() - kHeapObjectTag));
-      __ mov(kOtherNullReg, Operand(kNullReg));
-      __ InitializeFieldsNoBarrier(kInstanceReg, R1, kEndOfInstanceReg,
-                                   kNullReg, kOtherNullReg);
-    }
+      !target::Class::TraceAllocation(cls) &&
+      target::SizeFitsInSizeTag(instance_size)) {
     if (is_cls_parameterized) {
-      const intptr_t offset = target::Class::TypeArgumentsFieldOffset(cls);
-      __ StoreIntoObjectNoBarrier(
-          kInstanceReg, FieldAddress(kInstanceReg, offset), kTypeArgumentsReg);
+      if (!IsSameObject(NullObject(),
+                        CastHandle<Object>(allocat_object_parametrized))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocat_object_parametrized, /*is_tail_call=*/true));
+      } else {
+        __ ldr(PC,
+               Address(THR,
+                       target::Thread::
+                           allocate_object_parameterized_entry_point_offset()));
+      }
+    } else {
+      if (!IsSameObject(NullObject(), CastHandle<Object>(allocate_object))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocate_object, /*is_tail_call=*/true));
+      } else {
+        __ ldr(
+            PC,
+            Address(THR, target::Thread::allocate_object_entry_point_offset()));
+      }
     }
-
-    __ Ret();
-    __ Bind(&slow_case);
+  } else {
+    if (!is_cls_parameterized) {
+      __ LoadObject(kAllocationStubTypeArgumentsReg, NullObject());
+    }
+    __ ldr(PC,
+           Address(THR,
+                   target::Thread::allocate_object_slow_entry_point_offset()));
   }
-  // Create a stub frame as we are pushing some objects on the stack before
-  // calling into the runtime.
-  __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
-  __ LoadObject(R1, CastHandle<Object>(cls));
-  __ PushList(1 << kNullReg | 1 << R1);  // Pushes cls, result slot.
-  __ Push(is_cls_parameterized ? kTypeArgumentsReg : kNullReg);
-  __ CallRuntime(kAllocateObjectRuntimeEntry, 2);  // Allocate object.
-  __ ldr(
-      kInstanceReg,
-      Address(SP,
-              2 * target::kWordSize));  // Pop result (newly allocated object).
-
-  ASSERT(kInstanceReg == R0);
-  if (AllocateObjectInstr::WillAllocateNewOrRemembered(cls)) {
-    // Write-barrier elimination is enabled for [cls] and we therefore need to
-    // ensure that the object is in new-space or has remembered bit set.
-    EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
-  }
-
-  __ LeaveDartFrameAndReturn();  // Restores correct SP.
 }
 
 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
@@ -2226,7 +2345,8 @@
 
   if (type == kInstanceCall) {
     __ LoadTaggedClassIdMayBeSmi(R0, R0);
-    __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
+    __ ldr(R4, FieldAddress(
+                   R9, target::CallSiteData::arguments_descriptor_offset()));
     if (num_args == 2) {
       __ ldr(R1, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
       __ sub(R1, R1, Operand(target::ToRawSmi(2)));
@@ -2235,7 +2355,8 @@
     }
   } else {
     // Load arguments descriptor into R4.
-    __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
+    __ ldr(R4, FieldAddress(
+                   R9, target::CallSiteData::arguments_descriptor_offset()));
 
     // Get the receiver's class ID (first read number of arguments from
     // arguments descriptor array and then access the receiver from the stack).
@@ -2527,7 +2648,8 @@
   }
 
   // Load arguments descriptor into R4.
-  __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
+  __ ldr(R4,
+         FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
 
   // Get function and call it, if possible.
   __ LoadFromOffset(kWord, R0, R8, target_offset);
@@ -2580,7 +2702,7 @@
   __ LeaveStubFrame();
 
   // When using the interpreter, the function's code may now point to the
-  // InterpretCall stub. Make sure R0, R4, and R9 are preserved.
+  // InterpretCall stub. Make sure R0, R4 and R9 are preserved.
   __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
   __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 }
@@ -3315,8 +3437,9 @@
 //  R0: receiver
 //  R9: MegamorphicCache (preserved)
 // Passed to target:
-//  CODE_REG: target Code
+//  R0: function
 //  R4: arguments descriptor
+//  CODE_REG: target Code
 void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
   __ LoadTaggedClassIdMayBeSmi(R0, R0);
   // R0: receiver cid as Smi.
@@ -3327,7 +3450,7 @@
 
   // Compute the table index.
   ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
-  // Use reverse substract to multiply with 7 == 8 - 1.
+  // Use reverse subtract to multiply with 7 == 8 - 1.
   __ rsb(R3, R0, Operand(R0, LSL, 3));
   // R3: probe.
   Label loop;
@@ -3350,16 +3473,16 @@
   // be invoked as a normal Dart function.
   const auto target_address = FieldAddress(IP, base + target::kWordSize);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(ARGS_DESC_REG,
-           FieldAddress(
-               R9, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ ldr(
+        ARGS_DESC_REG,
+        FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
     __ Branch(target_address);
   } else {
     __ ldr(R0, target_address);
     __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
-    __ ldr(ARGS_DESC_REG,
-           FieldAddress(
-               R9, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ ldr(
+        ARGS_DESC_REG,
+        FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
     __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
   }
 
@@ -3377,7 +3500,8 @@
 void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
   Label loop, found, miss;
   __ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
-  __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
+  __ ldr(R4,
+         FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
   __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
   // R8: first IC entry
   __ LoadTaggedClassIdMayBeSmi(R1, R0);
@@ -3437,7 +3561,7 @@
         R2, R3, R9,
         target::MonomorphicSmiableCall::expected_cid_offset() - kHeapObjectTag);
     __ cmp(R2, Operand(IP));
-    __ Branch(Address(THR, target::Thread::monomorphic_miss_entry_offset()),
+    __ Branch(Address(THR, target::Thread::switchable_call_miss_entry_offset()),
               NE);
     __ bx(R3);
   } else {
@@ -3446,35 +3570,56 @@
             target::MonomorphicSmiableCall::target_offset() - kHeapObjectTag);
     __ mov(CODE_REG, Operand(R2));
     __ cmp(R3, Operand(IP));
-    __ Branch(Address(THR, target::Thread::monomorphic_miss_entry_offset()),
+    __ Branch(Address(THR, target::Thread::switchable_call_miss_entry_offset()),
               NE);
     __ LoadField(IP, FieldAddress(R2, target::Code::entry_point_offset()));
     __ bx(IP);
   }
 }
 
-// Called from switchable IC calls.
-//  R0: receiver
-//  R9: UnlinkedCall
-void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
-  __ EnterStubFrame();
-  __ Push(R0);  // Preserve receiver.
-
+static void CallSwitchableCallMissRuntimeEntry(Assembler* assembler,
+                                               Register receiver_reg) {
   __ LoadImmediate(IP, 0);
   __ Push(IP);  // Result slot
   __ Push(IP);  // Arg0: stub out
-  __ Push(R0);  // Arg1: Receiver
-  __ Push(R9);  // Arg2: UnlinkedCall
-  __ CallRuntime(kUnlinkedCallRuntimeEntry, 3);
-  __ Drop(2);
+  __ Push(receiver_reg);  // Arg1: Receiver
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
+  __ Pop(R0);        // Get the receiver
   __ Pop(CODE_REG);  // result = stub
   __ Pop(R9);        // result = IC
+}
 
-  __ Pop(R0);  // Restore receiver.
+// Called from switchable IC calls.
+//  R0: receiver
+void StubCodeCompiler::GenerateSwitchableCallMissStub(Assembler* assembler) {
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::switchable_call_miss_stub_offset()));
+  __ EnterStubFrame();
+  CallSwitchableCallMissRuntimeEntry(assembler, /*receiver_reg=*/R0);
   __ LeaveStubFrame();
 
   __ Branch(FieldAddress(
-      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kMonomorphic)));
+      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kNormal)));
+}
+
+// Called from megamorphic call sites and from megamorphic miss handlers.
+//  R9: ICData/MegamorphicCache
+void StubCodeCompiler::GenerateMegamorphicCallMissStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  // Load argument descriptor from ICData/MegamorphicCache.
+  __ ldr(R4,
+         FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
+
+  // Load the receiver.
+  __ ldr(R2, FieldAddress(R4, target::ArgumentsDescriptor::size_offset()));
+  __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
+  __ ldr(R8, Address(IP, target::frame_layout.param_end_from_fp *
+                             target::kWordSize));
+  CallSwitchableCallMissRuntimeEntry(assembler, /*receiver_reg=*/R8);
+  __ LeaveStubFrame();
+
+  __ Branch(FieldAddress(
+      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kNormal)));
 }
 
 // Called from switchable IC calls.
@@ -3501,42 +3646,7 @@
 
   __ Bind(&miss);
   __ EnterStubFrame();
-  __ Push(R0);  // Preserve receiver.
-
-  __ LoadImmediate(IP, 0);
-  __ Push(IP);  // Result slot
-  __ Push(IP);  // Arg0: stub out
-  __ Push(R0);  // Arg1: Receiver
-  __ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
-  __ Drop(1);
-  __ Pop(CODE_REG);  // result = stub
-  __ Pop(R9);        // result = IC
-
-  __ Pop(R0);  // Restore receiver.
-  __ LeaveStubFrame();
-
-  __ Branch(FieldAddress(
-      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kMonomorphic)));
-}
-
-// Called from the monomorphic checked entry.
-//  R0: receiver
-void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
-  __ ldr(CODE_REG,
-         Address(THR, target::Thread::monomorphic_miss_stub_offset()));
-  __ EnterStubFrame();
-  __ Push(R0);  // Preserve receiver.
-
-  __ LoadImmediate(IP, 0);
-  __ Push(IP);  // Result slot
-  __ Push(IP);  // Arg0: stub out
-  __ Push(R0);  // Arg1: Receiver
-  __ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
-  __ Drop(1);
-  __ Pop(CODE_REG);  // result = stub
-  __ Pop(R9);        // result = IC
-
-  __ Pop(R0);  // Restore receiver.
+  CallSwitchableCallMissRuntimeEntry(assembler, /*receiver_reg=*/R0);
   __ LeaveStubFrame();
 
   __ Branch(FieldAddress(
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index a477f9e..0730c37 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -175,12 +175,14 @@
   __ ret();
 }
 
-void GenerateSharedStub(Assembler* assembler,
-                        bool save_fpu_registers,
-                        const RuntimeEntry* target,
-                        intptr_t self_code_stub_offset_from_thread,
-                        bool allow_return,
-                        bool store_runtime_result_in_r0 = false) {
+void GenerateSharedStub(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    const RuntimeEntry* target,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return,
+    bool store_runtime_result_in_r0 = false,
+    std::initializer_list<Register> runtime_call_arguments = {}) {
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   RegisterSet all_registers;
@@ -199,15 +201,19 @@
     // Push an even value so it will not be seen as a pointer
     __ Push(LR);
   }
-  __ CallRuntime(*target, /*argument_count=*/0);
-
-  if (store_runtime_result_in_r0) {
-    __ Pop(R0);
+  for (Register argument_reg : runtime_call_arguments) {
+    __ PushRegister(argument_reg);
   }
+  __ CallRuntime(*target, /*argument_count=*/runtime_call_arguments.size());
   if (!allow_return) {
     __ Breakpoint();
     return;
   }
+
+  __ Drop(runtime_call_arguments.size());
+  if (store_runtime_result_in_r0) {
+    __ Pop(R0);
+  }
   __ LeaveStubFrame();
   if (store_runtime_result_in_r0) {
     // Stores the runtime result in stack where R0 was pushed ( R0 is the very
@@ -533,7 +539,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
@@ -541,7 +547,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithoutFPURegsStub(
@@ -549,7 +555,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithFPURegsStub(
@@ -557,7 +563,27 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
+}
+
+void StubCodeCompiler::GenerateRangeErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/false, &kRangeErrorRuntimeEntry,
+      target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false,
+      /*store_runtime_result_in_r0=*/false,
+      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+}
+
+void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kRangeErrorRuntimeEntry,
+      target::Thread::range_error_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/false,
+      /*store_runtime_result_in_r0=*/false,
+      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
@@ -565,7 +591,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/true);
+      /*allow_return=*/true, {});
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
@@ -573,7 +599,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/true);
+      /*allow_return=*/true, {});
 }
 
 void StubCodeCompiler::GeneratePrintStopMessageStub(Assembler* assembler) {
@@ -1027,15 +1053,13 @@
   __ ret();
 }
 
-static void GenerateDispatcherCode(Assembler* assembler,
-                                   Label* call_target_function) {
-  __ Comment("NoSuchMethodDispatch");
-  // When lazily generated invocation dispatchers are disabled, the
-  // miss-handler may return null.
-  __ CompareObject(R0, NullObject());
-  __ b(call_target_function, NE);
+// R5: ICData/MegamorphicCache
+static void GenerateNoSuchMethodDispatcherBody(Assembler* assembler) {
   __ EnterStubFrame();
 
+  __ ldr(R4,
+         FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
+
   // Load the receiver.
   __ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::size_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
@@ -1063,49 +1087,23 @@
   __ ret();
 }
 
-void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
-  __ EnterStubFrame();
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  __ CompareObject(R0, NullObject());
+  __ b(call_target_function, NE);
 
-  // Load the receiver.
-  __ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::size_offset());
-  __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
-  __ LoadFromOffset(R6, TMP,
-                    target::frame_layout.param_end_from_fp * target::kWordSize);
+  GenerateNoSuchMethodDispatcherBody(assembler);
+}
 
-  // Preserve IC data and arguments descriptor.
-  __ Push(R5);
-  __ Push(R4);
-
-  // Push space for the return value.
-  // Push the receiver.
-  // Push IC data object.
-  // Push arguments descriptor array.
-  __ Push(ZR);
-  __ Push(R6);
-  __ Push(R5);
-  __ Push(R4);
-  __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
-  // Remove arguments.
-  __ Drop(3);
-  __ Pop(R0);  // Get result into R0 (target function).
-
-  // Restore IC data and arguments descriptor.
-  __ Pop(R4);
-  __ Pop(R5);
-
-  __ RestoreCodePointer();
-  __ LeaveStubFrame();
-
-  if (!FLAG_lazy_dispatchers) {
-    Label call_target_function;
-    GenerateDispatcherCode(assembler, &call_target_function);
-    __ Bind(&call_target_function);
-  }
-
-  // Tail-call to target function.
-  __ LoadFieldFromOffset(CODE_REG, R0, target::Function::code_offset());
-  __ LoadFieldFromOffset(R2, R0, target::Function::entry_point_offset());
-  __ br(R2);
+// Input:
+//   R4 - arguments descriptor
+//   R5 - icdata/megamorphic_cache
+void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
+    Assembler* assembler) {
+  GenerateNoSuchMethodDispatcherBody(assembler);
 }
 
 // Called for inline allocation of arrays.
@@ -1257,7 +1255,7 @@
   __ ret();
 }
 
-void StubCodeCompiler::GenerateAllocateMintWithFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithFPURegsStub(
     Assembler* assembler) {
   // For test purpose call allocation stub without inline allocation attempt.
   if (!FLAG_use_slow_path) {
@@ -1272,10 +1270,10 @@
                      &kAllocateMintRuntimeEntry,
                      target::Thread::allocate_mint_with_fpu_regs_stub_offset(),
                      /*allow_return=*/true,
-                     /*store_runtime_result_in_r0=*/true);
+                     /*store_runtime_result_in_r0=*/true, {});
 }
 
-void StubCodeCompiler::GenerateAllocateMintWithoutFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub(
     Assembler* assembler) {
   // For test purpose call allocation stub without inline allocation attempt.
   if (!FLAG_use_slow_path) {
@@ -1290,7 +1288,7 @@
       assembler, /*save_fpu_registers=*/false, &kAllocateMintRuntimeEntry,
       target::Thread::allocate_mint_without_fpu_regs_stub_offset(),
       /*allow_return=*/true,
-      /*store_runtime_result_in_r0=*/true);
+      /*store_runtime_result_in_r0=*/true, {});
 }
 
 // Called when invoking Dart code from C++ (VM code).
@@ -1996,98 +1994,220 @@
       Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
+static void GenerateAllocateObjectHelper(Assembler* assembler,
+                                         bool is_cls_parameterized) {
+  const Register kInstanceReg = R0;
+  // kAllocationStubTypeArgumentsReg = R1
+  const Register kTagsReg = R2;
+
+  {
+    Label slow_case;
+
+    const Register kNewTopReg = R3;
+
+    // Bump allocation.
+    {
+      const Register kInstanceSizeReg = R4;
+      const Register kEndReg = R5;
+
+      __ ExtractInstanceSizeFromTags(kInstanceSizeReg, kTagsReg);
+
+      // Load two words from Thread::top: top and end.
+      // kInstanceReg: potential next object start.
+      __ ldp(kInstanceReg, kEndReg,
+             Address(THR, target::Thread::top_offset(), Address::PairOffset));
+
+      __ add(kNewTopReg, kInstanceReg, Operand(kInstanceSizeReg));
+
+      __ CompareRegisters(kEndReg, kNewTopReg);
+      __ b(&slow_case, UNSIGNED_LESS_EQUAL);
+
+      // Successfully allocated the object, now update top to point to
+      // next object start and store the class in the class field of object.
+      __ str(kNewTopReg, Address(THR, target::Thread::top_offset()));
+    }  // kInstanceSizeReg = R4, kEndReg = R5
+
+    // Tags.
+    __ str(kTagsReg, Address(kInstanceReg, target::Object::tags_offset()));
+
+    // Initialize the remaining words of the object.
+    {
+      const Register kFieldReg = R4;
+
+      __ AddImmediate(kFieldReg, kInstanceReg,
+                      target::Instance::first_field_offset());
+      Label done, init_loop;
+      __ Bind(&init_loop);
+      __ CompareRegisters(kFieldReg, kNewTopReg);
+      __ b(&done, UNSIGNED_GREATER_EQUAL);
+      __ str(NULL_REG,
+             Address(kFieldReg, target::kWordSize, Address::PostIndex));
+      __ b(&init_loop);
+
+      __ Bind(&done);
+    }  // kFieldReg = R4
+
+    if (is_cls_parameterized) {
+      Label not_parameterized_case;
+
+      const Register kClsIdReg = R4;
+      const Register kTypeOffestReg = R5;
+
+      __ ExtractClassIdFromTags(kClsIdReg, kTagsReg);
+
+      // Load class' type_arguments_field offset in words.
+      __ LoadClassById(kTypeOffestReg, kClsIdReg);
+      __ ldr(
+          kTypeOffestReg,
+          FieldAddress(kTypeOffestReg,
+                       target::Class::
+                           host_type_arguments_field_offset_in_words_offset()),
+          kWord);
+
+      // Set the type arguments in the new object.
+      __ StoreIntoObjectNoBarrier(
+          kInstanceReg,
+          Address(kInstanceReg, kTypeOffestReg, UXTX, Address::Scaled),
+          kAllocationStubTypeArgumentsReg);
+
+      __ Bind(&not_parameterized_case);
+    }  // kClsIdReg = R4, kTypeOffestReg = R5
+
+    __ AddImmediate(kInstanceReg, kInstanceReg, kHeapObjectTag);
+
+    __ ret();
+
+    __ Bind(&slow_case);
+  }  // kNewTopReg = R3
+
+  // Fall back on slow case:
+  if (!is_cls_parameterized) {
+    __ mov(kAllocationStubTypeArgumentsReg, NULL_REG);
+  }
+  // Tail call to generic allocation stub.
+  __ ldr(
+      R3,
+      Address(THR, target::Thread::allocate_object_slow_entry_point_offset()));
+  __ br(R3);
+}
+
+// Called for inline allocation of objects (any class).
+void StubCodeCompiler::GenerateAllocateObjectStub(Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/false);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectParameterizedStub(
+    Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/true);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectSlowStub(Assembler* assembler) {
+  const Register kInstanceReg = R0;
+  // kAllocationStubTypeArgumentsReg = R1
+  const Register kTagsToClsIdReg = R2;
+
+  if (!FLAG_use_bare_instructions) {
+    __ ldr(CODE_REG,
+           Address(THR, target::Thread::call_to_runtime_stub_offset()));
+  }
+
+  __ ExtractClassIdFromTags(kTagsToClsIdReg, kTagsToClsIdReg);
+
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
+  __ EnterStubFrame();
+
+  __ LoadClassById(R0, kTagsToClsIdReg);
+  __ PushPair(R0, NULL_REG);  // Pushes result slot, then class object.
+
+  // Should be Object::null() if class is non-parameterized.
+  __ Push(kAllocationStubTypeArgumentsReg);
+
+  __ CallRuntime(kAllocateObjectRuntimeEntry, 2);
+
+  // Load result off the stack into result register.
+  __ ldr(kInstanceReg, Address(SP, 2 * target::kWordSize));
+
+  // Write-barrier elimination is enabled for [cls] and we therefore need to
+  // ensure that the object is in new-space or has remembered bit set.
+  EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
+
+  __ LeaveStubFrame();
+
+  __ ret();
+}
+
 // Called for inline allocation of objects.
-// Input parameters:
-//   LR : return address.
-//   kAllocationStubTypeArgumentsReg (R1): type arguments object
-//                                         (only if class is parameterized).
-void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
-                                                      const Class& cls) {
+void StubCodeCompiler::GenerateAllocationStubForClass(
+    Assembler* assembler,
+    UnresolvedPcRelativeCalls* unresolved_calls,
+    const Class& cls,
+    const Code& allocate_object,
+    const Code& allocat_object_parametrized) {
+  static_assert(kAllocationStubTypeArgumentsReg == R1,
+                "Adjust register allocation in the AllocationStub");
+
+  classid_t cls_id = target::Class::GetId(cls);
+  ASSERT(cls_id != kIllegalCid);
+
+  RELEASE_ASSERT(AllocateObjectInstr::WillAllocateNewOrRemembered(cls));
+
   // The generated code is different if the class is parameterized.
   const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
   ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
                                       cls) != target::Class::kNoTypeArguments);
 
-  const Register kTypeArgumentsReg = kAllocationStubTypeArgumentsReg;
-  const Register kInstanceReg = R0;
-  const Register kNullReg = R3;
-  const Register kTempReg = R4;
-  const Register kTopReg = R5;
-  static_assert(kAllocationStubTypeArgumentsReg == R1,
-                "Adjust register allocation in the AllocationStub");
-
-  // kInlineInstanceSize is a constant used as a threshold for determining
-  // when the object initialization should be done as a loop or as
-  // straight line code.
-  const int kInlineInstanceSize = 12;
   const intptr_t instance_size = target::Class::GetInstanceSize(cls);
   ASSERT(instance_size > 0);
+  RELEASE_ASSERT(target::Heap::IsAllocatableInNewSpace(instance_size));
 
-  __ LoadObject(kNullReg, NullObject());
-  if (FLAG_inline_alloc &&
-      target::Heap::IsAllocatableInNewSpace(instance_size) &&
-      !target::Class::TraceAllocation(cls)) {
-    Label slow_case;
-    // Allocate the object & initialize header word.
-    __ TryAllocate(cls, &slow_case, kInstanceReg, kTopReg,
-                   /*tag_result=*/false);
+  const uint32_t tags =
+      target::MakeTagWordForNewSpaceObject(cls_id, instance_size);
 
-    // Initialize the remaining words of the object.
-    if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
-      intptr_t current_offset = target::Instance::first_field_offset();
-      while ((current_offset + target::kWordSize) < instance_size) {
-        __ stp(kNullReg, kNullReg,
-               Address(kInstanceReg, current_offset, Address::PairOffset));
-        current_offset += 2 * target::kWordSize;
-      }
-      while (current_offset < instance_size) {
-        __ str(kNullReg, Address(kInstanceReg, current_offset));
-        current_offset += target::kWordSize;
+  // Note: Keep in sync with helper function.
+  // kInstanceReg = R0
+  // kAllocationStubTypeArgumentsReg = R1
+  const Register kTagsReg = R2;
+
+  __ LoadImmediate(kTagsReg, tags);
+
+  if (!FLAG_use_slow_path && FLAG_inline_alloc &&
+      !target::Class::TraceAllocation(cls) &&
+      target::SizeFitsInSizeTag(instance_size)) {
+    if (is_cls_parameterized) {
+      if (!IsSameObject(NullObject(),
+                        CastHandle<Object>(allocat_object_parametrized))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocat_object_parametrized, /*is_tail_call=*/true));
+      } else {
+        __ ldr(R4,
+               Address(THR,
+                       target::Thread::
+                           allocate_object_parameterized_entry_point_offset()));
+        __ br(R4);
       }
     } else {
-      __ AddImmediate(kTempReg, kInstanceReg,
-                      target::Instance::first_field_offset());
-      Label done, init_loop;
-      __ Bind(&init_loop);
-      __ CompareRegisters(kTempReg, kTopReg);
-      __ b(&done, CS);
-      __ str(kNullReg,
-             Address(kTempReg, target::kWordSize, Address::PostIndex));
-      __ b(&init_loop);
-
-      __ Bind(&done);
+      if (!IsSameObject(NullObject(), CastHandle<Object>(allocate_object))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocate_object, /*is_tail_call=*/true));
+      } else {
+        __ ldr(
+            R4,
+            Address(THR, target::Thread::allocate_object_entry_point_offset()));
+        __ br(R4);
+      }
     }
-    if (is_cls_parameterized) {
-      const intptr_t offset = target::Class::TypeArgumentsFieldOffset(cls);
-      __ StoreToOffset(kTypeArgumentsReg, kInstanceReg, offset);
+  } else {
+    if (!is_cls_parameterized) {
+      __ LoadObject(kAllocationStubTypeArgumentsReg, NullObject());
     }
-    __ add(kInstanceReg, kInstanceReg, Operand(kHeapObjectTag));
-    __ ret();
-
-    __ Bind(&slow_case);
+    __ ldr(R4,
+           Address(THR,
+                   target::Thread::allocate_object_slow_entry_point_offset()));
+    __ br(R4);
   }
-
-  // If is_cls_parameterized:
-  // Create a stub frame as we are pushing some objects on the stack before
-  // calling into the runtime.
-  __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
-  __ LoadObject(R0, CastHandle<Object>(cls));
-  __ PushPair(R0, kNullReg);  // Pushes cls, result slot.
-  __ Push(is_cls_parameterized ? kTypeArgumentsReg : kNullReg);
-  __ CallRuntime(kAllocateObjectRuntimeEntry, 2);  // Allocate object.
-  __ ldr(
-      kInstanceReg,
-      Address(SP,
-              2 * target::kWordSize));  // Pop result (newly allocated object).
-
-  ASSERT(kInstanceReg == R0);
-  if (AllocateObjectInstr::WillAllocateNewOrRemembered(cls)) {
-    // Write-barrier elimination is enabled for [cls] and we therefore need to
-    // ensure that the object is in new-space or has remembered bit set.
-    EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
-  }
-  __ LeaveStubFrame();  // Restores correct SP.
-  __ ret();
 }
 
 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
@@ -2336,7 +2456,7 @@
   if (type == kInstanceCall) {
     __ LoadTaggedClassIdMayBeSmi(R0, R0);
     __ LoadFieldFromOffset(R4, R5,
-                           target::ICData::arguments_descriptor_offset());
+                           target::CallSiteData::arguments_descriptor_offset());
     if (num_args == 2) {
       __ LoadFieldFromOffset(R7, R4,
                              target::ArgumentsDescriptor::count_offset());
@@ -2348,7 +2468,7 @@
     }
   } else {
     __ LoadFieldFromOffset(R4, R5,
-                           target::ICData::arguments_descriptor_offset());
+                           target::CallSiteData::arguments_descriptor_offset());
     // Get the receiver's class ID (first read number of arguments from
     // arguments descriptor array and then access the receiver from the stack).
     __ LoadFieldFromOffset(R7, R4, target::ArgumentsDescriptor::count_offset());
@@ -2650,7 +2770,8 @@
   }
 
   // Load arguments descriptor into R4.
-  __ LoadFieldFromOffset(R4, R5, target::ICData::arguments_descriptor_offset());
+  __ LoadFieldFromOffset(R4, R5,
+                         target::CallSiteData::arguments_descriptor_offset());
 
   // Get function and call it, if possible.
   __ LoadFromOffset(R0, R6, target_offset);
@@ -3414,12 +3535,14 @@
   __ ret();
 }
 
-// Called from megamorphic calls.
-//  R0: receiver
+// Called from megamorphic call sites.
+//  R0: receiver (passed to target)
 //  R5: MegamorphicCache (preserved)
 // Passed to target:
+//  R0: receiver
 //  CODE_REG: target Code
 //  R4: arguments descriptor
+//  R5: MegamorphicCache
 void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
   // Jump if receiver is a smi.
   Label smi_case;
@@ -3466,15 +3589,15 @@
   const auto target_address = FieldAddress(TMP, base + target::kWordSize);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     __ ldr(R1, target_address);
-    __ ldr(ARGS_DESC_REG,
-           FieldAddress(
-               R5, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ ldr(
+        ARGS_DESC_REG,
+        FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
   } else {
     __ ldr(R0, target_address);
     __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
-    __ ldr(ARGS_DESC_REG,
-           FieldAddress(
-               R5, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ ldr(
+        ARGS_DESC_REG,
+        FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
     __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
   }
   __ br(R1);
@@ -3495,10 +3618,14 @@
   __ b(&cid_loaded);
 }
 
+// Input:
+//   R0 - receiver
+//   R5 - icdata
 void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
   Label loop, found, miss;
   __ ldr(R8, FieldAddress(R5, target::ICData::entries_offset()));
-  __ ldr(R4, FieldAddress(R5, target::ICData::arguments_descriptor_offset()));
+  __ ldr(R4,
+         FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
   __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
   // R8: first IC entry
   __ LoadTaggedClassIdMayBeSmi(R1, R0);
@@ -3573,23 +3700,24 @@
   }
 
   __ Bind(&miss);
-  __ ldr(IP0, Address(THR, target::Thread::monomorphic_miss_entry_offset()));
+  __ ldr(IP0,
+         Address(THR, target::Thread::switchable_call_miss_entry_offset()));
   __ br(IP0);
 }
 
 // Called from switchable IC calls.
 //  R0: receiver
-//  R5: SingleTargetCache
-void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSwitchableCallMissStub(Assembler* assembler) {
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::switchable_call_miss_stub_offset()));
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
   __ Push(ZR);  // Result slot.
   __ Push(ZR);  // Arg0: stub out.
   __ Push(R0);  // Arg1: Receiver
-  __ Push(R5);  // Arg2: UnlinkedCall
-  __ CallRuntime(kUnlinkedCallRuntimeEntry, 3);
-  __ Drop(2);
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
+  __ Drop(1);
   __ Pop(CODE_REG);  // result = stub
   __ Pop(R5);        // result = IC
 
@@ -3597,7 +3725,39 @@
   __ LeaveStubFrame();
 
   __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
-                                        CodeEntryKind::kMonomorphic)));
+                                        CodeEntryKind::kNormal)));
+  __ br(R1);
+}
+
+// Called from megamorphic call sites and from megamorphic miss handlers.
+//  R5: ICData/MegamorphicCache
+void StubCodeCompiler::GenerateMegamorphicCallMissStub(Assembler* assembler) {
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::switchable_call_miss_stub_offset()));
+  __ EnterStubFrame();
+  __ ldr(R4,
+         FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
+
+  // Load the receiver.
+  __ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::size_offset());
+  __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
+  __ LoadFromOffset(R6, TMP,
+                    target::frame_layout.param_end_from_fp * target::kWordSize);
+  __ Push(R6);  // Preserver receiver
+
+  __ Push(ZR);  // Result slot.
+  __ Push(ZR);  // Arg0: stub out.
+  __ Push(R6);  // Arg1: Receiver
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
+  __ Drop(1);
+  __ Pop(CODE_REG);  // result = stub
+  __ Pop(R5);        // result = IC
+
+  __ Pop(R0);  // Restore receiver into R0
+  __ LeaveStubFrame();
+
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kNormal)));
   __ br(R1);
 }
 
@@ -3631,31 +3791,7 @@
   __ Push(ZR);  // Result slot.
   __ Push(ZR);  // Arg0: Stub out.
   __ Push(R0);  // Arg1: Receiver
-  __ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
-  __ Drop(1);
-  __ Pop(CODE_REG);  // result = stub
-  __ Pop(R5);        // result = IC
-
-  __ Pop(R0);  // Restore receiver.
-  __ LeaveStubFrame();
-
-  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
-                                        CodeEntryKind::kMonomorphic)));
-  __ br(R1);
-}
-
-// Called from the monomorphic checked entry.
-//  R0: receiver
-void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
-  __ ldr(CODE_REG,
-         Address(THR, target::Thread::monomorphic_miss_stub_offset()));
-  __ EnterStubFrame();
-  __ Push(R0);  // Preserve receiver.
-
-  __ Push(ZR);  // Result slot.
-  __ Push(ZR);  // Arg0: stub out
-  __ Push(R0);  // Arg1: Receiver
-  __ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
   __ Drop(1);
   __ Pop(CODE_REG);  // result = stub
   __ Pop(R5);        // result = IC
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 328a17a..53b0cc1 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -313,6 +313,15 @@
     Assembler* assembler) {
   __ Breakpoint();
 }
+void StubCodeCompiler::GenerateRangeErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  __ Breakpoint();
+}
+
+void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
+  __ Breakpoint();
+}
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
     Assembler* assembler) {
@@ -701,15 +710,11 @@
   __ ret();
 }
 
-static void GenerateDispatcherCode(Assembler* assembler,
-                                   Label* call_target_function) {
-  __ Comment("NoSuchMethodDispatch");
-  // When lazily generated invocation dispatchers are disabled, the
-  // miss-handler may return null.
-  const Immediate& raw_null = Immediate(target::ToRawPointer(NullObject()));
-  __ cmpl(EAX, raw_null);
-  __ j(NOT_EQUAL, call_target_function);
+static void GenerateNoSuchMethodDispatcherCode(Assembler* assembler) {
   __ EnterStubFrame();
+  __ movl(EDX, FieldAddress(
+                   ECX, target::CallSiteData::arguments_descriptor_offset()));
+
   // Load the receiver.
   __ movl(EDI, FieldAddress(EDX, target::ArgumentsDescriptor::size_offset()));
   __ movl(EAX,
@@ -740,39 +745,20 @@
   __ ret();
 }
 
-void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
-  __ EnterStubFrame();
-  // Load the receiver into EAX.  The argument count in the arguments
-  // descriptor in EDX is a smi.
-  __ movl(EAX, FieldAddress(EDX, target::ArgumentsDescriptor::size_offset()));
-  // Two words (saved fp, stub's pc marker) in the stack above the return
-  // address.
-  __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * target::kWordSize));
-  // Preserve IC data and arguments descriptor.
-  __ pushl(ECX);
-  __ pushl(EDX);
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  const Immediate& raw_null = Immediate(target::ToRawPointer(NullObject()));
+  __ cmpl(EAX, raw_null);
+  __ j(NOT_EQUAL, call_target_function);
+  GenerateNoSuchMethodDispatcherCode(assembler);
+}
 
-  __ pushl(Immediate(0));  // Space for the result of the runtime call.
-  __ pushl(EAX);           // Pass receiver.
-  __ pushl(ECX);           // Pass IC data.
-  __ pushl(EDX);           // Pass arguments descriptor.
-  __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
-  // Discard arguments.
-  __ popl(EAX);
-  __ popl(EAX);
-  __ popl(EAX);
-  __ popl(EAX);  // Return value from the runtime call (function).
-  __ popl(EDX);  // Restore arguments descriptor.
-  __ popl(ECX);  // Restore IC data.
-  __ LeaveFrame();
-
-  if (!FLAG_lazy_dispatchers) {
-    Label call_target_function;
-    GenerateDispatcherCode(assembler, &call_target_function);
-    __ Bind(&call_target_function);
-  }
-
-  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
+void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
+    Assembler* assembler) {
+  GenerateNoSuchMethodDispatcherCode(assembler);
 }
 
 // Called for inline allocation of arrays.
@@ -1528,6 +1514,19 @@
       Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
+void StubCodeCompiler::GenerateAllocateObjectStub(Assembler* assembler) {
+  __ int3();
+}
+
+void StubCodeCompiler::GenerateAllocateObjectParameterizedStub(
+    Assembler* assembler) {
+  __ int3();
+}
+
+void StubCodeCompiler::GenerateAllocateObjectSlowStub(Assembler* assembler) {
+  __ int3();
+}
+
 // Called for inline allocation of objects.
 // Input parameters:
 //   ESP : points to return address.
@@ -1536,8 +1535,12 @@
 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers.
 // Returns patch_code_pc offset where patching code for disabling the stub
 // has been generated (similar to regularly generated Dart code).
-void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
-                                                      const Class& cls) {
+void StubCodeCompiler::GenerateAllocationStubForClass(
+    Assembler* assembler,
+    UnresolvedPcRelativeCalls* unresolved_calls,
+    const Class& cls,
+    const Code& allocate_object,
+    const Code& allocat_object_parametrized) {
   const Immediate& raw_null = Immediate(target::ToRawPointer(NullObject()));
   // The generated code is different if the class is parameterized.
   const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
@@ -1889,8 +1892,8 @@
   __ Comment("Extract ICData initial values and receiver cid");
   // ECX: IC data object (preserved).
   // Load arguments descriptor into EDX.
-  __ movl(EDX,
-          FieldAddress(ECX, target::ICData::arguments_descriptor_offset()));
+  __ movl(EDX, FieldAddress(
+                   ECX, target::CallSiteData::arguments_descriptor_offset()));
   // Loop that checks if there is an IC data match.
   Label loop, found, miss;
   // ECX: IC data object (preserved).
@@ -2042,12 +2045,12 @@
   __ Stop("Unimplemented");
 }
 
-void StubCodeCompiler::GenerateAllocateMintWithFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithFPURegsStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCodeCompiler::GenerateAllocateMintWithoutFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
@@ -2168,8 +2171,8 @@
   }
 
   // Load arguments descriptor into EDX.
-  __ movl(EDX,
-          FieldAddress(ECX, target::ICData::arguments_descriptor_offset()));
+  __ movl(EDX, FieldAddress(
+                   ECX, target::CallSiteData::arguments_descriptor_offset()));
 
   // Get function and call it, if possible.
   __ movl(EAX, Address(EBX, target_offset));
@@ -2792,7 +2795,7 @@
 }
 
 // Called from megamorphic calls.
-//  EBX: receiver
+//  EBX: receiver (passed to target)
 //  ECX: target::MegamorphicCache (preserved)
 // Passed to target:
 //  EBX: target entry point
@@ -2810,6 +2813,7 @@
 
   Label cid_loaded;
   __ Bind(&cid_loaded);
+  __ pushl(EBX);  // save receiver
   __ movl(EBX, FieldAddress(ECX, target::MegamorphicCache::mask_offset()));
   __ movl(EDI, FieldAddress(ECX, target::MegamorphicCache::buckets_offset()));
   // EDI: cache buckets array.
@@ -2841,9 +2845,9 @@
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
   __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, base + target::kWordSize));
-  __ movl(EDX,
-          FieldAddress(
-              ECX, target::MegamorphicCache::arguments_descriptor_offset()));
+  __ movl(EDX, FieldAddress(
+                   ECX, target::CallSiteData::arguments_descriptor_offset()));
+  __ popl(EBX);  // restore receiver
   __ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
 
   __ Bind(&probe_failed);
@@ -2871,22 +2875,18 @@
   __ int3();  // AOT only.
 }
 
-void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
-  __ int3();  // AOT only.
-}
-
-void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
-  __ int3();  // AOT only.
-}
-
-void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
+// Called from switchable IC calls.
+//  EBX: receiver
+void StubCodeCompiler::GenerateSwitchableCallMissStub(Assembler* assembler) {
+  __ movl(CODE_REG,
+          Address(THR, target::Thread::switchable_call_miss_stub_offset()));
   __ EnterStubFrame();
   __ pushl(EBX);  // Preserve receiver.
 
   __ pushl(Immediate(0));  // Result slot.
-  __ pushl(Immediate(0));  // Arg0: stub out
+  __ pushl(Immediate(0));  // Arg0: stub out.
   __ pushl(EBX);           // Arg1: Receiver
-  __ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
   __ popl(ECX);
   __ popl(CODE_REG);  // result = stub
   __ popl(ECX);       // result = IC
@@ -2895,10 +2895,23 @@
   __ LeaveFrame();
 
   __ movl(EAX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
-                                          CodeEntryKind::kMonomorphic)));
+                                          CodeEntryKind::kNormal)));
   __ jmp(EAX);
 }
 
+// Called from megamorphic call sites and from megamorphic miss handlers.
+//  EBX: receiver
+//  EDX: arguments descriptor(or zero if invoked from unlinked/monomorphic call)
+void StubCodeCompiler::GenerateMegamorphicCallMissStub(Assembler* assembler) {
+  // On ia32 there is no need to load receiver from the actual arguments using
+  // arg descriptor because (unlike on arm, arm64) receiver is always available.
+  GenerateSwitchableCallMissStub(assembler);
+}
+
+void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
+  __ int3();  // AOT only.
+}
+
 void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
     Assembler* assembler) {
   __ int3();  // Marker stub.
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 8bcf076..d981a03 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -154,11 +154,13 @@
   __ ret();
 }
 
-void GenerateSharedStub(Assembler* assembler,
-                        bool save_fpu_registers,
-                        const RuntimeEntry* target,
-                        intptr_t self_code_stub_offset_from_thread,
-                        bool allow_return) {
+void GenerateSharedStub(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    const RuntimeEntry* target,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return,
+    std::initializer_list<Register> runtime_call_arguments) {
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   __ PushRegisters(kDartAvailableCpuRegs,
@@ -181,11 +183,15 @@
   __ movq(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
 
   __ EnterStubFrame();
-  __ CallRuntime(*target, /*argument_count=*/0);
+  for (Register argument_reg : runtime_call_arguments) {
+    __ PushRegister(argument_reg);
+  }
+  __ CallRuntime(*target, /*argument_count=*/runtime_call_arguments.size());
   if (!allow_return) {
     __ Breakpoint();
     return;
   }
+  __ Drop(runtime_call_arguments.size());
   __ LeaveStubFrame();
 
   // Drop "official" return address -- we can just use the one stored above the
@@ -467,7 +473,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
@@ -475,7 +481,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithoutFPURegsStub(
@@ -483,7 +489,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithFPURegsStub(
@@ -491,7 +497,25 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false);
+      /*allow_return=*/false, {});
+}
+
+void StubCodeCompiler::GenerateRangeErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/false, &kRangeErrorRuntimeEntry,
+      target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false,
+      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+}
+
+void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kRangeErrorRuntimeEntry,
+      target::Thread::range_error_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/false,
+      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
@@ -499,7 +523,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/true);
+      /*allow_return=*/true, {});
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
@@ -507,7 +531,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/true);
+      /*allow_return=*/true, {});
 }
 
 // Input parameters:
@@ -946,21 +970,13 @@
   __ ret();
 }
 
-static void GenerateDispatcherCode(Assembler* assembler,
-                                   Label* call_target_function) {
-  __ Comment("NoSuchMethodDispatch");
-  // When lazily generated invocation dispatchers are disabled, the
-  // miss-handler may return null.
-  __ CompareObject(RAX, NullObject());
-  __ j(NOT_EQUAL, call_target_function);
-  __ EnterStubFrame();
-  // Load the receiver.
-  __ movq(RDI, FieldAddress(R10, target::ArgumentsDescriptor::size_offset()));
-  __ movq(RAX,
-          Address(RBP, RDI, TIMES_HALF_WORD_SIZE,
-                  target::frame_layout.param_end_from_fp * target::kWordSize));
+// Input:
+//   RBX - icdata/megamorphic_cache
+//   RDI - arguments descriptor size
+static void GenerateNoSuchMethodDispatcherBody(Assembler* assembler,
+                                               Register receiver_reg) {
   __ pushq(Immediate(0));  // Setup space on stack for result.
-  __ pushq(RAX);           // Receiver.
+  __ pushq(receiver_reg);  // Receiver.
   __ pushq(RBX);           // ICData/MegamorphicCache.
   __ pushq(R10);           // Arguments descriptor array.
 
@@ -984,43 +1000,39 @@
   __ ret();
 }
 
-void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
-  __ EnterStubFrame();
-  // Load the receiver into RAX.  The argument count in the arguments
-  // descriptor in R10 is a smi.
-  __ movq(RAX, FieldAddress(R10, target::ArgumentsDescriptor::size_offset()));
-  // Three words (saved pp, saved fp, stub's pc marker)
-  // in the stack above the return address.
-  __ movq(RAX,
-          Address(RSP, RAX, TIMES_4,
-                  target::frame_layout.saved_below_pc() * target::kWordSize));
-  // Preserve IC data and arguments descriptor.
-  __ pushq(RBX);
-  __ pushq(R10);
+// Input:
+//   RBX - icdata/megamorphic_cache
+//   R10 - argument descriptor
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  __ CompareObject(RAX, NullObject());
+  __ j(NOT_EQUAL, call_target_function);
 
-  // Space for the result of the runtime call.
-  __ pushq(Immediate(0));
-  __ pushq(RDX);  // Receiver.
-  __ pushq(RBX);  // IC data.
-  __ pushq(R10);  // Arguments descriptor.
-  __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
-  // Discard arguments.
-  __ popq(RAX);
-  __ popq(RAX);
-  __ popq(RAX);
-  __ popq(RAX);  // Return value from the runtime call (function).
-  __ popq(R10);  // Restore arguments descriptor.
-  __ popq(RBX);  // Restore IC data.
-  __ RestoreCodePointer();
-  __ LeaveStubFrame();
-  if (!FLAG_lazy_dispatchers) {
-    Label call_target_function;
-    GenerateDispatcherCode(assembler, &call_target_function);
-    __ Bind(&call_target_function);
-  }
-  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
-  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
-  __ jmp(RCX);
+  __ EnterStubFrame();
+  // Load the receiver.
+  __ movq(RDI, FieldAddress(R10, target::ArgumentsDescriptor::size_offset()));
+  __ movq(RAX,
+          Address(RBP, RDI, TIMES_HALF_WORD_SIZE,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
+
+  GenerateNoSuchMethodDispatcherBody(assembler, /*receiver_reg=*/RAX);
+}
+
+// Input:
+//   RBX - icdata/megamorphic_cache
+//   RDX - receiver
+void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
+    Assembler* assembler) {
+  __ EnterStubFrame();
+
+  __ movq(R10, FieldAddress(
+                   RBX, target::CallSiteData::arguments_descriptor_offset()));
+  __ movq(RDI, FieldAddress(R10, target::ArgumentsDescriptor::size_offset()));
+
+  GenerateNoSuchMethodDispatcherBody(assembler, /*receiver_reg=*/RDX);
 }
 
 // Called for inline allocation of arrays.
@@ -1161,12 +1173,12 @@
   __ ret();
 }
 
-void StubCodeCompiler::GenerateAllocateMintWithFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithFPURegsStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCodeCompiler::GenerateAllocateMintWithoutFPURegsStub(
+void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
@@ -1880,138 +1892,226 @@
       Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
-// Called for inline allocation of objects.
-// Input parameters:
-//   RSP : points to return address.
-//   kAllocationStubTypeArgumentsReg (RDX) : type arguments object
-//                                           (only if class is parameterized).
-void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
-                                                      const Class& cls) {
-  // The generated code is different if the class is parameterized.
-  const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
-  ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
-                                      cls) != target::Class::kNoTypeArguments);
-  // kInlineInstanceSize is a constant used as a threshold for determining
-  // when the object initialization should be done as a loop or as
-  // straight line code.
-  const int kInlineInstanceSize = 12;  // In words.
-  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
-  ASSERT(instance_size > 0);
-  __ LoadObject(R9, NullObject());
+static void GenerateAllocateObjectHelper(Assembler* assembler,
+                                         bool is_cls_parameterized) {
+  // Note: Keep in sync with calling function.
+  // kAllocationStubTypeArgumentsReg = RDX
+  const Register kTagsReg = R8;
 
-  // RDX: instantiated type arguments (if is_cls_parameterized).
-  static_assert(kAllocationStubTypeArgumentsReg == RDX,
-                "Adjust register allocation in the AllocationStub");
-
-  if (!FLAG_use_slow_path && FLAG_inline_alloc &&
-      target::Heap::IsAllocatableInNewSpace(instance_size) &&
-      !target::Class::TraceAllocation(cls)) {
+  {
     Label slow_case;
+    const Register kNewTopReg = R9;
+
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
-    // RDX: instantiated type arguments (if is_cls_parameterized).
-    __ movq(RAX, Address(THR, target::Thread::top_offset()));
-    __ leaq(RBX, Address(RAX, instance_size));
-    // Check if the allocation fits into the remaining space.
-    // RAX: potential new object start.
-    // RBX: potential next object start.
-    __ cmpq(RBX, Address(THR, target::Thread::end_offset()));
-    __ j(ABOVE_EQUAL, &slow_case);
+    {
+      const Register kInstanceSizeReg = RSI;
 
-    __ movq(Address(THR, target::Thread::top_offset()), RBX);
+      __ ExtractInstanceSizeFromTags(kInstanceSizeReg, kTagsReg);
 
-    // RAX: new object start (untagged).
-    // RBX: next object start.
-    // RDX: new object type arguments (if is_cls_parameterized).
+      __ movq(RAX, Address(THR, target::Thread::top_offset()));
+      __ leaq(kNewTopReg, Address(RAX, kInstanceSizeReg, TIMES_1, 0));
+      // Check if the allocation fits into the remaining space.
+      __ cmpq(kNewTopReg, Address(THR, target::Thread::end_offset()));
+      __ j(ABOVE_EQUAL, &slow_case);
+
+      __ movq(Address(THR, target::Thread::top_offset()), kNewTopReg);
+    }  // kInstanceSizeReg = RSI
+
     // Set the tags.
-    ASSERT(target::Class::GetId(cls) != kIllegalCid);
-    const uint32_t tags = target::MakeTagWordForNewSpaceObject(
-        target::Class::GetId(cls), instance_size);
     // 64 bit store also zeros the identity hash field.
-    __ movq(Address(RAX, target::Object::tags_offset()), Immediate(tags));
+    __ movq(Address(RAX, target::Object::tags_offset()), kTagsReg);
+
     __ addq(RAX, Immediate(kHeapObjectTag));
 
     // Initialize the remaining words of the object.
-    // RAX: new object (tagged).
-    // RBX: next object start.
-    // RDX: new object type arguments (if is_cls_parameterized).
-    // R9: raw null.
-    // First try inlining the initialization without a loop.
-    if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
-      // Check if the object contains any non-header fields.
-      // Small objects are initialized using a consecutive set of writes.
-      for (intptr_t current_offset = target::Instance::first_field_offset();
-           current_offset < instance_size;
-           current_offset += target::kWordSize) {
-        __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, current_offset), R9);
-      }
-    } else {
-      __ leaq(RCX, FieldAddress(RAX, target::Instance::first_field_offset()));
+    {
+      const Register kNextFieldReg = RDI;
+      __ leaq(kNextFieldReg,
+              FieldAddress(RAX, target::Instance::first_field_offset()));
+
+      const Register kNullReg = R10;
+      __ LoadObject(kNullReg, NullObject());
+
       // Loop until the whole object is initialized.
-      // RAX: new object (tagged).
-      // RBX: next object start.
-      // RCX: next word to be initialized.
-      // RDX: new object type arguments (if is_cls_parameterized).
       Label init_loop;
       Label done;
       __ Bind(&init_loop);
-      __ cmpq(RCX, RBX);
+      __ cmpq(kNextFieldReg, kNewTopReg);
 #if defined(DEBUG)
       static const bool kJumpLength = Assembler::kFarJump;
 #else
       static const bool kJumpLength = Assembler::kNearJump;
 #endif  // DEBUG
       __ j(ABOVE_EQUAL, &done, kJumpLength);
-      __ StoreIntoObjectNoBarrier(RAX, Address(RCX, 0), R9);
-      __ addq(RCX, Immediate(target::kWordSize));
+      __ StoreIntoObjectNoBarrier(RAX, Address(kNextFieldReg, 0), kNullReg);
+      __ addq(kNextFieldReg, Immediate(target::kWordSize));
       __ jmp(&init_loop, Assembler::kNearJump);
       __ Bind(&done);
-    }
+    }  // kNextFieldReg = RDI, kNullReg = R10
+
     if (is_cls_parameterized) {
-      // RAX: new object (tagged).
-      // RDX: new object type arguments.
+      Label not_parameterized_case;
+
+      const Register kClsIdReg = R9;
+      const Register kTypeOffsetReg = RDI;
+
+      __ ExtractClassIdFromTags(kClsIdReg, kTagsReg);
+
+      // Load class' type_arguments_field offset in words.
+      __ LoadClassById(kTypeOffsetReg, kClsIdReg);
+      __ movl(
+          kTypeOffsetReg,
+          FieldAddress(kTypeOffsetReg,
+                       target::Class::
+                           host_type_arguments_field_offset_in_words_offset()));
+
       // Set the type arguments in the new object.
-      const intptr_t offset = target::Class::TypeArgumentsFieldOffset(cls);
-      __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, offset),
-                                  kAllocationStubTypeArgumentsReg);
-    }
-    // Done allocating and initializing the instance.
-    // RAX: new object (tagged).
+      __ StoreIntoObject(RAX, FieldAddress(RAX, kTypeOffsetReg, TIMES_8, 0),
+                         kAllocationStubTypeArgumentsReg);
+
+      __ Bind(&not_parameterized_case);
+    }  // kTypeOffsetReg = RDI;
+
     __ ret();
 
     __ Bind(&slow_case);
-  }
-  // If is_cls_parameterized:
-  // RDX: new object type arguments.
-  // Create a stub frame.
-  __ EnterStubFrame();  // Uses PP to access class object.
+  }  // kNewTopReg = R9;
 
-  __ pushq(R9);  // Setup space on stack for return value.
-  __ PushObject(
-      CastHandle<Object>(cls));  // Push class of object to be allocated.
-  if (is_cls_parameterized) {
-    // Push type arguments of object to be allocated.
-    __ pushq(kAllocationStubTypeArgumentsReg);
-  } else {
-    __ pushq(R9);  // Push null type arguments.
+  // Fall back on slow case:
+  if (!is_cls_parameterized) {
+    __ LoadObject(kAllocationStubTypeArgumentsReg, NullObject());
   }
-  __ CallRuntime(kAllocateObjectRuntimeEntry, 2);  // Allocate object.
+  // Tail call to generic allocation stub.
+  __ jmp(
+      Address(THR, target::Thread::allocate_object_slow_entry_point_offset()));
+}
+
+// Called for inline allocation of objects (any class).
+void StubCodeCompiler::GenerateAllocateObjectStub(Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/false);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectParameterizedStub(
+    Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/true);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectSlowStub(Assembler* assembler) {
+  // Note: Keep in sync with calling stub.
+  // kAllocationStubTypeArgumentsReg = RDX
+  const Register kTagsToClsIdReg = R8;
+
+  if (!FLAG_use_bare_instructions) {
+    __ movq(CODE_REG,
+            Address(THR, target::Thread::call_to_runtime_stub_offset()));
+  }
+
+  __ ExtractClassIdFromTags(kTagsToClsIdReg, kTagsToClsIdReg);
+
+  // Create a stub frame.
+  // Ensure constant pool is allowed so we can e.g. load class object.
+  __ EnterStubFrame();
+
+  // Setup space on stack for return value.
+  __ LoadObject(RAX, NullObject());
+  __ pushq(RAX);
+
+  // Push class of object to be allocated.
+  __ LoadClassById(RAX, kTagsToClsIdReg);
+  __ pushq(RAX);
+
+  // Must be Object::null() if non-parameterized class.
+  __ pushq(kAllocationStubTypeArgumentsReg);
+
+  __ CallRuntime(kAllocateObjectRuntimeEntry, 2);
+
   __ popq(RAX);  // Pop argument (type arguments of object).
   __ popq(RAX);  // Pop argument (class of object).
   __ popq(RAX);  // Pop result (newly allocated object).
 
-  if (AllocateObjectInstr::WillAllocateNewOrRemembered(cls)) {
-    // Write-barrier elimination is enabled for [cls] and we therefore need to
-    // ensure that the object is in new-space or has remembered bit set.
-    EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
-  }
+  // Write-barrier elimination is enabled for [cls] and we therefore need to
+  // ensure that the object is in new-space or has remembered bit set.
+  EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
 
   // RAX: new object
   // Restore the frame pointer.
   __ LeaveStubFrame();
+
   __ ret();
 }
 
+// Called for inline allocation of objects.
+void StubCodeCompiler::GenerateAllocationStubForClass(
+    Assembler* assembler,
+    UnresolvedPcRelativeCalls* unresolved_calls,
+    const Class& cls,
+    const Code& allocate_object,
+    const Code& allocat_object_parametrized) {
+  static_assert(kAllocationStubTypeArgumentsReg == RDX,
+                "Adjust register allocation in the AllocationStub");
+
+  classid_t cls_id = target::Class::GetId(cls);
+  ASSERT(cls_id != kIllegalCid);
+
+  RELEASE_ASSERT(AllocateObjectInstr::WillAllocateNewOrRemembered(cls));
+
+  const intptr_t cls_type_arg_field_offset =
+      target::Class::TypeArgumentsFieldOffset(cls);
+
+  // The generated code is different if the class is parameterized.
+  const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
+  ASSERT(!is_cls_parameterized ||
+         cls_type_arg_field_offset != target::Class::kNoTypeArguments);
+
+  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
+  ASSERT(instance_size > 0);
+  // User-defined classes should always be allocatable in new space.
+  RELEASE_ASSERT(target::Heap::IsAllocatableInNewSpace(instance_size));
+
+  const uint32_t tags =
+      target::MakeTagWordForNewSpaceObject(cls_id, instance_size);
+
+  // Note: Keep in sync with helper function.
+  // kAllocationStubTypeArgumentsReg = RDX
+  const Register kTagsReg = R8;
+
+  __ movq(kTagsReg, Immediate(tags));
+
+  // Load the appropriate generic alloc. stub.
+  if (!FLAG_use_slow_path && FLAG_inline_alloc &&
+      !target::Class::TraceAllocation(cls) &&
+      target::SizeFitsInSizeTag(instance_size)) {
+    if (is_cls_parameterized) {
+      if (!IsSameObject(NullObject(),
+                        CastHandle<Object>(allocat_object_parametrized))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocat_object_parametrized, /*is_tail_call=*/true));
+      } else {
+        __ jmp(Address(THR,
+                       target::Thread::
+                           allocate_object_parameterized_entry_point_offset()));
+      }
+    } else {
+      if (!IsSameObject(NullObject(), CastHandle<Object>(allocate_object))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocate_object, /*is_tail_call=*/true));
+      } else {
+        __ jmp(
+            Address(THR, target::Thread::allocate_object_entry_point_offset()));
+      }
+    }
+  } else {
+    if (!is_cls_parameterized) {
+      __ LoadObject(kAllocationStubTypeArgumentsReg, NullObject());
+    }
+    __ jmp(Address(THR,
+                   target::Thread::allocate_object_slow_entry_point_offset()));
+  }
+}
+
 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
 // from the entry code of a dart function after an error in passed argument
 // name or number is detected.
@@ -2253,8 +2353,8 @@
 
   if (type == kInstanceCall) {
     __ LoadTaggedClassIdMayBeSmi(RAX, RDX);
-    __ movq(R10,
-            FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+    __ movq(R10, FieldAddress(
+                     RBX, target::CallSiteData::arguments_descriptor_offset()));
     if (num_args == 2) {
       __ movq(RCX,
               FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
@@ -2262,8 +2362,8 @@
       __ LoadTaggedClassIdMayBeSmi(RCX, R9);
     }
   } else {
-    __ movq(R10,
-            FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+    __ movq(R10, FieldAddress(
+                     RBX, target::CallSiteData::arguments_descriptor_offset()));
     __ movq(RCX,
             FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
     __ movq(RDX, Address(RSP, RCX, TIMES_4, 0));
@@ -2593,8 +2693,8 @@
   }
 
   // Load arguments descriptor into R10.
-  __ movq(R10,
-          FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+  __ movq(R10, FieldAddress(
+                   RBX, target::CallSiteData::arguments_descriptor_offset()));
 
   // Get function and call it, if possible.
   __ movq(RAX, Address(R12, target_offset));
@@ -3359,7 +3459,7 @@
 }
 
 // Called from megamorphic calls.
-//  RDX: receiver
+//  RDX: receiver (passed to target)
 //  RBX: target::MegamorphicCache (preserved)
 // Passed to target:
 //  CODE_REG: target Code
@@ -3409,15 +3509,13 @@
   const auto target_address =
       FieldAddress(RDI, RCX, TIMES_8, base + target::kWordSize);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ movq(R10,
-            FieldAddress(
-                RBX, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ movq(R10, FieldAddress(
+                     RBX, target::CallSiteData::arguments_descriptor_offset()));
     __ jmp(target_address);
   } else {
     __ movq(RAX, target_address);
-    __ movq(R10,
-            FieldAddress(
-                RBX, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ movq(R10, FieldAddress(
+                     RBX, target::CallSiteData::arguments_descriptor_offset()));
     __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
     __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
     __ jmp(RCX);
@@ -3439,11 +3537,14 @@
   __ jmp(&cid_loaded);
 }
 
+// Input:
+//  RBX - icdata
+//  RDX - receiver object
 void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
   Label loop, found, miss;
   __ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));
-  __ movq(R10,
-          FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+  __ movq(R10, FieldAddress(
+                   RBX, target::CallSiteData::arguments_descriptor_offset()));
   __ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
   // R13: first IC entry
   __ LoadTaggedClassIdMayBeSmi(RAX, RDX);
@@ -3505,21 +3606,21 @@
   }
 
   __ Bind(&miss);
-  __ jmp(Address(THR, target::Thread::monomorphic_miss_entry_offset()));
+  __ jmp(Address(THR, target::Thread::switchable_call_miss_entry_offset()));
 }
 
+// Called from switchable IC calls.
 //  RDX: receiver
-//  RBX: UnlinkedCall
-void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSwitchableCallMissStub(Assembler* assembler) {
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::switchable_call_miss_stub_offset()));
   __ EnterStubFrame();
   __ pushq(RDX);  // Preserve receiver.
 
   __ pushq(Immediate(0));  // Result slot.
   __ pushq(Immediate(0));  // Arg0: stub out.
   __ pushq(RDX);           // Arg1: Receiver
-  __ pushq(RBX);           // Arg2: UnlinkedCall
-  __ CallRuntime(kUnlinkedCallRuntimeEntry, 3);
-  __ popq(RBX);
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
   __ popq(RBX);
   __ popq(CODE_REG);  // result = stub
   __ popq(RBX);       // result = IC
@@ -3528,10 +3629,19 @@
   __ LeaveStubFrame();
 
   __ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
-                                          CodeEntryKind::kMonomorphic)));
+                                          CodeEntryKind::kNormal)));
   __ jmp(RCX);
 }
 
+// Called from megamorphic call sites and from megamorphic miss handlers.
+//  RDX: receiver
+//  R10: arguments descriptor
+void StubCodeCompiler::GenerateMegamorphicCallMissStub(Assembler* assembler) {
+  // On x64 there is no need to load receiver from the actual arguments using
+  // arg descriptor because (unlike on arm, arm64) receiver is always available.
+  GenerateSwitchableCallMissStub(assembler);
+}
+
 // Called from switchable IC calls.
 //  RDX: receiver
 //  RBX: SingleTargetCache
@@ -3561,31 +3671,7 @@
   __ pushq(Immediate(0));  // Result slot.
   __ pushq(Immediate(0));  // Arg0: stub out
   __ pushq(RDX);           // Arg1: Receiver
-  __ CallRuntime(kSingleTargetMissRuntimeEntry, 2);
-  __ popq(RBX);
-  __ popq(CODE_REG);  // result = stub
-  __ popq(RBX);       // result = IC
-
-  __ popq(RDX);  // Restore receiver.
-  __ LeaveStubFrame();
-
-  __ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
-                                          CodeEntryKind::kMonomorphic)));
-  __ jmp(RCX);
-}
-
-// Called from the monomorphic checked entry.
-//  RDX: receiver
-void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
-  __ movq(CODE_REG,
-          Address(THR, target::Thread::monomorphic_miss_stub_offset()));
-  __ EnterStubFrame();
-  __ pushq(RDX);  // Preserve receiver.
-
-  __ pushq(Immediate(0));  // Result slot.
-  __ pushq(Immediate(0));  // Arg0: stub out.
-  __ pushq(RDX);           // Arg1: Receiver
-  __ CallRuntime(kMonomorphicMissRuntimeEntry, 2);
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
   __ popq(RBX);
   __ popq(CODE_REG);  // result = stub
   __ popq(RBX);       // result = IC
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 8015373..48e015e 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -71,7 +71,7 @@
   R3 = 3,
   R4 = 4,
   R5 = 5,  // PP
-  R6 = 6,
+  R6 = 6,  // CODE
   R7 = 7,  // iOS FP
   R8 = 8,
   R9 = 9,
@@ -331,6 +331,9 @@
       (1 << kInstanceReg) | (1 << kDstTypeReg) |
       (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
       (1 << kSubtypeTestCacheReg);
+
+  // For call to InstanceOfStub.
+  static const Register kResultReg = R0;
 };
 
 // Registers used inside the implementation of type testing stubs.
@@ -347,6 +350,34 @@
   static const Register kFieldReg = R0;
 };
 
+// ABI for InitInstanceFieldStub.
+struct InitInstanceFieldABI {
+  static const Register kInstanceReg = R0;
+  static const Register kFieldReg = R1;
+};
+
+// ABI for ThrowStub.
+struct ThrowABI {
+  static const Register kExceptionReg = R0;
+};
+
+// ABI for ReThrowStub.
+struct ReThrowABI {
+  static const Register kExceptionReg = R0;
+  static const Register kStackTraceReg = R1;
+};
+
+// ABI for AssertBooleanStub.
+struct AssertBooleanABI {
+  static const Register kObjectReg = R0;
+};
+
+// ABI for RangeErrorStub.
+struct RangeErrorABI {
+  static const Register kLengthReg = R0;
+  static const Register kIndexReg = R1;
+};
+
 // TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
 // of reusing the constants of the instantiation stubs ABI.
 
@@ -487,6 +518,20 @@
   kInvalidCondition = 16
 };
 
+static inline Condition InvertCondition(Condition c) {
+  COMPILE_ASSERT((EQ ^ NE) == 1);
+  COMPILE_ASSERT((CS ^ CC) == 1);
+  COMPILE_ASSERT((MI ^ PL) == 1);
+  COMPILE_ASSERT((VS ^ VC) == 1);
+  COMPILE_ASSERT((HI ^ LS) == 1);
+  COMPILE_ASSERT((GE ^ LT) == 1);
+  COMPILE_ASSERT((GT ^ LE) == 1);
+  ASSERT(c != AL);
+  ASSERT(c != kSpecialCondition);
+  ASSERT(c != kInvalidCondition);
+  return static_cast<Condition>(c ^ 1);
+}
+
 // Opcodes for Data-processing instructions (instructions with a type 0 and 1)
 // as defined in section A3.4
 enum Opcode {
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 69dab7e..a7852d6 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -163,6 +163,9 @@
       (1 << kInstanceReg) | (1 << kDstTypeReg) |
       (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
       (1 << kSubtypeTestCacheReg);
+
+  // For call to InstanceOfStub.
+  static const Register kResultReg = R0;
 };
 
 // Registers used inside the implementation of type testing stubs.
@@ -179,6 +182,34 @@
   static const Register kFieldReg = R0;
 };
 
+// ABI for InitInstanceFieldStub.
+struct InitInstanceFieldABI {
+  static const Register kInstanceReg = R0;
+  static const Register kFieldReg = R1;
+};
+
+// ABI for ThrowStub.
+struct ThrowABI {
+  static const Register kExceptionReg = R0;
+};
+
+// ABI for ReThrowStub.
+struct ReThrowABI {
+  static const Register kExceptionReg = R0;
+  static const Register kStackTraceReg = R1;
+};
+
+// ABI for AssertBooleanStub.
+struct AssertBooleanABI {
+  static const Register kObjectReg = R0;
+};
+
+// ABI for RangeErrorStub.
+struct RangeErrorABI {
+  static const Register kLengthReg = R0;
+  static const Register kIndexReg = R1;
+};
+
 // TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
 // of reusing the constants of the instantiation stubs ABI.
 
@@ -338,8 +369,19 @@
 };
 
 static inline Condition InvertCondition(Condition c) {
-  const int32_t i = static_cast<int32_t>(c) ^ 0x1;
-  return static_cast<Condition>(i);
+  COMPILE_ASSERT((EQ ^ NE) == 1);
+  COMPILE_ASSERT((CS ^ CC) == 1);
+  COMPILE_ASSERT((MI ^ PL) == 1);
+  COMPILE_ASSERT((VS ^ VC) == 1);
+  COMPILE_ASSERT((HI ^ LS) == 1);
+  COMPILE_ASSERT((GE ^ LT) == 1);
+  COMPILE_ASSERT((GT ^ LE) == 1);
+  COMPILE_ASSERT((AL ^ NV) == 1);
+  // Although the NV condition is not valid for branches, it is used internally
+  // in the assembler in the implementation of far branches, so we have to
+  // allow AL and NV here. See EmitConditionalBranch.
+  ASSERT(c != kInvalidCondition);
+  return static_cast<Condition>(c ^ 1);
 }
 
 enum Bits {
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 00e1e97..398fdcc 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -109,6 +109,11 @@
   static const Register kDstTypeReg = EBX;
   static const Register kInstantiatorTypeArgumentsReg = EDX;
   static const Register kFunctionTypeArgumentsReg = ECX;
+  static const Register kSubtypeTestCacheReg =
+      EDI;  // On ia32 we don't use CODE_REG.
+
+  // For call to InstanceOfStub.
+  static const Register kResultReg = kNoRegister;
 };
 
 // ABI for InitStaticFieldStub.
@@ -116,6 +121,34 @@
   static const Register kFieldReg = EAX;
 };
 
+// ABI for InitInstanceFieldStub.
+struct InitInstanceFieldABI {
+  static const Register kInstanceReg = EAX;
+  static const Register kFieldReg = EBX;
+};
+
+// ABI for ThrowStub.
+struct ThrowABI {
+  static const Register kExceptionReg = EAX;
+};
+
+// ABI for ReThrowStub.
+struct ReThrowABI {
+  static const Register kExceptionReg = EAX;
+  static const Register kStackTraceReg = EBX;
+};
+
+// ABI for AssertBooleanStub.
+struct AssertBooleanABI {
+  static const Register kObjectReg = EAX;
+};
+
+// ABI for RangeErrorStub.
+struct RangeErrorABI {
+  static const Register kLengthReg = EAX;
+  static const Register kIndexReg = EBX;
+};
+
 typedef uint32_t RegList;
 const RegList kAllCpuRegistersList = 0xFF;
 
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index d29a0d4..fe2e01d 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -153,6 +153,9 @@
       (1 << kInstanceReg) | (1 << kDstTypeReg) |
       (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
       (1 << kSubtypeTestCacheReg);
+
+  // For call to InstanceOfStub.
+  static const Register kResultReg = RAX;
 };
 
 // ABI for InitStaticFieldStub.
@@ -160,6 +163,34 @@
   static const Register kFieldReg = RAX;
 };
 
+// ABI for InitInstanceFieldStub.
+struct InitInstanceFieldABI {
+  static const Register kInstanceReg = RAX;
+  static const Register kFieldReg = RBX;
+};
+
+// ABI for ThrowStub.
+struct ThrowABI {
+  static const Register kExceptionReg = RAX;
+};
+
+// ABI for ReThrowStub.
+struct ReThrowABI {
+  static const Register kExceptionReg = RAX;
+  static const Register kStackTraceReg = RBX;
+};
+
+// ABI for AssertBooleanStub.
+struct AssertBooleanABI {
+  static const Register kObjectReg = RAX;
+};
+
+// ABI for RangeErrorStub.
+struct RangeErrorABI {
+  static const Register kLengthReg = RAX;
+  static const Register kIndexReg = RBX;
+};
+
 // Registers used inside the implementation of type testing stubs.
 struct TTSInternalRegs {
   static const Register kInstanceTypeArgumentsReg = RSI;
diff --git a/runtime/vm/constants_x86.h b/runtime/vm/constants_x86.h
index 917c41b..dd77690 100644
--- a/runtime/vm/constants_x86.h
+++ b/runtime/vm/constants_x86.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_CONSTANTS_X86_H_
 #define RUNTIME_VM_CONSTANTS_X86_H_
 
+#include "platform/assert.h"
+
 namespace dart {
 
 enum Condition {
@@ -44,9 +46,22 @@
   UNSIGNED_GREATER = ABOVE,
   UNSIGNED_GREATER_EQUAL = ABOVE_EQUAL,
 
-  INVALID_CONDITION = 16
+  kInvalidCondition = 16
 };
 
+static inline Condition InvertCondition(Condition c) {
+  COMPILE_ASSERT((OVERFLOW ^ NO_OVERFLOW) == 1);
+  COMPILE_ASSERT((BELOW ^ ABOVE_EQUAL) == 1);
+  COMPILE_ASSERT((EQUAL ^ NOT_EQUAL) == 1);
+  COMPILE_ASSERT((BELOW_EQUAL ^ ABOVE) == 1);
+  COMPILE_ASSERT((SIGN ^ NOT_SIGN) == 1);
+  COMPILE_ASSERT((PARITY_EVEN ^ PARITY_ODD) == 1);
+  COMPILE_ASSERT((LESS ^ GREATER_EQUAL) == 1);
+  COMPILE_ASSERT((LESS_EQUAL ^ GREATER) == 1);
+  ASSERT(c != kInvalidCondition);
+  return static_cast<Condition>(c ^ 1);
+}
+
 #define X86_ZERO_OPERAND_1_BYTE_INSTRUCTIONS(F)                                \
   F(ret, 0xC3)                                                                 \
   F(leave, 0xC9)                                                               \
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 77f7ea6..ad905b6 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -264,7 +264,7 @@
     ASSERT(T != NULL);
     StackZone zone(T);
     HandleScope handle_scope(T);
-    Object::InitNull(vm_isolate_);
+    Object::InitNullAndBool(vm_isolate_);
     ObjectStore::Init(vm_isolate_);
     TargetCPUFeatures::Init();
     Object::Init(vm_isolate_);
@@ -732,7 +732,7 @@
 
 #if defined(DART_PRECOMPILED_RUNTIME)
   // AOT: The megamorphic miss function and code come from the snapshot.
-  ASSERT(I->object_store()->megamorphic_miss_code() != Code::null());
+  ASSERT(I->object_store()->megamorphic_call_miss_code() != Code::null());
   ASSERT(I->object_store()->build_method_extractor_code() != Code::null());
   if (FLAG_print_llvm_constant_pool) {
     StackZone printing_zone(T);
@@ -778,9 +778,9 @@
     THR_Print("%s", b.buf());
   }
 #else
-  // JIT: The megamorphic miss function and code come from the snapshot in JIT
-  // app snapshot, otherwise create them.
-  if (I->object_store()->megamorphic_miss_code() == Code::null()) {
+  // JIT: The megamorphic call miss function and code come from the snapshot in
+  // JIT app snapshot, otherwise create them.
+  if (I->object_store()->megamorphic_call_miss_code() == Code::null()) {
     MegamorphicCacheTable::InitMissHandler(I);
   }
 #if !defined(TARGET_ARCH_IA32)
@@ -791,9 +791,7 @@
 #endif
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
-  const Code& miss_code =
-      Code::Handle(I->object_store()->megamorphic_miss_code());
-  I->set_ic_miss_code(miss_code);
+  I->set_ic_miss_code(StubCode::SwitchableCallMiss());
 
   if ((snapshot_data == NULL) || (kernel_buffer != NULL)) {
     const Error& error = Error::Handle(I->object_store()->PreallocateObjects());
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 468a3b1..3ff092c 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6270,7 +6270,7 @@
   CHECK_NULL(buffer);
   CHECK_NULL(buffer_length);
   CompilationTraceSaver saver(thread->zone());
-  ProgramVisitor::VisitFunctions(&saver);
+  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
   saver.StealBuffer(buffer, buffer_length);
   return Api::Success();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -6292,7 +6292,7 @@
   saver.WriteHeader();
   saver.SaveClasses();
   saver.SaveFields();
-  ProgramVisitor::VisitFunctions(&saver);
+  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
   *buffer_length = stream.bytes_written();
 
   return Api::Success();
@@ -6612,7 +6612,7 @@
   BackgroundCompiler::Stop(I);
   DropRegExpMatchCode(Z);
 
-  ProgramVisitor::Dedup();
+  ProgramVisitor::Dedup(T);
   Symbols::Compact();
 
   TIMELINE_DURATION(T, Isolate, "WriteCoreJITSnapshot");
@@ -6688,7 +6688,7 @@
   BackgroundCompiler::Stop(I);
   DropRegExpMatchCode(Z);
 
-  ProgramVisitor::Dedup();
+  ProgramVisitor::Dedup(T);
   Symbols::Compact();
 
   if (FLAG_dump_tables) {
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 6ed1a09..762326e 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -1120,6 +1120,12 @@
   Exceptions::ThrowByType(Exceptions::kCompileTimeError, args);
 }
 
+void Exceptions::ThrowLateInitializationError(const String& name) {
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0, name);
+  Exceptions::ThrowByType(Exceptions::kLateInitializationError, args);
+}
+
 RawObject* Exceptions::Create(ExceptionType type, const Array& arguments) {
   Library& library = Library::Handle();
   const String* class_name = NULL;
@@ -1207,6 +1213,10 @@
       library = Library::CoreLibrary();
       class_name = &Symbols::_CompileTimeError();
       break;
+    case kLateInitializationError:
+      library = Library::CoreLibrary();
+      class_name = &Symbols::LateInitializationError();
+      break;
   }
 
   Thread* thread = Thread::Current();
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 40bc68a..1ec8e12 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -70,6 +70,7 @@
     kAbstractClassInstantiation,
     kCyclicInitializationError,
     kCompileTimeError,
+    kLateInitializationError,
   };
 
   DART_NORETURN static void ThrowByType(ExceptionType type,
@@ -85,6 +86,7 @@
                                             intptr_t expected_to);
   DART_NORETURN static void ThrowUnsupportedError(const char* msg);
   DART_NORETURN static void ThrowCompileTimeError(const LanguageError& error);
+  DART_NORETURN static void ThrowLateInitializationError(const String& name);
 
   // Returns a RawInstance if the exception is successfully created,
   // otherwise returns a RawError.
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 310aa8a..f01d690 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -143,6 +143,9 @@
   P(link_natives_lazily, bool, false, "Link native calls lazily")              \
   R(log_marker_tasks, false, bool, false,                                      \
     "Log debugging information for old gen GC marking tasks.")                 \
+  P(scavenger_tasks, int, 2,                                                   \
+    "The number of tasks to spawn during scavenging (0 means "                 \
+    "perform all marking on main thread).")                                    \
   P(marker_tasks, int, 2,                                                      \
     "The number of tasks to spawn during old gen GC marking (0 means "         \
     "perform all marking on main thread).")                                    \
diff --git a/runtime/vm/heap/freelist.cc b/runtime/vm/heap/freelist.cc
index d08ec12..20b02cc 100644
--- a/runtime/vm/heap/freelist.cc
+++ b/runtime/vm/heap/freelist.cc
@@ -54,8 +54,7 @@
   return ((size > RawObject::SizeTag::kMaxSizeTag) ? 3 : 2) * kWordSize;
 }
 
-FreeList::FreeList()
-    : mutex_(), freelist_search_budget_(kInitialFreeListSearchBudget) {
+FreeList::FreeList() : mutex_() {
   Reset();
 }
 
diff --git a/runtime/vm/heap/freelist.h b/runtime/vm/heap/freelist.h
index 7c885cf..5b2c14a 100644
--- a/runtime/vm/heap/freelist.h
+++ b/runtime/vm/heap/freelist.h
@@ -117,6 +117,46 @@
     return 0;
   }
 
+  uword TryAllocateBumpLocked(intptr_t size) {
+    ASSERT(mutex_.IsOwnedByCurrentThread());
+    uword result = top_;
+    uword new_top = result + size;
+    if (new_top <= end_) {
+      top_ = new_top;
+      unaccounted_size_ += size;
+      return result;
+    }
+    return 0;
+  }
+  intptr_t TakeUnaccountedSizeLocked() {
+    ASSERT(mutex_.IsOwnedByCurrentThread());
+    intptr_t result = unaccounted_size_;
+    unaccounted_size_ = 0;
+    return result;
+  }
+
+  // Ensures HeapPage::VisitObjects can successful walk over a partially
+  // allocated bump region.
+  void MakeIterable() {
+    if (top_ < end_) {
+      FreeListElement::AsElement(top_, end_ - top_);
+    }
+  }
+  // Returns the bump region to the free list.
+  void AbandonBumpAllocation() {
+    if (top_ < end_) {
+      Free(top_, end_ - top_);
+      top_ = 0;
+      end_ = 0;
+    }
+  }
+
+  uword top() const { return top_; }
+  uword end() const { return end_; }
+  void set_top(uword value) { top_ = value; }
+  void set_end(uword value) { end_ = value; }
+  void AddUnaccountedSize(intptr_t size) { unaccounted_size_ += size; }
+
   void MergeOtherFreelist(FreeList* freelist, bool is_protected);
 
  private:
@@ -161,6 +201,15 @@
   void PrintSmall() const;
   void PrintLarge() const;
 
+  // Bump pointer region.
+  uword top_ = 0;
+  uword end_ = 0;
+
+  // Allocated from the bump pointer region, but not yet added to
+  // PageSpace::usage_. Used to avoid expensive atomic adds during parallel
+  // scavenge.
+  intptr_t unaccounted_size_ = 0;
+
   // Lock protecting the free list data structures.
   mutable Mutex mutex_;
 
@@ -168,7 +217,7 @@
 
   FreeListElement* free_lists_[kNumLists + 1];
 
-  intptr_t freelist_search_budget_;
+  intptr_t freelist_search_budget_ = kInitialFreeListSearchBudget;
 
   // The largest available small size in bytes, or negative if there is none.
   intptr_t last_free_small_size_;
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 994a268..69dc98b 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -22,65 +22,6 @@
 
 namespace dart {
 
-class MarkerWorkList : public ValueObject {
- public:
-  explicit MarkerWorkList(MarkingStack* marking_stack)
-      : marking_stack_(marking_stack) {
-    work_ = marking_stack_->PopEmptyBlock();
-  }
-
-  ~MarkerWorkList() {
-    ASSERT(work_ == NULL);
-    ASSERT(marking_stack_ == NULL);
-  }
-
-  // Returns NULL if no more work was found.
-  RawObject* Pop() {
-    ASSERT(work_ != NULL);
-    if (work_->IsEmpty()) {
-      // TODO(koda): Track over/underflow events and use in heuristics to
-      // distribute work and prevent degenerate flip-flopping.
-      MarkingStack::Block* new_work = marking_stack_->PopNonEmptyBlock();
-      if (new_work == NULL) {
-        return NULL;
-      }
-      marking_stack_->PushBlock(work_);
-      work_ = new_work;
-      // Generated code appends to marking stacks; tell MemorySanitizer.
-      MSAN_UNPOISON(work_, sizeof(*work_));
-    }
-    return work_->Pop();
-  }
-
-  void Push(RawObject* raw_obj) {
-    if (work_->IsFull()) {
-      // TODO(koda): Track over/underflow events and use in heuristics to
-      // distribute work and prevent degenerate flip-flopping.
-      marking_stack_->PushBlock(work_);
-      work_ = marking_stack_->PopEmptyBlock();
-    }
-    work_->Push(raw_obj);
-  }
-
-  void Finalize() {
-    ASSERT(work_->IsEmpty());
-    marking_stack_->PushBlock(work_);
-    work_ = NULL;
-    // Fail fast on attempts to mark after finalizing.
-    marking_stack_ = NULL;
-  }
-
-  void AbandonWork() {
-    marking_stack_->PushBlock(work_);
-    work_ = NULL;
-    marking_stack_ = NULL;
-  }
-
- private:
-  MarkingStack::Block* work_;
-  MarkingStack* marking_stack_;
-};
-
 template <bool sync>
 class MarkingVisitorBase : public ObjectPointerVisitor {
  public:
@@ -496,7 +437,7 @@
   TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessRememberedSet");
   // Filter collected objects from the remembered set.
   StoreBuffer* store_buffer = isolate_group_->store_buffer();
-  StoreBufferBlock* reading = store_buffer->Blocks();
+  StoreBufferBlock* reading = store_buffer->TakeBlocks();
   StoreBufferBlock* writing = store_buffer->PopNonFullBlock();
   while (reading != NULL) {
     StoreBufferBlock* next = reading->next();
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 0461261..a171b2f 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -118,7 +118,8 @@
 }
 
 void HeapPage::VisitRememberedCards(ObjectPointerVisitor* visitor) {
-  ASSERT(Thread::Current()->IsAtSafepoint());
+  ASSERT(Thread::Current()->IsAtSafepoint() ||
+         (Thread::Current()->task_kind() == Thread::kScavengerTask));
   NoSafepointScope no_safepoint;
 
   if (card_table_ == NULL) {
@@ -218,11 +219,10 @@
 static const intptr_t kConservativeInitialMarkSpeed = 20;
 
 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words)
-    : freelist_(),
-      heap_(heap),
+    : heap_(heap),
+      num_freelists_(Utils::Maximum(FLAG_scavenger_tasks, 1) + 1),
+      freelists_(new FreeList[num_freelists_]),
       pages_lock_(),
-      bump_top_(0),
-      bump_end_(0),
       max_capacity_in_words_(max_capacity_in_words),
       usage_(),
       allocated_black_in_words_(0),
@@ -245,6 +245,10 @@
   // We aren't holding the lock but no one can reference us yet.
   UpdateMaxCapacityLocked();
   UpdateMaxUsed();
+
+  for (intptr_t i = 0; i < num_freelists_; i++) {
+    freelists_[i].Reset();
+  }
 }
 
 PageSpace::~PageSpace() {
@@ -259,6 +263,7 @@
   FreePages(large_pages_);
   FreePages(image_pages_);
   ASSERT(marker_ == NULL);
+  delete[] freelists_;
 }
 
 intptr_t PageSpace::LargePageSizeInWordsFor(intptr_t size) {
@@ -458,6 +463,7 @@
 }
 
 uword PageSpace::TryAllocateInFreshPage(intptr_t size,
+                                        FreeList* freelist,
                                         HeapPage::PageType type,
                                         GrowthPolicy growth_policy,
                                         bool is_locked) {
@@ -485,9 +491,9 @@
     intptr_t free_size = page->object_end() - free_start;
     if (free_size > 0) {
       if (is_locked) {
-        freelist_[type].FreeLocked(free_start, free_size);
+        freelist->FreeLocked(free_start, free_size);
       } else {
-        freelist_[type].Free(free_start, free_size);
+        freelist->Free(free_start, free_size);
       }
     }
   }
@@ -524,6 +530,7 @@
 }
 
 uword PageSpace::TryAllocateInternal(intptr_t size,
+                                     FreeList* freelist,
                                      HeapPage::PageType type,
                                      GrowthPolicy growth_policy,
                                      bool is_protected,
@@ -533,12 +540,13 @@
   uword result = 0;
   if (Heap::IsAllocatableViaFreeLists(size)) {
     if (is_locked) {
-      result = freelist_[type].TryAllocateLocked(size, is_protected);
+      result = freelist->TryAllocateLocked(size, is_protected);
     } else {
-      result = freelist_[type].TryAllocate(size, is_protected);
+      result = freelist->TryAllocate(size, is_protected);
     }
     if (result == 0) {
-      result = TryAllocateInFreshPage(size, type, growth_policy, is_locked);
+      result = TryAllocateInFreshPage(size, freelist, type, growth_policy,
+                                      is_locked);
       // usage_ is updated by the call above.
     } else {
       usage_.used_in_words += (size >> kWordSizeLog2);
@@ -551,20 +559,16 @@
   return result;
 }
 
-void PageSpace::AcquireDataLock() {
-  freelist_[HeapPage::kData].mutex()->Lock();
+void PageSpace::AcquireLock(FreeList* freelist) {
+  freelist->mutex()->Lock();
 }
 
-void PageSpace::ReleaseDataLock() {
-  freelist_[HeapPage::kData].mutex()->Unlock();
+void PageSpace::ReleaseLock(FreeList* freelist) {
+  intptr_t size = freelist->TakeUnaccountedSizeLocked();
+  usage_.used_in_words += (size >> kWordSizeLog2);
+  freelist->mutex()->Unlock();
 }
 
-#if defined(DEBUG)
-bool PageSpace::CurrentThreadOwnsDataLock() {
-  return freelist_[HeapPage::kData].mutex()->IsOwnedByCurrentThread();
-}
-#endif
-
 void PageSpace::AllocateExternal(intptr_t cid, intptr_t size) {
   intptr_t size_in_words = size >> kWordSizeLog2;
   usage_.external_in_words += size_in_words;
@@ -681,16 +685,14 @@
   // Assert not called from concurrent sweeper task.
   // TODO(koda): Use thread/task identity when implemented.
   ASSERT(IsolateGroup::Current()->heap() != NULL);
-  if (bump_top_ < bump_end_) {
-    FreeListElement::AsElement(bump_top_, bump_end_ - bump_top_);
+  for (intptr_t i = 0; i < num_freelists_; i++) {
+    freelists_[i].MakeIterable();
   }
 }
 
 void PageSpace::AbandonBumpAllocation() {
-  if (bump_top_ < bump_end_) {
-    freelist_[HeapPage::kData].Free(bump_top_, bump_end_ - bump_top_);
-    bump_top_ = 0;
-    bump_end_ = 0;
+  for (intptr_t i = 0; i < num_freelists_; i++) {
+    freelists_[i].AbandonBumpAllocation();
   }
 }
 
@@ -808,7 +810,8 @@
 }
 
 void PageSpace::VisitRememberedCards(ObjectPointerVisitor* visitor) const {
-  ASSERT(Thread::Current()->IsAtSafepoint());
+  ASSERT(Thread::Current()->IsAtSafepoint() ||
+         (Thread::Current()->task_kind() == Thread::kScavengerTask));
 
   // Wait for the sweeper to finish mutating the large page list.
   MonitorLocker ml(tasks_lock());
@@ -816,8 +819,21 @@
     ml.Wait();  // No safepoint check.
   }
 
-  for (HeapPage* page = large_pages_; page != nullptr; page = page->next()) {
+  // Large pages may be added concurrently due to promotion in another scavenge
+  // worker, so terminate the traversal when we hit the tail we saw while
+  // holding the pages lock, instead of at NULL, otherwise we are racing when we
+  // read HeapPage::next_ and HeapPage::remembered_cards_.
+  HeapPage* page;
+  HeapPage* tail;
+  {
+    MutexLocker ml(&pages_lock_);
+    page = large_pages_;
+    tail = large_pages_tail_;
+  }
+  while (page != nullptr) {
     page->VisitRememberedCards(visitor);
+    if (page == tail) break;
+    page = page->next();
   }
 }
 
@@ -1105,10 +1121,10 @@
   NoSafepointScope no_safepoints;
 
   if (FLAG_print_free_list_before_gc) {
-    OS::PrintErr("Data Freelist (before GC):\n");
-    freelist_[HeapPage::kData].Print();
-    OS::PrintErr("Executable Freelist (before GC):\n");
-    freelist_[HeapPage::kExecutable].Print();
+    for (intptr_t i = 0; i < num_freelists_; i++) {
+      OS::PrintErr("Before GC: Freelist %" Pd "\n", i);
+      freelists_[i].Print();
+    }
   }
 
   if (FLAG_verify_before_gc) {
@@ -1149,8 +1165,9 @@
   // Abandon the remainder of the bump allocation block.
   AbandonBumpAllocation();
   // Reset the freelists and setup sweeping.
-  freelist_[HeapPage::kData].Reset();
-  freelist_[HeapPage::kExecutable].Reset();
+  for (intptr_t i = 0; i < num_freelists_; i++) {
+    freelists_[i].Reset();
+  }
 
   int64_t mid2 = OS::GetCurrentMonotonicMicros();
   int64_t mid3 = 0;
@@ -1169,7 +1186,7 @@
     GCSweeper sweeper;
     HeapPage* prev_page = NULL;
     HeapPage* page = exec_pages_;
-    FreeList* freelist = &freelist_[HeapPage::kExecutable];
+    FreeList* freelist = &freelists_[HeapPage::kExecutable];
     MutexLocker ml(freelist->mutex());
     while (page != NULL) {
       HeapPage* next_page = page->next();
@@ -1215,10 +1232,10 @@
   heap_->RecordTime(kSweepLargePages, end - mid3);
 
   if (FLAG_print_free_list_after_gc) {
-    OS::PrintErr("Data Freelist (after GC):\n");
-    freelist_[HeapPage::kData].Print();
-    OS::PrintErr("Executable Freelist (after GC):\n");
-    freelist_[HeapPage::kExecutable].Print();
+    for (intptr_t i = 0; i < num_freelists_; i++) {
+      OS::PrintErr("After GC: Freelist %" Pd "\n", i);
+      freelists_[i].Print();
+    }
   }
 
   UpdateMaxUsed();
@@ -1251,14 +1268,21 @@
   TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "Sweep");
 
   GCSweeper sweeper;
+
+  intptr_t shard = 0;
+  const intptr_t num_shards = Utils::Maximum(FLAG_scavenger_tasks, 1);
+  for (intptr_t i = 0; i < num_shards; i++) {
+    DataFreeList(i)->mutex()->Lock();
+  }
+
   HeapPage* prev_page = nullptr;
   HeapPage* page = pages_;
-  FreeList* freelist = &freelist_[HeapPage::kData];
-  MutexLocker ml(freelist_->mutex());
   while (page != nullptr) {
     HeapPage* next_page = page->next();
     ASSERT(page->type() == HeapPage::kData);
-    bool page_in_use = sweeper.SweepPage(page, freelist, true /*is_locked*/);
+    shard = (shard + 1) % num_shards;
+    bool page_in_use =
+        sweeper.SweepPage(page, DataFreeList(shard), true /*is_locked*/);
     if (page_in_use) {
       prev_page = page;
     } else {
@@ -1268,6 +1292,10 @@
     page = next_page;
   }
 
+  for (intptr_t i = 0; i < num_shards; i++) {
+    DataFreeList(i)->mutex()->Unlock();
+  }
+
   if (FLAG_verify_after_gc) {
     OS::PrintErr("Verifying after sweeping...");
     heap_->VerifyGC(kForbidMarked);
@@ -1278,13 +1306,13 @@
 void PageSpace::ConcurrentSweep(IsolateGroup* isolate_group) {
   // Start the concurrent sweeper task now.
   GCSweeper::SweepConcurrent(isolate_group, pages_, pages_tail_, large_pages_,
-                             large_pages_tail_, &freelist_[HeapPage::kData]);
+                             large_pages_tail_, &freelists_[HeapPage::kData]);
 }
 
 void PageSpace::Compact(Thread* thread) {
   thread->isolate_group()->set_compaction_in_progress(true);
   GCCompactor compactor(thread, heap_);
-  compactor.Compact(pages_, &freelist_[HeapPage::kData], &pages_lock_);
+  compactor.Compact(pages_, &freelists_[HeapPage::kData], &pages_lock_);
   thread->isolate_group()->set_compaction_in_progress(false);
 
   if (FLAG_verify_after_gc) {
@@ -1294,63 +1322,57 @@
   }
 }
 
-uword PageSpace::TryAllocateDataBumpLocked(intptr_t size) {
+uword PageSpace::TryAllocateDataBumpLocked(FreeList* freelist, intptr_t size) {
   ASSERT(size >= kObjectAlignment);
   ASSERT(Utils::IsAligned(size, kObjectAlignment));
-  intptr_t remaining = bump_end_ - bump_top_;
+
+  intptr_t remaining = freelist->end() - freelist->top();
   if (UNLIKELY(remaining < size)) {
     // Checking this first would be logical, but needlessly slow.
     if (!Heap::IsAllocatableViaFreeLists(size)) {
-      return TryAllocateDataLocked(size, kForceGrowth);
+      return TryAllocateDataLocked(freelist, size, kForceGrowth);
     }
-    FreeListElement* block =
-        freelist_[HeapPage::kData].TryAllocateLargeLocked(size);
+    FreeListElement* block = freelist->TryAllocateLargeLocked(size);
     if (block == NULL) {
       // Allocating from a new page (if growth policy allows) will have the
       // side-effect of populating the freelist with a large block. The next
       // bump allocation request will have a chance to consume that block.
       // TODO(koda): Could take freelist lock just once instead of twice.
-      return TryAllocateInFreshPage(size, HeapPage::kData, kForceGrowth,
-                                    true /* is_locked*/);
+      return TryAllocateInFreshPage(size, freelist, HeapPage::kData,
+                                    kForceGrowth, true /* is_locked*/);
     }
     intptr_t block_size = block->HeapSize();
     if (remaining > 0) {
-      freelist_[HeapPage::kData].FreeLocked(bump_top_, remaining);
+      freelist->FreeLocked(freelist->top(), remaining);
     }
-    bump_top_ = reinterpret_cast<uword>(block);
-    bump_end_ = bump_top_ + block_size;
+    freelist->set_top(reinterpret_cast<uword>(block));
+    freelist->set_end(freelist->top() + block_size);
     remaining = block_size;
   }
   ASSERT(remaining >= size);
-  uword result = bump_top_;
-  bump_top_ += size;
+  uword result = freelist->top();
+  freelist->set_top(result + size);
 
-  // No need for atomic operation: This is either running during a scavenge or
-  // isolate snapshot loading. Note that operator+= is atomic.
-  usage_.used_in_words = usage_.used_in_words + (size >> kWordSizeLog2);
+  freelist->AddUnaccountedSize(size);
 
 // Note: Remaining block is unwalkable until MakeIterable is called.
 #ifdef DEBUG
-  if (bump_top_ < bump_end_) {
+  if (freelist->top() < freelist->end()) {
     // Fail fast if we try to walk the remaining block.
     COMPILE_ASSERT(kIllegalCid == 0);
-    *reinterpret_cast<uword*>(bump_top_) = 0;
+    *reinterpret_cast<uword*>(freelist->top()) = 0;
   }
 #endif  // DEBUG
   return result;
 }
 
-DART_FLATTEN
-uword PageSpace::TryAllocatePromoLocked(intptr_t size) {
-  FreeList* freelist = &freelist_[HeapPage::kData];
+uword PageSpace::TryAllocatePromoLockedSlow(FreeList* freelist, intptr_t size) {
   uword result = freelist->TryAllocateSmallLocked(size);
   if (result != 0) {
-    // No need for atomic operation: we're at a safepoint. Note that
-    // operator+= is atomic.
-    usage_.used_in_words = usage_.used_in_words + (size >> kWordSizeLog2);
+    freelist->AddUnaccountedSize(size);
     return result;
   }
-  return TryAllocateDataBumpLocked(size);
+  return TryAllocateDataBumpLocked(freelist, size);
 }
 
 void PageSpace::SetupImagePage(void* pointer, uword size, bool is_executable) {
@@ -1438,18 +1460,19 @@
 void PageSpace::MergeOtherPageSpace(PageSpace* other) {
   other->AbandonBumpAllocation();
 
-  ASSERT(other->bump_top_ == 0 && other->bump_end_ == 0);
   ASSERT(other->tasks_ == 0);
   ASSERT(other->concurrent_marker_tasks_ == 0);
   ASSERT(other->phase_ == kDone);
   DEBUG_ASSERT(other->iterating_thread_ == nullptr);
   ASSERT(other->marker_ == nullptr);
 
-  for (intptr_t i = 0; i < HeapPage::kNumPageTypes; ++i) {
+  for (intptr_t i = 0; i < num_freelists_; ++i) {
+    ASSERT(other->freelists_[i].top() == 0);
+    ASSERT(other->freelists_[i].end() == 0);
     const bool is_protected =
         FLAG_write_protect_code && i == HeapPage::kExecutable;
-    freelist_[i].MergeOtherFreelist(&other->freelist_[i], is_protected);
-    other->freelist_[i].Reset();
+    freelists_[i].MergeOtherFreelist(&other->freelists_[i], is_protected);
+    other->freelists_[i].Reset();
   }
 
   // The freelist locks will be taken in MergeOtherFreelist above, and the
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index d51e697..63aa158f 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -39,7 +39,7 @@
 // A page containing old generation objects.
 class HeapPage {
  public:
-  enum PageType { kData = 0, kExecutable, kNumPageTypes };
+  enum PageType { kExecutable = 0, kData };
 
   HeapPage* next() const { return next_; }
   void set_next(HeapPage* next) { next_ = next; }
@@ -303,8 +303,8 @@
     bool is_protected =
         (type == HeapPage::kExecutable) && FLAG_write_protect_code;
     bool is_locked = false;
-    return TryAllocateInternal(size, type, growth_policy, is_protected,
-                               is_locked);
+    return TryAllocateInternal(size, &freelists_[type], type, growth_policy,
+                               is_protected, is_locked);
   }
 
   bool NeedsGarbageCollection() const {
@@ -415,16 +415,18 @@
   void FreeExternal(intptr_t size);
 
   // Bulk data allocation.
-  void AcquireDataLock();
-  void ReleaseDataLock();
-#if defined(DEBUG)
-  bool CurrentThreadOwnsDataLock();
-#endif
+  FreeList* DataFreeList(intptr_t i = 0) {
+    return &freelists_[HeapPage::kData + i];
+  }
+  void AcquireLock(FreeList* freelist);
+  void ReleaseLock(FreeList* freelist);
 
-  uword TryAllocateDataLocked(intptr_t size, GrowthPolicy growth_policy) {
+  uword TryAllocateDataLocked(FreeList* freelist,
+                              intptr_t size,
+                              GrowthPolicy growth_policy) {
     bool is_protected = false;
     bool is_locked = true;
-    return TryAllocateInternal(size, HeapPage::kData, growth_policy,
+    return TryAllocateInternal(size, freelist, HeapPage::kData, growth_policy,
                                is_protected, is_locked);
   }
 
@@ -443,9 +445,19 @@
   void set_phase(Phase val) { phase_ = val; }
 
   // Attempt to allocate from bump block rather than normal freelist.
-  uword TryAllocateDataBumpLocked(intptr_t size);
-  // Prefer small freelist blocks, then chip away at the bump block.
-  uword TryAllocatePromoLocked(intptr_t size);
+  uword TryAllocateDataBumpLocked(intptr_t size) {
+    return TryAllocateDataBumpLocked(&freelists_[HeapPage::kData], size);
+  }
+  uword TryAllocateDataBumpLocked(FreeList* freelist, intptr_t size);
+  DART_FORCE_INLINE
+  uword TryAllocatePromoLocked(FreeList* freelist, intptr_t size) {
+    uword result = freelist->TryAllocateBumpLocked(size);
+    if (result != 0) {
+      return result;
+    }
+    return TryAllocatePromoLockedSlow(freelist, size);
+  }
+  uword TryAllocatePromoLockedSlow(FreeList* freelist, intptr_t size);
 
   void SetupImagePage(void* pointer, uword size, bool is_executable);
 
@@ -481,11 +493,13 @@
   };
 
   uword TryAllocateInternal(intptr_t size,
+                            FreeList* freelist,
                             HeapPage::PageType type,
                             GrowthPolicy growth_policy,
                             bool is_protected,
                             bool is_locked);
   uword TryAllocateInFreshPage(intptr_t size,
+                               FreeList* freelist,
                                HeapPage::PageType type,
                                GrowthPolicy growth_policy,
                                bool is_locked);
@@ -535,9 +549,15 @@
             (increase_in_words <= free_capacity_in_words));
   }
 
-  FreeList freelist_[HeapPage::kNumPageTypes];
+  Heap* const heap_;
 
-  Heap* heap_;
+  // One list for executable pages at freelists_[HeapPage::kExecutable].
+  // FLAG_scavenger_tasks count of lists for data pages starting at
+  // freelists_[HeapPage::kData]. The sweeper inserts into the data page
+  // freelists round-robin. The scavenger workers each use one of the data
+  // page freelists without locking.
+  const intptr_t num_freelists_;
+  FreeList* freelists_;
 
   // Use ExclusivePageIterator for safe access to these.
   mutable Mutex pages_lock_;
@@ -549,11 +569,6 @@
   HeapPage* large_pages_tail_ = nullptr;
   HeapPage* image_pages_ = nullptr;
 
-  // A block of memory in a data page, managed by bump allocation. The remainder
-  // is kept formatted as a FreeListElement, but is not in any freelist.
-  uword bump_top_;
-  uword bump_end_;
-
   // Various sizes being tracked for this generation.
   intptr_t max_capacity_in_words_;
 
diff --git a/runtime/vm/heap/pointer_block.cc b/runtime/vm/heap/pointer_block.cc
index 69bc1f5..2814465 100644
--- a/runtime/vm/heap/pointer_block.cc
+++ b/runtime/vm/heap/pointer_block.cc
@@ -69,7 +69,7 @@
 }
 
 template <int BlockSize>
-typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::Blocks() {
+typename BlockStack<BlockSize>::Block* BlockStack<BlockSize>::TakeBlocks() {
   MutexLocker ml(&mutex_);
   while (!partial_.IsEmpty()) {
     full_.Push(partial_.Pop());
diff --git a/runtime/vm/heap/pointer_block.h b/runtime/vm/heap/pointer_block.h
index b5fa276..a5505e2 100644
--- a/runtime/vm/heap/pointer_block.h
+++ b/runtime/vm/heap/pointer_block.h
@@ -24,7 +24,7 @@
 
   void Reset() {
     top_ = 0;
-    next_ = NULL;
+    next_ = nullptr;
   }
 
   PointerBlock<Size>* next() const { return next_; }
@@ -64,7 +64,7 @@
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
  private:
-  PointerBlock() : next_(NULL), top_(0) {}
+  PointerBlock() : next_(nullptr), top_(0) {}
   ~PointerBlock() {
     ASSERT(IsEmpty());  // Guard against unintentionally discarding pointers.
   }
@@ -100,7 +100,7 @@
   Block* PopNonEmptyBlock();
 
   // Pops and returns all non-empty blocks as a linked list (owned by caller).
-  Block* Blocks();
+  Block* TakeBlocks();
 
   // Discards the contents of all non-empty blocks.
   void Reset();
@@ -110,12 +110,12 @@
  protected:
   class List {
    public:
-    List() : head_(NULL), length_(0) {}
+    List() : head_(nullptr), length_(0) {}
     ~List();
     void Push(Block* block);
     Block* Pop();
     intptr_t length() const { return length_; }
-    bool IsEmpty() const { return head_ == NULL; }
+    bool IsEmpty() const { return head_ == nullptr; }
     Block* PopAll();
     Block* Peek() { return head_; }
 
@@ -144,6 +144,74 @@
   DISALLOW_COPY_AND_ASSIGN(BlockStack);
 };
 
+template <typename Stack>
+class BlockWorkList : public ValueObject {
+ public:
+  typedef typename Stack::Block Block;
+
+  explicit BlockWorkList(Stack* stack) : stack_(stack) {
+    work_ = stack_->PopEmptyBlock();
+  }
+
+  ~BlockWorkList() {
+    ASSERT(work_ == nullptr);
+    ASSERT(stack_ == nullptr);
+  }
+
+  // Returns nullptr if no more work was found.
+  RawObject* Pop() {
+    ASSERT(work_ != nullptr);
+    if (work_->IsEmpty()) {
+      // TODO(koda): Track over/underflow events and use in heuristics to
+      // distribute work and prevent degenerate flip-flopping.
+      Block* new_work = stack_->PopNonEmptyBlock();
+      if (new_work == nullptr) {
+        return nullptr;
+      }
+      stack_->PushBlock(work_);
+      work_ = new_work;
+      // Generated code appends to marking stacks; tell MemorySanitizer.
+      MSAN_UNPOISON(work_, sizeof(*work_));
+    }
+    return work_->Pop();
+  }
+
+  void Push(RawObject* raw_obj) {
+    if (work_->IsFull()) {
+      // TODO(koda): Track over/underflow events and use in heuristics to
+      // distribute work and prevent degenerate flip-flopping.
+      stack_->PushBlock(work_);
+      work_ = stack_->PopEmptyBlock();
+    }
+    work_->Push(raw_obj);
+  }
+
+  void Finalize() {
+    ASSERT(work_->IsEmpty());
+    stack_->PushBlock(work_);
+    work_ = nullptr;
+    // Fail fast on attempts to mark after finalizing.
+    stack_ = nullptr;
+  }
+
+  void AbandonWork() {
+    stack_->PushBlock(work_);
+    work_ = nullptr;
+    stack_ = nullptr;
+  }
+
+  bool IsEmpty() {
+    if (!work_->IsEmpty()) {
+      return false;
+    }
+    return stack_->IsEmpty();
+  }
+
+ private:
+  Block* work_;
+  Stack* stack_;
+};
+
 static const int kStoreBufferBlockSize = 1024;
 class StoreBuffer : public BlockStack<kStoreBufferBlockSize> {
  public:
@@ -176,6 +244,19 @@
 };
 
 typedef MarkingStack::Block MarkingStackBlock;
+typedef BlockWorkList<MarkingStack> MarkerWorkList;
+
+static const int kPromotionStackBlockSize = 64;
+class PromotionStack : public BlockStack<kPromotionStackBlockSize> {
+ public:
+  // Adds and transfers ownership of the block to the buffer.
+  void PushBlock(Block* block) {
+    BlockStack<Block::kSize>::PushBlockImpl(block);
+  }
+};
+
+typedef PromotionStack::Block PromotionStackBlock;
+typedef BlockWorkList<PromotionStack> PromotionWorkList;
 
 }  // namespace dart
 
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 3de0aa3..ee11b71 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -18,6 +18,7 @@
 #include "vm/object_id_ring.h"
 #include "vm/object_set.h"
 #include "vm/stack_frame.h"
+#include "vm/thread_barrier.h"
 #include "vm/thread_registry.h"
 #include "vm/timeline.h"
 #include "vm/visitor.h"
@@ -55,12 +56,19 @@
   return header & ~kForwardingMask;
 }
 
-static inline void ForwardTo(uword original, uword target) {
+static inline uword ForwardingHeader(uword target) {
   // Make sure forwarding can be encoded.
   ASSERT((target & kForwardingMask) == 0);
-  *reinterpret_cast<uword*>(original) = target | kForwarded;
+  return target | kForwarded;
 }
 
+// Races: The first word in the copied region is a header word that may be
+// updated by the scavenger worker in another thread, so we might copy either
+// the original object header or an installed forwarding pointer. This race is
+// harmless because if we copy the installed forwarding pointer, the scavenge
+// worker in the current thread will abandon this copy. We do not mark the loads
+// here as relaxed so the C++ compiler still has the freedom to reorder them.
+NO_SANITIZE_THREAD
 static inline void objcpy(void* dst, const void* src, size_t size) {
   // A memcopy specialized for objects. We can assume:
   //  - dst and src do not overlap
@@ -86,19 +94,28 @@
   } while (size > 0);
 }
 
-class ScavengerVisitor : public ObjectPointerVisitor {
+template <bool parallel>
+class ScavengerVisitorBase : public ObjectPointerVisitor {
  public:
-  explicit ScavengerVisitor(IsolateGroup* isolate_group,
-                            Scavenger* scavenger,
-                            SemiSpace* from)
+  explicit ScavengerVisitorBase(IsolateGroup* isolate_group,
+                                Scavenger* scavenger,
+                                SemiSpace* from,
+                                FreeList* freelist,
+                                PromotionStack* promotion_stack)
       : ObjectPointerVisitor(isolate_group),
-        thread_(Thread::Current()),
+        thread_(nullptr),
         scavenger_(scavenger),
         from_(from),
-        heap_(scavenger->heap_),
         page_space_(scavenger->heap_->old_space()),
+        freelist_(freelist),
         bytes_promoted_(0),
-        visiting_old_object_(NULL) {}
+        visiting_old_object_(NULL),
+        promoted_list_(promotion_stack),
+        labs_(8) {
+    ASSERT(labs_.length() == 0);
+    labs_.Add({0, 0, 0});
+    ASSERT(labs_.length() == 1);
+  }
 
   virtual void VisitTypedDataViewPointers(RawTypedDataView* view,
                                           RawObject** first,
@@ -157,6 +174,72 @@
 
   intptr_t bytes_promoted() const { return bytes_promoted_; }
 
+  void AddNewTLAB(uword top, uword end) {
+    producer_index_++;
+    ScavengerLAB lab;
+    lab.top = top;
+    lab.end = end;
+    lab.resolved_top = top;
+    labs_.Add(lab);
+  }
+
+  void ProcessRoots() {
+    thread_ = Thread::Current();
+    page_space_->AcquireLock(freelist_);
+    scavenger_->IterateRoots(this);
+  }
+
+  void ProcessSurvivors() {
+    // Iterate until all work has been drained.
+    do {
+      ProcessToSpace();
+      ProcessPromotedList();
+    } while (HasWork());
+  }
+
+  void ProcessAll() {
+    do {
+      ProcessSurvivors();
+      ProcessWeakProperties();
+    } while (HasWork());
+  }
+
+  inline void ProcessWeakProperties();
+
+  bool HasWork() {
+    // N.B.: Normally if any TLABs have things left to resolve, then the
+    // TLAB we are allocating from (producer_index_) will too because we
+    // always immediately allocate when we switch to a new TLAB. However,
+    // this first allocation may be undone if we lose the race to install
+    // the forwarding pointer, so we must also check that there aren't
+    // any TLABs after the resolution cursor.
+    return (consumer_index_ < producer_index_) ||
+           (labs_[producer_index_].top !=
+            labs_[producer_index_].resolved_top) ||
+           !promoted_list_.IsEmpty();
+  }
+
+  void Finalize() {
+    ASSERT(!HasWork());
+
+    for (intptr_t i = 0; i <= producer_index_; i++) {
+      ASSERT(labs_[i].top <= labs_[i].end);
+      ASSERT(labs_[i].resolved_top == labs_[i].top);
+    }
+
+    MakeProducerTLABIterable();
+
+    promoted_list_.Finalize();
+
+    MournWeakProperties();
+
+    page_space_->ReleaseLock(freelist_);
+    thread_ = nullptr;
+  }
+
+  uword last_top() { return labs_[producer_index_].top; }
+  uword last_end() { return labs_[producer_index_].end; }
+
  private:
   void UpdateStoreBuffer(RawObject** p, RawObject* obj) {
     ASSERT(obj->IsHeapObject());
@@ -182,39 +265,40 @@
     ASSERT(from_->Contains(raw_addr));
     // Read the header word of the object and determine if the object has
     // already been copied.
-    uword header = *reinterpret_cast<uword*>(raw_addr);
+    uword header = reinterpret_cast<std::atomic<uword>*>(raw_addr)->load(
+        std::memory_order_relaxed);
     uword new_addr = 0;
     if (IsForwarding(header)) {
       // Get the new location of the object.
       new_addr = ForwardedAddr(header);
     } else {
-      intptr_t size = raw_obj->HeapSize();
+      intptr_t size = raw_obj->HeapSize(header);
       // Check whether object should be promoted.
-      if (scavenger_->survivor_end_ <= raw_addr) {
+      if (raw_addr >= scavenger_->survivor_end_) {
         // Not a survivor of a previous scavenge. Just copy the object into the
         // to space.
-        new_addr = scavenger_->AllocateGC(size);
-      } else {
-        // TODO(iposva): Experiment with less aggressive promotion. For example
-        // a coin toss determines if an object is promoted or whether it should
-        // survive in this generation.
-        //
+        new_addr = TryAllocateCopy(size);
+      }
+      if (new_addr == 0) {
         // This object is a survivor of a previous scavenge. Attempt to promote
-        // the object.
-        new_addr = page_space_->TryAllocatePromoLocked(size);
-        if (new_addr != 0) {
+        // the object. (Or, unlikely, to-space was exhausted by fragmentation.)
+        new_addr = page_space_->TryAllocatePromoLocked(freelist_, size);
+        if (LIKELY(new_addr != 0)) {
           // If promotion succeeded then we need to remember it so that it can
           // be traversed later.
-          scavenger_->PushToPromotedStack(new_addr);
+          promoted_list_.Push(RawObject::FromAddr(new_addr));
           bytes_promoted_ += size;
         } else {
           // Promotion did not succeed. Copy into the to space instead.
           scavenger_->failed_to_promote_ = true;
-          new_addr = scavenger_->AllocateGC(size);
+          new_addr = TryAllocateCopy(size);
+          // To-space was exhausted by fragmentation and old-space could not
+          // grow.
+          if (UNLIKELY(new_addr == 0)) {
+            FATAL("Failed to allocate during scavenge");
+          }
         }
       }
-      // During a scavenge we always succeed to at least copy all of the
-      // current objects to the to space.
       ASSERT(new_addr != 0);
       // Copy the object to the new location.
       objcpy(reinterpret_cast<void*>(new_addr),
@@ -223,7 +307,7 @@
       RawObject* new_obj = RawObject::FromAddr(new_addr);
       if (new_obj->IsOldObject()) {
         // Promoted: update age/barrier tags.
-        uint32_t tags = new_obj->ptr()->tags_;
+        uint32_t tags = static_cast<uint32_t>(header);
         tags = RawObject::OldBit::update(true, tags);
         tags = RawObject::OldAndNotRememberedBit::update(true, tags);
         tags = RawObject::NewBit::update(false, tags);
@@ -235,18 +319,39 @@
         tags =
             RawObject::OldAndNotMarkedBit::update(!thread_->is_marking(), tags);
         new_obj->ptr()->tags_ = tags;
+      } else {
+        ASSERT(scavenger_->to_->Contains(new_addr));
       }
 
-      if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
+      intptr_t cid = RawObject::ClassIdTag::decode(header);
+      if (RawObject::IsTypedDataClassId(cid)) {
         reinterpret_cast<RawTypedData*>(new_obj)->RecomputeDataField();
       }
 
-      // Remember forwarding address.
-      ForwardTo(raw_addr, new_addr);
+      // Try to install forwarding address.
+      uword forwarding_header = ForwardingHeader(new_addr);
+      if (!InstallForwardingPointer(raw_addr, &header, forwarding_header)) {
+        ASSERT(IsForwarding(header));
+        if (new_obj->IsOldObject()) {
+          // Abandon as a free list element.
+          FreeListElement::AsElement(new_addr, size);
+          bytes_promoted_ -= size;
+        } else {
+          // Undo to-space allocation.
+          ASSERT(labs_[producer_index_].top == (new_addr + size));
+          labs_[producer_index_].top = new_addr;
+        }
+        // Use the winner's forwarding target.
+        new_addr = ForwardedAddr(header);
+        if (RawObject::FromAddr(new_addr)->IsNewObject()) {
+          ASSERT(scavenger_->to_->Contains(new_addr));
+        }
+      }
     }
+
     // Update the reference.
     RawObject* new_obj = RawObject::FromAddr(new_addr);
-    if (new_obj->IsOldObject()) {
+    if (!new_obj->IsNewObject()) {
       // Setting the mark bit above must not be ordered after a publishing store
       // of this object. Note this could be a publishing store even if the
       // object was promoted by an early invocation of ScavengePointer. Compare
@@ -254,6 +359,7 @@
       reinterpret_cast<std::atomic<RawObject*>*>(p)->store(
           new_obj, std::memory_order_release);
     } else {
+      ASSERT(scavenger_->to_->Contains(RawObject::ToAddr(new_obj)));
       *p = new_obj;
     }
     // Update the store buffer as needed.
@@ -262,20 +368,82 @@
     }
   }
 
+  DART_FORCE_INLINE
+  bool InstallForwardingPointer(uword addr,
+                                uword* old_header,
+                                uword new_header) {
+    if (parallel) {
+      return reinterpret_cast<std::atomic<uword>*>(addr)
+          ->compare_exchange_strong(*old_header, new_header,
+                                    std::memory_order_relaxed);
+    } else {
+      *reinterpret_cast<uword*>(addr) = new_header;
+      return true;
+    }
+  }
+
+  DART_FORCE_INLINE
+  uword TryAllocateCopy(intptr_t size) {
+    ASSERT(Utils::IsAligned(size, kObjectAlignment));
+    ScavengerLAB& lab = labs_[producer_index_];
+    uword result = lab.top;
+    uword new_top = result + size;
+    if (LIKELY(new_top <= lab.end)) {
+      ASSERT(scavenger_->to_->Contains(result));
+      ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
+      lab.top = new_top;
+      ASSERT((scavenger_->to_->Contains(new_top)) ||
+             (new_top == scavenger_->to_->end()));
+      return result;
+    }
+    return TryAllocateCopySlow(size);
+  }
+
+  DART_NOINLINE inline uword TryAllocateCopySlow(intptr_t size);
+
+  void MakeProducerTLABIterable() {
+    uword top = labs_[producer_index_].top;
+    uword end = labs_[producer_index_].end;
+    intptr_t size = end - top;
+    if (size != 0) {
+      ASSERT(Utils::IsAligned(size, kObjectAlignment));
+      ForwardingCorpse::AsForwarder(top, size);
+      ASSERT(RawObject::FromAddr(top)->HeapSize() == size);
+    }
+  }
+
+  inline void ProcessToSpace();
+  DART_FORCE_INLINE intptr_t ProcessCopied(RawObject* raw_obj);
+  inline void ProcessPromotedList();
+  inline void EnqueueWeakProperty(RawWeakProperty* raw_weak);
+  inline void MournWeakProperties();
+
   Thread* thread_;
   Scavenger* scavenger_;
   SemiSpace* from_;
-  Heap* heap_;
   PageSpace* page_space_;
-  RawWeakProperty* delayed_weak_properties_;
+  FreeList* freelist_;
   intptr_t bytes_promoted_;
   RawObject* visiting_old_object_;
 
-  friend class Scavenger;
+  PromotionWorkList promoted_list_;
+  RawWeakProperty* delayed_weak_properties_ = nullptr;
 
-  DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor);
+  struct ScavengerLAB {
+    uword top;
+    uword end;
+    uword resolved_top;
+  };
+  MallocGrowableArray<ScavengerLAB> labs_;
+  intptr_t consumer_index_ = 1;
+  intptr_t producer_index_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(ScavengerVisitorBase);
 };
 
+typedef ScavengerVisitorBase<false> SerialScavengerVisitor;
+typedef ScavengerVisitorBase<true> ParallelScavengerVisitor;
+
 class ScavengerWeakVisitor : public HandleVisitor {
  public:
   ScavengerWeakVisitor(Thread* thread, Scavenger* scavenger)
@@ -303,6 +471,103 @@
   DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor);
 };
 
+class ParallelScavengerTask : public ThreadPool::Task {
+ public:
+  ParallelScavengerTask(IsolateGroup* isolate_group,
+                        ThreadBarrier* barrier,
+                        ParallelScavengerVisitor* visitor,
+                        RelaxedAtomic<uintptr_t>* num_busy)
+      : isolate_group_(isolate_group),
+        barrier_(barrier),
+        visitor_(visitor),
+        num_busy_(num_busy) {}
+
+  virtual void Run() {
+    bool result = Thread::EnterIsolateGroupAsHelper(
+        isolate_group_, Thread::kScavengerTask, /*bypass_safepoint=*/true);
+    ASSERT(result);
+
+    RunEnteredIsolateGroup();
+
+    Thread::ExitIsolateGroupAsHelper(/*bypass_safepoint=*/true);
+
+    // This task is done. Notify the original thread.
+    barrier_->Exit();
+  }
+
+  void RunEnteredIsolateGroup() {
+    TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ParallelScavenge");
+
+    visitor_->ProcessRoots();
+
+    // Phase 1: Copying.
+    bool more_to_scavenge = false;
+    do {
+      do {
+        visitor_->ProcessSurvivors();
+
+        // I can't find more work right now. If no other task is busy,
+        // then there will never be more work (NB: 1 is *before* decrement).
+        if (num_busy_->fetch_sub(1u) == 1) break;
+
+        // Wait for some work to appear.
+        // TODO(iposva): Replace busy-waiting with a solution using Monitor,
+        // and redraw the boundaries between stack/visitor/task as needed.
+        while (!visitor_->HasWork() && num_busy_->load() > 0) {
+        }
+
+        // If no tasks are busy, there will never be more work.
+        if (num_busy_->load() == 0) break;
+
+        // I saw some work; get busy and compete for it.
+        num_busy_->fetch_add(1u);
+      } while (true);
+      // Wait for all scavengers to stop.
+      barrier_->Sync();
+#if defined(DEBUG)
+      ASSERT(num_busy_->load() == 0);
+      // Caveat: must not allow any marker to continue past the barrier
+      // before we checked num_busy, otherwise one of them might rush
+      // ahead and increment it.
+      barrier_->Sync();
+#endif
+      // Check if we have any pending properties with marked keys.
+      // Those might have been marked by another marker.
+      visitor_->ProcessWeakProperties();
+      more_to_scavenge = visitor_->HasWork();
+      if (more_to_scavenge) {
+        // We have more work to do. Notify others.
+        num_busy_->fetch_add(1u);
+      }
+
+      // Wait for all other scavengers to finish processing their pending
+      // weak properties and decide if they need to continue marking.
+      // Caveat: we need two barriers here to make this decision in lock step
+      // between all scavengers and the main thread.
+      barrier_->Sync();
+      if (!more_to_scavenge && (num_busy_->load() > 0)) {
+        // All scavengers continue to mark as long as any single marker has
+        // some work to do.
+        num_busy_->fetch_add(1u);
+        more_to_scavenge = true;
+      }
+      barrier_->Sync();
+    } while (more_to_scavenge);
+
+    // Phase 2: Weak processing, statistics.
+    visitor_->Finalize();
+    barrier_->Sync();
+  }
+
+ private:
+  IsolateGroup* isolate_group_;
+  ThreadBarrier* barrier_;
+  ParallelScavengerVisitor* visitor_;
+  RelaxedAtomic<uintptr_t>* num_busy_;
+
+  DISALLOW_COPY_AND_ASSIGN(ParallelScavengerTask);
+};
+
 SemiSpace::SemiSpace(VirtualMemory* reserved)
     : reserved_(reserved), region_(NULL, 0) {
   if (reserved != NULL) {
@@ -384,6 +649,9 @@
     old_cache = cache_;
     cache_ = this;
   }
+  // TODO(rmacnak): This can take an order of magnitude longer the rest of
+  // a scavenge. Consider moving it to another thread, perhaps the idle
+  // notifier.
   delete old_cache;
 }
 
@@ -404,7 +672,6 @@
     : heap_(heap),
       max_semi_capacity_in_words_(max_semi_capacity_in_words),
       scavenging_(false),
-      delayed_weak_properties_(NULL),
       gc_time_micros_(0),
       collections_(0),
       scavenge_words_per_micro_(kConservativeInitialScavengeSpeed),
@@ -543,8 +810,10 @@
   }
 }
 
-SemiSpace* Scavenger::Prologue(IsolateGroup* isolate_group) {
-  isolate_group->ReleaseStoreBuffers();
+SemiSpace* Scavenger::Prologue() {
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "Prologue");
+
+  heap_->isolate_group()->ReleaseStoreBuffers();
 
   if (FLAG_verify_store_buffer) {
     OS::PrintErr("Verifying remembered set before Scavenge...");
@@ -553,6 +822,10 @@
     OS::PrintErr(" done.\n");
   }
 
+  // Need to stash the old remembered set before any worker begins adding to the
+  // new remembered set.
+  blocks_ = heap_->isolate_group()->store_buffer()->TakeBlocks();
+
   // Flip the two semi-spaces so that to_ is always the space for allocating
   // objects.
   SemiSpace* from = to_;
@@ -572,13 +845,15 @@
   return from;
 }
 
-void Scavenger::Epilogue(IsolateGroup* isolate_group, SemiSpace* from) {
+void Scavenger::Epilogue(SemiSpace* from) {
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "Epilogue");
+
   // All objects in the to space have been copied from the from space at this
   // moment.
 
   // Ensure the mutator thread will fail the next allocation. This will force
   // mutator to allocate a new TLAB
-  isolate_group->ForEachIsolate(
+  heap_->isolate_group()->ForEachIsolate(
       [&](Isolate* isolate) {
         Thread* mutator_thread = isolate->mutator_thread();
         ASSERT((mutator_thread == NULL) || (!mutator_thread->HasActiveTLAB()));
@@ -646,7 +921,7 @@
     // a program to hit a store buffer overflow a bit sooner than it might
     // otherwise, since overflow is measured in blocks. Store buffer overflows
     // are very rare.
-    isolate_group->ReleaseStoreBuffers();
+    heap_->isolate_group()->ReleaseStoreBuffers();
 
     OS::PrintErr("Verifying remembered set after Scavenge...");
     heap_->WaitForSweeperTasksAtSafepoint(Thread::Current());
@@ -677,11 +952,21 @@
   return estimated_scavenge_completion <= deadline;
 }
 
-void Scavenger::IterateStoreBuffers(IsolateGroup* isolate_group,
-                                    ScavengerVisitor* visitor) {
+void Scavenger::IterateIsolateRoots(ObjectPointerVisitor* visitor) {
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "IterateIsolateRoots");
+  heap_->isolate_group()->VisitObjectPointers(
+      visitor, ValidationPolicy::kDontValidateFrames);
+}
+
+template <bool parallel>
+void Scavenger::IterateStoreBuffers(ScavengerVisitorBase<parallel>* visitor) {
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "IterateStoreBuffers");
+
   // Iterating through the store buffers.
   // Grab the deduplication sets out of the isolate's consolidated store buffer.
-  StoreBufferBlock* pending = isolate_group->store_buffer()->Blocks();
+  StoreBuffer* store_buffer = heap_->isolate_group()->store_buffer();
+  StoreBufferBlock* pending = blocks_;
+  blocks_ = nullptr;
   intptr_t total_count = 0;
   while (pending != NULL) {
     StoreBufferBlock* next = pending->next();
@@ -695,29 +980,35 @@
       ASSERT(raw_object->IsRemembered());
       raw_object->ClearRememberedBit();
       visitor->VisitingOldObject(raw_object);
+      // Note that this treats old-space WeakProperties as strong. A dead key
+      // won't be reclaimed until after the key is promoted.
       raw_object->VisitPointersNonvirtual(visitor);
     }
     pending->Reset();
     // Return the emptied block for recycling (no need to check threshold).
-    isolate_group->store_buffer()->PushBlock(pending,
-                                             StoreBuffer::kIgnoreThreshold);
+    store_buffer->PushBlock(pending, StoreBuffer::kIgnoreThreshold);
     pending = next;
   }
-
+  // Done iterating through old objects remembered in the store buffers.
   visitor->VisitingOldObject(NULL);
-  heap_->old_space()->VisitRememberedCards(visitor);
 
   heap_->RecordData(kStoreBufferEntries, total_count);
   heap_->RecordData(kDataUnused1, 0);
   heap_->RecordData(kDataUnused2, 0);
-  // Done iterating through old objects remembered in the store buffers.
+}
+
+template <bool parallel>
+void Scavenger::IterateRememberedCards(
+    ScavengerVisitorBase<parallel>* visitor) {
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "IterateRememberedCards");
+  heap_->old_space()->VisitRememberedCards(visitor);
   visitor->VisitingOldObject(NULL);
 }
 
-void Scavenger::IterateObjectIdTable(IsolateGroup* isolate_group,
-                                     ScavengerVisitor* visitor) {
+void Scavenger::IterateObjectIdTable(ObjectPointerVisitor* visitor) {
 #ifndef PRODUCT
-  isolate_group->ForEachIsolate(
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "IterateObjectIdTable");
+  heap_->isolate_group()->ForEachIsolate(
       [&](Isolate* isolate) {
         isolate->object_id_ring()->VisitPointers(visitor);
       },
@@ -725,28 +1016,39 @@
 #endif  // !PRODUCT
 }
 
-void Scavenger::IterateRoots(IsolateGroup* isolate_group,
-                             ScavengerVisitor* visitor) {
-#ifdef SUPPORT_TIMELINE
-  Thread* thread = Thread::Current();
-#endif
-  int64_t start = OS::GetCurrentMonotonicMicros();
-  {
-    TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessRoots");
-    isolate_group->VisitObjectPointers(visitor,
-                                       ValidationPolicy::kDontValidateFrames);
+enum RootSlices {
+  kIsolate = 0,
+  kObjectIdRing,
+  kCards,
+  kStoreBuffer,
+  kNumRootSlices,
+};
+
+template <bool parallel>
+void Scavenger::IterateRoots(ScavengerVisitorBase<parallel>* visitor) {
+  for (;;) {
+    intptr_t slice = root_slices_started_.fetch_add(1);
+    if (slice >= kNumRootSlices) {
+      return;  // No more slices.
+    }
+
+    switch (slice) {
+      case kIsolate:
+        IterateIsolateRoots(visitor);
+        break;
+      case kObjectIdRing:
+        IterateObjectIdTable(visitor);
+        break;
+      case kCards:
+        IterateRememberedCards(visitor);
+        break;
+      case kStoreBuffer:
+        IterateStoreBuffers(visitor);
+        break;
+      default:
+        UNREACHABLE();
+    }
   }
-  int64_t middle = OS::GetCurrentMonotonicMicros();
-  {
-    TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessRememberedSet");
-    IterateStoreBuffers(isolate_group, visitor);
-  }
-  IterateObjectIdTable(isolate_group, visitor);
-  int64_t end = OS::GetCurrentMonotonicMicros();
-  heap_->RecordData(kToKBAfterStoreBuffer, RoundWordsToKB(UsedInWords()));
-  heap_->RecordTime(kVisitIsolateRoots, middle - start);
-  heap_->RecordTime(kIterateStoreBuffers, end - middle);
-  heap_->RecordTime(kDummyScavengeTime, 0);
 }
 
 bool Scavenger::IsUnreachable(RawObject** p) {
@@ -770,81 +1072,85 @@
   return true;
 }
 
-void Scavenger::IterateWeakRoots(IsolateGroup* isolate_group,
-                                 HandleVisitor* visitor) {
-  isolate_group->VisitWeakPersistentHandles(visitor);
+void Scavenger::MournWeakHandles() {
+  Thread* thread = Thread::Current();
+  TIMELINE_FUNCTION_GC_DURATION(thread, "MournWeakHandles");
+  ScavengerWeakVisitor weak_visitor(thread, this);
+  heap_->isolate_group()->VisitWeakPersistentHandles(&weak_visitor);
 }
 
-void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) {
-  Thread* thread = Thread::Current();
+template <bool parallel>
+void ScavengerVisitorBase<parallel>::ProcessToSpace() {
+  intptr_t i = consumer_index_;
+  while (i <= producer_index_) {
+    uword resolved_top = labs_[i].resolved_top;
+    while (resolved_top < labs_[i].top) {
+      RawObject* raw_obj = RawObject::FromAddr(resolved_top);
+      resolved_top += ProcessCopied(raw_obj);
+    }
+    labs_[i].resolved_top = resolved_top;
 
-  // Iterate until all work has been drained.
-  while ((resolved_top_ < top_) || PromotedStackHasMore()) {
-    while (resolved_top_ < top_) {
-      RawObject* raw_obj = RawObject::FromAddr(resolved_top_);
-      intptr_t class_id = raw_obj->GetClassId();
-      intptr_t size;
-      if (class_id != kWeakPropertyCid) {
-        size = raw_obj->VisitPointersNonvirtual(visitor);
-      } else {
-        RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj);
-        size = ProcessWeakProperty(raw_weak, visitor);
-      }
-      resolved_top_ += size;
+    if (i == producer_index_) {
+      return;  // More objects may yet be copied to this TLAB.
     }
-    {
-      // Visit all the promoted objects and update/scavenge their internal
-      // pointers. Potentially this adds more objects to the to space.
-      while (PromotedStackHasMore()) {
-        RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack());
-        // Resolve or copy all objects referred to by the current object. This
-        // can potentially push more objects on this stack as well as add more
-        // objects to be resolved in the to space.
-        ASSERT(!raw_object->IsRemembered());
-        visitor->VisitingOldObject(raw_object);
-        raw_object->VisitPointersNonvirtual(visitor);
-        if (raw_object->IsMarked()) {
-          // Complete our promise from ScavengePointer. Note that marker cannot
-          // visit this object until it pops a block from the mark stack, which
-          // involves a memory fence from the mutex, so even on architectures
-          // with a relaxed memory model, the marker will see the fully
-          // forwarded contents of this object.
-          thread->MarkingStackAddObject(raw_object);
-        }
-      }
-      visitor->VisitingOldObject(NULL);
+
+    i++;
+    consumer_index_ = i;
+    ASSERT(consumer_index_ < labs_.length());
+  }
+}
+
+template <bool parallel>
+void ScavengerVisitorBase<parallel>::ProcessPromotedList() {
+  while (RawObject* raw_object = promoted_list_.Pop()) {
+    // Resolve or copy all objects referred to by the current object. This
+    // can potentially push more objects on this stack as well as add more
+    // objects to be resolved in the to space.
+    ASSERT(!raw_object->IsRemembered());
+    VisitingOldObject(raw_object);
+    raw_object->VisitPointersNonvirtual(this);
+    if (raw_object->IsMarked()) {
+      // Complete our promise from ScavengePointer. Note that marker cannot
+      // visit this object until it pops a block from the mark stack, which
+      // involves a memory fence from the mutex, so even on architectures
+      // with a relaxed memory model, the marker will see the fully
+      // forwarded contents of this object.
+      thread_->MarkingStackAddObject(raw_object);
     }
-    {
-      // Finished this round of scavenging. Process the pending weak properties
-      // for which the keys have become reachable. Potentially this adds more
-      // objects to the to space.
-      RawWeakProperty* cur_weak = delayed_weak_properties_;
-      delayed_weak_properties_ = NULL;
-      while (cur_weak != NULL) {
-        uword next_weak = cur_weak->ptr()->next_;
-        // Promoted weak properties are not enqueued. So we can guarantee that
-        // we do not need to think about store barriers here.
-        ASSERT(cur_weak->IsNewObject());
-        RawObject* raw_key = cur_weak->ptr()->key_;
-        ASSERT(raw_key->IsHeapObject());
-        // Key still points into from space even if the object has been
-        // promoted to old space by now. The key will be updated accordingly
-        // below when VisitPointers is run.
-        ASSERT(raw_key->IsNewObject());
-        uword raw_addr = RawObject::ToAddr(raw_key);
-        ASSERT(visitor->from_->Contains(raw_addr));
-        uword header = *reinterpret_cast<uword*>(raw_addr);
-        // Reset the next pointer in the weak property.
-        cur_weak->ptr()->next_ = 0;
-        if (IsForwarding(header)) {
-          cur_weak->VisitPointersNonvirtual(visitor);
-        } else {
-          EnqueueWeakProperty(cur_weak);
-        }
-        // Advance to next weak property in the queue.
-        cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
-      }
+  }
+  VisitingOldObject(NULL);
+}
+
+template <bool parallel>
+void ScavengerVisitorBase<parallel>::ProcessWeakProperties() {
+  // Finished this round of scavenging. Process the pending weak properties
+  // for which the keys have become reachable. Potentially this adds more
+  // objects to the to space.
+  RawWeakProperty* cur_weak = delayed_weak_properties_;
+  delayed_weak_properties_ = NULL;
+  while (cur_weak != NULL) {
+    uword next_weak = cur_weak->ptr()->next_;
+    // Promoted weak properties are not enqueued. So we can guarantee that
+    // we do not need to think about store barriers here.
+    ASSERT(cur_weak->IsNewObject());
+    RawObject* raw_key = cur_weak->ptr()->key_;
+    ASSERT(raw_key->IsHeapObject());
+    // Key still points into from space even if the object has been
+    // promoted to old space by now. The key will be updated accordingly
+    // below when VisitPointers is run.
+    ASSERT(raw_key->IsNewObject());
+    uword raw_addr = RawObject::ToAddr(raw_key);
+    ASSERT(from_->Contains(raw_addr));
+    uword header = *reinterpret_cast<uword*>(raw_addr);
+    // Reset the next pointer in the weak property.
+    cur_weak->ptr()->next_ = 0;
+    if (IsForwarding(header)) {
+      cur_weak->VisitPointersNonvirtual(this);
+    } else {
+      EnqueueWeakProperty(cur_weak);
     }
+    // Advance to next weak property in the queue.
+    cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
   }
 }
 
@@ -877,7 +1183,9 @@
 #endif  // !defined(PRODUCT)
 }
 
-void Scavenger::EnqueueWeakProperty(RawWeakProperty* raw_weak) {
+template <bool parallel>
+void ScavengerVisitorBase<parallel>::EnqueueWeakProperty(
+    RawWeakProperty* raw_weak) {
   ASSERT(raw_weak->IsHeapObject());
   ASSERT(raw_weak->IsNewObject());
   ASSERT(raw_weak->IsWeakProperty());
@@ -891,24 +1199,30 @@
   delayed_weak_properties_ = raw_weak;
 }
 
-uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak,
-                                     ScavengerVisitor* visitor) {
-  // The fate of the weak property is determined by its key.
-  RawObject* raw_key = raw_weak->ptr()->key_;
-  if (raw_key->IsHeapObject() && raw_key->IsNewObject()) {
-    uword raw_addr = RawObject::ToAddr(raw_key);
-    uword header = *reinterpret_cast<uword*>(raw_addr);
-    if (!IsForwarding(header)) {
-      // Key is white.  Enqueue the weak property.
-      EnqueueWeakProperty(raw_weak);
-      return raw_weak->HeapSize();
+template <bool parallel>
+intptr_t ScavengerVisitorBase<parallel>::ProcessCopied(RawObject* raw_obj) {
+  intptr_t class_id = raw_obj->GetClassId();
+  if (UNLIKELY(class_id == kWeakPropertyCid)) {
+    RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj);
+    // The fate of the weak property is determined by its key.
+    RawObject* raw_key = raw_weak->ptr()->key_;
+    if (raw_key->IsHeapObject() && raw_key->IsNewObject()) {
+      uword raw_addr = RawObject::ToAddr(raw_key);
+      uword header = *reinterpret_cast<uword*>(raw_addr);
+      if (!IsForwarding(header)) {
+        // Key is white.  Enqueue the weak property.
+        EnqueueWeakProperty(raw_weak);
+        return raw_weak->HeapSize();
+      }
     }
+    // Key is gray or black.  Make the weak property black.
   }
-  // Key is gray or black.  Make the weak property black.
-  return raw_weak->VisitPointersNonvirtual(visitor);
+  return raw_obj->VisitPointersNonvirtual(this);
 }
 
-void Scavenger::ProcessWeakReferences() {
+void Scavenger::MournWeakTables() {
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "MournWeakTables");
+
   auto rehash_weak_table = [](WeakTable* table, WeakTable* replacement_new,
                               WeakTable* replacement_old) {
     intptr_t size = table->size();
@@ -958,31 +1272,32 @@
         }
       },
       /*at_safepoint=*/true);
+}
 
+template <bool parallel>
+void ScavengerVisitorBase<parallel>::MournWeakProperties() {
   // The queued weak properties at this point do not refer to reachable keys,
   // so we clear their key and value fields.
-  {
-    RawWeakProperty* cur_weak = delayed_weak_properties_;
-    delayed_weak_properties_ = NULL;
-    while (cur_weak != NULL) {
-      uword next_weak = cur_weak->ptr()->next_;
-      // Reset the next pointer in the weak property.
-      cur_weak->ptr()->next_ = 0;
+  RawWeakProperty* cur_weak = delayed_weak_properties_;
+  delayed_weak_properties_ = NULL;
+  while (cur_weak != NULL) {
+    uword next_weak = cur_weak->ptr()->next_;
+    // Reset the next pointer in the weak property.
+    cur_weak->ptr()->next_ = 0;
 
 #if defined(DEBUG)
-      RawObject* raw_key = cur_weak->ptr()->key_;
-      uword raw_addr = RawObject::ToAddr(raw_key);
-      uword header = *reinterpret_cast<uword*>(raw_addr);
-      ASSERT(!IsForwarding(header));
-      ASSERT(raw_key->IsHeapObject());
-      ASSERT(raw_key->IsNewObject());  // Key still points into from space.
-#endif                                 // defined(DEBUG)
+    RawObject* raw_key = cur_weak->ptr()->key_;
+    uword raw_addr = RawObject::ToAddr(raw_key);
+    uword header = *reinterpret_cast<uword*>(raw_addr);
+    ASSERT(!IsForwarding(header));
+    ASSERT(raw_key->IsHeapObject());
+    ASSERT(raw_key->IsNewObject());  // Key still points into from space.
+#endif                               // defined(DEBUG)
 
-      WeakProperty::Clear(cur_weak);
+    WeakProperty::Clear(cur_weak);
 
-      // Advance to next weak property in the queue.
-      cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
-    }
+    // Advance to next weak property in the queue.
+    cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
   }
 }
 
@@ -1009,8 +1324,9 @@
       /*at_safepoint=*/true);
 }
 
-void Scavenger::AbandonTLABsLocked(IsolateGroup* isolate_group) {
+void Scavenger::AbandonTLABsLocked() {
   ASSERT(Thread::Current()->IsAtSafepoint());
+  IsolateGroup* isolate_group = heap_->isolate_group();
   MonitorLocker ml(isolate_group->threads_lock(), false);
   Thread* current = isolate_group->thread_registry()->active_list();
   while (current != NULL) {
@@ -1125,31 +1441,67 @@
   thread->set_end(0);
 }
 
+template <bool parallel>
+uword ScavengerVisitorBase<parallel>::TryAllocateCopySlow(intptr_t size) {
+  MakeProducerTLABIterable();
+
+  if (!scavenger_->TryAllocateNewTLAB(this)) {
+    return 0;
+  }
+
+  const uword result = labs_[producer_index_].top;
+  const intptr_t remaining =
+      labs_[producer_index_].end - labs_[producer_index_].top;
+  ASSERT(size <= remaining);
+  ASSERT(scavenger_->to_->Contains(result));
+  ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
+  labs_[producer_index_].top = result + size;
+  return result;
+}
+
+template <bool parallel>
+bool Scavenger::TryAllocateNewTLAB(ScavengerVisitorBase<parallel>* visitor) {
+  intptr_t size = kTLABSize;
+  ASSERT(Utils::IsAligned(size, kObjectAlignment));
+  ASSERT(heap_ != Dart::vm_isolate()->heap());
+  ASSERT(scavenging_);
+  MutexLocker ml(&space_lock_);
+  const uword result = top_;
+  const intptr_t remaining = end_ - top_;
+  if (remaining < size) {
+    // Grab whatever is remaining
+    size = Utils::RoundDown(remaining, kObjectAlignment);
+  }
+  if (size == 0) {
+    return false;
+  }
+  ASSERT(to_->Contains(result));
+  ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
+  top_ += size;
+  ASSERT(to_->Contains(top_) || (top_ == to_->end()));
+  ASSERT(result < top_);
+  visitor->AddNewTLAB(result, top_);
+  return true;
+}
+
 void Scavenger::Scavenge() {
-  auto isolate_group = heap_->isolate_group();
+  int64_t start = OS::GetCurrentMonotonicMicros();
+
   // Ensure that all threads for this isolate are at a safepoint (either stopped
   // or in native code). If two threads are racing at this point, the loser
   // will continue with its scavenge after waiting for the winner to complete.
   // TODO(koda): Consider moving SafepointThreads into allocation failure/retry
   // logic to avoid needless collections.
-
-  int64_t start = OS::GetCurrentMonotonicMicros();
-
   Thread* thread = Thread::Current();
   SafepointOperationScope safepoint_scope(thread);
 
+  int64_t safe_point = OS::GetCurrentMonotonicMicros();
+  heap_->RecordTime(kSafePoint, safe_point - start);
+
   // Scavenging is not reentrant. Make sure that is the case.
   ASSERT(!scavenging_);
   scavenging_ = true;
 
-  failed_to_promote_ = false;
-
-  PageSpace* page_space = heap_->old_space();
-  NoSafepointScope no_safepoints;
-
-  int64_t safe_point = OS::GetCurrentMonotonicMicros();
-  heap_->RecordTime(kSafePoint, safe_point - start);
-
   if (FLAG_verify_before_gc) {
     OS::PrintErr("Verifying before Scavenge...");
     heap_->WaitForSweeperTasksAtSafepoint(thread);
@@ -1158,48 +1510,33 @@
   }
 
   // Prepare for a scavenge.
-  AbandonTLABsLocked(isolate_group);
+  AbandonTLABsLocked();
+  failed_to_promote_ = false;
+  root_slices_started_ = 0;
   intptr_t abandoned_bytes = GetAndResetAbandonedInBytes();
-
   SpaceUsage usage_before = GetCurrentUsage();
   intptr_t promo_candidate_words =
       (survivor_end_ - FirstObjectStart()) / kWordSize;
-  SemiSpace* from = Prologue(isolate_group);
-  // The API prologue/epilogue may create/destroy zones, so we must not
-  // depend on zone allocations surviving beyond the epilogue callback.
-  {
-    StackZone zone(thread);
-    // Setup the visitor and run the scavenge.
-    ScavengerVisitor visitor(isolate_group, this, from);
-    page_space->AcquireDataLock();
-    IterateRoots(isolate_group, &visitor);
-    int64_t iterate_roots = OS::GetCurrentMonotonicMicros();
-    {
-      TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessToSpace");
-      ProcessToSpace(&visitor);
-    }
-    int64_t process_to_space = OS::GetCurrentMonotonicMicros();
-    {
-      TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessWeakHandles");
-      ScavengerWeakVisitor weak_visitor(thread, this);
-      IterateWeakRoots(isolate_group, &weak_visitor);
-    }
-    ProcessWeakReferences();
-    page_space->ReleaseDataLock();
+  SemiSpace* from = Prologue();
 
-    // Restore write-barrier assumptions.
-    isolate_group->RememberLiveTemporaries();
-
-    // Scavenge finished. Run accounting.
-    int64_t end = OS::GetCurrentMonotonicMicros();
-    heap_->RecordTime(kProcessToSpace, process_to_space - iterate_roots);
-    heap_->RecordTime(kIterateWeaks, end - process_to_space);
-    stats_history_.Add(ScavengeStats(start, end, usage_before,
-                                     GetCurrentUsage(), promo_candidate_words,
-                                     visitor.bytes_promoted() >> kWordSizeLog2,
-                                     abandoned_bytes >> kWordSizeLog2));
+  intptr_t bytes_promoted;
+  if (FLAG_scavenger_tasks == 0) {
+    bytes_promoted = SerialScavenge(from);
+  } else {
+    bytes_promoted = ParallelScavenge(from);
   }
-  Epilogue(isolate_group, from);
+  MournWeakHandles();
+  MournWeakTables();
+
+  // Restore write-barrier assumptions.
+  heap_->isolate_group()->RememberLiveTemporaries();
+
+  // Scavenge finished. Run accounting.
+  int64_t end = OS::GetCurrentMonotonicMicros();
+  stats_history_.Add(ScavengeStats(
+      start, end, usage_before, GetCurrentUsage(), promo_candidate_words,
+      bytes_promoted >> kWordSizeLog2, abandoned_bytes >> kWordSizeLog2));
+  Epilogue(from);
 
   if (FLAG_verify_after_gc) {
     OS::PrintErr("Verifying after Scavenge...");
@@ -1213,6 +1550,69 @@
   scavenging_ = false;
 }
 
+intptr_t Scavenger::SerialScavenge(SemiSpace* from) {
+  FreeList* freelist = heap_->old_space()->DataFreeList(0);
+  SerialScavengerVisitor visitor(heap_->isolate_group(), this, from, freelist,
+                                 &promotion_stack_);
+  visitor.ProcessRoots();
+  {
+    TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessToSpace");
+    visitor.ProcessAll();
+  }
+  visitor.Finalize();
+
+  // Donate last bit of TLAB.
+  uword top = visitor.last_top();
+  uword end = visitor.last_end();
+  if (end == top_) {
+    top_ = top;
+  }
+  return visitor.bytes_promoted();
+}
+
+intptr_t Scavenger::ParallelScavenge(SemiSpace* from) {
+  intptr_t bytes_promoted = 0;
+  const intptr_t num_tasks = FLAG_scavenger_tasks;
+  ASSERT(num_tasks > 0);
+
+  ThreadBarrier barrier(num_tasks, heap_->barrier(), heap_->barrier_done());
+  RelaxedAtomic<uintptr_t> num_busy = num_tasks;
+
+  ParallelScavengerVisitor** visitors =
+      new ParallelScavengerVisitor*[num_tasks];
+  for (intptr_t i = 0; i < num_tasks; i++) {
+    FreeList* freelist = heap_->old_space()->DataFreeList(i);
+    visitors[i] = new ParallelScavengerVisitor(
+        heap_->isolate_group(), this, from, freelist, &promotion_stack_);
+    if (i < (num_tasks - 1)) {
+      // Begin scavenging on a helper thread.
+      bool result = Dart::thread_pool()->Run<ParallelScavengerTask>(
+          heap_->isolate_group(), &barrier, visitors[i], &num_busy);
+      ASSERT(result);
+    } else {
+      // Last worker is the main thread.
+      ParallelScavengerTask task(heap_->isolate_group(), &barrier, visitors[i],
+                                 &num_busy);
+      task.RunEnteredIsolateGroup();
+      barrier.Exit();
+    }
+  }
+
+  for (intptr_t i = 0; i < num_tasks; i++) {
+    bytes_promoted += visitors[i]->bytes_promoted();
+    // Donate last bit of TLAB.
+    uword top = visitors[i]->last_top();
+    uword end = visitors[i]->last_end();
+    if (end == top_) {
+      top_ = top;
+    }
+    delete visitors[i];
+  }
+
+  delete[] visitors;
+  return bytes_promoted;
+}
+
 void Scavenger::WriteProtect(bool read_only) {
   ASSERT(!scavenging_);
   to_->WriteProtect(read_only);
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 9dacdd3..d02d623 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -24,7 +24,8 @@
 class Isolate;
 class JSONObject;
 class ObjectSet;
-class ScavengerVisitor;
+template <bool parallel>
+class ScavengerVisitorBase;
 
 // Wrapper around VirtualMemory that adds caching and handles the empty case.
 class SemiSpace {
@@ -139,23 +140,8 @@
   }
   void MakeTLABIterable(Thread* thread);
   void AbandonRemainingTLAB(Thread* thread);
-
-  uword AllocateGC(intptr_t size) {
-    ASSERT(Utils::IsAligned(size, kObjectAlignment));
-    ASSERT(heap_ != Dart::vm_isolate()->heap());
-    ASSERT(scavenging_);
-    uword result = top_;
-    intptr_t remaining = end_ - top_;
-
-    // This allocation happens only in GC and only when copying objects to
-    // the new to_ space. It must succeed.
-    ASSERT(size <= remaining);
-    ASSERT(to_->Contains(result));
-    ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
-    top_ += size;
-    ASSERT((to_->Contains(top_)) || (top_ == to_->end()));
-    return result;
-  }
+  template <bool parallel>
+  bool TryAllocateNewTLAB(ScavengerVisitorBase<parallel>* visitor);
 
   // Collect the garbage in this scavenger.
   void Scavenge();
@@ -163,15 +149,6 @@
   // Promote all live objects.
   void Evacuate();
 
-  uword top() { return top_; }
-  uword end() { return end_; }
-
-  void set_top(uword value) { top_ = value; }
-  void set_end(uword value) {
-    ASSERT(to_->end() == value);
-    end_ = value;
-  }
-
   // Report (TLAB) abandoned bytes that should be taken account when
   // deciding whether to grow new space or not.
   void AddAbandonedInBytes(intptr_t value) {
@@ -225,6 +202,8 @@
   void MakeNewSpaceIterable() const;
   int64_t FreeSpaceInWords(Isolate* isolate) const;
 
+  bool scavenging() const { return scavenging_; }
+
  private:
   static const intptr_t kTLABSize = 512 * KB;
 
@@ -264,58 +243,33 @@
   void TryAllocateNewTLAB(Thread* thread);
   void AddAbandonedInBytesLocked(intptr_t value) { abandoned_ += value; }
   void AbandonRemainingTLABLocked(Thread* thread);
-  void AbandonTLABsLocked(IsolateGroup* isolate_group);
+  void AbandonTLABsLocked();
 
   uword FirstObjectStart() const {
     return to_->start() + kNewObjectAlignmentOffset;
   }
-  SemiSpace* Prologue(IsolateGroup* isolate_group);
-  void IterateStoreBuffers(IsolateGroup* isolate_group,
-                           ScavengerVisitor* visitor);
-  void IterateObjectIdTable(IsolateGroup* isolate_group,
-                            ScavengerVisitor* visitor);
-  void IterateRoots(IsolateGroup* isolate_group, ScavengerVisitor* visitor);
-  void IterateWeakProperties(IsolateGroup* isolate_group,
-                             ScavengerVisitor* visitor);
-  void IterateWeakReferences(IsolateGroup* isolate_group,
-                             ScavengerVisitor* visitor);
-  void IterateWeakRoots(IsolateGroup* isolate_group, HandleVisitor* visitor);
-  void ProcessToSpace(ScavengerVisitor* visitor);
-  void EnqueueWeakProperty(RawWeakProperty* raw_weak);
-  uword ProcessWeakProperty(RawWeakProperty* raw_weak,
-                            ScavengerVisitor* visitor);
-  void Epilogue(IsolateGroup* isolate_group, SemiSpace* from);
+  SemiSpace* Prologue();
+  intptr_t ParallelScavenge(SemiSpace* from);
+  intptr_t SerialScavenge(SemiSpace* from);
+  void IterateIsolateRoots(ObjectPointerVisitor* visitor);
+  template <bool parallel>
+  void IterateStoreBuffers(ScavengerVisitorBase<parallel>* visitor);
+  template <bool parallel>
+  void IterateRememberedCards(ScavengerVisitorBase<parallel>* visitor);
+  void IterateObjectIdTable(ObjectPointerVisitor* visitor);
+  template <bool parallel>
+  void IterateRoots(ScavengerVisitorBase<parallel>* visitor);
+  void MournWeakHandles();
+  void Epilogue(SemiSpace* from);
 
   bool IsUnreachable(RawObject** p);
 
   void VerifyStoreBuffers();
 
-  // During a scavenge we need to remember the promoted objects.
-  // This is implemented as a stack of objects at the end of the to space. As
-  // object sizes are always greater than sizeof(uword) and promoted objects do
-  // not consume space in the to space they leave enough room for this stack.
-  void PushToPromotedStack(uword addr) {
-    ASSERT(scavenging_);
-    end_ -= sizeof(addr);
-    ASSERT(end_ > top_);
-    *reinterpret_cast<uword*>(end_) = addr;
-  }
-  uword PopFromPromotedStack() {
-    ASSERT(scavenging_);
-    uword result = *reinterpret_cast<uword*>(end_);
-    end_ += sizeof(result);
-    ASSERT(end_ <= to_->end());
-    return result;
-  }
-  bool PromotedStackHasMore() const {
-    ASSERT(scavenging_);
-    return end_ < to_->end();
-  }
-
   void UpdateMaxHeapCapacity();
   void UpdateMaxHeapUsage();
 
-  void ProcessWeakReferences();
+  void MournWeakTables();
 
   intptr_t NewSizeInWords(intptr_t old_size_in_words) const;
 
@@ -337,13 +291,14 @@
   // whether to grow newspace or not.
   intptr_t abandoned_ = 0;
 
+  PromotionStack promotion_stack_;
+
   intptr_t max_semi_capacity_in_words_;
 
   // Keep track whether a scavenge is currently running.
   bool scavenging_;
-
-  // Keep track of pending weak properties discovered while scagenging.
-  RawWeakProperty* delayed_weak_properties_;
+  RelaxedAtomic<intptr_t> root_slices_started_;
+  StoreBufferBlock* blocks_;
 
   int64_t gc_time_micros_;
   intptr_t collections_;
@@ -361,7 +316,8 @@
   // Protects new space during the allocation of new TLABs
   mutable Mutex space_lock_;
 
-  friend class ScavengerVisitor;
+  template <bool>
+  friend class ScavengerVisitorBase;
   friend class ScavengerWeakVisitor;
 
   DISALLOW_COPY_AND_ASSIGN(Scavenger);
diff --git a/runtime/vm/heap/sweeper.cc b/runtime/vm/heap/sweeper.cc
index 405357d..2a19fba 100644
--- a/runtime/vm/heap/sweeper.cc
+++ b/runtime/vm/heap/sweeper.cc
@@ -111,20 +111,17 @@
                         HeapPage* first,
                         HeapPage* last,
                         HeapPage* large_first,
-                        HeapPage* large_last,
-                        FreeList* freelist)
+                        HeapPage* large_last)
       : task_isolate_group_(isolate_group),
         old_space_(old_space),
         first_(first),
         last_(last),
         large_first_(large_first),
-        large_last_(large_last),
-        freelist_(freelist) {
+        large_last_(large_last) {
     ASSERT(task_isolate_group_ != NULL);
     ASSERT(first_ != NULL);
     ASSERT(old_space_ != NULL);
     ASSERT(last_ != NULL);
-    ASSERT(freelist_ != NULL);
     MonitorLocker ml(old_space_->tasks_lock());
     old_space_->set_tasks(old_space_->tasks() + 1);
     old_space_->set_phase(PageSpace::kSweepingLarge);
@@ -169,6 +166,8 @@
         ml.NotifyAll();
       }
 
+      intptr_t shard = 0;
+      const intptr_t num_shards = Utils::Maximum(FLAG_scavenger_tasks, 1);
       page = first_;
       prev_page = NULL;
       while (page != NULL) {
@@ -181,7 +180,9 @@
           next_page = page->next();
         }
         ASSERT(page->type() == HeapPage::kData);
-        bool page_in_use = sweeper.SweepPage(page, freelist_, false);
+        shard = (shard + 1) % num_shards;
+        bool page_in_use =
+            sweeper.SweepPage(page, old_space_->DataFreeList(shard), false);
         if (page_in_use) {
           prev_page = page;
         } else {
@@ -215,7 +216,6 @@
   HeapPage* last_;
   HeapPage* large_first_;
   HeapPage* large_last_;
-  FreeList* freelist_;
 };
 
 void GCSweeper::SweepConcurrent(IsolateGroup* isolate_group,
@@ -226,7 +226,7 @@
                                 FreeList* freelist) {
   bool result = Dart::thread_pool()->Run<ConcurrentSweeperTask>(
       isolate_group, isolate_group->heap()->old_space(), first, last,
-      large_first, large_last, freelist);
+      large_first, large_last);
   ASSERT(result);
 }
 
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index e61fd02..e344120 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -544,35 +544,14 @@
                                                  const Code& code) {
   if (code.raw() == object_store->build_method_extractor_code()) {
     return "_iso_stub_BuildMethodExtractorStub";
-  } else if (code.raw() == object_store->dispatch_table_null_error_stub()) {
-    return "_iso_stub_DispatchTableNullErrorStub";
-  } else if (code.raw() == object_store->null_error_stub_with_fpu_regs_stub()) {
-    return "_iso_stub_NullErrorSharedWithFPURegsStub";
-  } else if (code.raw() ==
-             object_store->null_error_stub_without_fpu_regs_stub()) {
-    return "_iso_stub_NullErrorSharedWithoutFPURegsStub";
-  } else if (code.raw() ==
-             object_store->null_arg_error_stub_with_fpu_regs_stub()) {
-    return "_iso_stub_NullArgErrorSharedWithFPURegsStub";
-  } else if (code.raw() ==
-             object_store->null_arg_error_stub_without_fpu_regs_stub()) {
-    return "_iso_stub_NullArgErrorSharedWithoutFPURegsStub";
-  } else if (code.raw() == object_store->allocate_mint_with_fpu_regs_stub()) {
-    return "_iso_stub_AllocateMintWithFPURegsStub";
-  } else if (code.raw() ==
-             object_store->allocate_mint_without_fpu_regs_stub()) {
-    return "_iso_stub_AllocateMintWithoutFPURegsStub";
-  } else if (code.raw() ==
-             object_store->stack_overflow_stub_with_fpu_regs_stub()) {
-    return "_iso_stub_StackOverflowStubWithFPURegsStub";
-  } else if (code.raw() ==
-             object_store->stack_overflow_stub_without_fpu_regs_stub()) {
-    return "_iso_stub_StackOverflowStubWithoutFPURegsStub";
-  } else if (code.raw() == object_store->write_barrier_wrappers_stub()) {
-    return "_iso_stub_WriteBarrierWrappersStub";
-  } else if (code.raw() == object_store->array_write_barrier_stub()) {
-    return "_iso_stub_ArrayWriteBarrierStub";
   }
+
+#define DO(member, name)                                                       \
+  if (code.raw() == object_store->member()) {                                  \
+    return "_iso_stub_" #name "Stub";                                          \
+  }
+  OBJECT_STORE_STUB_CODE_LIST(DO)
+#undef DO
   return nullptr;
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -605,7 +584,7 @@
                        code_index);
   } else if (owner_.IsAbstractType()) {
     const char* name = namer_.StubNameForType(AbstractType::Cast(owner_));
-    return OS::SCreate(zone_, "%s%s", prefix, name);
+    return OS::SCreate(zone_, "%s%s_%" Pd, prefix, name, code_index);
   } else if (owner_.IsFunction()) {
     const char* name = Function::Cast(owner_).ToQualifiedCString();
     EnsureAssemblerIdentifier(const_cast<char*>(name));
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index 2dab069..545d5eb 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -382,8 +382,19 @@
 bool PcRelativeCallPattern::IsValid() const {
   // bl.<cond> <offset>
   const uint32_t word = *reinterpret_cast<uint32_t*>(pc_);
-  const uint32_t branch_link = 0x05;
-  return ((word >> kTypeShift) & ((1 << kTypeBits) - 1)) == branch_link;
+  const uint32_t branch = 0x05;
+  const uword type = ((word >> kTypeShift) & ((1 << kTypeBits) - 1));
+  const uword link = ((word >> kLinkShift) & ((1 << kLinkBits) - 1));
+  return type == branch && link == 1;
+}
+
+bool PcRelativeTailCallPattern::IsValid() const {
+  // b.<cond> <offset>
+  const uint32_t word = *reinterpret_cast<uint32_t*>(pc_);
+  const uint32_t branch = 0x05;
+  const uword type = ((word >> kTypeShift) & ((1 << kTypeBits) - 1));
+  const uword link = ((word >> kLinkShift) & ((1 << kLinkBits) - 1));
+  return type == branch && link == 0;
 }
 
 void PcRelativeTrampolineJumpPattern::Initialize() {
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h
index 65bfdb3..92f8acf 100644
--- a/runtime/vm/instructions_arm.h
+++ b/runtime/vm/instructions_arm.h
@@ -188,13 +188,13 @@
   const uword pc_;
 };
 
-class PcRelativeCallPattern : public ValueObject {
+class PcRelativeCallPatternBase : public ValueObject {
  public:
   // 24 bit signed integer which will get multiplied by 4.
-  static const intptr_t kLowerCallingRange = -(1 << 25);
+  static const intptr_t kLowerCallingRange = -(1 << 25) + Instr::kPCReadOffset;
   static const intptr_t kUpperCallingRange = (1 << 25) - 1;
 
-  explicit PcRelativeCallPattern(uword pc) : pc_(pc) {}
+  explicit PcRelativeCallPatternBase(uword pc) : pc_(pc) {}
 
   static const int kLengthInBytes = 1 * Instr::kInstrSize;
 
@@ -217,12 +217,25 @@
 #endif
   }
 
-  bool IsValid() const;
-
- private:
+ protected:
   uword pc_;
 };
 
+class PcRelativeCallPattern : public PcRelativeCallPatternBase {
+ public:
+  explicit PcRelativeCallPattern(uword pc) : PcRelativeCallPatternBase(pc) {}
+
+  bool IsValid() const;
+};
+
+class PcRelativeTailCallPattern : public PcRelativeCallPatternBase {
+ public:
+  explicit PcRelativeTailCallPattern(uword pc)
+      : PcRelativeCallPatternBase(pc) {}
+
+  bool IsValid() const;
+};
+
 // Instruction pattern for a tail call to a signed 32-bit PC-relative offset
 //
 // The AOT compiler can emit PC-relative calls. If the destination of such a
diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc
index 3e3db82..f308138 100644
--- a/runtime/vm/instructions_arm64.cc
+++ b/runtime/vm/instructions_arm64.cc
@@ -494,6 +494,13 @@
   return (word >> 26) == branch_link;
 }
 
+bool PcRelativeTailCallPattern::IsValid() const {
+  // b <offset>
+  const uint32_t word = *reinterpret_cast<uint32_t*>(pc_);
+  const uint32_t branch_link = 0x5;
+  return (word >> 26) == branch_link;
+}
+
 void PcRelativeTrampolineJumpPattern::Initialize() {
 #if !defined(DART_PRECOMPILED_RUNTIME)
   uint32_t* pattern = reinterpret_cast<uint32_t*>(pattern_start_);
diff --git a/runtime/vm/instructions_arm64.h b/runtime/vm/instructions_arm64.h
index dfbf7d3..ab8bff9 100644
--- a/runtime/vm/instructions_arm64.h
+++ b/runtime/vm/instructions_arm64.h
@@ -198,13 +198,13 @@
   const uword pc_;
 };
 
-class PcRelativeCallPattern : public ValueObject {
+class PcRelativePatternBase : public ValueObject {
  public:
   // 26 bit signed integer which will get multiplied by 4.
   static const intptr_t kLowerCallingRange = -(1 << 27);
   static const intptr_t kUpperCallingRange = (1 << 27) - 1;
 
-  explicit PcRelativeCallPattern(uword pc) : pc_(pc) {}
+  explicit PcRelativePatternBase(uword pc) : pc_(pc) {}
 
   static const int kLengthInBytes = 1 * Instr::kInstrSize;
 
@@ -229,10 +229,24 @@
 
   bool IsValid() const;
 
- private:
+ protected:
   uword pc_;
 };
 
+class PcRelativeCallPattern : public PcRelativePatternBase {
+ public:
+  explicit PcRelativeCallPattern(uword pc) : PcRelativePatternBase(pc) {}
+
+  bool IsValid() const;
+};
+
+class PcRelativeTailCallPattern : public PcRelativePatternBase {
+ public:
+  explicit PcRelativeTailCallPattern(uword pc) : PcRelativePatternBase(pc) {}
+
+  bool IsValid() const;
+};
+
 // Instruction pattern for a tail call to a signed 32-bit PC-relative offset
 //
 // The AOT compiler can emit PC-relative calls. If the destination of such a
diff --git a/runtime/vm/instructions_x64.h b/runtime/vm/instructions_x64.h
index da8f077..81e69c6 100644
--- a/runtime/vm/instructions_x64.h
+++ b/runtime/vm/instructions_x64.h
@@ -180,6 +180,15 @@
   uword pattern_start_;
 };
 
+class PcRelativeTailCallPattern : public PcRelativeTrampolineJumpPattern {
+ public:
+  static const intptr_t kLowerCallingRange = -(1ul << 31) + kLengthInBytes;
+  static const intptr_t kUpperCallingRange = (1ul << 31) - 1;
+
+  explicit PcRelativeTailCallPattern(uword pc)
+      : PcRelativeTrampolineJumpPattern(pc) {}
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_INSTRUCTIONS_X64_H_
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index d9d98f0..bd0db66 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -79,6 +79,7 @@
     FLAG_background_compilation = false;  // Timing dependent.
     FLAG_concurrent_mark = false;         // Timing dependent.
     FLAG_concurrent_sweep = false;        // Timing dependent.
+    FLAG_scavenger_tasks = 0;             // Timing dependent.
     FLAG_random_seed = 0x44617274;        // "Dart"
   }
 }
@@ -2497,7 +2498,8 @@
     ASSERT(Thread::Current()->IsAtSafepoint() ||
            (Thread::Current()->task_kind() == Thread::kMutatorTask) ||
            (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
-           (Thread::Current()->task_kind() == Thread::kCompactorTask));
+           (Thread::Current()->task_kind() == Thread::kCompactorTask) ||
+           (Thread::Current()->task_kind() == Thread::kScavengerTask));
     for (Isolate* isolate : isolates_) {
       function(isolate);
     }
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 67d8ad5..1c936d4 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -2124,6 +2124,10 @@
     }
     value_ ^= instance.GetField(field);
     if (value_.raw() == Object::sentinel().raw()) {
+      if (field.is_late()) {
+        // Late fields already have lazy initialization logic.
+        return;
+      }
       // Needs guard for initialization.
       ASSERT(!FLAG_identity_reload);
       field.set_needs_load_guard(true);
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index fab8c65..ed39f1a 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -4477,6 +4477,48 @@
   EXPECT_STREQ("ac", SimpleInvokeStr(lib, "main"));
 }
 
+TEST_CASE(IsolateReload_StaticTargetArityChange) {
+  const char* kScript = R"(
+    class A {
+      final x;
+      final y;
+      const A(this.x, this.y);
+    }
+
+    dynamic closure;
+
+    main() {
+      closure = () => A(1, 2);
+      return "okay";
+    }
+  )";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
+
+  const char* kReloadScript = R"(
+    class A {
+      final x;
+      const A(this.x);
+    }
+
+    dynamic closure;
+
+    main() {
+      // Call the old closure, which will try to call A(1, 2).
+      closure();
+
+      return "okay";
+    }
+  )";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_ERROR(SimpleInvokeError(lib, "main"),
+               "Unimplemented handling of static target arity change");
+}
+
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index e68ef66..ca2f6e2 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -60,6 +60,13 @@
 
 enum LogicalOperator { kAnd, kOr };
 
+enum NonNullableByDefaultCompiledMode {
+  kNNBDDisabled,
+  kNNBDWeak,
+  kNNBDStrong,
+  kNNBDAgnostic
+};
+
 class Program {
  public:
   // Read a kernel Program from the given Reader. Note the returned Program
@@ -100,6 +107,7 @@
   bool single_program_;
   uint32_t binary_version_;
   NameIndex main_method_reference_;  // Procedure.
+  NonNullableByDefaultCompiledMode compilation_mode_;
   intptr_t library_count_;
 
   // The offset from the start of the binary to the start of the source table.
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index fe02d0b..3d5a2c3 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -85,7 +85,7 @@
 
 std::unique_ptr<Program> Program::ReadFrom(Reader* reader, const char** error) {
   if (reader->size() < 60) {
-    // A kernel file currently contains at least the following:
+    // A kernel file (v41) currently contains at least the following:
     //   * Magic number (32)
     //   * Kernel version (32)
     //   * List of problems (8)
@@ -94,9 +94,9 @@
     //   * Metadata length (32)
     //   * Length of string table (8)
     //   * Length of constant table (8)
-    //   * Component index (10 * 32)
+    //   * Component index (11 * 32)
     //
-    // so is at least 60 bytes.
+    // so is at least 64 bytes.
     // (Technically it will also contain an empty entry in both source map and
     // string table, taking up another 8 bytes.)
     if (error != nullptr) {
@@ -150,10 +150,17 @@
   // Read backwards at the end.
   program->library_count_ = reader->ReadFromIndexNoReset(
       reader->size_, LibraryCountFieldCountFromEnd, 1, 0);
+  static_assert(kMinSupportedKernelFormatVersion < 41, "cleanup this code");
+  intptr_t count_from_first_library_offset =
+      SourceTableFieldCountFromFirstLibraryOffsetPre41;
+  if (formatVersion >= 41) {
+    count_from_first_library_offset =
+        SourceTableFieldCountFromFirstLibraryOffset41Plus;
+  }
   program->source_table_offset_ = reader->ReadFromIndexNoReset(
       reader->size_,
       LibraryCountFieldCountFromEnd + 1 + program->library_count_ + 1 +
-          SourceTableFieldCountFromFirstLibraryOffset,
+          count_from_first_library_offset,
       1, 0);
   program->name_table_offset_ = reader->ReadUInt32();
   program->metadata_payloads_offset_ = reader->ReadUInt32();
@@ -162,6 +169,13 @@
   program->constant_table_offset_ = reader->ReadUInt32();
 
   program->main_method_reference_ = NameIndex(reader->ReadUInt32() - 1);
+  if (formatVersion >= 41) {
+    NonNullableByDefaultCompiledMode compilation_mode =
+        static_cast<NonNullableByDefaultCompiledMode>(reader->ReadUInt32());
+    program->compilation_mode_ = compilation_mode;
+  } else {
+    program->compilation_mode_ = kNNBDDisabled;
+  }
 
   return program;
 }
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 43c3700..4ceb1c7 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
 
 // Both version numbers are inclusive.
 static const uint32_t kMinSupportedKernelFormatVersion = 29;
-static const uint32_t kMaxSupportedKernelFormatVersion = 40;
+static const uint32_t kMaxSupportedKernelFormatVersion = 42;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -199,7 +199,9 @@
 
 static const int SpecializedIntLiteralBias = 3;
 static const int LibraryCountFieldCountFromEnd = 1;
-static const int SourceTableFieldCountFromFirstLibraryOffset = 6;
+static const int KernelFormatVersionOffset = 4;
+static const int SourceTableFieldCountFromFirstLibraryOffsetPre41 = 6;
+static const int SourceTableFieldCountFromFirstLibraryOffset41Plus = 7;
 
 static const int HeaderSize = 8;  // 'magic', 'formatVersion'.
 
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 0b07be9..b36b2a9 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -2182,7 +2182,8 @@
   }
   ASSERT(field.NeedsGetter());
 
-  if (field.is_late() && field.has_nontrivial_initializer()) {
+  if (field.is_late() && !field.is_static() &&
+      field.has_nontrivial_initializer()) {
     // Late fields are initialized to Object::sentinel, which is a flavor of
     // null. So we need to record that store so that the field guard doesn't
     // prematurely optimise out the late field's sentinel checking logic.
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 19deb0a..d0550ee3 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -45,9 +45,9 @@
 }
 
 RawFunction* MegamorphicCacheTable::miss_handler(Isolate* isolate) {
-  ASSERT(isolate->object_store()->megamorphic_miss_function() !=
+  ASSERT(isolate->object_store()->megamorphic_call_miss_function() !=
          Function::null());
-  return isolate->object_store()->megamorphic_miss_function();
+  return isolate->object_store()->megamorphic_call_miss_function();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -56,8 +56,8 @@
   // normal Dart function.
   compiler::ObjectPoolBuilder object_pool_builder;
   const Code& code = Code::Handle(StubCode::Generate(
-      "_stub_MegamorphicMiss", &object_pool_builder,
-      compiler::StubCodeCompiler::GenerateMegamorphicMissStub));
+      "_stub_MegamorphicCallMiss", &object_pool_builder,
+      compiler::StubCodeCompiler::GenerateMegamorphicCallMissStub));
 
   const auto& object_pool =
       ObjectPool::Handle(ObjectPool::NewFromBuilder(object_pool_builder));
@@ -69,14 +69,14 @@
   code.set_exception_handlers(Object::empty_exception_handlers());
   const Class& cls =
       Class::Handle(Type::Handle(Type::DartFunctionType()).type_class());
-  const Function& function = Function::Handle(
-      Function::New(Symbols::MegamorphicMiss(), RawFunction::kRegularFunction,
-                    true,   // Static, but called as a method.
-                    false,  // Not const.
-                    false,  // Not abstract.
-                    false,  // Not external.
-                    false,  // Not native.
-                    cls, TokenPosition::kNoSource));
+  const Function& function = Function::Handle(Function::New(
+      Symbols::MegamorphicCallMiss(), RawFunction::kRegularFunction,
+      true,   // Static, but called as a method.
+      false,  // Not const.
+      false,  // Not abstract.
+      false,  // Not external.
+      false,  // Not native.
+      cls, TokenPosition::kNoSource));
   function.set_result_type(Type::Handle(Type::DynamicType()));
   function.set_is_debuggable(false);
   function.set_is_visible(false);
@@ -84,9 +84,9 @@
   // For inclusion in Snapshot::kFullJIT.
   function.set_unoptimized_code(code);
 
-  ASSERT(isolate->object_store()->megamorphic_miss_function() ==
+  ASSERT(isolate->object_store()->megamorphic_call_miss_function() ==
          Function::null());
-  isolate->object_store()->SetMegamorphicMissHandler(code, function);
+  isolate->object_store()->SetMegamorphicCallMissHandler(code, function);
 }
 
 void MegamorphicCacheTable::ReInitMissHandlerCode(
@@ -95,14 +95,15 @@
   ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
 
   const Code& code = Code::Handle(StubCode::Generate(
-      "_stub_MegamorphicMiss", wrapper,
-      compiler::StubCodeCompiler::GenerateMegamorphicMissStub));
+      "_stub_MegamorphicCallMiss", wrapper,
+      compiler::StubCodeCompiler::GenerateMegamorphicCallMissStub));
   code.set_exception_handlers(Object::empty_exception_handlers());
 
   auto object_store = isolate->object_store();
-  auto& function = Function::Handle(object_store->megamorphic_miss_function());
+  auto& function =
+      Function::Handle(object_store->megamorphic_call_miss_function());
   function.AttachCode(code);
-  object_store->SetMegamorphicMissHandler(code, function);
+  object_store->SetMegamorphicCallMissHandler(code, function);
 }
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b51f1c1..6df21cb 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -128,6 +128,8 @@
 #undef DEFINE_SHARED_READONLY_HANDLE
 
 RawObject* Object::null_ = reinterpret_cast<RawObject*>(RAW_NULL);
+RawBool* Object::true_ = reinterpret_cast<RawBool*>(RAW_NULL);
+RawBool* Object::false_ = reinterpret_cast<RawBool*>(RAW_NULL);
 RawClass* Object::class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -534,7 +536,7 @@
   return bytecode.raw();
 }
 
-void Object::InitNull(Isolate* isolate) {
+void Object::InitNullAndBool(Isolate* isolate) {
   // Should only be run by the vm isolate.
   ASSERT(isolate == Dart::vm_isolate());
 
@@ -552,6 +554,42 @@
     // The call below is using 'null_' to initialize itself.
     InitializeObject(address, kNullCid, Instance::InstanceSize());
   }
+
+  // Allocate and initialize the bool instances.
+  // These must be allocated such that at kBoolValueBitPosition, the address
+  // of true is 0 and the address of false is 1, and their addresses are
+  // otherwise identical.
+  {
+    // Allocate a dummy bool object to give true the desired alignment.
+    uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
+    InitializeObject(address, kBoolCid, Bool::InstanceSize());
+  }
+  {
+    // Allocate true.
+    uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
+    true_ = reinterpret_cast<RawBool*>(address + kHeapObjectTag);
+    InitializeObject(address, kBoolCid, Bool::InstanceSize());
+    true_->ptr()->value_ = true;
+    true_->SetCanonical();
+  }
+  {
+    // Allocate false.
+    uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
+    false_ = reinterpret_cast<RawBool*>(address + kHeapObjectTag);
+    InitializeObject(address, kBoolCid, Bool::InstanceSize());
+    false_->ptr()->value_ = false;
+    false_->SetCanonical();
+  }
+
+  // Check that the objects have been allocated at appropriate addresses.
+  ASSERT(reinterpret_cast<uword>(true_) ==
+         reinterpret_cast<uword>(null_) + kTrueOffsetFromNull);
+  ASSERT(reinterpret_cast<uword>(false_) ==
+         reinterpret_cast<uword>(null_) + kFalseOffsetFromNull);
+  ASSERT((reinterpret_cast<uword>(true_) & kBoolValueMask) == 0);
+  ASSERT((reinterpret_cast<uword>(false_) & kBoolValueMask) != 0);
+  ASSERT(reinterpret_cast<uword>(false_) ==
+         (reinterpret_cast<uword>(true_) | kBoolValueMask));
 }
 
 void Object::InitVtables() {
@@ -671,6 +709,8 @@
   *empty_type_arguments_ = TypeArguments::null();
   *null_abstract_type_ = AbstractType::null();
   *null_compressed_stack_maps_ = CompressedStackMaps::null();
+  *bool_true_ = true_;
+  *bool_false_ = false_;
 
   // Initialize the empty and zero array handles to null_ in order to be able to
   // check if the empty and zero arrays were allocated (RAW_NULL is not
@@ -1064,11 +1104,8 @@
   cls.SetFields(Object::empty_array());
   cls.SetFunctions(Object::empty_array());
 
-  // Allocate and initialize singleton true and false boolean objects.
   cls = Class::New<Bool, RTN::Bool>(isolate);
   isolate->object_store()->set_bool_class(cls);
-  *bool_true_ = Bool::New(true);
-  *bool_false_ = Bool::New(false);
 
   *smi_illegal_cid_ = Smi::New(kIllegalCid);
   *smi_zero_ = Smi::New(0);
@@ -1223,6 +1260,8 @@
 
 void Object::Cleanup() {
   null_ = reinterpret_cast<RawObject*>(RAW_NULL);
+  true_ = reinterpret_cast<RawBool*>(RAW_NULL);
+  false_ = reinterpret_cast<RawBool*>(RAW_NULL);
   class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -2068,6 +2107,8 @@
     object_store->set_legacy_int_type(type);
     type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
     object_store->set_non_nullable_int_type(type);
+    type = type.ToNullability(Nullability::kNullable, Heap::kOld);
+    object_store->set_nullable_int_type(type);
 
     cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
                                               /*register_class=*/true,
@@ -2082,6 +2123,8 @@
     object_store->set_legacy_double_type(type);
     type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
     object_store->set_non_nullable_double_type(type);
+    type = type.ToNullability(Nullability::kNullable, Heap::kOld);
+    object_store->set_nullable_double_type(type);
 
     name = Symbols::_String().raw();
     cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
@@ -2549,12 +2592,15 @@
     ASSERT(vtable() == builtin_vtables_[cid]);
     if (FLAG_verify_handles && raw_->IsHeapObject()) {
       Heap* isolate_heap = IsolateGroup::Current()->heap();
-      Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-      uword addr = RawObject::ToAddr(raw_);
-      if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
-        ASSERT(FLAG_write_protect_code);
-        addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
-        ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
+      if (!isolate_heap->new_space()->scavenging()) {
+        Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
+        uword addr = RawObject::ToAddr(raw_);
+        if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
+          ASSERT(FLAG_write_protect_code);
+          addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
+          ASSERT(isolate_heap->Contains(addr) ||
+                 vm_isolate_heap->Contains(addr));
+        }
       }
     }
   }
@@ -4312,8 +4358,14 @@
     // Compute instance size. First word contains a pointer to a properly
     // sized typed array once the first native field has been set.
     const intptr_t host_instance_size = sizeof(RawInstance) + kWordSize;
+#if defined(PRECOMPILER)
+    const intptr_t target_instance_size =
+        compiler::target::Instance::InstanceSize() +
+        compiler::target::kWordSize;
+#else
     const intptr_t target_instance_size =
         sizeof(RawInstance) + compiler::target::kWordSize;
+#endif
     cls.set_instance_size(
         RoundedAllocationSize(host_instance_size),
         compiler::target::RoundedAllocationSize(target_instance_size));
@@ -5597,6 +5649,39 @@
   set.Release();
 }
 
+bool Class::RequireLegacyErasureOfConstants(Zone* zone) const {
+  const intptr_t num_type_params = NumTypeParameters();
+  const intptr_t num_type_args = NumTypeArguments();
+  const intptr_t from_index = num_type_args - num_type_params;
+  Instance& constant = Instance::Handle(zone);
+  TypeArguments& type_arguments = TypeArguments::Handle(zone);
+  AbstractType& type = AbstractType::Handle(zone);
+  CanonicalInstancesSet set(zone, constants());
+  CanonicalInstancesSet::Iterator it(&set);
+  while (it.MoveNext()) {
+    constant ^= set.GetKey(it.Current());
+    ASSERT(!constant.IsNull());
+    ASSERT(!constant.IsTypeArguments());
+    ASSERT(!constant.IsType());
+    type_arguments = constant.GetTypeArguments();
+    if (type_arguments.IsNull()) {
+      continue;
+    }
+    for (intptr_t i = 0; i < num_type_params; i++) {
+      type = type_arguments.TypeAt(from_index + i);
+      if (!type.IsLegacy() && !type.IsVoidType() && !type.IsDynamicType() &&
+          !type.IsNullType()) {
+        return true;
+      }
+      // It is not possible for a legacy type to have non-legacy type
+      // arguments or for a legacy function type to have non-legacy parameter
+      // types, non-legacy type parameters, or required named parameters.
+    }
+  }
+  set.Release();
+  return false;
+}
+
 intptr_t TypeArguments::ComputeNullability() const {
   if (IsNull()) return 0;
   const intptr_t num_types = Length();
@@ -7177,7 +7262,7 @@
 }
 
 bool Function::IsRequiredAt(intptr_t index) const {
-  if (index < num_fixed_parameters()) {
+  if (index < num_fixed_parameters() + NumOptionalPositionalParameters()) {
     return false;
   }
   intptr_t flag_mask;
@@ -7558,7 +7643,8 @@
   }
   if (isolate->null_safety()) {
     // Verify that all required named parameters are filled.
-    for (intptr_t j = num_positional_args; j < num_parameters; j++) {
+    for (intptr_t j = num_parameters - NumOptionalNamedParameters();
+         j < num_parameters; j++) {
       if (IsRequiredAt(j)) {
         parameter_name = ParameterNameAt(j);
         ASSERT(parameter_name.IsSymbol());
@@ -8027,7 +8113,7 @@
     // Check that for each required named parameter in this function, there's a
     // corresponding required named parameter in the other function.
     String& param_name = other_param_name;
-    for (intptr_t j = num_fixed_params; j < num_params; j++) {
+    for (intptr_t j = num_params - num_opt_named_params; j < num_params; j++) {
       if (IsRequiredAt(j)) {
         param_name = ParameterNameAt(j);
         ASSERT(param_name.IsSymbol());
@@ -8404,7 +8490,7 @@
       printer->AddString("{");
     }
     for (intptr_t i = num_fixed_params; i < num_params; i++) {
-      if (IsRequiredAt(i)) {
+      if (num_opt_named_params > 0 && IsRequiredAt(i)) {
         printer->AddString("required ");
       }
       param_type = ParameterTypeAt(i);
@@ -9843,17 +9929,34 @@
   ASSERT(IsOriginal());
   ASSERT(is_static());
   if (StaticValue() == Object::sentinel().raw()) {
-    SetStaticValue(Object::transition_sentinel());
-    const Object& value = Object::Handle(EvaluateInitializer());
-    if (!value.IsNull() && value.IsError()) {
-      SetStaticValue(Object::null_instance());
-      return Error::Cast(value).raw();
+    auto& value = Object::Handle();
+    if (is_late()) {
+      if (!has_initializer()) {
+        Exceptions::ThrowLateInitializationError(String::Handle(name()));
+        UNREACHABLE();
+      }
+      value = EvaluateInitializer();
+      if (value.IsError()) {
+        return Error::Cast(value).raw();
+      }
+      if (is_final() && (StaticValue() != Object::sentinel().raw())) {
+        Exceptions::ThrowLateInitializationError(String::Handle(name()));
+        UNREACHABLE();
+      }
+    } else {
+      SetStaticValue(Object::transition_sentinel());
+      value = EvaluateInitializer();
+      if (value.IsError()) {
+        SetStaticValue(Object::null_instance());
+        return Error::Cast(value).raw();
+      }
     }
     ASSERT(value.IsNull() || value.IsInstance());
     SetStaticValue(value.IsNull() ? Instance::null_instance()
                                   : Instance::Cast(value));
     return Error::null();
   } else if (StaticValue() == Object::transition_sentinel().raw()) {
+    ASSERT(!is_late());
     const Array& ctor_args = Array::Handle(Array::New(1));
     const String& field_name = String::Handle(name());
     ctor_args.SetAt(0, field_name);
@@ -12014,12 +12117,12 @@
   result.StorePointer(&result.raw_ptr()->exported_names_, Array::null());
   result.StorePointer(&result.raw_ptr()->dictionary_,
                       Object::empty_array().raw());
-  result.StorePointer(&result.raw_ptr()->metadata_,
-                      GrowableObjectArray::New(4, Heap::kOld));
+  GrowableObjectArray& list = GrowableObjectArray::Handle(zone);
+  list = GrowableObjectArray::New(4, Heap::kOld);
+  result.StorePointer(&result.raw_ptr()->metadata_, list.raw());
   result.StorePointer(&result.raw_ptr()->toplevel_class_, Class::null());
-  const GrowableObjectArray& scripts = GrowableObjectArray::Handle(zone,
-      GrowableObjectArray::New(Object::empty_array(), Heap::kOld));
-  result.StorePointer(&result.raw_ptr()->used_scripts_, scripts.raw());
+  list = GrowableObjectArray::New(Object::empty_array(), Heap::kOld);
+  result.StorePointer(&result.raw_ptr()->used_scripts_, list.raw());
   result.StorePointer(&result.raw_ptr()->imports_, Object::empty_array().raw());
   result.StorePointer(&result.raw_ptr()->exports_, Object::empty_array().raw());
   result.StorePointer(&result.raw_ptr()->loaded_scripts_, Array::null());
@@ -14172,6 +14275,22 @@
   return "MonomorphicSmiableCall";
 }
 
+const char* CallSiteData::ToCString() const {
+  // CallSiteData is an abstract class.  We should never reach here.
+  UNREACHABLE();
+  return "CallSiteData";
+}
+
+void CallSiteData::set_target_name(const String& value) const {
+  ASSERT(!value.IsNull());
+  StorePointer(&raw_ptr()->target_name_, value.raw());
+}
+
+void CallSiteData::set_arguments_descriptor(const Array& value) const {
+  ASSERT(!value.IsNull());
+  StorePointer(&raw_ptr()->args_descriptor_, value.raw());
+}
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
 void ICData::SetReceiversStaticType(const AbstractType& type) const {
   StorePointer(&raw_ptr()->receivers_static_type_, type.raw());
@@ -14235,16 +14354,6 @@
   StorePointer(&raw_ptr()->owner_, reinterpret_cast<RawObject*>(value.raw()));
 }
 
-void ICData::set_target_name(const String& value) const {
-  ASSERT(!value.IsNull());
-  StorePointer(&raw_ptr()->target_name_, value.raw());
-}
-
-void ICData::set_arguments_descriptor(const Array& value) const {
-  ASSERT(!value.IsNull());
-  StorePointer(&raw_ptr()->args_descriptor_, value.raw());
-}
-
 void ICData::set_deopt_id(intptr_t value) const {
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
@@ -16141,9 +16250,9 @@
   const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map());
   if (map.IsNull()) {
     ASSERT(!IsFunctionCode() ||
-           (Isolate::Current()->object_store()->megamorphic_miss_code() ==
+           (Isolate::Current()->object_store()->megamorphic_call_miss_code() ==
             this->raw()));
-    return;  // VM stub, allocation stub, or megamorphic miss function.
+    return;  // VM stub, allocation stub, or megamorphic call miss function.
   }
   const Array& id_map = Array::Handle(inlined_id_to_function());
   const Function& root = Function::Handle(function());
@@ -16685,14 +16794,6 @@
   StoreNonPointer(&raw_ptr()->filled_entry_count_, count);
 }
 
-void MegamorphicCache::set_target_name(const String& value) const {
-  StorePointer(&raw_ptr()->target_name_, value.raw());
-}
-
-void MegamorphicCache::set_arguments_descriptor(const Array& value) const {
-  StorePointer(&raw_ptr()->args_descriptor_, value.raw());
-}
-
 RawMegamorphicCache* MegamorphicCache::New() {
   MegamorphicCache& result = MegamorphicCache::Handle();
   {
@@ -17827,7 +17928,8 @@
   }
   const Class& cls = Class::Handle(zone, clazz());
   if (cls.IsClosureClass()) {
-    if (other.IsDartFunctionType() || other.IsDartClosureType()) {
+    if (other.IsDartFunctionType() || other.IsDartClosureType() ||
+        other.IsObjectType()) {
       return true;
     }
     AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
@@ -18145,6 +18247,32 @@
   return Nullability::kNullable;
 }
 
+bool AbstractType::IsStrictlyNonNullable() const {
+  // Null can be assigned to legacy and nullable types.
+  if (!IsNonNullable()) {
+    return false;
+  }
+
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+
+  // In weak mode null can be assigned to any type.
+  if (!thread->isolate()->null_safety()) {
+    return false;
+  }
+
+  if (IsTypeParameter()) {
+    const auto& bound =
+        AbstractType::Handle(zone, TypeParameter::Cast(*this).bound());
+    ASSERT(!bound.IsNull());
+    return bound.IsStrictlyNonNullable();
+  }
+  if (IsFutureOrType()) {
+    return AbstractType::Handle(zone, UnwrapFutureOr()).IsStrictlyNonNullable();
+  }
+  return true;
+}
+
 RawAbstractType* AbstractType::SetInstantiatedNullability(
     const TypeParameter& type_param,
     Heap::Space space) const {
@@ -18855,6 +18983,10 @@
   return Isolate::Current()->object_store()->int_type();
 }
 
+RawType* Type::NullableIntType() {
+  return Isolate::Current()->object_store()->nullable_int_type();
+}
+
 RawType* Type::SmiType() {
   return Isolate::Current()->object_store()->smi_type();
 }
@@ -18867,6 +18999,10 @@
   return Isolate::Current()->object_store()->double_type();
 }
 
+RawType* Type::NullableDouble() {
+  return Isolate::Current()->object_store()->nullable_double_type();
+}
+
 RawType* Type::Float32x4() {
   return Isolate::Current()->object_store()->float32x4_type();
 }
@@ -19541,7 +19677,9 @@
         param_name = sig_fun.ParameterNameAt(i);
         result = CombineHashes(result, param_name.Hash());
       }
+      // Required flag is not hashed, see comment above.
     }
+    // TODO(regis): Missing hash of type parameters.
   }
   result = FinalizeHash(result, kHashBits);
   SetHash(result);
@@ -19807,7 +19945,7 @@
   if (nullability() == value) {
     return raw();
   }
-  // Clone type and set new nullability.
+  // Clone type parameter and set new nullability.
   TypeParameter& type_parameter = TypeParameter::Handle();
   type_parameter ^= Object::Clone(*this, space);
   type_parameter.set_nullability(value);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index f6f53bb..8c2c21b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -524,7 +524,7 @@
   }
 
   // Initialize the VM isolate.
-  static void InitNull(Isolate* isolate);
+  static void InitNullAndBool(Isolate* isolate);
   static void Init(Isolate* isolate);
   static void InitVtables();
   static void FinishInit(Isolate* isolate);
@@ -752,6 +752,8 @@
   // The static values below are singletons shared between the different
   // isolates. They are all allocated in the non-GC'd Dart::vm_isolate_.
   static RawObject* null_;
+  static RawBool* true_;
+  static RawBool* false_;
 
   static RawClass* class_class_;           // Class of the Class vm object.
   static RawClass* dynamic_class_;         // Class of the 'dynamic' type.
@@ -1315,6 +1317,8 @@
 
   void RehashConstants(Zone* zone) const;
 
+  bool RequireLegacyErasureOfConstants(Zone* zone) const;
+
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawClass));
   }
@@ -1751,7 +1755,7 @@
   friend class Type;
   friend class InterpreterHelpers;
   friend class Intrinsifier;
-  friend class ClassFunctionVisitor;
+  friend class ProgramWalker;
 };
 
 // Classification of type genericity according to type parameter owners.
@@ -1930,12 +1934,37 @@
   friend class Class;
 };
 
+class CallSiteData : public Object {
+ public:
+  RawString* target_name() const { return raw_ptr()->target_name_; }
+
+  RawArray* arguments_descriptor() const { return raw_ptr()->args_descriptor_; }
+
+  static intptr_t target_name_offset() {
+    return OFFSET_OF(RawCallSiteData, target_name_);
+  }
+
+  static intptr_t arguments_descriptor_offset() {
+    return OFFSET_OF(RawCallSiteData, args_descriptor_);
+  }
+
+ private:
+  void set_target_name(const String& value) const;
+
+  void set_arguments_descriptor(const Array& value) const;
+
+  HEAP_OBJECT_IMPLEMENTATION(CallSiteData, Object)
+
+  friend class ICData;
+  friend class MegamorphicCache;
+};
+
 // Object holding information about an IC: test classes and their
 // corresponding targets. The owner of the ICData can be either the function
 // or the original ICData object. In case of background compilation we
 // copy the ICData in a child object, thus freezing it during background
 // compilation. Code may contain only original ICData objects.
-class ICData : public Object {
+class ICData : public CallSiteData {
  public:
   RawFunction* Owner() const;
 
@@ -1945,10 +1974,6 @@
 
   bool IsOriginal() const { return Original() == this->raw(); }
 
-  RawString* target_name() const { return raw_ptr()->target_name_; }
-
-  RawArray* arguments_descriptor() const { return raw_ptr()->args_descriptor_; }
-
   intptr_t NumArgsTested() const;
 
   intptr_t TypeArgsLen() const;
@@ -2086,10 +2111,6 @@
     return RoundedAllocationSize(sizeof(RawICData));
   }
 
-  static intptr_t target_name_offset() {
-    return OFFSET_OF(RawICData, target_name_);
-  }
-
   static intptr_t state_bits_offset() {
     return OFFSET_OF(RawICData, state_bits_);
   }
@@ -2100,10 +2121,6 @@
     return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
   }
 
-  static intptr_t arguments_descriptor_offset() {
-    return OFFSET_OF(RawICData, args_descriptor_);
-  }
-
   static intptr_t entries_offset() { return OFFSET_OF(RawICData, entries_); }
 
   static intptr_t owner_offset() { return OFFSET_OF(RawICData, owner_); }
@@ -2280,8 +2297,6 @@
   RawArray* Grow(intptr_t* index) const;
 
   void set_owner(const Function& value) const;
-  void set_target_name(const String& value) const;
-  void set_arguments_descriptor(const Array& value) const;
   void set_deopt_id(intptr_t value) const;
   void SetNumArgsTested(intptr_t value) const;
   void set_entries(const Array& value) const;
@@ -2370,7 +2385,7 @@
   // A cache of VM heap allocated preinitialized empty ic data entry arrays.
   static RawArray* cached_icdata_arrays_[kCachedICDataArrayCount];
 
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, CallSiteData);
   friend class CallSiteResetter;
   friend class CallTargets;
   friend class Class;
@@ -6028,7 +6043,8 @@
 
   enum CallKind {
     kPcRelativeCall = 1,
-    kCallViaCode = 2,
+    kPcRelativeTailCall = 2,
+    kCallViaCode = 3,
   };
 
   enum CallEntryPoint {
@@ -6745,7 +6761,7 @@
   friend class Object;
 };
 
-class MegamorphicCache : public Object {
+class MegamorphicCache : public CallSiteData {
  public:
   static const intptr_t kInitialCapacity = 16;
   static const intptr_t kSpreadFactor = 7;
@@ -6763,10 +6779,6 @@
   intptr_t mask() const;
   void set_mask(intptr_t mask) const;
 
-  RawString* target_name() const { return raw_ptr()->target_name_; }
-
-  RawArray* arguments_descriptor() const { return raw_ptr()->args_descriptor_; }
-
   intptr_t filled_entry_count() const;
   void set_filled_entry_count(intptr_t num) const;
 
@@ -6800,9 +6812,6 @@
 
   static RawMegamorphicCache* New();
 
-  void set_target_name(const String& value) const;
-  void set_arguments_descriptor(const Array& value) const;
-
   // The caller must hold Isolate::megamorphic_mutex().
   void EnsureCapacityLocked() const;
   void InsertLocked(const Smi& class_id, const Object& target) const;
@@ -6816,7 +6825,7 @@
   static inline RawObject* GetTargetFunction(const Array& array,
                                              intptr_t index);
 
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache, Object);
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache, CallSiteData);
 };
 
 class SubtypeTestCache : public Object {
@@ -7566,21 +7575,21 @@
   virtual Nullability nullability() const;
   // Returns true if type has '?' nullability suffix, or it is a
   // built-in type which is always nullable (Null, dynamic or void).
-  virtual bool IsNullable() const {
-    return nullability() == Nullability::kNullable;
-  }
+  bool IsNullable() const { return nullability() == Nullability::kNullable; }
   // Returns true if type does not have any nullability suffix.
   // This function also returns true for type parameters without
   // nullability suffix ("T") which can be instantiated with
   // nullable or legacy types.
-  virtual bool IsNonNullable() const {
+  bool IsNonNullable() const {
     return nullability() == Nullability::kNonNullable;
   }
   // Returns true if type has '*' nullability suffix, i.e.
   // it is from a legacy (opted-out) library.
-  virtual bool IsLegacy() const {
-    return nullability() == Nullability::kLegacy;
-  }
+  bool IsLegacy() const { return nullability() == Nullability::kLegacy; }
+  // Returns true if it is guaranteed that null cannot be
+  // assigned to this type.
+  bool IsStrictlyNonNullable() const;
+
   virtual RawAbstractType* SetInstantiatedNullability(
       const TypeParameter& type_param,
       Heap::Space space) const;
@@ -7908,6 +7917,9 @@
   // The 'int' type.
   static RawType* IntType();
 
+  // The 'int?' type.
+  static RawType* NullableIntType();
+
   // The 'Smi' type.
   static RawType* SmiType();
 
@@ -7917,6 +7929,9 @@
   // The 'double' type.
   static RawType* Double();
 
+  // The 'double?' type.
+  static RawType* NullableDouble();
+
   // The 'Float32x4' type.
   static RawType* Float32x4();
 
@@ -10847,12 +10862,16 @@
   if (FLAG_verify_handles && raw_->IsHeapObject()) {
     Isolate* isolate = Isolate::Current();
     Heap* isolate_heap = isolate->heap();
-    Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-    uword addr = RawObject::ToAddr(raw_);
-    if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
-      ASSERT(FLAG_write_protect_code);
-      addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
-      ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
+    // TODO(rmacnak): Remove after rewriting StackFrame::VisitObjectPointers
+    // to not use handles.
+    if (!isolate_heap->new_space()->scavenging()) {
+      Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
+      uword addr = RawObject::ToAddr(raw_);
+      if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
+        ASSERT(FLAG_write_protect_code);
+        addr = RawObject::ToAddr(HeapPage::ToWritable(raw_));
+        ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
+      }
     }
   }
 #endif
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 638876c..3cf2741 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -261,7 +261,7 @@
   }
   // Oddball functions (not known to their owner) fall back to use the object
   // id ring. Current known examples are signature functions of closures
-  // and stubs like 'megamorphic_miss'.
+  // and stubs like 'megamorphic_call_miss'.
   jsobj.AddServiceId(f);
 }
 
@@ -824,6 +824,10 @@
   jsobj.AddProperty("_target", Code::Handle(target()));
 }
 
+void CallSiteData::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  UNREACHABLE();
+}
+
 void ICData::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Object", ref);
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index b9fbe72..1b6f035 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -10,6 +10,7 @@
 #include "vm/object.h"
 #include "vm/raw_object.h"
 #include "vm/resolver.h"
+#include "vm/stub_code.h"
 #include "vm/symbols.h"
 #include "vm/visitor.h"
 
@@ -38,6 +39,12 @@
   ASSERT(isolate->object_store() == NULL);
   ObjectStore* store = new ObjectStore();
   isolate->set_object_store(store);
+
+  if (!Dart::VmIsolateNameEquals(isolate->name())) {
+#define DO(member, name) store->set_##member(StubCode::name());
+    OBJECT_STORE_STUB_CODE_LIST(DO)
+#undef DO
+  }
 }
 
 #ifndef PRODUCT
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 04e6e70..5a8640c 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -53,6 +53,7 @@
   RW(Type, int_type)                                                           \
   RW(Type, legacy_int_type)                                                    \
   RW(Type, non_nullable_int_type)                                              \
+  RW(Type, nullable_int_type)                                                  \
   RW(Class, integer_implementation_class)                                      \
   RW(Type, int64_type)                                                         \
   RW(Class, smi_class)                                                         \
@@ -67,6 +68,7 @@
   RW(Type, double_type)                                                        \
   RW(Type, legacy_double_type)                                                 \
   RW(Type, non_nullable_double_type)                                           \
+  RW(Type, nullable_double_type)                                               \
   RW(Type, float32x4_type)                                                     \
   RW(Type, int32x4_type)                                                       \
   RW(Type, float64x2_type)                                                     \
@@ -175,14 +177,27 @@
   RW(Code, null_error_stub_without_fpu_regs_stub)                              \
   RW(Code, null_arg_error_stub_with_fpu_regs_stub)                             \
   RW(Code, null_arg_error_stub_without_fpu_regs_stub)                          \
+  RW(Code, range_error_stub_with_fpu_regs_stub)                                \
+  RW(Code, range_error_stub_without_fpu_regs_stub)                             \
   RW(Code, allocate_mint_with_fpu_regs_stub)                                   \
   RW(Code, allocate_mint_without_fpu_regs_stub)                                \
   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_context_stub)                                              \
+  RW(Code, allocate_object_stub)                                               \
+  RW(Code, allocate_object_parametrized_stub)                                  \
+  RW(Code, clone_context_stub)                                                 \
   RW(Code, write_barrier_wrappers_stub)                                        \
   RW(Code, array_write_barrier_stub)                                           \
-  R_(Code, megamorphic_miss_code)                                              \
-  R_(Function, megamorphic_miss_function)                                      \
+  RW(Code, throw_stub)                                                         \
+  RW(Code, re_throw_stub)                                                      \
+  RW(Code, assert_boolean_stub)                                                \
+  RW(Code, instance_of_stub)                                                   \
+  RW(Code, init_static_field_stub)                                             \
+  RW(Code, call_closure_no_such_method_stub)                                   \
+  R_(Code, megamorphic_call_miss_code)                                         \
+  R_(Function, megamorphic_call_miss_function)                                 \
   R_(GrowableObjectArray, resume_capabilities)                                 \
   R_(GrowableObjectArray, exit_listeners)                                      \
   R_(GrowableObjectArray, error_listeners)                                     \
@@ -193,7 +208,35 @@
   RW(Class, ffi_native_type_class)                                             \
   RW(Class, ffi_struct_class)                                                  \
   RW(Object, ffi_as_function_internal)                                         \
-// Please remember the last entry must be referred in the 'to' function below.
+  // Please remember the last entry must be referred in the 'to' function below.
+
+#define OBJECT_STORE_STUB_CODE_LIST(DO)                                        \
+  DO(dispatch_table_null_error_stub, DispatchTableNullError)                   \
+  DO(null_error_stub_with_fpu_regs_stub, NullErrorSharedWithFPURegs)           \
+  DO(null_error_stub_without_fpu_regs_stub, NullErrorSharedWithoutFPURegs)     \
+  DO(null_arg_error_stub_with_fpu_regs_stub, NullArgErrorSharedWithFPURegs)    \
+  DO(null_arg_error_stub_without_fpu_regs_stub,                                \
+     NullArgErrorSharedWithoutFPURegs)                                         \
+  DO(range_error_stub_with_fpu_regs_stub, RangeErrorSharedWithFPURegs)         \
+  DO(range_error_stub_without_fpu_regs_stub, RangeErrorSharedWithoutFPURegs)   \
+  DO(allocate_mint_with_fpu_regs_stub, AllocateMintSharedWithFPURegs)          \
+  DO(allocate_mint_without_fpu_regs_stub, AllocateMintSharedWithoutFPURegs)    \
+  DO(stack_overflow_stub_with_fpu_regs_stub, StackOverflowSharedWithFPURegs)   \
+  DO(stack_overflow_stub_without_fpu_regs_stub,                                \
+     StackOverflowSharedWithoutFPURegs)                                        \
+  DO(allocate_array_stub, AllocateArray)                                       \
+  DO(allocate_context_stub, AllocateContext)                                   \
+  DO(allocate_object_stub, AllocateObject)                                     \
+  DO(allocate_object_parametrized_stub, AllocateObjectParameterized)           \
+  DO(clone_context_stub, CloneContext)                                         \
+  DO(call_closure_no_such_method_stub, CallClosureNoSuchMethod)                \
+  DO(write_barrier_wrappers_stub, WriteBarrierWrappers)                        \
+  DO(array_write_barrier_stub, ArrayWriteBarrier)                              \
+  DO(throw_stub, Throw)                                                        \
+  DO(re_throw_stub, ReThrow)                                                   \
+  DO(assert_boolean_stub, AssertBoolean)                                       \
+  DO(init_static_field_stub, InitStaticField)                                  \
+  DO(instance_of_stub, InstanceOf)
 
 // The object store is a per isolate instance which stores references to
 // objects used by the VM.
@@ -247,10 +290,10 @@
     }
   }
 
-  void SetMegamorphicMissHandler(const Code& code, const Function& func) {
+  void SetMegamorphicCallMissHandler(const Code& code, const Function& func) {
     // Hold onto the code so it is traced and not detached from the function.
-    megamorphic_miss_code_ = code.raw();
-    megamorphic_miss_function_ = func.raw();
+    megamorphic_call_miss_code_ = code.raw();
+    megamorphic_call_miss_function_ = func.raw();
   }
 
   // Visit all object pointers.
@@ -291,7 +334,7 @@
         return reinterpret_cast<RawObject**>(&global_object_pool_);
       case Snapshot::kFullJIT:
       case Snapshot::kFullAOT:
-        return reinterpret_cast<RawObject**>(&megamorphic_miss_function_);
+        return reinterpret_cast<RawObject**>(&megamorphic_call_miss_function_);
       case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
diff --git a/runtime/vm/pointer_tagging.h b/runtime/vm/pointer_tagging.h
index 487f3f8..70fd9d7 100644
--- a/runtime/vm/pointer_tagging.h
+++ b/runtime/vm/pointer_tagging.h
@@ -34,6 +34,13 @@
   static constexpr intptr_t kObjectAlignment = 2 * word_size;
   static constexpr intptr_t kObjectAlignmentLog2 = word_size_log2 + 1;
   static constexpr intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
+
+  // Discriminate between true and false based on the alignment bit.
+  static constexpr intptr_t kBoolValueBitPosition = kObjectAlignmentLog2;
+  static constexpr intptr_t kBoolValueMask = 1 << kBoolValueBitPosition;
+
+  static constexpr intptr_t kTrueOffsetFromNull = kObjectAlignment * 2;
+  static constexpr intptr_t kFalseOffsetFromNull = kObjectAlignment * 3;
 };
 
 using HostObjectAlignment = ObjectAlignment<kWordSize, kWordSizeLog2>;
@@ -50,6 +57,13 @@
     HostObjectAlignment::kObjectAlignmentLog2;
 static constexpr intptr_t kObjectAlignmentMask =
     HostObjectAlignment::kObjectAlignmentMask;
+static constexpr intptr_t kBoolValueBitPosition =
+    HostObjectAlignment::kBoolValueBitPosition;
+static constexpr intptr_t kBoolValueMask = HostObjectAlignment::kBoolValueMask;
+static constexpr intptr_t kTrueOffsetFromNull =
+    HostObjectAlignment::kTrueOffsetFromNull;
+static constexpr intptr_t kFalseOffsetFromNull =
+    HostObjectAlignment::kFalseOffsetFromNull;
 
 // The largest value of kObjectAlignment across all configurations.
 static constexpr intptr_t kMaxObjectAlignment = 16;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index d067f5f..fdc4c54 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -464,7 +464,11 @@
       EXPECT_STREQ("[Bytecode] main", walker.CurrentName());
       EXPECT(!walker.Down());
     } else {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT(walker.Down());
       EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
       EXPECT(walker.Down());
@@ -660,7 +664,11 @@
       EXPECT_STREQ("[Bytecode] main", walker.CurrentName());
       EXPECT(!walker.Down());
     } else {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT(walker.Down());
       EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
       EXPECT(walker.Down());
@@ -755,7 +763,11 @@
       EXPECT_EQ(0, walker.CurrentExclusiveTicks());
       EXPECT(!walker.Down());
     } else {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT_EQ(3, walker.CurrentExclusiveTicks());
       EXPECT(walker.Down());
       EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
@@ -828,7 +840,11 @@
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
 
     if (!FLAG_enable_interpreter) {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT_EQ(3, walker.CurrentExclusiveTicks());
       EXPECT(walker.Down());
     }
@@ -1116,7 +1132,11 @@
 
     EXPECT_SUBSTRING("DRT_AllocateObject", walker.VMTagName());
     if (!FLAG_enable_interpreter) {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate _Closure", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT(walker.Down());
     }
     EXPECT_SUBSTRING("foo", walker.CurrentName());
@@ -1480,7 +1500,11 @@
       ProfileStackWalker walker(&profile);
       // We have two code objects: mainA and B.boo.
       EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
       EXPECT(walker.Down());
       EXPECT_STREQ("[Optimized] B.boo", walker.CurrentName());
@@ -1496,7 +1520,11 @@
       // Inline expansion should show us the complete call chain:
       // mainA -> B.boo -> B.foo -> B.choo.
       EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
       EXPECT(walker.Down());
       EXPECT_STREQ("B.choo", walker.CurrentName());
@@ -1618,7 +1646,11 @@
 
     // Inline expansion should show us the complete call chain:
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+    EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
     EXPECT(walker.Down());
     EXPECT_STREQ("maybeAlloc", walker.CurrentName());
     EXPECT(walker.Down());
@@ -1732,7 +1764,11 @@
       EXPECT_STREQ("[Bytecode] main", walker.CurrentName());
       EXPECT(!walker.Down());
     } else {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT(walker.Down());
       EXPECT_STREQ("[Unoptimized] B.boo", walker.CurrentName());
       EXPECT(walker.Down());
@@ -1825,7 +1861,11 @@
 
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
     if (!FLAG_enable_interpreter) {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT_EQ(1, walker.CurrentExclusiveTicks());
       EXPECT(walker.Down());
     }
@@ -1906,7 +1946,11 @@
 
     // Move down from the root.
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+    EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
     EXPECT_EQ(1, walker.CurrentExclusiveTicks());
     EXPECT(walker.Down());
     EXPECT_STREQ("B.boo", walker.CurrentName());
@@ -1980,7 +2024,11 @@
 
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
     if (!FLAG_enable_interpreter) {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT_EQ(1, walker.CurrentExclusiveTicks());
       EXPECT(walker.Down());
     }
@@ -2088,7 +2136,11 @@
     ProfileStackWalker walker(&profile, true);
 
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+    EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
     EXPECT_EQ(1, walker.CurrentExclusiveTicks());
     EXPECT(walker.Down());
     EXPECT_STREQ("B.boo", walker.CurrentName());
@@ -2180,7 +2232,11 @@
 
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
     if (!FLAG_enable_interpreter) {
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
       EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+      EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
       EXPECT_EQ(1, walker.CurrentExclusiveTicks());
       EXPECT(walker.Down());
     }
@@ -2296,7 +2352,11 @@
     ProfileStackWalker walker(&profile, true);
 
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
+#if defined(TARGET_ARCH_IA32)  // Alloc. stub not impl. for ia32.
     EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+#else
+    EXPECT_STREQ("[Stub] AllocateObjectSlow", walker.CurrentName());
+#endif
     EXPECT_EQ(1, walker.CurrentExclusiveTicks());
     EXPECT(walker.Down());
     EXPECT_STREQ("B.boo", walker.CurrentName());
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index d8b80fc..93c239a 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -13,52 +13,31 @@
 
 namespace dart {
 
-void ProgramVisitor::VisitClasses(ClassVisitor* visitor) {
-  Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
-  GrowableObjectArray& libraries =
-      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
-  Library& lib = Library::Handle(zone);
-  Class& cls = Class::Handle(zone);
-  Object& entry = Object::Handle(zone);
-  GrowableObjectArray& patches = GrowableObjectArray::Handle(zone);
-
-  for (intptr_t i = 0; i < libraries.Length(); i++) {
-    lib ^= libraries.At(i);
-    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
-    while (it.HasNext()) {
-      cls = it.GetNextClass();
-      visitor->Visit(cls);
-    }
-    patches = lib.used_scripts();
-    for (intptr_t j = 0; j < patches.Length(); j++) {
-      entry = patches.At(j);
-      if (entry.IsClass()) {
-        visitor->Visit(Class::Cast(entry));
-      }
-    }
-  }
-}
-
-class ClassFunctionVisitor : public ClassVisitor {
+class ProgramWalker : public CodeVisitor {
  public:
-  ClassFunctionVisitor(Zone* zone, FunctionVisitor* visitor)
+  ProgramWalker(Zone* zone, ClassVisitor* visitor)
       : visitor_(visitor),
-        functions_(Array::Handle(zone)),
-        function_(Function::Handle(zone)),
         object_(Object::Handle(zone)),
         fields_(Array::Handle(zone)),
-        field_(Field::Handle(zone)) {}
+        field_(Field::Handle(zone)),
+        functions_(Array::Handle(zone)),
+        function_(Function::Handle(zone)),
+        code_(Code::Handle(zone)) {}
 
-  void Visit(const Class& cls) {
+  void VisitClass(const Class& cls) {
+    ASSERT(!cls.IsNull());
+    if (cls.InVMIsolateHeap()) return;
+    visitor_->VisitClass(cls);
+
+    if (!visitor_->IsFunctionVisitor()) return;
+
     functions_ = cls.functions();
     for (intptr_t j = 0; j < functions_.Length(); j++) {
       function_ ^= functions_.At(j);
-      visitor_->Visit(function_);
+      VisitFunction(function_);
       if (function_.HasImplicitClosureFunction()) {
         function_ = function_.ImplicitClosureFunction();
-        visitor_->Visit(function_);
+        VisitFunction(function_);
       }
     }
 
@@ -67,7 +46,7 @@
       object_ = functions_.At(j);
       if (object_.IsFunction()) {
         function_ ^= functions_.At(j);
-        visitor_->Visit(function_);
+        VisitFunction(function_);
       }
     }
 
@@ -76,84 +55,121 @@
       field_ ^= fields_.At(j);
       if (field_.is_static() && field_.HasInitializerFunction()) {
         function_ = field_.InitializerFunction();
-        visitor_->Visit(function_);
+        VisitFunction(function_);
       }
     }
+
+    if (!visitor_->IsCodeVisitor()) return;
+
+    code_ = cls.allocation_stub();
+    if (!code_.IsNull()) VisitCode(code_);
+  }
+
+  void VisitFunction(const Function& function) {
+    ASSERT(visitor_->IsFunctionVisitor());
+    ASSERT(!function.IsNull());
+    if (function.InVMIsolateHeap()) return;
+    visitor_->AsFunctionVisitor()->VisitFunction(function);
+    if (!visitor_->IsCodeVisitor() || !function.HasCode()) return;
+    code_ = function.CurrentCode();
+    VisitCode(code_);
+  }
+
+  void VisitCode(const Code& code) {
+    ASSERT(visitor_->IsCodeVisitor());
+    ASSERT(!code.IsNull());
+    if (code.InVMIsolateHeap()) return;
+    visitor_->AsCodeVisitor()->VisitCode(code);
+  }
+
+  void VisitObject(const Object& object) {
+    if (object.IsNull()) return;
+    if (object.IsClass()) {
+      VisitClass(Class::Cast(object));
+    } else if (visitor_->IsFunctionVisitor() && object.IsFunction()) {
+      VisitFunction(Function::Cast(object));
+    } else if (visitor_->IsCodeVisitor() && object.IsCode()) {
+      VisitCode(Code::Cast(object));
+    }
   }
 
  private:
-  FunctionVisitor* visitor_;
-  Array& functions_;
-  Function& function_;
+  ClassVisitor* const visitor_;
   Object& object_;
   Array& fields_;
   Field& field_;
+  Array& functions_;
+  Function& function_;
+  Code& code_;
 };
 
-void ProgramVisitor::VisitFunctions(FunctionVisitor* visitor) {
-  Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
+void ProgramVisitor::WalkProgram(Zone* zone,
+                                 Isolate* isolate,
+                                 ClassVisitor* visitor) {
+  auto const object_store = isolate->object_store();
+  ProgramWalker walker(zone, visitor);
 
-  ClassFunctionVisitor class_visitor(zone, visitor);
-  VisitClasses(&class_visitor);
+  // Walk through the libraries and patches, looking for visitable objects.
+  const auto& libraries =
+      GrowableObjectArray::Handle(zone, object_store->libraries());
+  auto& lib = Library::Handle(zone);
+  auto& cls = Class::Handle(zone);
+  auto& entry = Object::Handle(zone);
+  auto& patches = GrowableObjectArray::Handle(zone);
 
-  Function& function = Function::Handle(zone);
-  const GrowableObjectArray& closures = GrowableObjectArray::Handle(
-      zone, isolate->object_store()->closure_functions());
+  for (intptr_t i = 0; i < libraries.Length(); i++) {
+    lib ^= libraries.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      walker.VisitClass(cls);
+    }
+    patches = lib.used_scripts();
+    for (intptr_t j = 0; j < patches.Length(); j++) {
+      entry = patches.At(j);
+      walker.VisitObject(entry);
+    }
+  }
+
+  if (!visitor->IsFunctionVisitor()) return;
+
+  // Function objects not necessarily reachable from classes.
+  auto& function = Function::Handle(zone);
+  const auto& closures =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
   ASSERT(!closures.IsNull());
   for (intptr_t i = 0; i < closures.Length(); i++) {
     function ^= closures.At(i);
-    visitor->Visit(function);
+    walker.VisitFunction(function);
     ASSERT(!function.HasImplicitClosureFunction());
   }
 
-  const auto& global_object_pool = ObjectPool::Handle(
-      zone, isolate->object_store()->global_object_pool());
+  // If there's a global object pool, check for functions like FfiTrampolines.
+  const auto& global_object_pool =
+      ObjectPool::Handle(zone, object_store->global_object_pool());
   if (!global_object_pool.IsNull()) {
     auto& object = Object::Handle(zone);
     for (intptr_t i = 0; i < global_object_pool.Length(); i++) {
       auto const type = global_object_pool.TypeAt(i);
       if (type != ObjectPool::EntryType::kTaggedObject) continue;
       object = global_object_pool.ObjectAt(i);
-      if (!object.IsFunction()) continue;
-      visitor->Visit(Function::Cast(object));
+      if (object.IsFunction() && visitor->IsFunctionVisitor()) {
+        walker.VisitFunction(Function::Cast(object));
+      }
     }
   }
-}
 
-class FunctionCodeVisitor : public FunctionVisitor {
- public:
-  FunctionCodeVisitor(Zone* zone, CodeVisitor* visitor)
-      : visitor_(visitor), code_(Code::Handle(zone)) {}
+  if (!visitor->IsCodeVisitor()) return;
 
-  void Visit(const Function& function) {
-    if (!function.HasCode()) return;
-    code_ = function.CurrentCode();
-    visitor_->Visit(code_);
-  }
-
- private:
-  CodeVisitor* const visitor_;
-  Code& code_;
-};
-
-void ProgramVisitor::VisitCode(CodeVisitor* visitor) {
-  Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
-
-  FunctionCodeVisitor function_visitor(zone, visitor);
-  VisitFunctions(&function_visitor);
-
-  const auto& dispatch_table_entries = Array::Handle(
-      zone, isolate->object_store()->dispatch_table_code_entries());
+  // Code objects not necessarily reachable from functions.
+  auto& code = Code::Handle(zone);
+  const auto& dispatch_table_entries =
+      Array::Handle(zone, object_store->dispatch_table_code_entries());
   if (!dispatch_table_entries.IsNull()) {
-    auto& code = Code::Handle(zone);
     for (intptr_t i = 0; i < dispatch_table_entries.Length(); i++) {
-      code = Code::RawCast(dispatch_table_entries.At(i));
+      code ^= dispatch_table_entries.At(i);
       if (code.IsNull()) continue;
-      visitor->Visit(code);
+      walker.VisitCode(code);
     }
   }
 }
@@ -168,16 +184,6 @@
   explicit Dedupper(Zone* zone) : zone_(zone), canonical_objects_(zone) {}
   virtual ~Dedupper() {}
 
-  void AddVMBaseObjects() {
-    const auto& object_table = Object::vm_isolate_snapshot_object_table();
-    auto& obj = Object::Handle(zone_);
-    for (intptr_t i = 0; i < object_table.Length(); i++) {
-      obj = object_table.At(i);
-      if (!ShouldAdd(obj)) continue;
-      AddCanonical(T::Cast(obj));
-    }
-  }
-
  protected:
   // Predicate for objects of type T. Must be overridden for class hierarchies
   // like Instance and AbstractType, as it defaults to class ID comparison.
@@ -200,6 +206,16 @@
     canonical_objects_.Insert(&T::ZoneHandle(zone_, obj.raw()));
   }
 
+  void AddVMBaseObjects() {
+    const auto& object_table = Object::vm_isolate_snapshot_object_table();
+    auto& obj = Object::Handle(zone_);
+    for (intptr_t i = 0; i < object_table.Length(); i++) {
+      obj = object_table.At(i);
+      if (!ShouldAdd(obj)) continue;
+      AddCanonical(T::Cast(obj));
+    }
+  }
+
   typename T::RawObjectType* Dedup(const T& obj) {
     if (ShouldAdd(obj)) {
       if (auto const canonical = canonical_objects_.LookupValue(&obj)) {
@@ -214,7 +230,7 @@
   DirectChainedHashMap<S> canonical_objects_;
 };
 
-void ProgramVisitor::BindStaticCalls() {
+void ProgramVisitor::BindStaticCalls(Zone* zone, Isolate* isolate) {
   class BindStaticCallsVisitor : public CodeVisitor {
    public:
     explicit BindStaticCallsVisitor(Zone* zone)
@@ -223,8 +239,10 @@
           target_(Object::Handle(zone)),
           target_code_(Code::Handle(zone)) {}
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       table_ = code.static_calls_target_table();
+      if (table_.IsNull()) return;
+
       StaticCallsTable static_calls(table_);
       // We can only remove the target table in precompiled mode, since more
       // calls may be added later otherwise.
@@ -233,7 +251,8 @@
         kind_and_offset_ = view.Get<Code::kSCallTableKindAndOffset>();
         auto const kind = Code::KindField::decode(kind_and_offset_.Value());
         if (kind != Code::kCallViaCode) {
-          ASSERT(!FLAG_precompiled_mode || kind == Code::kPcRelativeCall);
+          ASSERT(!FLAG_precompiled_mode || kind == Code::kPcRelativeCall ||
+                 kind == Code::kPcRelativeTailCall);
           only_call_via_code = false;
           continue;
         }
@@ -283,18 +302,13 @@
     Code& target_code_;
   };
 
-  auto const zone = Thread::Current()->zone();
   BindStaticCallsVisitor visitor(zone);
-  ProgramVisitor::VisitCode(&visitor);
+  WalkProgram(zone, isolate, &visitor);
 }
 
 DECLARE_FLAG(charp, write_v8_snapshot_profile_to);
 
-void ProgramVisitor::ShareMegamorphicBuckets() {
-  Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
-
+void ProgramVisitor::ShareMegamorphicBuckets(Zone* zone, Isolate* isolate) {
   const GrowableObjectArray& table = GrowableObjectArray::Handle(
       zone, isolate->object_store()->megamorphic_cache_table());
   if (table.IsNull()) return;
@@ -424,7 +438,8 @@
 
 typedef DirectChainedHashMap<StackMapEntryKeyIntValueTrait> StackMapEntryIntMap;
 
-void ProgramVisitor::NormalizeAndDedupCompressedStackMaps() {
+void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(Zone* zone,
+                                                          Isolate* isolate) {
   // Walks all the CSMs in Code objects and collects their entry information
   // for consolidation.
   class CollectStackMapEntriesVisitor : public CodeVisitor {
@@ -440,7 +455,7 @@
       ASSERT(old_global_table_.IsNull() || old_global_table_.IsGlobalTable());
     }
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       compressed_stackmaps_ = code.compressed_stackmaps();
       CompressedStackMapsIterator it(compressed_stackmaps_, old_global_table_);
       while (it.MoveNext()) {
@@ -505,18 +520,40 @@
         public Dedupper<CompressedStackMaps,
                         PointerKeyValueTrait<const CompressedStackMaps>> {
    public:
-    NormalizeAndDedupCompressedStackMapsVisitor(
-        Zone* zone,
-        const CompressedStackMaps& global_table,
-        const StackMapEntryIntMap& entry_offsets)
+    NormalizeAndDedupCompressedStackMapsVisitor(Zone* zone, Isolate* isolate)
         : Dedupper(zone),
-          old_global_table_(global_table),
-          entry_offsets_(entry_offsets),
+          old_global_table_(CompressedStackMaps::Handle(
+              zone,
+              isolate->object_store()->canonicalized_stack_map_entries())),
+          entry_offsets_(zone),
           maps_(CompressedStackMaps::Handle(zone)) {
       ASSERT(old_global_table_.IsNull() || old_global_table_.IsGlobalTable());
+      // The stack map normalization and deduplication happens in two phases:
+      //
+      // 1) Visit all CompressedStackMaps (CSM) objects and collect individual
+      // entry info as canonicalized StackMapEntries (SMEs). Also record the
+      // frequency the same entry info was seen across all CSMs in each SME.
+
+      CollectStackMapEntriesVisitor collect_visitor(zone, old_global_table_);
+      WalkProgram(zone, isolate, &collect_visitor);
+
+      // The results of phase 1 are used to create a new global table with
+      // entries sorted by decreasing frequency, so that entries that appear
+      // more often in CSMs have smaller payload offsets (less bytes used in
+      // the LEB128 encoding). The new global table is put into place
+      // immediately, as we already have a handle on the old table.
+
+      const auto& new_global_table = CompressedStackMaps::Handle(
+          zone, collect_visitor.CreateGlobalTable(&entry_offsets_));
+      isolate->object_store()->set_canonicalized_stack_map_entries(
+          new_global_table);
+
+      // 2) Visit all CSMs and replace each with a canonicalized normalized
+      // version that uses the new global table for non-PC offset entry
+      // information. This part is done in VisitCode.
     }
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       maps_ = code.compressed_stackmaps();
       if (maps_.IsNull()) return;
       // First check is to make sure [maps] hasn't already been normalized,
@@ -549,42 +586,12 @@
     }
 
     const CompressedStackMaps& old_global_table_;
-    const StackMapEntryIntMap& entry_offsets_;
+    StackMapEntryIntMap entry_offsets_;
     CompressedStackMaps& maps_;
   };
 
-  // The stack map deduplication happens in two phases:
-  // 1) Visit all CompressedStackMaps (CSM) objects and collect individual entry
-  //    info as canonicalized StackMapEntries (SMEs). Also record the number of
-  //    times the same entry info was seen across all CSMs in each SME.
-  //
-  // The results of phase 1 are used to create a new global table with entries
-  // sorted by decreasing frequency, so that entries that appear more often in
-  // CSMs have smaller payload offsets (less bytes used in the LEB128 encoding).
-  //
-  // 2) Visit all CSMs and replace each with a canonicalized normalized version
-  //    that uses the new global table for non-PC offset entry information.
-  Thread* const t = Thread::Current();
-  StackZone temp_zone(t);
-  HandleScope temp_handles(t);
-  Zone* zone = temp_zone.GetZone();
-  auto object_store = t->isolate()->object_store();
-  const auto& old_global_table = CompressedStackMaps::Handle(
-      zone, object_store->canonicalized_stack_map_entries());
-  CollectStackMapEntriesVisitor collect_visitor(zone, old_global_table);
-  ProgramVisitor::VisitCode(&collect_visitor);
-
-  // We retrieve the new offsets for CSM entries by creating the new global
-  // table now. We go ahead and put it in place, as we already have a handle
-  // on the old table that we can pass to the normalizing visitor.
-  StackMapEntryIntMap entry_offsets(zone);
-  const auto& new_global_table = CompressedStackMaps::Handle(
-      zone, collect_visitor.CreateGlobalTable(&entry_offsets));
-  object_store->set_canonicalized_stack_map_entries(new_global_table);
-
-  NormalizeAndDedupCompressedStackMapsVisitor dedup_visitor(
-      zone, old_global_table, entry_offsets);
-  ProgramVisitor::VisitCode(&dedup_visitor);
+  NormalizeAndDedupCompressedStackMapsVisitor dedup_visitor(zone, isolate);
+  WalkProgram(zone, isolate, &dedup_visitor);
 }
 
 class PcDescriptorsKeyValueTrait {
@@ -605,24 +612,28 @@
   }
 };
 
-void ProgramVisitor::DedupPcDescriptors() {
+void ProgramVisitor::DedupPcDescriptors(Zone* zone, Isolate* isolate) {
   class DedupPcDescriptorsVisitor
       : public CodeVisitor,
-        public Dedupper<PcDescriptors, PcDescriptorsKeyValueTrait>,
-        public FunctionVisitor {
+        public Dedupper<PcDescriptors, PcDescriptorsKeyValueTrait> {
    public:
     explicit DedupPcDescriptorsVisitor(Zone* zone)
         : Dedupper(zone),
           bytecode_(Bytecode::Handle(zone)),
-          pc_descriptor_(PcDescriptors::Handle(zone)) {}
+          pc_descriptor_(PcDescriptors::Handle(zone)) {
+      if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
+        // Prefer existing objects in the VM isolate.
+        AddVMBaseObjects();
+      }
+    }
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       pc_descriptor_ = code.pc_descriptors();
       pc_descriptor_ = Dedup(pc_descriptor_);
       code.set_pc_descriptors(pc_descriptor_);
     }
 
-    void Visit(const Function& function) {
+    void VisitFunction(const Function& function) {
       bytecode_ = function.bytecode();
       if (bytecode_.IsNull()) return;
       if (bytecode_.InVMIsolateHeap()) return;
@@ -636,16 +647,8 @@
     PcDescriptors& pc_descriptor_;
   };
 
-  auto const zone = Thread::Current()->zone();
   DedupPcDescriptorsVisitor visitor(zone);
-  if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
-    // Prefer existing objects in the VM isolate.
-    visitor.AddVMBaseObjects();
-  }
-  // The function iteration handles the bytecode only, leaving code-related
-  // work for the code iteration.
-  ProgramVisitor::VisitFunctions(&visitor);
-  ProgramVisitor::VisitCode(&visitor);
+  WalkProgram(zone, isolate, &visitor);
 }
 
 class TypedDataKeyValueTrait {
@@ -674,7 +677,7 @@
   bool IsCorrectType(const Object& obj) const { return obj.IsTypedData(); }
 };
 
-void ProgramVisitor::DedupDeoptEntries() {
+void ProgramVisitor::DedupDeoptEntries(Zone* zone, Isolate* isolate) {
   class DedupDeoptEntriesVisitor : public CodeVisitor,
                                    public TypedDataDedupper {
    public:
@@ -685,7 +688,7 @@
           offset_(Smi::Handle(zone)),
           reason_and_flags_(Smi::Handle(zone)) {}
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       deopt_table_ = code.deopt_info_array();
       if (deopt_table_.IsNull()) return;
       intptr_t length = DeoptTable::GetLength(deopt_table_);
@@ -707,12 +710,12 @@
     Smi& reason_and_flags_;
   };
 
-  DedupDeoptEntriesVisitor visitor(Thread::Current()->zone());
-  ProgramVisitor::VisitCode(&visitor);
+  DedupDeoptEntriesVisitor visitor(zone);
+  WalkProgram(zone, isolate, &visitor);
 }
 
 #if defined(DART_PRECOMPILER)
-void ProgramVisitor::DedupCatchEntryMovesMaps() {
+void ProgramVisitor::DedupCatchEntryMovesMaps(Zone* zone, Isolate* isolate) {
   class DedupCatchEntryMovesMapsVisitor : public CodeVisitor,
                                           public TypedDataDedupper {
    public:
@@ -720,7 +723,7 @@
         : TypedDataDedupper(zone),
           catch_entry_moves_maps_(TypedData::Handle(zone)) {}
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       catch_entry_moves_maps_ = code.catch_entry_moves_maps();
       catch_entry_moves_maps_ = Dedup(catch_entry_moves_maps_);
       code.set_catch_entry_moves_maps(catch_entry_moves_maps_);
@@ -731,8 +734,8 @@
   };
 
   if (!FLAG_precompiled_mode) return;
-  DedupCatchEntryMovesMapsVisitor visitor(Thread::Current()->zone());
-  ProgramVisitor::VisitCode(&visitor);
+  DedupCatchEntryMovesMapsVisitor visitor(zone);
+  WalkProgram(zone, isolate, &visitor);
 }
 
 class UnlinkedCallKeyValueTrait {
@@ -753,15 +756,20 @@
   }
 };
 
-void ProgramVisitor::DedupUnlinkedCalls() {
+void ProgramVisitor::DedupUnlinkedCalls(Zone* zone, Isolate* isolate) {
   class DedupUnlinkedCallsVisitor
       : public CodeVisitor,
         public Dedupper<UnlinkedCall, UnlinkedCallKeyValueTrait> {
    public:
-    explicit DedupUnlinkedCallsVisitor(Zone* zone)
+    explicit DedupUnlinkedCallsVisitor(Zone* zone, Isolate* isolate)
         : Dedupper(zone),
           entry_(Object::Handle(zone)),
-          pool_(ObjectPool::Handle(zone)) {}
+          pool_(ObjectPool::Handle(zone)) {
+      auto& gop = ObjectPool::Handle(
+          zone, isolate->object_store()->global_object_pool());
+      ASSERT_EQUAL(!gop.IsNull(), FLAG_use_bare_instructions);
+      DedupPool(gop);
+    }
 
     void DedupPool(const ObjectPool& pool) {
       if (pool.IsNull()) return;
@@ -776,7 +784,7 @@
       }
     }
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       pool_ = code.object_pool();
       DedupPool(pool_);
     }
@@ -788,16 +796,7 @@
 
   if (!FLAG_precompiled_mode) return;
 
-  auto const t = Thread::Current();
-  auto Z = t->zone();
-  auto const I = t->isolate();
-
-  DedupUnlinkedCallsVisitor deduper(Z);
-  auto& gop = ObjectPool::Handle(Z, I->object_store()->global_object_pool());
-  ASSERT_EQUAL(gop.IsNull(), !FLAG_use_bare_instructions);
-  if (FLAG_use_bare_instructions) {
-    deduper.DedupPool(gop);
-  }
+  DedupUnlinkedCallsVisitor deduper(zone, isolate);
 
   // Note: in bare instructions mode we can still have object pools attached
   // to code objects and these pools need to be deduplicated.
@@ -807,10 +806,10 @@
   // to produce more informative snapshot profile.
   if (!FLAG_use_bare_instructions ||
       FLAG_write_v8_snapshot_profile_to != nullptr) {
-    VisitCode(&deduper);
+    WalkProgram(zone, isolate, &deduper);
   }
 }
-#endif  // !defined(DART_PRECOMPILER)
+#endif  // defined(DART_PRECOMPILER)
 
 class CodeSourceMapKeyValueTrait {
  public:
@@ -834,15 +833,20 @@
   }
 };
 
-void ProgramVisitor::DedupCodeSourceMaps() {
+void ProgramVisitor::DedupCodeSourceMaps(Zone* zone, Isolate* isolate) {
   class DedupCodeSourceMapsVisitor
       : public CodeVisitor,
         public Dedupper<CodeSourceMap, CodeSourceMapKeyValueTrait> {
    public:
     explicit DedupCodeSourceMapsVisitor(Zone* zone)
-        : Dedupper(zone), code_source_map_(CodeSourceMap::Handle(zone)) {}
+        : Dedupper(zone), code_source_map_(CodeSourceMap::Handle(zone)) {
+      if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
+        // Prefer existing objects in the VM isolate.
+        AddVMBaseObjects();
+      }
+    }
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       code_source_map_ = code.code_source_map();
       code_source_map_ = Dedup(code_source_map_);
       code.set_code_source_map(code_source_map_);
@@ -852,13 +856,8 @@
     CodeSourceMap& code_source_map_;
   };
 
-  auto const zone = Thread::Current()->zone();
   DedupCodeSourceMapsVisitor visitor(zone);
-  if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
-    // Prefer existing objects in the VM isolate.
-    visitor.AddVMBaseObjects();
-  }
-  ProgramVisitor::VisitCode(&visitor);
+  WalkProgram(zone, isolate, &visitor);
 }
 
 class ArrayKeyValueTrait {
@@ -887,17 +886,18 @@
   }
 };
 
-void ProgramVisitor::DedupLists() {
+void ProgramVisitor::DedupLists(Zone* zone, Isolate* isolate) {
   class DedupListsVisitor : public CodeVisitor,
-                            public Dedupper<Array, ArrayKeyValueTrait>,
-                            public FunctionVisitor {
+                            public Dedupper<Array, ArrayKeyValueTrait> {
    public:
     explicit DedupListsVisitor(Zone* zone)
         : Dedupper(zone),
           list_(Array::Handle(zone)),
           function_(Function::Handle(zone)) {}
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
+      if (!code.IsFunctionCode()) return;
+
       list_ = code.inlined_id_to_function();
       list_ = Dedup(list_);
       code.set_inlined_id_to_function(list_);
@@ -911,7 +911,7 @@
       code.set_static_calls_target_table(list_);
     }
 
-    void Visit(const Function& function) {
+    void VisitFunction(const Function& function) {
       list_ = PrepareParameterTypes(function);
       list_ = Dedup(list_);
       function.set_parameter_types(list_);
@@ -961,9 +961,8 @@
     Function& function_;
   };
 
-  DedupListsVisitor visitor(Thread::Current()->zone());
-  ProgramVisitor::VisitFunctions(&visitor);
-  ProgramVisitor::VisitCode(&visitor);
+  DedupListsVisitor visitor(zone);
+  WalkProgram(zone, isolate, &visitor);
 }
 
 // Traits for comparing two [Instructions] objects for equality, which is
@@ -1046,9 +1045,9 @@
     return Instructions::Equals(pair->instructions(), key->instructions());
   }
 };
-#endif  // defined(DART_PRECOMPILER)
+#endif
 
-void ProgramVisitor::DedupInstructions() {
+void ProgramVisitor::DedupInstructions(Zone* zone, Isolate* isolate) {
   class DedupInstructionsVisitor
       : public CodeVisitor,
         public Dedupper<Instructions, InstructionsKeyValueTrait>,
@@ -1057,7 +1056,12 @@
     explicit DedupInstructionsVisitor(Zone* zone)
         : Dedupper(zone),
           function_(Function::Handle(zone)),
-          instructions_(Instructions::Handle(zone)) {}
+          instructions_(Instructions::Handle(zone)) {
+      if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
+        // Prefer existing objects in the VM isolate.
+        Dart::vm_isolate()->heap()->VisitObjectsImagePages(this);
+      }
+    }
 
     void VisitObject(RawObject* obj) {
       if (!obj->IsInstructions()) return;
@@ -1065,7 +1069,7 @@
       AddCanonical(instructions_);
     }
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       instructions_ = code.instructions();
       instructions_ = Dedup(instructions_);
       code.SetActiveInstructions(instructions_,
@@ -1082,15 +1086,6 @@
     Instructions& instructions_;
   };
 
-  DedupInstructionsVisitor visitor(Thread::Current()->zone());
-  if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
-    // Prefer existing objects in the VM isolate.
-    Dart::vm_isolate()->heap()->VisitObjectsImagePages(&visitor);
-  }
-  ProgramVisitor::VisitCode(&visitor);
-}
-
-void ProgramVisitor::DedupInstructionsWithSameMetadata() {
 #if defined(DART_PRECOMPILER)
   class DedupInstructionsWithSameMetadataVisitor
       : public CodeVisitor,
@@ -1109,7 +1104,7 @@
       AddCanonical(canonical_);
     }
 
-    void Visit(const Code& code) {
+    void VisitCode(const Code& code) {
       if (code.IsDisabled()) return;
       canonical_ = Dedup(code);
       instructions_ = canonical_.instructions();
@@ -1130,37 +1125,39 @@
     Instructions& instructions_;
   };
 
-  DedupInstructionsWithSameMetadataVisitor visitor(Thread::Current()->zone());
-  ProgramVisitor::VisitCode(&visitor);
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    DedupInstructionsWithSameMetadataVisitor visitor(zone);
+    return WalkProgram(zone, isolate, &visitor);
+  }
 #endif  // defined(DART_PRECOMPILER)
+
+  DedupInstructionsVisitor visitor(zone);
+  WalkProgram(zone, isolate, &visitor);
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-void ProgramVisitor::Dedup() {
+void ProgramVisitor::Dedup(Thread* thread) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  Thread* thread = Thread::Current();
+  auto const isolate = thread->isolate();
   StackZone stack_zone(thread);
   HANDLESCOPE(thread);
+  auto const zone = thread->zone();
 
-  BindStaticCalls();
-  ShareMegamorphicBuckets();
-  NormalizeAndDedupCompressedStackMaps();
-  DedupPcDescriptors();
-  NOT_IN_PRECOMPILED(DedupDeoptEntries());
+  BindStaticCalls(zone, isolate);
+  ShareMegamorphicBuckets(zone, isolate);
+  NormalizeAndDedupCompressedStackMaps(zone, isolate);
+  DedupPcDescriptors(zone, isolate);
+  NOT_IN_PRECOMPILED(DedupDeoptEntries(zone, isolate));
 #if defined(DART_PRECOMPILER)
-  DedupCatchEntryMovesMaps();
-  DedupUnlinkedCalls();
+  DedupCatchEntryMovesMaps(zone, isolate);
+  DedupUnlinkedCalls(zone, isolate);
 #endif
-  DedupCodeSourceMaps();
-  DedupLists();
+  DedupCodeSourceMaps(zone, isolate);
+  DedupLists(zone, isolate);
 
   // Reduces binary size but obfuscates profiler results.
   if (FLAG_dedup_instructions) {
-    if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-      DedupInstructionsWithSameMetadata();
-    } else {
-      DedupInstructions();
-    }
+    DedupInstructions(zone, isolate);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h
index 7c7cf0e..9edc6ad 100644
--- a/runtime/vm/program_visitor.h
+++ b/runtime/vm/program_visitor.h
@@ -9,50 +9,109 @@
 
 namespace dart {
 
+// Currently, we have three types of abstract visitors that can be extended and
+// used for program walking:
+//
+// * ClassVisitor, a visitor for classes in the program.
+// * FunctionVisitor, a visitor for functions in the program.
+// * CodeVisitor, a visitor for code objects in the program.
+//
+// To find the functions in a program, we must traverse the classes in the
+// program, and similarly for code objects and functions. Thus, each
+// FunctionVisitor is also a ClassVisitor, and each CodeVisitor is also a
+// FunctionVisitor (and thus a ClassVisitor).
+//
+// Only the most specific visitor method is abstract. Derived visitors have a
+// default empty implementation for base visitor methods to limit boilerplate
+// needed when extending. For example, subclasses of CodeVisitor that only do
+// per-Code work do not need to add empty implementations for VisitClass and
+// VisitFunction.
+//
+// There are no guarantees for the order in which objects of a given type will
+// be visited or how many times they will be visited. The only guarantee is that
+// objects will be visited before any visitable sub-objects they contain. For
+// example, if a FunctionVisitor has a VisitClass implementation that drops
+// methods from a class, the function objects for those methods will not be
+// visited unless they are also found via another source of function objects.
+//
+// Note that WalkProgram only visits objects in the isolate heap. Deduplicating
+// visitors that want to use VM objects as canonical when possible should
+// instead add the appropriate VM objects first in their constructor.
+
 class Class;
 class Code;
 class Function;
 
-template <typename T>
-class Visitor : public ValueObject {
+class CodeVisitor;
+class FunctionVisitor;
+
+class ClassVisitor : public ValueObject {
  public:
-  virtual ~Visitor() {}
-  virtual void Visit(const T& obj) = 0;
+  virtual ~ClassVisitor() {}
+
+  virtual bool IsFunctionVisitor() const { return false; }
+  const FunctionVisitor* AsFunctionVisitor() const {
+    return const_cast<FunctionVisitor*>(
+      const_cast<ClassVisitor*>(this)->AsFunctionVisitor());
+  }
+  FunctionVisitor* AsFunctionVisitor() {
+    if (!IsFunctionVisitor()) return nullptr;
+    return reinterpret_cast<FunctionVisitor*>(this);
+  }
+
+  virtual bool IsCodeVisitor() const { return false; }
+  const CodeVisitor* AsCodeVisitor() const {
+    return const_cast<CodeVisitor*>(
+      const_cast<ClassVisitor*>(this)->AsCodeVisitor());
+  }
+  CodeVisitor* AsCodeVisitor() {
+    if (!IsCodeVisitor()) return nullptr;
+    return reinterpret_cast<CodeVisitor*>(this);
+  }
+
+  virtual void VisitClass(const Class& cls) = 0;
 };
 
-using ClassVisitor = Visitor<Class>;
-using CodeVisitor = Visitor<Code>;
-using FunctionVisitor = Visitor<Function>;
+class FunctionVisitor : public ClassVisitor {
+ public:
+  bool IsFunctionVisitor() const { return true; }
+  virtual void VisitClass(const Class& cls) {}
+  virtual void VisitFunction(const Function& function) = 0;
+};
+
+class CodeVisitor : public FunctionVisitor {
+ public:
+  bool IsCodeVisitor() const { return true; }
+  virtual void VisitFunction(const Function& function) {}
+  virtual void VisitCode(const Code& code) = 0;
+};
+
+class Thread;
+class Isolate;
 
 class ProgramVisitor : public AllStatic {
  public:
-  // Currently visits the following code objects:
-  // * Code objects for functions (visited via VisitFunctions) where HasCode()
-  //   is true.
-  // * Code objects for entries in the dispatch table (if applicable).
-  //
-  // Notably, it does not visit any stubs not reachable via these routes.
-  static void VisitCode(CodeVisitor* visitor);
-  static void VisitFunctions(FunctionVisitor* visitor);
-  static void VisitClasses(ClassVisitor* visitor);
+  // Walks all non-null class, function, and code objects in the program as
+  // necessary for the given visitor.
+  static void WalkProgram(Zone* zone, Isolate* isolate, ClassVisitor* visitor);
 
-  static void Dedup();
+  static void Dedup(Thread* thread);
 
  private:
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  static void BindStaticCalls();
-  static void ShareMegamorphicBuckets();
-  static void NormalizeAndDedupCompressedStackMaps();
-  static void DedupPcDescriptors();
-  static void DedupDeoptEntries();
+  static void BindStaticCalls(Zone* zone, Isolate* isolate);
+  static void ShareMegamorphicBuckets(Zone* zone, Isolate* isolate);
+  static void NormalizeAndDedupCompressedStackMaps(Zone* zone,
+                                                   Isolate* isolate);
+  static void DedupPcDescriptors(Zone* zone, Isolate* isolate);
+  static void DedupDeoptEntries(Zone* zone, Isolate* isolate);
 #if defined(DART_PRECOMPILER)
-  static void DedupCatchEntryMovesMaps();
-  static void DedupUnlinkedCalls();
+  static void DedupCatchEntryMovesMaps(Zone* zone, Isolate* isolate);
+  static void DedupUnlinkedCalls(Zone* zone, Isolate* isolate);
 #endif
-  static void DedupCodeSourceMaps();
-  static void DedupLists();
-  static void DedupInstructions();
-  static void DedupInstructionsWithSameMetadata();
+  static void DedupCodeSourceMaps(Zone* zone, Isolate* isolate);
+  static void DedupLists(Zone* zone, Isolate* isolate);
+  static void DedupInstructions(Zone* zone, Isolate* isolate);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 };
 
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 2519af7..85c05f2 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -73,7 +73,7 @@
     return;
   }
   intptr_t size_from_tags = SizeTag::decode(tags);
-  intptr_t size_from_class = HeapSizeFromClass();
+  intptr_t size_from_class = HeapSizeFromClass(tags);
   if ((size_from_tags != 0) && (size_from_tags != size_from_class)) {
     FATAL3(
         "Inconsistent size encountered "
@@ -85,11 +85,12 @@
 // Can't look at the class object because it can be called during
 // compaction when the class objects are moving. Can use the class
 // id in the header and the sizes in the Class Table.
-intptr_t RawObject::HeapSizeFromClass() const {
+// Cannot deference ptr()->tags_. May dereference other parts of the object.
+intptr_t RawObject::HeapSizeFromClass(uint32_t tags) const {
   // Only reasonable to be called on heap objects.
   ASSERT(IsHeapObject());
 
-  intptr_t class_id = GetClassId();
+  intptr_t class_id = ClassIdTag::decode(tags);
   intptr_t instance_size = 0;
   switch (class_id) {
     case kCodeCid: {
@@ -158,9 +159,9 @@
       CLASS_LIST_TYPED_DATA(SIZE_FROM_CLASS) {
         const RawTypedData* raw_obj =
             reinterpret_cast<const RawTypedData*>(this);
-        intptr_t cid = raw_obj->GetClassId();
         intptr_t array_len = Smi::Value(raw_obj->ptr()->length_);
-        intptr_t lengthInBytes = array_len * TypedData::ElementSizeInBytes(cid);
+        intptr_t lengthInBytes =
+            array_len * TypedData::ElementSizeInBytes(class_id);
         instance_size = TypedData::InstanceSize(lengthInBytes);
         break;
       }
@@ -245,7 +246,7 @@
       if (!class_table->IsValidIndex(class_id) ||
           (!class_table->HasValidClassAt(class_id) && !use_saved_class_table)) {
         FATAL3("Invalid cid: %" Pd ", obj: %p, tags: %x. Corrupt heap?",
-               class_id, this, static_cast<uint32_t>(ptr()->tags_));
+               class_id, this, static_cast<uint32_t>(tags));
       }
 #endif  // DEBUG
       instance_size = isolate_group->GetClassSizeForHeapWalkAt(class_id);
@@ -253,7 +254,6 @@
   }
   ASSERT(instance_size != 0);
 #if defined(DEBUG)
-  uint32_t tags = ptr()->tags_;
   intptr_t tags_size = SizeTag::decode(tags);
   if ((class_id == kArrayCid) && (instance_size > tags_size && tags_size > 0)) {
     // TODO(22501): Array::MakeFixedLength could be in the process of shrinking
@@ -575,6 +575,7 @@
 VARIABLE_NULL_VISITOR(TwoByteString, Smi::Value(raw_obj->ptr()->length_))
 // Abstract types don't have their visitor called.
 UNREACHABLE_VISITOR(AbstractType)
+UNREACHABLE_VISITOR(CallSiteData)
 UNREACHABLE_VISITOR(TypedDataBase)
 UNREACHABLE_VISITOR(Error)
 UNREACHABLE_VISITOR(Number)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 10566c2..07293c9 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -167,6 +167,11 @@
       return SizeBits::update(SizeToTagValue(size), tag);
     }
 
+    static UNLESS_DEBUG(constexpr) bool SizeFits(intptr_t size) {
+      DEBUG_ASSERT(Utils::IsAligned(size, kObjectAlignment));
+      return (size <= kMaxSizeTag);
+    }
+
    private:
     // The actual unscaled bit field used within the tag field.
     class SizeBits
@@ -174,7 +179,7 @@
 
     static UNLESS_DEBUG(constexpr) intptr_t SizeToTagValue(intptr_t size) {
       DEBUG_ASSERT(Utils::IsAligned(size, kObjectAlignment));
-      return (size > kMaxSizeTag) ? 0 : (size >> kObjectAlignmentLog2);
+      return !SizeFits(size) ? 0 : (size >> kObjectAlignmentLog2);
     }
     static constexpr intptr_t TagValueToSize(intptr_t value) {
       return value << kObjectAlignmentLog2;
@@ -437,7 +442,7 @@
       // leading to inconsistency between HeapSizeFromClass() and
       // SizeTag::decode(tags). We are working around it by reloading tags_ and
       // recomputing size from tags.
-      const intptr_t size_from_class = HeapSizeFromClass();
+      const intptr_t size_from_class = HeapSizeFromClass(tags);
       if ((result > size_from_class) && (GetClassId() == kArrayCid) &&
           (ptr()->tags_) != tags) {
         result = SizeTag::decode(ptr()->tags_);
@@ -446,7 +451,19 @@
 #endif
       return result;
     }
-    result = HeapSizeFromClass();
+    result = HeapSizeFromClass(tags);
+    ASSERT(result > SizeTag::kMaxSizeTag);
+    return result;
+  }
+
+  // This variant must not deference ptr()->tags_.
+  intptr_t HeapSize(uint32_t tags) const {
+    ASSERT(IsHeapObject());
+    intptr_t result = SizeTag::decode(tags);
+    if (result != 0) {
+      return result;
+    }
+    result = HeapSizeFromClass(tags);
     ASSERT(result > SizeTag::kMaxSizeTag);
     return result;
   }
@@ -605,7 +622,7 @@
   intptr_t VisitPointersPredefined(ObjectPointerVisitor* visitor,
                                    intptr_t class_id);
 
-  intptr_t HeapSizeFromClass() const;
+  intptr_t HeapSizeFromClass(uint32_t tags) const;
 
   void SetClassId(intptr_t new_cid) {
     ptr()->tags_.UpdateUnsynchronized<ClassIdTag>(new_cid);
@@ -761,7 +778,8 @@
   friend class OneByteString;  // StoreSmi
   friend class RawInstance;
   friend class Scavenger;
-  friend class ScavengerVisitor;
+  template <bool>
+  friend class ScavengerVisitorBase;
   friend class ImageReader;  // tags_ check
   friend class ImageWriter;
   friend class AssemblyImageWriter;
@@ -781,6 +799,7 @@
   friend class ObjectLocator;
   friend class WriteBarrierUpdateVisitor;  // CheckHeapPointerStore
   friend class OffsetsTable;
+  friend class Object;
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject);
@@ -2095,13 +2114,21 @@
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
-class RawICData : public RawObject {
-  RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
-
-  VISIT_FROM(RawObject*, entries_);
-  RawArray* entries_;          // Contains class-ids, target and count.
+// Abstract base class for RawICData/RawMegamorphicCache
+class RawCallSiteData : public RawObject {
+ protected:
   RawString* target_name_;     // Name of target function.
+  // arg_descriptor in RawICData and in RawMegamorphicCache should be
+  // in the same position so that NoSuchMethod can access it.
   RawArray* args_descriptor_;  // Arguments descriptor.
+ private:
+  RAW_HEAP_OBJECT_IMPLEMENTATION(CallSiteData)
+};
+
+class RawICData : public RawCallSiteData {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
+  VISIT_FROM(RawObject*, target_name_);
+  RawArray* entries_;  // Contains class-ids, target and count.
   // Static type of the receiver, if instance call and available.
   NOT_IN_PRECOMPILED(RawAbstractType* receivers_static_type_);
   RawObject* owner_;  // Parent/calling function or original IC of cloned IC.
@@ -2109,7 +2136,7 @@
   RawObject** to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFullAOT:
-        return reinterpret_cast<RawObject**>(&ptr()->args_descriptor_);
+        return reinterpret_cast<RawObject**>(&ptr()->entries_);
       case Snapshot::kFull:
       case Snapshot::kFullJIT:
         return to();
@@ -2125,15 +2152,12 @@
   uint32_t state_bits_;  // Number of arguments tested in IC, deopt reasons.
 };
 
-class RawMegamorphicCache : public RawObject {
+class RawMegamorphicCache : public RawCallSiteData {
   RAW_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache);
-
-  VISIT_FROM(RawObject*, buckets_)
+  VISIT_FROM(RawObject*, target_name_)
   RawArray* buckets_;
   RawSmi* mask_;
-  RawString* target_name_;     // Name of target function.
-  RawArray* args_descriptor_;  // Arguments descriptor.
-  VISIT_TO(RawObject*, args_descriptor_)
+  VISIT_TO(RawObject*, mask_)
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
   int32_t filled_entry_count_;
@@ -2596,7 +2620,8 @@
   friend class ObjectPoolSerializationCluster;
   friend class RawObjectPool;
   friend class GCCompactor;
-  friend class ScavengerVisitor;
+  template <bool>
+  friend class ScavengerVisitorBase;
   friend class SnapshotReader;
 };
 
@@ -2623,6 +2648,8 @@
   VISIT_NOTHING();
 
   bool value_;
+
+  friend class Object;
 };
 
 class RawArray : public RawInstance {
@@ -2888,7 +2915,8 @@
   template <bool>
   friend class MarkingVisitorBase;
   friend class Scavenger;
-  friend class ScavengerVisitor;
+  template <bool>
+  friend class ScavengerVisitorBase;
 };
 
 // MirrorReferences are used by mirrors to hold reflectees that are VM
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index f68c4a2..88c11a5 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -120,14 +120,12 @@
   F(UnlinkedCall, args_descriptor_)                                            \
   F(MonomorphicSmiableCall, expected_cid_)                                     \
   F(MonomorphicSmiableCall, target_)                                           \
+  F(CallSiteData, target_name_)                                                \
+  F(CallSiteData, args_descriptor_)                                            \
   F(ICData, entries_)                                                          \
-  F(ICData, target_name_)                                                      \
-  F(ICData, args_descriptor_)                                                  \
   F(ICData, owner_)                                                            \
   F(MegamorphicCache, buckets_)                                                \
   F(MegamorphicCache, mask_)                                                   \
-  F(MegamorphicCache, target_name_)                                            \
-  F(MegamorphicCache, args_descriptor_)                                        \
   F(SubtypeTestCache, cache_)                                                  \
   F(ApiError, message_)                                                        \
   F(LanguageError, previous_error_)                                            \
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 0f2d0c8..4fce40c 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -539,6 +539,7 @@
 MESSAGE_SNAPSHOT_UNREACHABLE(FfiTrampolineData);
 MESSAGE_SNAPSHOT_UNREACHABLE(Field);
 MESSAGE_SNAPSHOT_UNREACHABLE(Function);
+MESSAGE_SNAPSHOT_UNREACHABLE(CallSiteData);
 MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
 MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
 MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsSection);
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 1a097cc..6bb8000 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1415,7 +1415,6 @@
   arguments.SetReturn(target);
 }
 
-#if defined(DART_PRECOMPILED_RUNTIME)
 static bool IsSingleTarget(Isolate* isolate,
                            Zone* zone,
                            intptr_t lower_cid,
@@ -1438,101 +1437,6 @@
   }
   return true;
 }
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
-
-// Handle a miss of a single target cache.
-//   Arg1: Receiver.
-//   Arg0: Stub out.
-//   Returns: the ICData used to continue with a polymorphic call.
-DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 2) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  UNREACHABLE();
-#else
-  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
-
-  DartFrameIterator iterator(thread,
-                             StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* caller_frame = iterator.NextFrame();
-  ASSERT(caller_frame->IsDartFrame());
-  const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
-  const Function& caller_function =
-      Function::Handle(zone, caller_frame->LookupDartFunction());
-
-  SingleTargetCache& cache = SingleTargetCache::Handle(zone);
-  cache ^=
-      CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code);
-  Code& old_target_code = Code::Handle(zone, cache.target());
-  Function& old_target = Function::Handle(zone);
-  old_target ^= old_target_code.owner();
-
-  // We lost the original ICData when we patched to the monomorphic case.
-  const String& name = String::Handle(zone, old_target.name());
-  ASSERT(!old_target.HasOptionalParameters());
-  ASSERT(!old_target.IsGeneric());
-  const int kTypeArgsLen = 0;
-  // TODO(dartbug.com/33549): Update this code to use the size of the parameters
-  // when supporting calls to non-static methods with unboxed parameters.
-  const Array& descriptor =
-      Array::Handle(zone, ArgumentsDescriptor::NewBoxed(
-                              kTypeArgsLen, old_target.num_fixed_parameters()));
-  const ICData& ic_data =
-      ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
-                                       DeoptId::kNone, 1, /* args_tested */
-                                       ICData::kInstance));
-
-  // Maybe add the new target.
-  Class& cls = Class::Handle(zone, receiver.clazz());
-  ArgumentsDescriptor args_desc(descriptor);
-  Function& target_function = Function::Handle(
-      zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
-  if (target_function.IsNull()) {
-    target_function = InlineCacheMissHelper(cls, descriptor, name);
-  }
-  if (target_function.IsNull()) {
-    ASSERT(!FLAG_lazy_dispatchers);
-  } else {
-    ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
-  }
-
-  if (old_target.raw() == target_function.raw()) {
-    intptr_t lower, upper, unchecked_lower, unchecked_upper;
-    if (receiver.GetClassId() < cache.lower_limit()) {
-      lower = receiver.GetClassId();
-      unchecked_lower = receiver.GetClassId();
-      upper = cache.upper_limit();
-      unchecked_upper = cache.lower_limit() - 1;
-    } else {
-      lower = cache.lower_limit();
-      unchecked_lower = cache.upper_limit() + 1;
-      upper = receiver.GetClassId();
-      unchecked_upper = receiver.GetClassId();
-    }
-
-    if (IsSingleTarget(isolate, zone, unchecked_lower, unchecked_upper,
-                       target_function, name)) {
-      cache.set_lower_limit(lower);
-      cache.set_upper_limit(upper);
-      // Return the ICData. The single target stub will jump to continue in the
-      // IC call stub.
-      arguments.SetArgAt(0, StubCode::ICCallThroughCode());
-      arguments.SetReturn(ic_data);
-      return;
-    }
-  }
-
-  // Call site is not single target, switch to call using ICData.
-  const Code& stub = StubCode::ICCallThroughCode();
-  CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
-                                     stub);
-
-  // Return the ICData. The single target stub will jump to continue in the
-  // IC call stub.
-  arguments.SetArgAt(0, stub);
-  arguments.SetReturn(ic_data);
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
-}
-
-#if defined(DART_PRECOMPILED_RUNTIME)
 
 class SavedUnlinkedCallMapKeyEqualsTraits : public AllStatic {
  public:
@@ -1569,6 +1473,7 @@
   object_store->set_saved_unlinked_calls(unlinked_call_map.Release());
 }
 
+#if defined(DART_PRECOMPILED_RUNTIME)
 static RawUnlinkedCall* LoadUnlinkedCall(Zone* zone,
                                          Isolate* isolate,
                                          uword pc) {
@@ -1586,48 +1491,81 @@
 
   return unlinked_call.raw();
 }
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
+#endif
 
-// Handle the first use of an instance call
-//   Arg2: UnlinkedCall.
-//   Arg1: Receiver.
-//   Arg0: Stub out.
-//   Returns: the ICData used to continue with a polymorphic call.
-DEFINE_RUNTIME_ENTRY(UnlinkedCall, 3) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  UNREACHABLE();
-#else
-  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
-  const UnlinkedCall& unlinked =
-      UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(2));
+class SwitchableCallHandler {
+ public:
+  SwitchableCallHandler(Thread* thread,
+                        const Instance& receiver,
+                        NativeArguments arguments,
+                        StackFrame* caller_frame,
+                        const Code& caller_code,
+                        const Function& caller_function)
+      : isolate_(thread->isolate()),
+        thread_(thread),
+        zone_(thread->zone()),
+        receiver_(receiver),
+        arguments_(arguments),
+        caller_frame_(caller_frame),
+        caller_code_(caller_code),
+        caller_function_(caller_function) {}
 
-  DartFrameIterator iterator(thread,
-                             StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* caller_frame = iterator.NextFrame();
-  ASSERT(caller_frame->IsDartFrame());
-  const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
-  const Function& caller_function =
-      Function::Handle(zone, caller_frame->LookupDartFunction());
+  void HandleMiss(const Object& old_data, const Code& old_target);
 
-  const String& name = String::Handle(zone, unlinked.target_name());
-  const Array& descriptor = Array::Handle(zone, unlinked.args_descriptor());
-  const ICData& ic_data =
-      ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
-                                       DeoptId::kNone, 1, /* args_tested */
-                                       ICData::kInstance));
+ private:
+  RawFunction* ResolveAndAddReceiverCheck(const String& name,
+                                          const Array& descriptor,
+                                          const ICData& ic_data);
+  void DoUnlinkedCall(const UnlinkedCall& unlinked);
+  bool CanExtendSingleTargetRange(const String& name,
+                                  const Function& old_target,
+                                  const Function& target_function,
+                                  intptr_t* lower,
+                                  intptr_t* upper);
+  void DoMonomorphicMiss(const Object& data);
+  void DoSingleTargetMiss(const SingleTargetCache& data);
+  void DoICDataMiss(const ICData& data);
+  void DoMegamorphicMiss(const MegamorphicCache& data);
 
-  Class& cls = Class::Handle(zone, receiver.clazz());
+  Isolate* isolate_;
+  Thread* thread_;
+  Zone* zone_;
+  const Instance& receiver_;
+  NativeArguments arguments_;
+  StackFrame* caller_frame_;
+  const Code& caller_code_;
+  const Function& caller_function_;
+};
+
+RawFunction* SwitchableCallHandler::ResolveAndAddReceiverCheck(
+    const String& name,
+    const Array& descriptor,
+    const ICData& ic_data) {
   ArgumentsDescriptor args_desc(descriptor);
+  const Class& cls = Class::Handle(zone_, receiver_.clazz());
   Function& target_function = Function::Handle(
-      zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
+      zone_, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
   if (target_function.IsNull()) {
     target_function = InlineCacheMissHelper(cls, descriptor, name);
   }
   if (target_function.IsNull()) {
     ASSERT(!FLAG_lazy_dispatchers);
   } else {
-    ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
+    ic_data.AddReceiverCheck(receiver_.GetClassId(), target_function);
   }
+  return target_function.raw();
+}
+
+void SwitchableCallHandler::DoUnlinkedCall(const UnlinkedCall& unlinked) {
+  const String& name = String::Handle(zone_, unlinked.target_name());
+  const Array& descriptor = Array::Handle(zone_, unlinked.args_descriptor());
+  const ICData& ic_data =
+      ICData::Handle(zone_, ICData::New(caller_function_, name, descriptor,
+                                        DeoptId::kNone, 1, /* args_tested */
+                                        ICData::kInstance));
+
+  const Function& target_function = Function::Handle(
+      zone_, ResolveAndAddReceiverCheck(name, descriptor, ic_data));
 
   // In AOT bare mode, the PC -> Code mapping is ambiguous, since multiple code
   // objects can have the same deduped instructions and bare frames are compact
@@ -1643,7 +1581,7 @@
   //
   // If not, we'll save the unlinked call object in a map.
   //
-  // See [MonomorphicMiss]
+  // See [DoMonomorphicMiss]
   const bool need_saved_unlinked_call =
       (FLAG_use_bare_instructions && FLAG_dedup_instructions);
 
@@ -1656,13 +1594,11 @@
   //
   // We assume here that generated code never moves.
   if (need_saved_unlinked_call) {
-#if defined(DART_PRECOMPILED_RUNTIME)
-    SaveUnlinkedCall(zone, isolate, caller_frame->pc(), unlinked);
-#else
-    UNREACHABLE();
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
+    SaveUnlinkedCall(zone_, isolate_, caller_frame_->pc(), unlinked);
   }
 
+  Object& object = Object::Handle(zone_, ic_data.raw());
+  Code& code = Code::Handle(zone_, StubCode::ICCallThroughCode().raw());
   // If the target function has optional parameters or is generic, it's
   // prologue requires ARGS_DESC_REG to be populated. Yet the switchable calls
   // do not populate that on the call site, which is why we don't transition
@@ -1675,37 +1611,50 @@
       !target_function.IsGeneric()) {
     // Patch to monomorphic call.
     ASSERT(target_function.HasCode());
-    const Code& target_code = Code::Handle(zone, target_function.CurrentCode());
+    const Code& target_code =
+        Code::Handle(zone_, target_function.CurrentCode());
     const Smi& expected_cid =
-        Smi::Handle(zone, Smi::New(receiver.GetClassId()));
+        Smi::Handle(zone_, Smi::New(receiver_.GetClassId()));
 
     if (unlinked.can_patch_to_monomorphic()) {
-      CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
-                                         expected_cid, target_code);
+      object = expected_cid.raw();
+      code = target_code.raw();
     } else {
-      const MonomorphicSmiableCall& call = MonomorphicSmiableCall::Handle(
-          zone, MonomorphicSmiableCall::New(expected_cid.Value(), target_code));
-      CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, call,
-                                         StubCode::MonomorphicSmiableCheck());
+      object = MonomorphicSmiableCall::New(expected_cid.Value(), target_code);
+      code = StubCode::MonomorphicSmiableCheck().raw();
     }
-
-    // Return the ICData. The miss stub will jump to continue in the IC call
-    // stub.
-    arguments.SetArgAt(0, StubCode::ICCallThroughCode());
-    arguments.SetReturn(ic_data);
-    return;
   }
-
-  // Patch to call through stub.
-  const Code& stub = StubCode::ICCallThroughCode();
-  CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
-                                     stub);
+  CodePatcher::PatchSwitchableCallAt(caller_frame_->pc(), caller_code_, object,
+                                     code);
 
   // Return the ICData. The miss stub will jump to continue in the IC lookup
   // stub.
-  arguments.SetArgAt(0, stub);
-  arguments.SetReturn(ic_data);
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
+  arguments_.SetArgAt(0, StubCode::ICCallThroughCode());
+  arguments_.SetReturn(ic_data);
+}
+
+bool SwitchableCallHandler::CanExtendSingleTargetRange(
+    const String& name,
+    const Function& old_target,
+    const Function& target_function,
+    intptr_t* lower,
+    intptr_t* upper) {
+  if (old_target.raw() != target_function.raw()) {
+    return false;
+  }
+  intptr_t unchecked_lower, unchecked_upper;
+  if (receiver_.GetClassId() < *lower) {
+    unchecked_lower = receiver_.GetClassId();
+    unchecked_upper = *lower - 1;
+    *lower = receiver_.GetClassId();
+  } else {
+    unchecked_upper = receiver_.GetClassId();
+    unchecked_lower = *upper + 1;
+    *upper = receiver_.GetClassId();
+  }
+
+  return IsSingleTarget(isolate_, zone_, unchecked_lower, unchecked_upper,
+                        target_function, name);
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -1728,48 +1677,32 @@
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-// Handle a miss of a megamorphic cache.
-//   Arg1: Receiver.
-//   Arg0: continuation Code (out parameter).
-//   Returns: the ICData used to continue with a polymorphic call.
-DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 2) {
+void SwitchableCallHandler::DoMonomorphicMiss(const Object& data) {
 #if defined(DART_PRECOMPILED_RUNTIME)
-  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
-
-  DartFrameIterator iterator(thread,
-                             StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* caller_frame = iterator.NextFrame();
-  ASSERT(caller_frame->IsDartFrame());
-  const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
-  const Function& caller_function =
-      Function::Handle(zone, caller_frame->LookupDartFunction());
-
-  Object& old_data = Object::Handle(
-      CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code));
   classid_t old_expected_cid;
-  Function& old_target = Function::Handle(zone);
-  if (old_data.IsSmi()) {
-    old_expected_cid = Smi::Cast(old_data).Value();
-  } else if (old_data.IsMonomorphicSmiableCall()) {
-    old_expected_cid = MonomorphicSmiableCall::Cast(old_data).expected_cid();
+  Function& old_target = Function::Handle(zone_);
+  if (data.IsSmi()) {
+    old_expected_cid = Smi::Cast(data).Value();
+  } else if (data.IsMonomorphicSmiableCall()) {
+    old_expected_cid = MonomorphicSmiableCall::Cast(data).expected_cid();
     old_target ^=
-        Code::Handle(zone, MonomorphicSmiableCall::Cast(old_data).target())
+        Code::Handle(zone_, MonomorphicSmiableCall::Cast(data).target())
             .owner();
   } else {
     UNREACHABLE();
   }
 
-  String& name = String::Handle(zone);
-  Array& descriptor = Array::Handle(zone);
+  String& name = String::Handle(zone_);
+  Array& descriptor = Array::Handle(zone_);
   if (FLAG_use_bare_instructions && FLAG_dedup_instructions) {
-    const auto& unlinked_call = UnlinkedCall::Handle(
-        zone, LoadUnlinkedCall(zone, isolate, caller_frame->pc()));
+    const UnlinkedCall& unlinked_call = UnlinkedCall::Handle(
+        zone_, LoadUnlinkedCall(zone_, isolate_, caller_frame_->pc()));
     name = unlinked_call.target_name();
     descriptor = unlinked_call.args_descriptor();
 
     ArgumentsDescriptor args_desc(descriptor);
-    const auto& old_receiver_class =
-        Class::Handle(zone, isolate->class_table()->At(old_expected_cid));
+    const Class& old_receiver_class =
+        Class::Handle(zone_, isolate_->class_table()->At(old_expected_cid));
     old_target = Resolver::ResolveDynamicForReceiverClass(old_receiver_class,
                                                           name, args_desc);
     if (old_target.IsNull()) {
@@ -1784,8 +1717,8 @@
     // optional parameters, see DEFINE_RUNTIME_ENTRY(UnlinkedCall) above).
     if (old_target.IsNull()) {
       const Code& old_target_code =
-          Code::Handle(zone, CodePatcher::GetSwitchableCallTargetAt(
-                                 caller_frame->pc(), caller_code));
+          Code::Handle(zone_, CodePatcher::GetSwitchableCallTargetAt(
+                                  caller_frame_->pc(), caller_code_));
       old_target ^= old_target_code.owner();
     }
 
@@ -1799,202 +1732,294 @@
   }
 
   const ICData& ic_data =
-      ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
-                                       DeoptId::kNone, 1, /* args_tested */
-                                       ICData::kInstance));
+      ICData::Handle(zone_, ICData::New(caller_function_, name, descriptor,
+                                        DeoptId::kNone, 1, /* args_tested */
+                                        ICData::kInstance));
 
   // Add the first target.
   if (!old_target.IsNull()) {
     ic_data.AddReceiverCheck(old_expected_cid, old_target);
   }
 
-  // Maybe add the new target.
-  ArgumentsDescriptor args_desc(descriptor);
-  const Class& cls = Class::Handle(zone, receiver.clazz());
-  Function& target_function = Function::Handle(
-      zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
-  if (target_function.IsNull()) {
-    target_function = InlineCacheMissHelper(cls, descriptor, name);
-  }
-  if (target_function.IsNull()) {
-    ASSERT(!FLAG_lazy_dispatchers);
-  } else {
-    ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
-  }
+  const Function& target_function = Function::Handle(
+      zone_, ResolveAndAddReceiverCheck(name, descriptor, ic_data));
 
-  if (old_target.raw() == target_function.raw()) {
-    intptr_t lower, upper;
-    if (old_expected_cid < receiver.GetClassId()) {
-      lower = old_expected_cid;
-      upper = receiver.GetClassId();
-    } else {
-      lower = receiver.GetClassId();
-      upper = old_expected_cid;
-    }
-
-    if (IsSingleTarget(isolate, zone, lower, upper, target_function, name)) {
-      const SingleTargetCache& cache =
-          SingleTargetCache::Handle(SingleTargetCache::New());
-      const Code& code = Code::Handle(target_function.CurrentCode());
-      cache.set_target(code);
-      cache.set_entry_point(code.EntryPoint());
-      cache.set_lower_limit(lower);
-      cache.set_upper_limit(upper);
-      const Code& stub = StubCode::SingleTargetCall();
-      CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, cache,
-                                         stub);
-      // Return the ICData. The miss stub will jump to continue in the IC call
-      // stub.
-      arguments.SetArgAt(0, StubCode::ICCallThroughCode());
-      arguments.SetReturn(ic_data);
-      return;
-    }
+  intptr_t lower = old_expected_cid;
+  intptr_t upper = old_expected_cid;
+  if (CanExtendSingleTargetRange(name, old_target, target_function, &lower,
+                                 &upper)) {
+    const SingleTargetCache& cache =
+        SingleTargetCache::Handle(SingleTargetCache::New());
+    const Code& code = Code::Handle(target_function.CurrentCode());
+    cache.set_target(code);
+    cache.set_entry_point(code.EntryPoint());
+    cache.set_lower_limit(lower);
+    cache.set_upper_limit(upper);
+    const Code& stub = StubCode::SingleTargetCall();
+    CodePatcher::PatchSwitchableCallAt(caller_frame_->pc(), caller_code_, cache,
+                                       stub);
+    // Return the ICData. The miss stub will jump to continue in the IC call
+    // stub.
+    arguments_.SetArgAt(0, StubCode::ICCallThroughCode());
+    arguments_.SetReturn(ic_data);
+    return;
   }
 
   // Patch to call through stub.
   const Code& stub = StubCode::ICCallThroughCode();
-  CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
+  CodePatcher::PatchSwitchableCallAt(caller_frame_->pc(), caller_code_, ic_data,
                                      stub);
 
   // Return the ICData. The miss stub will jump to continue in the IC lookup
   // stub.
-  arguments.SetArgAt(0, stub);
-  arguments.SetReturn(ic_data);
+  arguments_.SetArgAt(0, stub);
+  arguments_.SetReturn(ic_data);
 #else   // JIT
-  DartFrameIterator iterator(thread,
-                             StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* caller_frame = iterator.NextFrame();
-  ASSERT(caller_frame->IsDartFrame());
-  ASSERT(!caller_frame->is_interpreted());
-  const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
-  ASSERT(!caller_code.is_optimized());
-
   const ICData& ic_data = ICData::Handle(
-      zone, FindICDataForInstanceCall(zone, caller_code, caller_frame->pc()));
+      zone_,
+      FindICDataForInstanceCall(zone_, caller_code_, caller_frame_->pc()));
   RELEASE_ASSERT(!ic_data.IsNull());
 
   ASSERT(ic_data.NumArgsTested() == 1);
   const Code& stub = ic_data.is_tracking_exactness()
                          ? StubCode::OneArgCheckInlineCacheWithExactnessCheck()
                          : StubCode::OneArgCheckInlineCache();
-  CodePatcher::PatchInstanceCallAt(caller_frame->pc(), caller_code, ic_data,
+  CodePatcher::PatchInstanceCallAt(caller_frame_->pc(), caller_code_, ic_data,
                                    stub);
   if (FLAG_trace_ic) {
     OS::PrintErr("Instance call at %" Px
                  " switching to polymorphic dispatch, %s\n",
-                 caller_frame->pc(), ic_data.ToCString());
+                 caller_frame_->pc(), ic_data.ToCString());
   }
 
-  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
   // ICData can be shared between unoptimized and optimized code, so beware that
   // the new receiver class may have already been added through the optimized
   // code.
-  if (!ic_data.HasReceiverClassId(receiver.GetClassId())) {
+  if (!ic_data.HasReceiverClassId(receiver_.GetClassId())) {
     GrowableArray<const Instance*> args(1);
-    args.Add(&receiver);
+    args.Add(&receiver_);
     // Don't count during insertion because the IC stub we continue through will
     // do an increment.
     intptr_t count = 0;
     InlineCacheMissHandler(args, ic_data, count);
   }
-  arguments.SetArgAt(0, stub);
-  arguments.SetReturn(ic_data);
+  arguments_.SetArgAt(0, stub);
+  arguments_.SetReturn(ic_data);
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
-// Handle a miss of a megamorphic cache.
-//   Arg0: Receiver.
-//   Arg1: ICData or MegamorphicCache.
-//   Arg2: Arguments descriptor array.
-//   Returns: target function to call.
-DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
-  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
-  const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1));
-  const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(2));
-  String& name = String::Handle(zone);
-  if (ic_data_or_cache.IsICData()) {
-    name = ICData::Cast(ic_data_or_cache).target_name();
-  } else {
-    ASSERT(ic_data_or_cache.IsMegamorphicCache());
-    name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
+void SwitchableCallHandler::DoSingleTargetMiss(const SingleTargetCache& data) {
+  const Code& old_target_code = Code::Handle(zone_, data.target());
+  const Function& old_target =
+      Function::Handle(zone_, Function::RawCast(old_target_code.owner()));
+
+  // We lost the original ICData when we patched to the monomorphic case.
+  const String& name = String::Handle(zone_, old_target.name());
+  ASSERT(!old_target.HasOptionalParameters());
+  ASSERT(!old_target.IsGeneric());
+  const int kTypeArgsLen = 0;
+  const Array& descriptor = Array::Handle(
+      zone_, ArgumentsDescriptor::NewBoxed(kTypeArgsLen,
+                                           old_target.num_fixed_parameters()));
+  const ICData& ic_data =
+      ICData::Handle(zone_, ICData::New(caller_function_, name, descriptor,
+                                        DeoptId::kNone, 1, /* args_tested */
+                                        ICData::kInstance));
+
+  const Function& target_function = Function::Handle(
+      zone_, ResolveAndAddReceiverCheck(name, descriptor, ic_data));
+
+  intptr_t lower = data.lower_limit();
+  intptr_t upper = data.upper_limit();
+  if (CanExtendSingleTargetRange(name, old_target, target_function, &lower,
+                                 &upper)) {
+    data.set_lower_limit(lower);
+    data.set_upper_limit(upper);
+    // Return the ICData. The single target stub will jump to continue in the
+    // IC call stub.
+    arguments_.SetArgAt(0, StubCode::ICCallThroughCode());
+    arguments_.SetReturn(ic_data);
+    return;
   }
-  Class& cls = Class::Handle(zone, receiver.clazz());
+
+  // Call site is not single target, switch to call using ICData.
+  const Code& stub = StubCode::ICCallThroughCode();
+  CodePatcher::PatchSwitchableCallAt(caller_frame_->pc(), caller_code_, ic_data,
+                                     stub);
+
+  // Return the ICData. The single target stub will jump to continue in the
+  // IC call stub.
+  arguments_.SetArgAt(0, stub);
+  arguments_.SetReturn(ic_data);
+}
+
+void SwitchableCallHandler::DoICDataMiss(const ICData& ic_data) {
+  const String& name = String::Handle(zone_, ic_data.target_name());
+  const Class& cls = Class::Handle(zone_, receiver_.clazz());
   ASSERT(!cls.IsNull());
+  const Array& descriptor =
+      Array::CheckedHandle(zone_, ic_data.arguments_descriptor());
   ArgumentsDescriptor args_desc(descriptor);
   if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) {
-    OS::PrintErr("Megamorphic IC miss (%s), class=%s, function<%" Pd ">=%s\n",
-                 ic_data_or_cache.IsICData() ? "icdata" : "cache",
+    OS::PrintErr("ICData miss, class=%s, function<%" Pd ">=%s\n",
                  cls.ToCString(), args_desc.TypeArgsLen(), name.ToCString());
   }
   Function& target_function = Function::Handle(
-      zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
+      zone_, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
   if (target_function.IsNull()) {
     target_function = InlineCacheMissHelper(cls, descriptor, name);
     if (target_function.IsNull()) {
       ASSERT(!FLAG_lazy_dispatchers);
-      arguments.SetReturn(target_function);
+      arguments_.SetArgAt(0, StubCode::NoSuchMethodDispatcher());
+      arguments_.SetReturn(ic_data);
       return;
     }
   }
 
-  if (ic_data_or_cache.IsICData()) {
-    const ICData& ic_data = ICData::Cast(ic_data_or_cache);
-    const intptr_t number_of_checks = ic_data.NumberOfChecks();
+  const intptr_t number_of_checks = ic_data.NumberOfChecks();
 
-    if ((number_of_checks == 0) &&
-        (!FLAG_precompiled_mode || ic_data.receiver_cannot_be_smi()) &&
-        !target_function.HasOptionalParameters() &&
-        !target_function.IsGeneric()) {
-      // This call site is unlinked: transition to a monomorphic direct call.
-      // Note we cannot do this if the target has optional parameters because
-      // the monomorphic direct call does not load the arguments descriptor.
-      // We cannot do this if we are still in the middle of precompiling because
-      // the monomorphic case hides a live instance selector from the
-      // treeshaker.
-
-      const Code& target_code =
-          Code::Handle(zone, target_function.EnsureHasCode());
-
-      DartFrameIterator iterator(thread,
-                                 StackFrameIterator::kNoCrossThreadIteration);
-      StackFrame* miss_function_frame = iterator.NextFrame();
-      ASSERT(miss_function_frame->IsDartFrame());
-      StackFrame* caller_frame = iterator.NextFrame();
-      ASSERT(caller_frame->IsDartFrame());
-      const Code& caller_code =
-          Code::Handle(zone, caller_frame->LookupDartCode());
-      const Smi& expected_cid =
-          Smi::Handle(zone, Smi::New(receiver.GetClassId()));
-
-      CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
-                                         expected_cid, target_code);
-    } else {
-      ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
-      if (number_of_checks > FLAG_max_polymorphic_checks) {
-        // Switch to megamorphic call.
-        const MegamorphicCache& cache = MegamorphicCache::Handle(
-            zone, MegamorphicCacheTable::Lookup(thread, name, descriptor));
-        DartFrameIterator iterator(thread,
-                                   StackFrameIterator::kNoCrossThreadIteration);
-        StackFrame* miss_function_frame = iterator.NextFrame();
-        ASSERT(miss_function_frame->IsDartFrame());
-        StackFrame* caller_frame = iterator.NextFrame();
-        ASSERT(caller_frame->IsDartFrame());
-        const Code& caller_code =
-            Code::Handle(zone, caller_frame->LookupDartCode());
-        const Code& stub = StubCode::MegamorphicCall();
-
-        CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
-                                           cache, stub);
-      }
-    }
+  if ((number_of_checks == 0) &&
+      (!FLAG_precompiled_mode || ic_data.receiver_cannot_be_smi()) &&
+      !target_function.HasOptionalParameters() &&
+      !target_function.IsGeneric()) {
+    // This call site is unlinked: transition to a monomorphic direct call.
+    // Note we cannot do this if the target has optional parameters because
+    // the monomorphic direct call does not load the arguments descriptor.
+    // We cannot do this if we are still in the middle of precompiling because
+    // the monomorphic case hides a live instance selector from the
+    // treeshaker.
+    const Code& target_code =
+        Code::Handle(zone_, target_function.EnsureHasCode());
+    const Smi& expected_cid =
+        Smi::Handle(zone_, Smi::New(receiver_.GetClassId()));
+    CodePatcher::PatchSwitchableCallAt(caller_frame_->pc(), caller_code_,
+                                       expected_cid, target_code);
+    arguments_.SetArgAt(0, target_code);
+    arguments_.SetReturn(expected_cid);
   } else {
-    const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache);
-    // Insert function found into cache and return it.
-    const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id()));
-    cache.Insert(class_id, target_function);
+    ic_data.AddReceiverCheck(receiver_.GetClassId(), target_function);
+    if (number_of_checks > FLAG_max_polymorphic_checks) {
+      // Switch to megamorphic call.
+      const MegamorphicCache& cache = MegamorphicCache::Handle(
+          zone_, MegamorphicCacheTable::Lookup(thread_, name, descriptor));
+      const Code& stub = StubCode::MegamorphicCall();
+
+      CodePatcher::PatchSwitchableCallAt(caller_frame_->pc(), caller_code_,
+                                         cache, stub);
+      arguments_.SetArgAt(0, stub);
+      arguments_.SetReturn(cache);
+    } else {
+      arguments_.SetArgAt(0, StubCode::ICCallThroughCode());
+      arguments_.SetReturn(ic_data);
+    }
   }
-  arguments.SetReturn(target_function);
+}
+
+void SwitchableCallHandler::DoMegamorphicMiss(const MegamorphicCache& data) {
+  const String& name = String::Handle(zone_, data.target_name());
+  const Class& cls = Class::Handle(zone_, receiver_.clazz());
+  ASSERT(!cls.IsNull());
+  const Array& descriptor =
+      Array::CheckedHandle(zone_, data.arguments_descriptor());
+  ArgumentsDescriptor args_desc(descriptor);
+  if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) {
+    OS::PrintErr("Megamorphic miss, class=%s, function<%" Pd ">=%s\n",
+                 cls.ToCString(), args_desc.TypeArgsLen(), name.ToCString());
+  }
+  Function& target_function = Function::Handle(
+      zone_, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
+  if (target_function.IsNull()) {
+    target_function = InlineCacheMissHelper(cls, descriptor, name);
+    if (target_function.IsNull()) {
+      ASSERT(!FLAG_lazy_dispatchers);
+      arguments_.SetArgAt(0, StubCode::NoSuchMethodDispatcher());
+      arguments_.SetReturn(data);
+      return;
+    }
+  }
+
+  // Insert function found into cache.
+  const Smi& class_id = Smi::Handle(zone_, Smi::New(cls.id()));
+  data.Insert(class_id, target_function);
+  arguments_.SetArgAt(0, StubCode::MegamorphicCall());
+  arguments_.SetReturn(data);
+}
+
+void SwitchableCallHandler::HandleMiss(const Object& old_data,
+                                       const Code& old_target) {
+  switch (old_data.GetClassId()) {
+    case kUnlinkedCallCid:
+      ASSERT(old_target.raw() == StubCode::SwitchableCallMiss().raw());
+      DoUnlinkedCall(UnlinkedCall::Cast(old_data));
+      break;
+    case kMonomorphicSmiableCallCid:
+      ASSERT(old_target.raw() == StubCode::MonomorphicSmiableCheck().raw());
+      FALL_THROUGH;
+#if defined(DART_PRECOMPILED_RUNTIME)
+    case kSmiCid:
+#else  // JIT
+    case kArrayCid:
+      // ICData three-element array: Smi(receiver CID), Smi(count),
+      // Function(target). It is the Array from ICData::entries_.
+#endif
+      DoMonomorphicMiss(old_data);
+      break;
+    case kSingleTargetCacheCid:
+      ASSERT(old_target.raw() == StubCode::SingleTargetCall().raw());
+      DoSingleTargetMiss(SingleTargetCache::Cast(old_data));
+      break;
+    case kICDataCid:
+      ASSERT(old_target.raw() == StubCode::ICCallThroughCode().raw());
+      DoICDataMiss(ICData::Cast(old_data));
+      break;
+    case kMegamorphicCacheCid:
+      ASSERT(old_target.raw() == StubCode::MegamorphicCall().raw());
+      DoMegamorphicMiss(MegamorphicCache::Cast(old_data));
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+// Handle the first use of an instance call
+//   Arg1: Receiver.
+//   Arg0: Stub out.
+//   Returns: the ICData used to continue with the call.
+DEFINE_RUNTIME_ENTRY(SwitchableCallMiss, 2) {
+  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
+
+  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
+                              StackFrameIterator::kNoCrossThreadIteration);
+  StackFrame* exit_frame = iterator.NextFrame();
+  ASSERT(exit_frame->IsExitFrame());
+  StackFrame* miss_handler_frame = iterator.NextFrame();
+  // This runtime entry can be called either from miss stub or from
+  // switchable_call_miss "dart" stub/function set up in
+  // [MegamorphicCacheTable::InitMissHandler].
+  ASSERT(miss_handler_frame->IsStubFrame() ||
+         miss_handler_frame->IsDartFrame());
+  StackFrame* caller_frame = iterator.NextFrame();
+  ASSERT(caller_frame->IsDartFrame());
+  const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
+  const Function& caller_function =
+      Function::Handle(zone, caller_frame->LookupDartFunction());
+
+  Object& old_data = Object::Handle(zone);
+  Code& old_code = Code::Handle(zone);
+#if defined(DART_PRECOMPILED_RUNTIME)
+  old_data =
+      CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code);
+#if defined(DEBUG)
+  old_code ^=
+      CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(), caller_code);
+#endif
+#else
+  old_code ^= CodePatcher::GetInstanceCallAt(caller_frame->pc(), caller_code,
+                                             &old_data);
+#endif
+  SwitchableCallHandler handler(thread, receiver, arguments, caller_frame,
+                                caller_code, caller_function);
+  handler.HandleMiss(old_data, old_code);
 }
 
 // Handles interpreted interface call cache miss.
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index cd9c4d6..e2773db 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -34,7 +34,6 @@
   V(NoSuchMethodFromCallStub)                                                  \
   V(NoSuchMethodFromPrologue)                                                  \
   V(InvokeNoSuchMethod)                                                        \
-  V(MegamorphicCacheMissHandler)                                               \
   V(OptimizeInvokedFunction)                                                   \
   V(TraceICCall)                                                               \
   V(PatchStaticCall)                                                           \
@@ -56,9 +55,7 @@
   V(InitStaticField)                                                           \
   V(CompileFunction)                                                           \
   V(CompileInterpretedFunction)                                                \
-  V(MonomorphicMiss)                                                           \
-  V(SingleTargetMiss)                                                          \
-  V(UnlinkedCall)
+  V(SwitchableCallMiss)
 
 #define LEAF_RUNTIME_ENTRY_LIST(V)                                             \
   V(void, PrintStopMessage, const char*)                                       \
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 2f451ce..181322e 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2437,6 +2437,12 @@
       ObjectIdRing::LookupResult lookup_result;
       Object& argument = Object::Handle(
           zone, LookupHeapObject(thread, argument_id, &lookup_result));
+      // Invoke only accepts Instance arguments.
+      if (!(argument.IsInstance() || argument.IsNull()) ||
+          ContainsNonInstance(argument)) {
+        PrintInvalidParamError(js, "argumentIds");
+        return true;
+      }
       if (argument.raw() == Object::sentinel().raw()) {
         if (lookup_result == ObjectIdRing::kCollected) {
           PrintSentinel(js, kCollectedSentinel);
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index c96ab96..06bec8d 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -3516,7 +3516,7 @@
 
 ```
 class Timeline extends Response {
-  // A list of timeline events.
+  // A list of timeline events. No order is guarenteed for these events; in particular, these events may be unordered with respect to their timestamps.
   TimelineEvent[] traceEvents;
 
   // The start of the period of time in which traceEvents were collected.
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 8968b17..ad55238 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -685,18 +685,6 @@
   return NULL;
 }
 
-class HeapLocker : public StackResource {
- public:
-  HeapLocker(Thread* thread, PageSpace* page_space)
-      : StackResource(thread), page_space_(page_space) {
-    page_space_->AcquireDataLock();
-  }
-  ~HeapLocker() { page_space_->ReleaseDataLock(); }
-
- private:
-  PageSpace* page_space_;
-};
-
 RawApiError* SnapshotReader::VerifyVersionAndFeatures(Isolate* isolate) {
   // If the version string doesn't match, return an error.
   // Note: New things are allocated only if we're going to return an error.
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index b890b0b..ba40148 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -61,6 +61,7 @@
 class RawFloat64x2;
 class RawFunction;
 class RawGrowableObjectArray;
+class RawCallSiteData;
 class RawICData;
 class RawImmutableArray;
 class RawInstructions;
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 9e619bd..b0d9974 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1993,4 +1993,59 @@
   EXPECT(!Dart_IsKernel(buffer, ARRAY_SIZE(buffer)));
 }
 
+VM_UNIT_TEST_CASE(LegacyErasureDetectionInFullSnapshot) {
+  const char* kScriptChars =
+      "class Generic<T> {\n"
+      "  const Generic();\n"
+      "  static const Generic<int> g = const Generic<int>();\n"
+      "  static testMain() => g.runtimeType;\n"
+      "}\n";
+
+  // Start an Isolate, load and execute a script and check if legacy erasure is
+  // required, preventing to write a full snapshot.
+  {
+    TestIsolateScope __test_isolate__;
+
+    // Create a test library and Load up a test script in it.
+    Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+    EXPECT_VALID(lib);
+
+    Thread* thread = Thread::Current();
+    Isolate* isolate = thread->isolate();
+    ASSERT(isolate == __test_isolate__.isolate());
+    TransitionNativeToVM transition(thread);
+    StackZone zone(thread);
+    HandleScope scope(thread);
+
+    Dart_Handle result = Api::CheckAndFinalizePendingClasses(thread);
+    Dart_Handle cls;
+    {
+      TransitionVMToNative to_native(thread);
+      EXPECT_VALID(result);
+
+      // Invoke a function so that the constant is evaluated.
+      cls = Dart_GetClass(TestCase::lib(), NewString("Generic"));
+      result = Dart_Invoke(cls, NewString("testMain"), 0, NULL);
+      EXPECT_VALID(result);
+    }
+    // Verify that legacy erasure is required in strong mode.
+    Type& type = Type::Handle();
+    type ^= Api::UnwrapHandle(cls);  // Dart_GetClass actually returns a Type.
+    const Class& clazz = Class::Handle(type.type_class());
+    const bool required = clazz.RequireLegacyErasureOfConstants(zone.GetZone());
+    EXPECT(required == isolate->null_safety());
+
+    // Verify that snapshot writing succeeds if erasure is not required.
+    if (!required) {
+      // Write snapshot with object content.
+      uint8_t* isolate_snapshot_data_buffer;
+      FullSnapshotWriter writer(
+          Snapshot::kFull, NULL, &isolate_snapshot_data_buffer,
+          &malloc_allocator, NULL, /*image_writer*/ nullptr);
+      writer.WriteFullSnapshot();
+      free(isolate_snapshot_data_buffer);
+    }
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 98f20cf..6ebb23a 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -124,13 +124,45 @@
   return (pc >= entry) && (pc < (entry + size));
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+static RawArray* BuildStaticCallsTable(
+    Zone* zone,
+    compiler::UnresolvedPcRelativeCalls* unresolved_calls) {
+  if (unresolved_calls->length() == 0) {
+    return Array::null();
+  }
+  const intptr_t array_length =
+      unresolved_calls->length() * Code::kSCallTableEntryLength;
+  const auto& static_calls_table =
+      Array::Handle(zone, Array::New(array_length, Heap::kOld));
+  StaticCallsTable entries(static_calls_table);
+  auto& kind_type_and_offset = Smi::Handle(zone);
+  for (intptr_t i = 0; i < unresolved_calls->length(); i++) {
+    auto& unresolved_call = (*unresolved_calls)[i];
+    auto call_kind = unresolved_call->is_tail_call() ? Code::kPcRelativeTailCall
+                                                     : Code::kPcRelativeCall;
+    kind_type_and_offset =
+        Smi::New(Code::KindField::encode(call_kind) |
+                 Code::EntryPointField::encode(Code::kDefaultEntry) |
+                 Code::OffsetField::encode(unresolved_call->offset()));
+    auto view = entries[i];
+    view.Set<Code::kSCallTableKindAndOffset>(kind_type_and_offset);
+    view.Set<Code::kSCallTableCodeTarget>(unresolved_call->target());
+  }
+  return static_calls_table.raw();
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 RawCode* StubCode::GetAllocationStubForClass(const Class& cls) {
   Thread* thread = Thread::Current();
+  auto object_store = thread->isolate()->object_store();
   Zone* zone = thread->zone();
   const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
   ASSERT(error.IsNull());
   if (cls.id() == kArrayCid) {
-    return AllocateArray().raw();
+    return object_store->allocate_array_stub();
+  } else if (cls.id() == kContextCid) {
+    return object_store->allocate_context_stub();
   }
   Code& stub = Code::Handle(zone, cls.allocation_stub());
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -148,9 +180,25 @@
             ? Code::PoolAttachment::kNotAttachPool
             : Code::PoolAttachment::kAttachPool;
 
+    auto zone = thread->zone();
+    auto object_store = thread->isolate()->object_store();
+    auto& allocate_object_stub = Code::ZoneHandle(zone);
+    auto& allocate_object_parametrized_stub = Code::ZoneHandle(zone);
+    if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+      allocate_object_stub = object_store->allocate_object_stub();
+      allocate_object_parametrized_stub =
+          object_store->allocate_object_parametrized_stub();
+    }
+
     compiler::Assembler assembler(wrapper);
+    compiler::UnresolvedPcRelativeCalls unresolved_calls;
     const char* name = cls.ToCString();
-    compiler::StubCodeCompiler::GenerateAllocationStubForClass(&assembler, cls);
+    compiler::StubCodeCompiler::GenerateAllocationStubForClass(
+        &assembler, &unresolved_calls, cls, allocate_object_stub,
+        allocate_object_parametrized_stub);
+
+    const auto& static_calls_table =
+        Array::Handle(zone, BuildStaticCallsTable(zone, &unresolved_calls));
 
     auto mutator_fun = [&]() {
       stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
@@ -159,6 +207,9 @@
       // Check if background compilation thread has not already added the stub.
       if (cls.allocation_stub() == Code::null()) {
         stub.set_owner(cls);
+        if (!static_calls_table.IsNull()) {
+          stub.set_static_calls_target_table(static_calls_table);
+        }
         cls.set_allocation_stub(stub);
       }
     };
@@ -172,6 +223,9 @@
       stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
                                 /*optimized=*/false, /*stats=*/nullptr);
       stub.set_owner(cls);
+      if (!static_calls_table.IsNull()) {
+        stub.set_static_calls_target_table(static_calls_table);
+      }
       cls.set_allocation_stub(stub);
     };
 
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index 3554661..f6058e6 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -19,9 +19,12 @@
   V(ArrayWriteBarrier)                                                         \
   V(PrintStopMessage)                                                          \
   V(AllocateArray)                                                             \
-  V(AllocateMintWithFPURegs)                                                   \
-  V(AllocateMintWithoutFPURegs)                                                \
+  V(AllocateMintSharedWithFPURegs)                                             \
+  V(AllocateMintSharedWithoutFPURegs)                                          \
   V(AllocateContext)                                                           \
+  V(AllocateObject)                                                            \
+  V(AllocateObjectParameterized)                                               \
+  V(AllocateObjectSlow)                                                        \
   V(CloneContext)                                                              \
   V(CallToRuntime)                                                             \
   V(LazyCompile)                                                               \
@@ -35,8 +38,7 @@
   V(InvokeDartCode)                                                            \
   V(InvokeDartCodeFromBytecode)                                                \
   V(DebugStepCheck)                                                            \
-  V(UnlinkedCall)                                                              \
-  V(MonomorphicMiss)                                                           \
+  V(SwitchableCallMiss)                                                        \
   V(MonomorphicSmiableCheck)                                                   \
   V(SingleTargetCall)                                                          \
   V(ICCallThroughCode)                                                         \
@@ -79,6 +81,8 @@
   V(NullErrorSharedWithoutFPURegs)                                             \
   V(NullArgErrorSharedWithFPURegs)                                             \
   V(NullArgErrorSharedWithoutFPURegs)                                          \
+  V(RangeErrorSharedWithFPURegs)                                               \
+  V(RangeErrorSharedWithoutFPURegs)                                            \
   V(StackOverflowSharedWithFPURegs)                                            \
   V(StackOverflowSharedWithoutFPURegs)                                         \
   V(OneArgCheckInlineCacheWithExactnessCheck)                                  \
@@ -87,9 +91,15 @@
   V(ExitSafepoint)                                                             \
   V(CallNativeThroughSafepoint)                                                \
   V(InitStaticField)                                                           \
+  V(InitInstanceField)                                                         \
+  V(Throw)                                                                     \
+  V(ReThrow)                                                                   \
+  V(AssertBoolean)                                                             \
+  V(InstanceOf)                                                                \
   V(InstantiateTypeArguments)                                                  \
   V(InstantiateTypeArgumentsMayShareInstantiatorTA)                            \
-  V(InstantiateTypeArgumentsMayShareFunctionTA)
+  V(InstantiateTypeArgumentsMayShareFunctionTA)                                \
+  V(NoSuchMethodDispatcher)
 
 }  // namespace dart
 
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index c58f83f..73ecaaa 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -208,7 +208,7 @@
   V(Map, "Map")                                                                \
   V(MapLiteralFactory, "Map._fromLiteral")                                     \
   V(MegamorphicCache, "MegamorphicCache")                                      \
-  V(MegamorphicMiss, "megamorphic_miss")                                       \
+  V(MegamorphicCallMiss, "megamorphic_call_miss")                              \
   V(MonomorphicSmiableCall, "MonomorphicSmiableCall")                          \
   V(MoveNext, "moveNext")                                                      \
   V(Namespace, "Namespace")                                                    \
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 1132a6e..077fa83 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -116,15 +116,29 @@
     StubCode::NullArgErrorSharedWithoutFPURegs().raw(), nullptr)               \
   V(RawCode*, null_arg_error_shared_with_fpu_regs_stub_,                       \
     StubCode::NullArgErrorSharedWithFPURegs().raw(), nullptr)                  \
+  V(RawCode*, range_error_shared_without_fpu_regs_stub_,                       \
+    StubCode::RangeErrorSharedWithoutFPURegs().raw(), nullptr)                 \
+  V(RawCode*, range_error_shared_with_fpu_regs_stub_,                          \
+    StubCode::RangeErrorSharedWithFPURegs().raw(), nullptr)                    \
   V(RawCode*, allocate_mint_with_fpu_regs_stub_,                               \
-    StubCode::AllocateMintWithFPURegs().raw(), NULL)                           \
+    StubCode::AllocateMintSharedWithFPURegs().raw(), NULL)                     \
   V(RawCode*, allocate_mint_without_fpu_regs_stub_,                            \
-    StubCode::AllocateMintWithoutFPURegs().raw(), NULL)                        \
+    StubCode::AllocateMintSharedWithoutFPURegs().raw(), NULL)                  \
+  V(RawCode*, allocate_object_stub_, StubCode::AllocateObject().raw(),         \
+    nullptr)                                                                   \
+  V(RawCode*, allocate_object_parameterized_stub_,                             \
+    StubCode::AllocateObjectParameterized().raw(), nullptr)                    \
+  V(RawCode*, allocate_object_slow_stub_,                                      \
+    StubCode::AllocateObjectSlow().raw(), nullptr)                             \
   V(RawCode*, stack_overflow_shared_without_fpu_regs_stub_,                    \
     StubCode::StackOverflowSharedWithoutFPURegs().raw(), NULL)                 \
   V(RawCode*, stack_overflow_shared_with_fpu_regs_stub_,                       \
     StubCode::StackOverflowSharedWithFPURegs().raw(), NULL)                    \
-  V(RawCode*, monomorphic_miss_stub_, StubCode::MonomorphicMiss().raw(), NULL) \
+  V(RawCode*, switchable_call_miss_stub_,                                      \
+    StubCode::SwitchableCallMiss().raw(), NULL)                                \
+  V(RawCode*, throw_stub_, StubCode::Throw().raw(), NULL)                      \
+  V(RawCode*, re_throw_stub_, StubCode::Throw().raw(), NULL)                   \
+  V(RawCode*, assert_boolean_stub_, StubCode::AssertBoolean().raw(), NULL)     \
   V(RawCode*, optimize_stub_, StubCode::OptimizeFunction().raw(), NULL)        \
   V(RawCode*, deoptimize_stub_, StubCode::Deoptimize().raw(), NULL)            \
   V(RawCode*, lazy_deopt_from_return_stub_,                                    \
@@ -163,26 +177,24 @@
     StubCode::ArrayWriteBarrier().EntryPoint(), 0)                             \
   V(uword, call_to_runtime_entry_point_,                                       \
     StubCode::CallToRuntime().EntryPoint(), 0)                                 \
-  V(uword, null_error_shared_without_fpu_regs_entry_point_,                    \
-    StubCode::NullErrorSharedWithoutFPURegs().EntryPoint(), 0)                 \
-  V(uword, null_error_shared_with_fpu_regs_entry_point_,                       \
-    StubCode::NullErrorSharedWithFPURegs().EntryPoint(), 0)                    \
-  V(uword, null_arg_error_shared_without_fpu_regs_entry_point_,                \
-    StubCode::NullArgErrorSharedWithoutFPURegs().EntryPoint(), 0)              \
-  V(uword, null_arg_error_shared_with_fpu_regs_entry_point_,                   \
-    StubCode::NullArgErrorSharedWithFPURegs().EntryPoint(), 0)                 \
   V(uword, allocate_mint_with_fpu_regs_entry_point_,                           \
-    StubCode::AllocateMintWithFPURegs().EntryPoint(), 0)                       \
+    StubCode::AllocateMintSharedWithFPURegs().EntryPoint(), 0)                 \
   V(uword, allocate_mint_without_fpu_regs_entry_point_,                        \
-    StubCode::AllocateMintWithoutFPURegs().EntryPoint(), 0)                    \
+    StubCode::AllocateMintSharedWithoutFPURegs().EntryPoint(), 0)              \
+  V(uword, allocate_object_entry_point_,                                       \
+    StubCode::AllocateObject().EntryPoint(), 0)                                \
+  V(uword, allocate_object_parameterized_entry_point_,                         \
+    StubCode::AllocateObjectParameterized().EntryPoint(), 0)                   \
+  V(uword, allocate_object_slow_entry_point_,                                  \
+    StubCode::AllocateObjectSlow().EntryPoint(), 0)                            \
   V(uword, stack_overflow_shared_without_fpu_regs_entry_point_,                \
     StubCode::StackOverflowSharedWithoutFPURegs().EntryPoint(), 0)             \
   V(uword, stack_overflow_shared_with_fpu_regs_entry_point_,                   \
     StubCode::StackOverflowSharedWithFPURegs().EntryPoint(), 0)                \
   V(uword, megamorphic_call_checked_entry_,                                    \
     StubCode::MegamorphicCall().EntryPoint(), 0)                               \
-  V(uword, monomorphic_miss_entry_, StubCode::MonomorphicMiss().EntryPoint(),  \
-    0)                                                                         \
+  V(uword, switchable_call_miss_entry_,                                        \
+    StubCode::SwitchableCallMiss().EntryPoint(), 0)                            \
   V(uword, optimize_entry_, StubCode::OptimizeFunction().EntryPoint(), 0)      \
   V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)          \
   V(uword, call_native_through_safepoint_entry_point_,                         \
@@ -238,6 +250,7 @@
     kMarkerTask = 0x4,
     kSweeperTask = 0x8,
     kCompactorTask = 0x10,
+    kScavengerTask = 0x20,
   };
   // Converts a TaskKind to its corresponding C-String name.
   static const char* TaskKindToCString(TaskKind kind);
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 45ea803..3fcd8b7 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -24,12 +24,8 @@
 
 const char* TypeTestingStubNamer::StubNameForType(
     const AbstractType& type) const {
-  NoSafepointScope no_safepoint;
-  const uintptr_t address =
-      reinterpret_cast<uintptr_t>(type.raw()) & 0x7fffffff;
   Zone* Z = Thread::Current()->zone();
-  return OS::SCreate(Z, "TypeTestingStub_%s__%" Pd "", StringifyType(type),
-                     address);
+  return OS::SCreate(Z, "TypeTestingStub_%s", StringifyType(type));
 }
 
 const char* TypeTestingStubNamer::StringifyType(
diff --git a/sdk/lib/_http/embedder_config.dart b/sdk/lib/_http/embedder_config.dart
new file mode 100644
index 0000000..fb13bea
--- /dev/null
+++ b/sdk/lib/_http/embedder_config.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.
+
+// @dart = 2.6
+
+part of dart._http;
+
+/// Embedder-specific `dart:_http` configuration.
+
+/// [HttpClient] will disallow HTTP URLs if this value is set to `false`.
+@pragma("vm:entry-point")
+bool _embedderAllowsHttp = true;
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index 6883fbc..e80369c 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -24,6 +24,7 @@
 import 'dart:typed_data';
 
 part 'crypto.dart';
+part 'embedder_config.dart';
 part 'http_date.dart';
 part 'http_headers.dart';
 part 'http_impl.dart';
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 7101ca9..81e60db 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -2266,6 +2266,32 @@
     });
   }
 
+  /// Whether HTTP requests are currently allowed.
+  ///
+  /// If the [Zone] variable `#dart.library.io.allow_http` is set to a boolean,
+  /// it determines whether the HTTP protocol is allowed. If the zone variable
+  /// is set to any other non-null value, HTTP is not allowed.
+  /// Otherwise, if the `dart.library.io.allow_http` environment flag
+  /// is set to `false`, HTTP is not allowed.
+  /// Otherwise, [_embedderAllowsHTTP] determines the result.
+  bool get _isHttpAllowed {
+    final zoneOverride = Zone.current[#dart.library.io.allow_http];
+    if (zoneOverride != null) return true == zoneOverride;
+    bool envOverride =
+        bool.fromEnvironment("dart.library.io.allow_http", defaultValue: true);
+    return envOverride && _embedderAllowsHttp;
+  }
+
+  bool _isLoopback(String host) {
+    if (host.isEmpty) return false;
+    if ("localhost" == host) return true;
+    try {
+      return InternetAddress(host).isLoopback;
+    } on ArgumentError {
+      return false;
+    }
+  }
+
   Future<_HttpClientRequest> _openUrl(String method, Uri uri) {
     if (_closing) {
       throw new StateError("Client is closed");
@@ -2286,7 +2312,12 @@
       }
     }
 
-    bool isSecure = (uri.scheme == "https");
+    bool isSecure = uri.isScheme("https");
+    if (!_isHttpAllowed && !isSecure && !_isLoopback(uri.host)) {
+      throw new StateError(
+          "Insecure HTTP is not allowed by the current platform: $uri");
+    }
+
     int port = uri.port;
     if (port == 0) {
       port =
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
index 04b4f2f..1592218 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
@@ -60,27 +60,29 @@
   var setter = JS('', '#.set', desc);
   if (getter != null) {
     if (setter == null) {
-      var obj = JS(
-          '',
+      var obj = JS<Object>(
+          '!',
           '#.set = { __proto__: #.__proto__, '
               'set [#](x) { return super[#] = x; } }',
           desc,
           to,
           name,
           name);
-      JS('', '#.set = #.set', desc, getOwnPropertyDescriptor(obj, name));
+      JS<Object>(
+          '!', '#.set = #.set', desc, getOwnPropertyDescriptor(obj, name));
     }
   } else if (setter != null) {
     if (getter == null) {
-      var obj = JS(
-          '',
+      var obj = JS<Object>(
+          '!',
           '#.get = { __proto__: #.__proto__, '
               'get [#]() { return super[#]; } }',
           desc,
           to,
           name,
           name);
-      JS('', '#.get = #.get', desc, getOwnPropertyDescriptor(obj, name));
+      JS<Object>(
+          '!', '#.get = #.get', desc, getOwnPropertyDescriptor(obj, name));
     }
   }
   defineProperty(to, name, desc);
@@ -128,6 +130,9 @@
 ///
 /// This normalization should mirror the normalization performed at compile time
 /// in the method named `_normalizeFutureOr()`.
+///
+/// **NOTE** Normalization of FutureOr<T?>? --> FutureOr<T?> is handled in
+/// [nullable].
 normalizeFutureOr(typeConstructor, setBaseClass) {
   // The canonical version of the generic FutureOr type constructor.
   var genericFutureOrType =
@@ -137,20 +142,30 @@
     // Normalize raw FutureOr --> dynamic
     if (JS<bool>('!', '# == void 0', typeArg)) return _dynamic;
 
-    // FutureOr<dynamic|void|Object> --> dynamic|void|Object
-    if (_isTop(typeArg)) return typeArg;
+    // FutureOr<dynamic|void|Object?|Object*|Object> -->
+    //   dynamic|void|Object?|Object*|Object
+    if (_isTop(typeArg) ||
+        _equalType(typeArg, Object) ||
+        (_jsInstanceOf(typeArg, LegacyType) &&
+            JS<bool>('!', '#.type === #', typeArg, Object))) {
+      return typeArg;
+    }
 
-    // FutureOr<Null> --> Future<Null>
-    // NOTE: These are a legacy FutureOr and Future that can be null already.
-    if (typeArg == unwrapType(Null)) {
+    // FutureOr<Never> --> Future<Never>
+    if (_equalType(typeArg, Never)) {
       return JS('!', '#(#)', getGenericClass(Future), typeArg);
     }
+    // FutureOr<Null> --> Future<Null>?
+    if (_equalType(typeArg, Null)) {
+      return nullable(JS('!', '#(#)', getGenericClass(Future), typeArg));
+    }
     // Otherwise, create the FutureOr<T> type as a normal generic type.
     var genericType = JS('!', '#(#)', genericFutureOrType, typeArg);
     // Overwrite the original declaration so that it correctly points back to
     // this method. This ensures that the we can test a type value returned here
     // as a FutureOr because it is equal to 'async.FutureOr` (in the JS).
     JS('!', '#[#] = #', genericType, _originalDeclaration, normalize);
+    JS('!', '#(#)', addTypeCaches, genericType);
     return genericType;
   }
 
@@ -206,16 +221,19 @@
     return value;
   }
   makeGenericType[$_genericTypeCtor] = $typeConstructor;
+  $addTypeCaches(makeGenericType);
   return makeGenericType;
 })()''');
 
 getGenericClass(type) => safeGetOwnProperty(type, _originalDeclaration);
 
+// TODO(markzipan): Make this non-nullable if we can ensure this returns
+// an empty list or if null and the empty list are semantically the same.
 List getGenericArgs(type) =>
-    JS('List', '#', safeGetOwnProperty(type, _typeArguments));
+    JS<List>('', '#', safeGetOwnProperty(type, _typeArguments));
 
 List getGenericArgVariances(type) =>
-    JS('List', '#', safeGetOwnProperty(type, _variances));
+    JS<List>('', '#', safeGetOwnProperty(type, _variances));
 
 void setGenericArgVariances(f, variances) =>
     JS('', '#[#] = #', f, _variances, variances);
@@ -272,7 +290,7 @@
   // Note that it is still possible to call typed JS interop methods on
   // extension types but the calls must be statically typed.
   if (JS('!', '#[#] != null', obj, _extensionType)) return false;
-  return JS('!', '!($obj instanceof $Object)');
+  return !_jsInstanceOf(obj, Object);
 }
 
 /// Get the type of a method from a type using the stored signature
@@ -368,19 +386,19 @@
   }
   // If the extension methods of the parent have been installed on the parent
   // of [jsProto], the methods will be available via prototype inheritance.
-  var dartSupertype = JS('', '#.__proto__', dartType);
+  var dartSupertype = JS<Object>('!', '#.__proto__', dartType);
   if (JS('!', '# !== #', dartSupertype, installedParent)) {
     _installProperties(jsProto, dartSupertype, installedParent);
   }
 
-  var dartProto = JS('', '#.prototype', dartType);
+  var dartProto = JS<Object>('!', '#.prototype', dartType);
   copyTheseProperties(jsProto, dartProto, getOwnPropertySymbols(dartProto));
 }
 
 void _installPropertiesForObject(jsProto) {
   // core.Object members need to be copied from the non-symbol name to the
   // symbol name.
-  var coreObjProto = JS('', '#.prototype', Object);
+  var coreObjProto = JS<Object>('!', '#.prototype', Object);
   var names = getOwnPropertyNames(coreObjProto);
   for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
     var name = JS<String>('!', '#[#]', names, i);
@@ -399,7 +417,7 @@
 
 final _extensionMap = JS('', 'new Map()');
 
-_applyExtension(jsType, dartExtType) {
+void _applyExtension(jsType, dartExtType) {
   // TODO(vsm): Not all registered js types are real.
   if (jsType == null) return;
   var jsProto = JS('', '#.prototype', jsType);
@@ -474,13 +492,13 @@
 }
 
 /// Like [defineExtensionMethods], but for getter/setter pairs.
-defineExtensionAccessors(type, Iterable memberNames) {
-  var proto = JS('', '#.prototype', type);
+void defineExtensionAccessors(type, Iterable memberNames) {
+  var proto = JS<Object>('!', '#.prototype', type);
   for (var name in memberNames) {
     // Find the member. It should always exist (or we have a compiler bug).
     var member;
     var p = proto;
-    for (;; p = JS('', '#.__proto__', p)) {
+    for (;; p = JS<Object>('!', '#.__proto__', p)) {
       member = getOwnPropertyDescriptor(p, name);
       if (member != null) break;
     }
@@ -534,7 +552,7 @@
   JS(
       '',
       '''#.as = function as_C(obj) {
-    if (obj == null || obj[#]) return obj;
+    if (obj != null && obj[#]) return obj;
     return #(obj, this);
   }''',
       ctor,
@@ -544,8 +562,16 @@
 
 /// Pre-initializes types with empty type caches.
 ///
-/// Required for the null-safe SDK. Stubbed here.
-addTypeCaches(type) => null;
+/// Allows us to perform faster lookups on local caches without having to
+/// filter out the prototype chain. Also allows types to remain relatively
+/// monomorphic, which results in faster execution in V8.
+addTypeCaches(type) {
+  JS('', '#[#] = void 0', type, _cachedLegacy);
+  JS('', '#[#] = void 0', type, _cachedNullable);
+  var subtypeCacheMap = JS<Object>('!', 'new Map()');
+  JS('', '#[#] = #', type, _subtypeCache, subtypeCacheMap);
+  JS('', '#.push(#)', _cacheMaps, subtypeCacheMap);
+}
 
 // TODO(jmesserly): should we do this for all interfaces?
 
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 699f415..02827b1 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
@@ -26,7 +26,28 @@
   throw AssertionErrorImpl(message, fileUri, line, column, conditionSource);
 }
 
-throwCyclicInitializationError([Object field]) {
+final _nullFailedSet = JS('!', 'new Set()');
+// Run-time null safety assertion per:
+// https://github.com/dart-lang/language/blob/master/accepted/future-releases/nnbd/feature-specification.md#automatic-debug-assertion-insertion
+nullFailed(String fileUri, int line, int column, String variable) {
+  if (_strictSubtypeChecks) {
+    throw AssertionErrorImpl(
+        'A null value was passed into a non-nullable parameter $variable',
+        fileUri,
+        line,
+        column,
+        '$variable != null');
+  } else {
+    var key = '$fileUri:$line:$column';
+    if (!JS('!', '#.has(#)', _nullFailedSet, key)) {
+      JS('', '#.add(#)', _nullFailedSet, key);
+      _nullWarn(
+          'A null value was passed into a non-nullable parameter $variable');
+    }
+  }
+}
+
+throwCyclicInitializationError([String field]) {
   throw CyclicInitializationError(field);
 }
 
@@ -34,8 +55,7 @@
   // TODO(vsm): Per spec, we should throw an NSM here.  Technically, we ought
   // to thread through method info, but that uglifies the code and can't
   // actually be queried ... it only affects how the error is printed.
-  throw NoSuchMethodError(
-      null, Symbol('<Unexpected Null Value>'), null, null, null);
+  throw NoSuchMethodError(null, Symbol('<Unexpected Null Value>'), null, null);
 }
 
 castError(obj, expectedType) {
@@ -47,20 +67,21 @@
 String _castErrorMessage(from, to) {
   // If both types are generic classes, see if we can infer generic type
   // arguments for `from` that would allow the subtype relation to work.
-  var fromClass = getGenericClass(from);
-  if (fromClass != null) {
-    var fromTypeFormals = getGenericTypeFormals(fromClass);
-    var fromType = instantiateClass(fromClass, fromTypeFormals);
-    var inferrer = _TypeInferrer(fromTypeFormals);
-    if (inferrer.trySubtypeMatch(fromType, to)) {
-      var inferredTypes = inferrer.getInferredTypes();
-      if (inferredTypes != null) {
-        var inferred = instantiateClass(fromClass, inferredTypes);
-        return "Type '${typeName(from)}' should be '${typeName(inferred)}' "
-            "to implement expected type '${typeName(to)}'.";
-      }
-    }
-  }
+  // TODO(#40326) Fix suggested type or remove this code if no longer needed.
+  // var fromClass = getGenericClass(from);
+  // if (fromClass != null) {
+  //   var fromTypeFormals = getGenericTypeFormals(fromClass);
+  //   var fromType = instantiateClass(fromClass, fromTypeFormals);
+  //   var inferrer = _TypeInferrer(fromTypeFormals);
+  //   if (inferrer.trySubtypeMatch(fromType, to)) {
+  //     var inferredTypes = inferrer.getInferredTypes();
+  //     if (inferredTypes != null) {
+  //       var inferred = instantiateClass(fromClass, inferredTypes);
+  //       return "Type '${typeName(from)}' should be '${typeName(inferred)}' "
+  //           "to implement expected type '${typeName(to)}'.";
+  //     }
+  //   }
+  // }
   return "Expected a value of type '${typeName(to)}', "
       "but got one of type '${typeName(from)}'";
 }
@@ -253,8 +274,9 @@
     String trace = '';
     if (e != null && JS<bool>('!', 'typeof # === "object"', e)) {
       trace = e is NativeError ? e.dartStack() : JS<String>('', '#.stack', e);
-      if (trace != null && stackTraceMapper != null) {
-        trace = stackTraceMapper(trace);
+      var mapper = stackTraceMapper;
+      if (trace != null && mapper != null) {
+        trace = mapper(trace);
       }
     }
     if (trace.isEmpty || _jsObjectMissingTrace != null) {
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 a89ec92..916ed53 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
@@ -21,7 +21,7 @@
 
   InvocationImpl(memberName, List<Object> positionalArguments,
       {namedArguments,
-      List typeArguments,
+      List typeArguments = const [],
       this.isMethod = false,
       this.isGetter = false,
       this.isSetter = false,
@@ -30,9 +30,7 @@
             isSetter ? _setterSymbol(memberName) : _dartSymbol(memberName),
         positionalArguments = List.unmodifiable(positionalArguments),
         namedArguments = _namedArgsToSymbols(namedArguments),
-        typeArguments = typeArguments == null
-            ? const []
-            : List.unmodifiable(typeArguments.map(wrapType));
+        typeArguments = List.unmodifiable(typeArguments.map(wrapType));
 
   static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
     if (namedArgs == null) return const {};
@@ -169,14 +167,33 @@
   // Check if we have invalid named arguments.
   Iterable names;
   var named = type.named;
+  var requiredNamed = type.requiredNamed;
   if (namedActuals != null) {
     names = getOwnPropertyNames(namedActuals);
     for (var name in names) {
-      if (!JS('!', '#.hasOwnProperty(#)', named, name)) {
+      if (!JS<bool>('!', '(#.hasOwnProperty(#) || #.hasOwnProperty(#))', named,
+          name, requiredNamed, name)) {
         return "Dynamic call with unexpected named argument '$name'.";
       }
     }
   }
+  // Verify that all required named parameters are provided an argument.
+  Iterable requiredNames = getOwnPropertyNames(requiredNamed);
+  if (requiredNames.isNotEmpty) {
+    var missingRequired = namedActuals == null
+        ? requiredNames
+        : requiredNames.where((name) =>
+            !JS<bool>('!', '#.hasOwnProperty(#)', namedActuals, name));
+    if (missingRequired.isNotEmpty) {
+      var error = "Dynamic call with missing required named arguments: "
+          "${missingRequired.join(', ')}.";
+      if (!_strictSubtypeChecks) {
+        _nullWarn(error);
+      } else {
+        return error;
+      }
+    }
+  }
   // Now that we know the signature matches, we can perform type checks.
   for (var i = 0; i < requiredCount; ++i) {
     JS('', '#[#].as(#[#])', required, i, actuals, i);
@@ -186,7 +203,8 @@
   }
   if (names != null) {
     for (var name in names) {
-      JS('', '#[#].as(#[#])', named, name, namedActuals, name);
+      JS('', '(#[#] || #[#]).as(#[#])', named, name, requiredNamed, name,
+          namedActuals, name);
     }
   }
   return null;
@@ -244,7 +262,9 @@
     return $noSuchMethod(originalTarget, new $InvocationImpl.new(
         $displayName, $args, {
           namedArguments: $named,
-          typeArguments: $typeArgs,
+          // Repeated the default value here to avoid passing null from JS to a
+          // non-nullable argument.
+          typeArguments: $typeArgs || [],
           isMethod: true,
           failureMessage: errorMessage
         }));
@@ -283,7 +303,7 @@
   }
 
   // Apply type arguments
-  if ($ftype instanceof $GenericFunctionType) {
+  if (${_jsInstanceOf(ftype, GenericFunctionType)}) {
     let formalCount = $ftype.formalCount;
 
     if ($typeArgs == null) {
@@ -311,8 +331,8 @@
 dcall(f, args, [@undefined named]) => _checkAndCall(
     f, null, JS('', 'void 0'), null, args, named, JS('', 'f.name'));
 
-dgcall(f, typeArgs, args, [@undefined named]) =>
-    _checkAndCall(f, null, JS('', 'void 0'), typeArgs, args, named, 'call');
+dgcall(f, typeArgs, args, [@undefined named]) => _checkAndCall(f, null,
+    JS('', 'void 0'), typeArgs, args, named, JS('', "f.name || 'call'"));
 
 /// Helper for REPL dynamic invocation variants that make a best effort to
 /// enable accessing private members across library boundaries.
@@ -387,52 +407,75 @@
 dsetindex(obj, index, value) =>
     callMethod(obj, '_set', null, [index, value], null, '[]=');
 
+/// General implementation of the Dart `is` operator.
+///
+/// Some basic cases are handled directly by the `.is` methods that are attached
+/// directly on types, but any query that requires checking subtyping relations
+/// is handled here.
 @notNull
 @JSExportName('is')
 bool instanceOf(obj, type) {
   if (obj == null) {
-    return identical(type, unwrapType(Null)) || _isTop(type);
+    return _equalType(type, Null) ||
+        _isTop(type) ||
+        _jsInstanceOf(type, NullableType);
   }
   return isSubtypeOf(getReifiedType(obj), type);
 }
 
+/// General implementation of the Dart `as` operator.
+///
+/// Some basic cases are handled directly by the `.as` methods that are attached
+/// directly on types, but any query that requires checking subtyping relations
+/// is handled here.
 @JSExportName('as')
 cast(obj, type) {
-  if (obj == null) return obj;
-  var actual = getReifiedType(obj);
-  if (isSubtypeOf(actual, type)) {
+  // We hoist the common case where null is checked against another type here
+  // for better performance.
+  if (obj == null && !_strictSubtypeChecks) {
+    // Check the null comparison cache to avoid emitting repeated warnings.
+    _nullWarnOnType(type);
     return obj;
+  } else {
+    var actual = getReifiedType(obj);
+    if (isSubtypeOf(actual, type)) return obj;
   }
+
   return castError(obj, type);
 }
 
 bool test(bool obj) {
-  if (obj == null) _throwBooleanConversionError();
+  if (obj == null) throw BooleanConversionAssertionError();
   return obj;
 }
 
 bool dtest(obj) {
-  if (obj is! bool) booleanConversionFailed(obj);
+  // Only throw an AssertionError in weak mode for compatibility. Strong mode
+  // should throw a TypeError.
+  if (obj is! bool)
+    booleanConversionFailed(_strictSubtypeChecks ? obj : test(obj));
   return obj;
 }
 
-void _throwBooleanConversionError() => throw BooleanConversionAssertionError();
-
 void booleanConversionFailed(obj) {
   var actual = typeName(getReifiedType(obj));
   throw TypeErrorImpl("type '$actual' is not a 'bool' in boolean expression");
 }
 
 asInt(obj) {
-  if (obj == null) return null;
-
+  // Note: null (and undefined) will fail this test.
   if (JS('!', 'Math.floor(#) != #', obj, obj)) {
-    castError(obj, JS('', '#', int));
+    if (obj == null && !_strictSubtypeChecks) {
+      _nullWarnOnType(JS('', '#', int));
+      return null;
+    } else {
+      castError(obj, JS('', '#', int));
+    }
   }
   return obj;
 }
 
-asNullableInt(obj) => asInt(obj);
+asNullableInt(obj) => obj == null ? null : asInt(obj);
 
 /// Checks that `x` is not null or undefined.
 //
@@ -447,11 +490,25 @@
   return x;
 }
 
-/// No-op without null safety enabled.
-nullCast(x, type) => x;
+/// Checks that `x` is not null or undefined.
+///
+/// Unlike `_notNull`, this throws a `CastError` (under strict checking)
+/// or emits a runtime warning (otherwise).  This is only used by the
+/// compiler when casting from nullable to non-nullable variants of the
+/// same type.
+nullCast(x, type) {
+  if (x == null) {
+    if (!_strictSubtypeChecks) {
+      _nullWarnOnType(type);
+    } else {
+      castError(x, type);
+    }
+  }
+  return x;
+}
 
 /// The global constant map table.
-final constantMaps = JS('', 'new Map()');
+final constantMaps = JS<Object>('!', 'new Map()');
 
 // TODO(leafp): This table gets quite large in apps.
 // Keeping the paths is probably expensive.  It would probably
@@ -471,14 +528,14 @@
     map = _lookupNonTerminal(map, JS('', '#[#]', elements, i));
   }
   map = _lookupNonTerminal(map, K);
-  var result = JS('', '#.get(#)', map, V);
+  Map<K, V> result = JS('', '#.get(#)', map, V);
   if (result != null) return result;
   result = ImmutableMap<K, V>.from(elements);
   JS('', '#.set(#, #)', map, V, result);
   return result;
 }
 
-final constantSets = JS('', 'new Map()');
+final constantSets = JS<Object>('!', 'new Map()');
 var _immutableSetConstructor;
 
 // We cannot invoke private class constructors directly in Dart.
@@ -494,7 +551,7 @@
   for (var i = 0; i < count; i++) {
     map = _lookupNonTerminal(map, JS('', '#[#]', elements, i));
   }
-  var result = JS('', '#.get(#)', map, E);
+  Set<E> result = JS('', '#.get(#)', map, E);
   if (result != null) return result;
   result = _createImmutableSet<E>(elements);
   JS('', '#.set(#, #)', map, E, result);
@@ -537,7 +594,7 @@
 /// and value of the field.  The final map is
 /// indexed by runtime type, and contains the canonical
 /// version of the object.
-final constants = JS('', 'new Map()');
+final constants = JS('!', 'new Map()');
 
 ///
 /// Canonicalize a constant object.
@@ -656,7 +713,7 @@
   return obj == null ? Null : JS('', '#[dartx.runtimeType]', obj);
 }
 
-final identityHashCode_ = JS('', 'Symbol("_identityHashCode")');
+final identityHashCode_ = JS<Object>('!', 'Symbol("_identityHashCode")');
 
 /// Adapts a Dart `get iterator` into a JS `[Symbol.iterator]`.
 // TODO(jmesserly): instead of an adaptor, we could compile Dart iterators
@@ -697,8 +754,89 @@
 Future loadLibrary() => Future.value();
 
 /// Defines lazy statics.
-void defineLazy(to, from, bool checkCycles) {
+///
+/// TODO: Remove useOldSemantics when non-null-safe late static field behavior is
+/// deprecated.
+void defineLazy(to, from, bool useOldSemantics) {
   for (var name in getOwnNamesAndSymbols(from)) {
-    defineLazyField(to, name, getOwnPropertyDescriptor(from, name));
+    if (useOldSemantics) {
+      defineLazyFieldOld(to, name, getOwnPropertyDescriptor(from, name));
+    } else {
+      defineLazyField(to, name, getOwnPropertyDescriptor(from, name));
+    }
   }
 }
+
+/// Defines a lazy static field.
+/// After initial get or set, it will replace itself with a value property.
+// TODO(jmesserly): reusing descriptor objects has been shown to improve
+// performance in other projects (e.g. webcomponents.js ShadowDOM polyfill).
+defineLazyField(to, name, desc) => JS('', '''(() => {
+  const initializer = $desc.get;
+  let init = initializer;
+  let value = null;
+  let executed = false;
+  $desc.get = function() {
+    if (init == null) return value;
+    if (!executed) {
+      // Record the field on first execution so we can reset it later if
+      // needed (hot restart).
+      $_resetFields.push(() => {
+        init = initializer;
+        value = null;
+      });
+      executed = true;
+    }
+    value = init();
+    init = null;
+    return value;
+  };
+  $desc.configurable = true;
+  if ($desc.set != null) {
+    $desc.set = function(x) {
+      init = null;
+      value = x;
+    };
+  }
+  return ${defineProperty(to, name, desc)};
+})()''');
+
+/// Defines a lazy static field with pre-null-safety semantics.
+defineLazyFieldOld(to, name, desc) => JS('', '''(() => {
+  const initializer = $desc.get;
+  let init = initializer;
+  let value = null;
+  $desc.get = function() {
+    if (init == null) return value;
+    let f = init;
+    init = $throwCyclicInitializationError;
+    if (f === init) f($name); // throw cycle error
+
+    // On the first (non-cyclic) execution, record the field so we can reset it
+    // later if needed (hot restart).
+    $_resetFields.push(() => {
+      init = initializer;
+      value = null;
+    });
+
+    // Try to evaluate the field, using try+catch to ensure we implement the
+    // correct Dart error semantics.
+    try {
+      value = f();
+      init = null;
+      return value;
+    } catch (e) {
+      init = null;
+      value = null;
+      throw e;
+    }
+  };
+  $desc.configurable = true;
+  if ($desc.set != null) {
+    $desc.set = function(x) {
+      init = null;
+      value = x;
+    };
+  }
+  return ${defineProperty(to, name, desc)};
+})()''');
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
index a869a3f..4d731ce 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
@@ -71,9 +71,9 @@
 }
 
 // TODO(vsm): How should we encode the runtime type?
-final _runtimeType = JS('', 'Symbol("_runtimeType")');
+final Object _runtimeType = JS('!', 'Symbol("_runtimeType")');
 
-final _moduleName = JS('', 'Symbol("_moduleName")');
+final Object _moduleName = JS('!', 'Symbol("_moduleName")');
 
 getFunctionType(obj) {
   // TODO(vsm): Encode this properly on the function for Dart-generated code.
@@ -90,7 +90,7 @@
   switch (JS<String>('!', 'typeof #', obj)) {
     case "object":
       if (obj == null) return JS('', '#', Null);
-      if (JS('!', '# instanceof #', obj, Object)) {
+      if (_jsInstanceOf(obj, Object)) {
         return JS('', '#.constructor', obj);
       }
       var result = JS('', '#[#]', obj, _extensionType);
@@ -123,7 +123,7 @@
 final _loadedSourceMaps = JS('', 'new Map()');
 
 List<String> getModuleNames() {
-  return JSArray<String>.of(JS('', 'Array.from(#.keys())', _loadedModules));
+  return JS<List<String>>('', 'Array.from(#.keys())', _loadedModules);
 }
 
 String getSourceMap(String moduleName) {
@@ -148,7 +148,7 @@
     // Added for backwards compatibility.
     // package:build_web_compilers currently invokes this without [parts]
     // in its bootstrap code.
-    sourceMap = parts as String;
+    sourceMap = parts;
     parts = JS('', '{}');
   }
   JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap);
@@ -171,6 +171,8 @@
   for (var name in modules) {
     // Add libraries from each module.
     var module = getModuleLibraries(name);
+    // TODO(nshahan) Can we optimize this cast and the one below to use
+    // JsArray.of() to be more efficient?
     var libraries = getOwnPropertyNames(module).cast<String>();
     _libraries.addAll(libraries);
     for (var library in libraries) {
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 68eef6d..433393d 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
@@ -107,7 +107,7 @@
 })()''');
 
 @JSExportName('global')
-final global_ = JS('', '''
+final Object global_ = JS('', '''
   function () {
     // Find global object.
     var globalState = (typeof window != "undefined") ? window
@@ -172,6 +172,8 @@
 ///
 /// This is used by [hotRestart] to ensure we don't leak types from previous
 /// libraries.
+/// Results made against Null are cached in _nullComparisonSet and must be
+/// cleared separately.
 @notNull
 final List<Object> _cacheMaps = JS('!', '[]');
 
@@ -201,6 +203,7 @@
   _resetFields.clear();
   for (var m in _cacheMaps) JS('', '#.clear()', m);
   _cacheMaps.clear();
+  JS('', '#.clear()', _nullComparisonSet);
   JS('', '#.clear()', constantMaps);
 }
 
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 b3fad43..ef5fcd6 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
@@ -7,6 +7,16 @@
 /// This library defines the representation of runtime types.
 part of dart._runtime;
 
+@notNull
+bool _strictSubtypeChecks = false;
+
+/// Sets the mode of the runtime subtype checks.
+///
+/// Changing the mode after any calls to dart.isSubtype() is not supported.
+void strictSubtypeChecks(bool flag) {
+  _strictSubtypeChecks = flag;
+}
+
 final metadata = JS('', 'Symbol("metadata")');
 
 /// Types in dart are represented internally at runtime as follows.
@@ -63,16 +73,22 @@
 
   @JSExportName('as')
   as_T(object) => cast(object, this);
+
+  DartType() {
+    // Every instance of a DartType requires a set of type caches.
+    JS('', '#(this)', addTypeCaches);
+  }
 }
 
 class DynamicType extends DartType {
   toString() => 'dynamic';
 
+  @notNull
   @JSExportName('is')
   bool is_T(object) => true;
 
   @JSExportName('as')
-  as_T(object) => object;
+  Object as_T(Object object) => object;
 }
 
 @notNull
@@ -84,7 +100,9 @@
 /// function before it is passed to native JS code.
 @NoReifyGeneric()
 F assertInterop<F extends Function>(F f) {
-  assert(_isJsObject(f) || !JS('bool', '# instanceof #.Function', f, global_),
+  assert(
+      _isJsObject(f) ||
+          !JS<bool>('bool', '# instanceof #.Function', f, global_),
       'Dart function requires `allowInterop` to be passed to JavaScript.');
   return f;
 }
@@ -99,7 +117,7 @@
 F tearoffInterop<F extends Function>(F f) {
   // Wrap a JS function with a closure that ensures all function arguments are
   // native JS functions.
-  if (!_isJsObject(f)) return f;
+  if (!_isJsObject(f) || f == null) return f;
   var ret = _assertInteropExpando[f];
   if (ret == null) {
     ret = JS(
@@ -193,8 +211,32 @@
   JS('void', 'console.warn(#)', arg);
 }
 
-var _lazyJSTypes = JS('', 'new Map()');
-var _anonymousJSTypes = JS('', 'new Map()');
+void _nullWarn(arg) {
+  _warn('$arg\n'
+      'This will become a failure when runtime null safety is enabled.');
+}
+
+/// Tracks objects that have been compared against null (i.e., null is Type).
+/// Separating this null set out from _cacheMaps lets us fast-track common
+/// legacy type checks.
+/// TODO: Delete this set when legacy nullability is phased out.
+var _nullComparisonSet = JS<Object>('', 'new Set()');
+
+/// Warn on null cast failures when casting to a particular non-nullable
+/// `type`.  Note, we cache by type to avoid excessive warning messages at
+/// runtime.
+/// TODO(vsm): Consider changing all invocations to pass / cache on location
+/// instead.  That gives more useful feedback to the user.
+void _nullWarnOnType(type) {
+  bool result = JS('', '#.has(#)', _nullComparisonSet, type);
+  if (!result) {
+    JS('', '#.add(#)', _nullComparisonSet, type);
+    _nullWarn("Null is not a subtype of $type.");
+  }
+}
+
+var _lazyJSTypes = JS<Object>('', 'new Map()');
+var _anonymousJSTypes = JS<Object>('', 'new Map()');
 
 lazyJSType(Function() getJSTypeCallback, String name) {
   var ret = JS('', '#.get(#)', _lazyJSTypes, name);
@@ -214,22 +256,163 @@
   return ret;
 }
 
+/// A javascript Symbol used to store a canonical version of T? on T.
+final _cachedNullable = JS('', 'Symbol("cachedNullable")');
+
+/// A javascript Symbol used to store a canonical version of T* on T.
+final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
+
+/// A javascript Symbol used to store prior subtype checks and their results.
+final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+
+/// Returns a nullable (question, ?) version of [type].
+///
+/// The resulting type returned in a normalized form based on the rules from the
+/// normalization doc:
+/// https://github.com/dart-lang/language/blob/master/resources/type-system/normalization.md
+@notNull
+Object nullable(type) {
+  // Check if a nullable version of this type has already been created.
+  var cached = JS<Object>('', '#[#]', type, _cachedNullable);
+  if (JS<bool>('!', '# !== void 0', cached)) {
+    return cached;
+  }
+
+  // Cache a canonical nullable version of this type on this type.
+  Object cachedType = _computeNullable(type);
+  JS('', '#[#] = #', type, _cachedNullable, cachedType);
+  return cachedType;
+}
+
+Object _computeNullable(type) {
+  // *? normalizes to ?.
+  if (_jsInstanceOf(type, LegacyType)) {
+    return nullable(JS<Object>('!', '#.type', type));
+  }
+  if (_jsInstanceOf(type, NullableType) ||
+      _isTop(type) ||
+      _equalType(type, Null) ||
+      // Normalize FutureOr<T?>? --> FutureOr<T?>
+      // All other runtime FutureOr normalization is in `normalizeFutureOr()`.
+      ((_isFutureOr(type)) &&
+          _jsInstanceOf(
+              JS<Object>('!', '#[0]', getGenericArgs(type)), NullableType))) {
+    return type;
+  }
+  if (_equalType(type, Never)) return unwrapType(Null);
+  return NullableType(JS<Type>('!', '#', type));
+}
+
+/// Returns a legacy (star, *) version of [type].
+///
+/// The resulting type returned in a normalized form based on the rules from the
+/// normalization doc:
+/// https://github.com/dart-lang/language/blob/master/resources/type-system/normalization.md
+@notNull
+Object legacy(type) {
+  // Check if a legacy version of this type has already been created.
+  var cached = JS<Object>('', '#[#]', type, _cachedLegacy);
+  if (JS<bool>('!', '# !== void 0', cached)) {
+    return cached;
+  }
+
+  // Cache a canonical legacy version of this type on this type.
+  Object cachedType = _computeLegacy(type);
+  JS('', '#[#] = #', type, _cachedLegacy, cachedType);
+  return cachedType;
+}
+
+Object _computeLegacy(type) {
+  // Note: ?* normalizes to ?, so we cache type? at type?[_cachedLegacy].
+  if (_jsInstanceOf(type, LegacyType) ||
+      _jsInstanceOf(type, NullableType) ||
+      _isTop(type) ||
+      _equalType(type, Null)) {
+    return type;
+  }
+  return LegacyType(JS<Type>('!', '#', type));
+}
+
+/// A wrapper to identify a nullable (question, ?) type of the form [type]?.
+class NullableType extends DartType {
+  final Type type;
+
+  NullableType(this.type);
+
+  @override
+  String get name => '$type?';
+
+  @override
+  String toString() => name;
+
+  @JSExportName('is')
+  bool is_T(obj) => obj == null || JS<bool>('!', '#.is(#)', type, obj);
+
+  @JSExportName('as')
+  as_T(obj) => obj == null || JS<bool>('!', '#.is(#)', type, obj)
+      ? obj
+      : cast(obj, this);
+}
+
+/// A wrapper to identify a legacy (star, *) type of the form [type]*.
+class LegacyType extends DartType {
+  final Type type;
+
+  LegacyType(this.type);
+
+  @override
+  String get name => '$type';
+
+  @override
+  String toString() => name;
+
+  @JSExportName('is')
+  bool is_T(obj) {
+    if (obj == null) {
+      // Object and Never are the only legacy types that should return true if
+      // obj is `null`.
+      return _equalType(type, Object) || _equalType(type, Never);
+    }
+    return JS<bool>('!', '#.is(#)', type, obj);
+  }
+
+  @JSExportName('as')
+  as_T(obj) => obj == null || JS<bool>('!', '#.is(#)', type, obj)
+      ? obj
+      : cast(obj, this);
+}
+
+// TODO(nshahan) Add override optimizations for is and as?
+class NeverType extends DartType {
+  @override
+  toString() => 'Never';
+}
+
+@JSExportName('Never')
+final _never = NeverType();
+
 @JSExportName('dynamic')
 final _dynamic = DynamicType();
 
 class VoidType extends DartType {
   toString() => 'void';
+
+  @notNull
+  @JSExportName('is')
+  bool is_T(object) => true;
+
+  @JSExportName('as')
+  Object as_T(Object object) => object;
 }
 
 @JSExportName('void')
 final void_ = VoidType();
 
+// TODO(nshahan): Cleanup and consolidate NeverType, BottomType, bottom, _never.
 class BottomType extends DartType {
   toString() => 'bottom';
 }
 
-// TODO(vsm): We reify bottom as Null.  We will revisit this with
-// non-nullable types.
 final bottom = unwrapType(Null);
 
 class JSObjectType extends DartType {
@@ -254,19 +437,99 @@
   Type get runtimeType => Type;
 }
 
-/// Given an internal runtime type object, wraps it in a `_Type` object
+/// Given an internal runtime type object [type], wraps it in a `_Type` object
 /// that implements the dart:core Type interface.
-Type wrapType(type) {
+///
+/// [isNormalized] is true when [type] is known to be in a canonicalized
+/// normal form, so the algorithm can directly wrap and return the value.
+Type wrapType(type, [@notNull bool isNormalized = false]) {
   // If we've already wrapped this type once, use the previous wrapper. This
   // way, multiple references to the same type return an identical Type.
   if (JS('!', '#.hasOwnProperty(#)', type, _typeObject)) {
     return JS('', '#[#]', type, _typeObject);
   }
-  var result = _Type(type);
+  var result = isNormalized
+      ? _Type(type)
+      : (_jsInstanceOf(type, LegacyType)
+          ? wrapType(JS<Object>('!', '#.type', type))
+          : _canonicalizeNormalizedTypeObject(type));
   JS('', '#[#] = #', type, _typeObject, result);
   return result;
 }
 
+/// Constructs a normalized version of a type.
+///
+/// Used for type object identity. Normalization requires us to return a
+/// canonicalized version of the input with all legacy wrappers removed.
+Type _canonicalizeNormalizedTypeObject(type) {
+  assert(!_jsInstanceOf(type, LegacyType));
+  // We don't call _canonicalizeNormalizedTypeObject recursively but call wrap
+  // + unwrap to handle legacy types automatically and force caching the
+  // canonicalized type under the _typeObject cache property directly. This
+  // way we ensure we always use the canonical normalized instance for each
+  // type term.
+  Object normalizeHelper(a) => unwrapType(wrapType(a));
+
+  // GenericFunctionTypeIdentifiers are implicitly normalized.
+  if (_jsInstanceOf(type, GenericFunctionTypeIdentifier)) {
+    return wrapType(type, true);
+  }
+  if (_jsInstanceOf(type, FunctionType)) {
+    var normReturnType = normalizeHelper(type.returnType);
+    var normArgs = type.args.map(normalizeHelper).toList();
+    if (JS<bool>('!', '#.Object.keys(#).length === 0', global_, type.named) &&
+        JS<bool>('!', '#.Object.keys(#).length === 0', global_,
+            type.requiredNamed)) {
+      if (type.optionals.isEmpty) {
+        var normType = fnType(normReturnType, normArgs);
+        return wrapType(normType, true);
+      }
+      var normOptionals = type.optionals.map(normalizeHelper).toList();
+      var normType = fnType(normReturnType, normArgs, normOptionals);
+      return wrapType(normType, true);
+    }
+    var normNamed = JS('', '{}');
+    _transformJSObject(type.named, normNamed, normalizeHelper);
+    var normRequiredNamed = JS('', '{}');
+    _transformJSObject(type.requiredNamed, normRequiredNamed, normalizeHelper);
+    var normType =
+        fnType(normReturnType, normArgs, normNamed, normRequiredNamed);
+    return wrapType(normType, true);
+  }
+  if (_jsInstanceOf(type, GenericFunctionType)) {
+    var formals = _getCanonicalTypeFormals(type.typeFormals.length);
+    var normBounds =
+        type.instantiateTypeBounds(formals).map(normalizeHelper).toList();
+    var normFunc = normalizeHelper(type.instantiate(formals)) as FunctionType;
+    // Create a comparison key for structural identity.
+    var typeObjectIdKey = JS('', '[]');
+    JS('', '#.push(...#)', typeObjectIdKey, normBounds);
+    JS('', '#.push(#)', typeObjectIdKey, normFunc);
+    var memoizedId = _memoizeArray(_gFnTypeTypeMap, typeObjectIdKey,
+        () => GenericFunctionTypeIdentifier(formals, normBounds, normFunc));
+    return wrapType(memoizedId, true);
+  }
+  var args = getGenericArgs(type);
+  var normType;
+  if (args == null || args.isEmpty) {
+    normType = type;
+  } else {
+    var genericClass = getGenericClass(type);
+    var normArgs = args.map(normalizeHelper).toList();
+    normType = JS('!', '#(...#)', genericClass, normArgs);
+  }
+  return wrapType(normType, true);
+}
+
+/// Generates new values by applying [transform] to the values of [srcObject],
+/// storing them in [dstObject] with the same key.
+void _transformJSObject(srcObject, dstObject, Function transform) {
+  for (Object key in JS('!', '#.Object.keys(#)', global_, srcObject)) {
+    JS('', '#[#] = #', dstObject, key,
+        transform(JS('', '#[#]', srcObject, key)));
+  }
+}
+
 /// The symbol used to store the cached `Type` object associated with a class.
 final _typeObject = JS('', 'Symbol("typeObject")');
 
@@ -305,6 +568,38 @@
 /// index path (if present) is the canonical function type.
 final List _fnTypeSmallMap = JS('', '[new Map(), new Map(), new Map()]');
 
+/// Memo table for generic function types. The index path consists of the
+/// type parameters' bounds and the underlying function instantiated to its
+/// bounds, subject to the same restrictions mentioned in _fnTypeTypeMap.
+final _gFnTypeTypeMap = JS('', 'new Map()');
+
+/// Pre-initialized type variables used to ensure that generic functions with
+/// the same generic relationship structure but different names canonicalize
+/// correctly.
+final _typeVariablePool = <TypeVariable>[];
+
+/// Returns a canonicalized sequence of type variables of size [count].
+List<TypeVariable> _getCanonicalTypeFormals(int count) {
+  while (count > _typeVariablePool.length) {
+    _fillTypeVariable();
+  }
+  return _typeVariablePool.sublist(0, count);
+}
+
+/// Inserts a new type variable into _typeVariablePool according to a
+/// pre-determined pattern.
+///
+/// The first 26 generics are alphanumerics; the remainder are represented as
+/// T$N, where N increments from 0.
+void _fillTypeVariable() {
+  if (_typeVariablePool.length < 26) {
+    _typeVariablePool
+        .add(TypeVariable(String.fromCharCode(65 + _typeVariablePool.length)));
+  } else {
+    _typeVariablePool.add(TypeVariable('T${_typeVariablePool.length - 26}'));
+  }
+}
+
 @NoReifyGeneric()
 T _memoizeArray<T>(map, arr, T create()) => JS('', '''(() => {
   let len = $arr.length;
@@ -321,8 +616,8 @@
 List _canonicalizeArray(List array, map) =>
     _memoizeArray(map, array, () => array);
 
-// TODO(leafp): This only canonicalizes of the names are
-// emitted in a consistent order.
+// TODO(leafp): This only canonicalizes if the names are emitted
+// in a consistent order.
 _canonicalizeNamed(named, map) => JS('', '''(() => {
   let key = [];
   let names = $getOwnPropertyNames($named);
@@ -346,7 +641,7 @@
  }
  let result = map.get($returnType);
  if (result !== void 0) return result;
- result = ${new FunctionType(returnType, required, [], JS('', '{}'))};
+ result = ${new FunctionType(returnType, required, [], JS('', '{}'), JS('', '{}'))};
  map.set($returnType, result);
  return result;
 })()''');
@@ -357,6 +652,7 @@
   final List optionals;
   // Named arguments native JS Object of the form { namedArgName: namedArgType }
   final named;
+  final requiredNamed;
   String _stringValue;
 
   /// Construct a function type.
@@ -369,35 +665,40 @@
   ///
   /// Note: Generic function subtype checks assume types have been canonicalized
   /// when testing if type bounds are equal.
-  static FunctionType create(returnType, List args, extra) {
-    // Note that if extra is ever passed as an empty array
-    // or an empty map, we can end up with semantically
-    // identical function types that don't canonicalize
-    // to the same object since we won't fall into this
-    // fast path.
-    if (extra == null && JS<bool>('!', '#.length < 3', args)) {
+  static FunctionType create(
+      returnType, List args, optionalArgs, requiredNamedArgs) {
+    // Note that if optionalArgs is ever passed as an empty array or an empty
+    // map, we can end up with semantically identical function types that don't
+    // canonicalize to the same object since we won't fall into this fast path.
+    var noOptionalArgs = optionalArgs == null && requiredNamedArgs == null;
+    if (noOptionalArgs && JS<bool>('!', '#.length < 3', args)) {
       return _createSmall(returnType, args);
     }
     args = _canonicalizeArray(args, _fnTypeArrayArgMap);
-    var keys;
+    var keys = [];
     FunctionType Function() create;
-    if (extra == null) {
+    if (noOptionalArgs) {
       keys = [returnType, args];
-      create = () => FunctionType(returnType, args, [], JS('', '{}'));
-    } else if (JS('!', '# instanceof Array', extra)) {
+      create =
+          () => FunctionType(returnType, args, [], JS('', '{}'), JS('', '{}'));
+    } else if (JS('!', '# instanceof Array', optionalArgs)) {
       var optionals =
-          _canonicalizeArray(JS('', '#', extra), _fnTypeArrayArgMap);
+          _canonicalizeArray(JS('', '#', optionalArgs), _fnTypeArrayArgMap);
       keys = [returnType, args, optionals];
-      create = () => FunctionType(returnType, args, optionals, JS('', '{}'));
+      create = () =>
+          FunctionType(returnType, args, optionals, JS('', '{}'), JS('', '{}'));
     } else {
-      var named = _canonicalizeNamed(extra, _fnTypeNamedArgMap);
-      keys = [returnType, args, named];
-      create = () => FunctionType(returnType, args, [], named);
+      var named = _canonicalizeNamed(optionalArgs, _fnTypeNamedArgMap);
+      var requiredNamed =
+          _canonicalizeNamed(requiredNamedArgs, _fnTypeNamedArgMap);
+      keys = [returnType, args, named, requiredNamed];
+      create = () => FunctionType(returnType, args, [], named, requiredNamed);
     }
     return _memoizeArray(_fnTypeTypeMap, keys, create);
   }
 
-  FunctionType(this.returnType, this.args, this.optionals, this.named);
+  FunctionType(this.returnType, this.args, this.optionals, this.named,
+      this.requiredNamed);
 
   toString() => name;
 
@@ -409,9 +710,10 @@
     return i < n ? args[i] : optionals[i + n];
   }
 
-  Map<String, Object> getNamedParameters() {
+  /// Maps argument names to their canonicalized type.
+  Map<String, Object> _createNameMap(List<Object> names) {
     var result = <String, Object>{};
-    var names = getOwnPropertyNames(named);
+    // TODO: Remove this sort if ordering can be conserved.
     JS('', '#.sort()', names);
     for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
       String name = JS('!', '#[#]', names, i);
@@ -420,9 +722,16 @@
     return result;
   }
 
+  /// Maps optional named parameter names to their canonicalized type.
+  Map<String, Object> getNamedParameters() =>
+      _createNameMap(getOwnPropertyNames(named).toList());
+
+  /// Maps required named parameter names to their canonicalized type.
+  Map<String, Object> getRequiredNamedParameters() =>
+      _createNameMap(getOwnPropertyNames(requiredNamed).toList());
+
   get name {
     if (_stringValue != null) return _stringValue;
-
     var buffer = '(';
     for (var i = 0; JS<bool>('!', '# < #.length', i, args); ++i) {
       if (i > 0) {
@@ -440,21 +749,33 @@
         buffer += typeName(JS('', '#[#]', optionals, i));
       }
       buffer += ']';
-    } else if (JS('!', 'Object.keys(#).length > 0', named)) {
+    } else if (JS('!', 'Object.keys(#).length > 0 || Object.keys(#).length > 0',
+        named, requiredNamed)) {
       if (JS('!', '#.length > 0', args)) buffer += ', ';
       buffer += '{';
       var names = getOwnPropertyNames(named);
       JS('', '#.sort()', names);
-      for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
+      for (var i = 0; JS<bool>('!', '# < #.length', i, names); i++) {
         if (i > 0) {
           buffer += ', ';
         }
         var typeNameString = typeName(JS('', '#[#[#]]', named, names, i));
         buffer += '$typeNameString ${JS('', '#[#]', names, i)}';
       }
+      if (JS('!', 'Object.keys(#).length > 0 && #.length > 0', requiredNamed,
+          names)) buffer += ', ';
+      names = getOwnPropertyNames(requiredNamed);
+      JS('', '#.sort()', names);
+      for (var i = 0; JS<bool>('!', '# < #.length', i, names); i++) {
+        if (i > 0) {
+          buffer += ', ';
+        }
+        var typeNameString =
+            typeName(JS('', '#[#[#]]', requiredNamed, names, i));
+        buffer += 'required $typeNameString ${JS('', '#[#]', names, i)}';
+      }
       buffer += '}';
     }
-
     var returnTypeName = typeName(returnType);
     buffer += ') => $returnTypeName';
     _stringValue = buffer;
@@ -474,7 +795,6 @@
 
   @JSExportName('as')
   as_T(obj) {
-    if (obj == null) return obj;
     if (JS('!', 'typeof # == "function"', obj)) {
       var actual = JS('', '#[#]', obj, _runtimeType);
       // If there's no actual type, it's a JS function.
@@ -503,20 +823,59 @@
   static const int invariant = 3;
 }
 
+/// Uniquely identifies the runtime type object of a generic function.
+///
+/// We require that all objects stored in this object not have legacy
+/// nullability wrappers.
+class GenericFunctionTypeIdentifier extends AbstractFunctionType {
+  final typeFormals;
+  final typeBounds;
+  final FunctionType function;
+  String _stringValue;
+
+  GenericFunctionTypeIdentifier(
+      this.typeFormals, this.typeBounds, this.function);
+
+  /// Returns the string-representation of the first generic function
+  /// with this runtime type object canonicalization.
+  ///
+  /// Type formal names may not correspond to those of the originating type.
+  /// We should consider auto-generating these to avoid confusion.
+  toString() {
+    if (_stringValue != null) return _stringValue;
+    String s = "<";
+    var typeFormals = this.typeFormals;
+    var typeBounds = this.typeBounds;
+    for (int i = 0, n = typeFormals.length; i < n; i++) {
+      if (i != 0) s += ", ";
+      s += JS<String>('!', '#[#].name', typeFormals, i);
+      var bound = typeBounds[i];
+      if (_equalType(bound, dynamic) ||
+          JS<bool>('!', '# === #', bound, nullable(unwrapType(Object))) ||
+          (!_strictSubtypeChecks && _equalType(bound, Object))) {
+        // Do not print the bound when it is a top type. In weak mode the bounds
+        // of Object and Object* will also be elided.
+        continue;
+      }
+      s += " extends $bound";
+    }
+    s += ">" + this.function.toString();
+    return this._stringValue = s;
+  }
+}
+
 class GenericFunctionType extends AbstractFunctionType {
   final _instantiateTypeParts;
   final int formalCount;
   final _instantiateTypeBounds;
-  List<TypeVariable> _typeFormals;
+  final List<TypeVariable> _typeFormals;
 
   GenericFunctionType(instantiateTypeParts, this._instantiateTypeBounds)
       : _instantiateTypeParts = instantiateTypeParts,
-        formalCount = JS('!', '#.length', instantiateTypeParts);
+        formalCount = JS('!', '#.length', instantiateTypeParts),
+        _typeFormals = _typeFormalsFromFunction(instantiateTypeParts);
 
-  List<TypeVariable> get typeFormals {
-    if (_typeFormals != null) return _typeFormals;
-    return _typeFormals = _typeFormalsFromFunction(_instantiateTypeParts);
-  }
+  List<TypeVariable> get typeFormals => _typeFormals;
 
   /// `true` if there are bounds on any of the generic type parameters.
   get hasTypeBounds => _instantiateTypeBounds != null;
@@ -537,16 +896,17 @@
 
   FunctionType instantiate(typeArgs) {
     var parts = JS('', '#.apply(null, #)', _instantiateTypeParts, typeArgs);
-    return FunctionType.create(
-        JS('', '#[0]', parts), JS('', '#[1]', parts), JS('', '#[2]', parts));
+    return FunctionType.create(JS('', '#[0]', parts), JS('', '#[1]', parts),
+        JS('', '#[2]', parts), JS('', '#[3]', parts));
   }
 
   List instantiateTypeBounds(List typeArgs) {
     if (!hasTypeBounds) {
-      // The Dart 1 spec says omitted type parameters have an upper bound of
-      // Object. However Dart 2 uses `dynamic` for the purpose of instantiate to
-      // bounds, so we use that here.
-      return List.filled(formalCount, _dynamic);
+      // We ommit the a bound to represent Object*. Other bounds are explicitly
+      // represented, including Object, Object? and dynamic.
+      // TODO(nshahan) Revisit this representation when more libraries have
+      // migrated to null safety.
+      return List.filled(formalCount, legacy(unwrapType(Object)));
     }
     // Bounds can be recursive or depend on other type parameters, so we need to
     // apply type arguments and return the resulting bounds.
@@ -586,7 +946,7 @@
     // formal if known, or it will be the original TypeVariable if we are still
     // solving for it. This array is passed to `instantiateToBounds` as we are
     // progressively solving for type variables.
-    var defaults = List<Object>(typeFormals.length);
+    var defaults = List<Object>.filled(typeFormals.length, null);
     // not ground
     var partials = Map<TypeVariable, Object>.identity();
 
@@ -603,21 +963,21 @@
       }
     }
 
-    bool hasFreeFormal(Object t) {
+    bool hasFreeFormal(t) {
+      // Ignore nullability wrappers.
+      if (_jsInstanceOf(t, LegacyType) || _jsInstanceOf(t, NullableType)) {
+        return hasFreeFormal(JS<Object>('!', '#.type', t));
+      }
       if (partials.containsKey(t)) return true;
-
       // Generic classes and typedefs.
       var typeArgs = getGenericArgs(t);
       if (typeArgs != null) return typeArgs.any(hasFreeFormal);
-
       if (t is GenericFunctionType) {
         return hasFreeFormal(t.instantiate(t.typeFormals));
       }
-
       if (t is FunctionType) {
         return hasFreeFormal(t.returnType) || t.args.any(hasFreeFormal);
       }
-
       return false;
     }
 
@@ -660,7 +1020,7 @@
 
   @JSExportName('as')
   as_T(obj) {
-    if (obj == null || is_T(obj)) return obj;
+    if (is_T(obj)) return obj;
     return castError(obj, this);
   }
 }
@@ -690,8 +1050,9 @@
 }
 
 /// Create a function type.
-FunctionType fnType(returnType, List args, [@undefined extra]) =>
-    FunctionType.create(returnType, args, extra);
+FunctionType fnType(returnType, List args,
+        [@undefined optional, @undefined requiredNamed]) =>
+    FunctionType.create(returnType, args, optional, requiredNamed);
 
 /// Creates a generic function type from [instantiateFn] and [typeBounds].
 ///
@@ -727,7 +1088,7 @@
   if ($type === void 0) return "undefined type";
   if ($type === null) return "null type";
   // Non-instance types
-  if ($type instanceof $DartType) {
+  if (${_jsInstanceOf(type, DartType)}) {
     return $type.toString();
   }
 
@@ -754,7 +1115,7 @@
 })()''');
 
 /// Returns true if [ft1] <: [ft2].
-_isFunctionSubtype(ft1, ft2) => JS('', '''(() => {
+_isFunctionSubtype(ft1, ft2, bool strictMode) => JS('', '''(() => {
   let ret1 = $ft1.returnType;
   let ret2 = $ft2.returnType;
 
@@ -766,7 +1127,7 @@
   }
 
   for (let i = 0; i < args1.length; ++i) {
-    if (!$_isSubtype(args2[i], args1[i])) {
+    if (!$_isSubtype(args2[i], args1[i], strictMode)) {
       return false;
     }
   }
@@ -780,21 +1141,44 @@
 
   let j = 0;
   for (let i = args1.length; i < args2.length; ++i, ++j) {
-    if (!$_isSubtype(args2[i], optionals1[j])) {
+    if (!$_isSubtype(args2[i], optionals1[j], strictMode)) {
       return false;
     }
   }
 
   for (let i = 0; i < optionals2.length; ++i, ++j) {
-    if (!$_isSubtype(optionals2[i], optionals1[j])) {
+    if (!$_isSubtype(optionals2[i], optionals1[j], strictMode)) {
       return false;
     }
   }
 
+  // Named parameter invariants:
+  // 1) All named params in the superclass are named params in the subclass.
+  // 2) All required named params in the subclass are required named params
+  //    in the superclass.
+  // 3) With strict null checking disabled, we treat required named params as
+  //    optional named params.
   let named1 = $ft1.named;
+  let requiredNamed1 = $ft1.requiredNamed;
   let named2 = $ft2.named;
+  let requiredNamed2 = $ft2.requiredNamed;
+  if (!strictMode) {
+    // In weak mode, treat required named params as optional named params.
+    named1 = Object.assign({}, named1, requiredNamed1);
+    named2 = Object.assign({}, named2, requiredNamed2);
+    requiredNamed1 = {};
+    requiredNamed2 = {};
+  }
 
-  let names = $getOwnPropertyNames(named2);
+  let names = $getOwnPropertyNames(requiredNamed1);
+  for (let i = 0; i < names.length; ++i) {
+    let name = names[i];
+    let n2 = requiredNamed2[name];
+    if (n2 === void 0) {
+      return false;
+    }
+  }
+  names = $getOwnPropertyNames(named2);
   for (let i = 0; i < names.length; ++i) {
     let name = names[i];
     let n1 = named1[name];
@@ -802,12 +1186,24 @@
     if (n1 === void 0) {
       return false;
     }
-    if (!$_isSubtype(n2, n1)) {
+    if (!$_isSubtype(n2, n1, strictMode)) {
+      return false;
+    }
+  }
+  names = $getOwnPropertyNames(requiredNamed2);
+  for (let i = 0; i < names.length; ++i) {
+    let name = names[i];
+    let n1 = named1[name] || requiredNamed1[name];
+    let n2 = requiredNamed2[name];
+    if (n1 === void 0) {
+      return false;
+    }
+    if (!$_isSubtype(n2, n1, strictMode)) {
       return false;
     }
   }
 
-  return $_isSubtype(ret1, ret2);
+  return $_isSubtype(ret1, ret2, strictMode);
 })()''');
 
 /// Returns true if [t1] <: [t2].
@@ -815,48 +1211,149 @@
 bool isSubtypeOf(Object t1, Object t2) {
   // TODO(jmesserly): we've optimized `is`/`as`/implicit type checks, so they're
   // dispatched on the type. Can we optimize the subtype relation too?
-  Object map;
-  if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
-    JS('', '#[#] = # = new Map()', t1, _subtypeCache, map);
-    _cacheMaps.add(map);
-  } else {
-    map = JS('', '#[#]', t1, _subtypeCache);
-    bool result = JS('', '#.get(#)', map, t2);
-    if (JS('!', '# !== void 0', result)) return result;
+  var map = JS<Object>('!', '#[#]', t1, _subtypeCache);
+  bool result = JS('', '#.get(#)', map, t2);
+  if (JS('!', '# !== void 0', result)) return result;
+
+  var validSubtype = _isSubtype(t1, t2, true);
+  if (!validSubtype && !_strictSubtypeChecks) {
+    validSubtype = _isSubtype(t1, t2, false);
+    if (validSubtype) {
+      // TODO(nshahan) Need more information to be helpful here.
+      // File and line number that caused the subtype check?
+      // Possibly break into debugger?
+      _nullWarn("$t1 is not a subtype of $t2.");
+    }
   }
-  var result = _isSubtype(t1, t2);
-  JS('', '#.set(#, #)', map, t2, result);
-  return result;
+  JS('', '#.set(#, #)', map, t2, validSubtype);
+  return validSubtype;
 }
 
-final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
-
 @notNull
-bool _isBottom(type) => JS('!', '# == # || # == #', type, bottom, type, Null);
+bool _isBottom(type, @notNull bool strictMode) =>
+    _equalType(type, Never) || (!strictMode && _equalType(type, Null));
 
 @notNull
 bool _isTop(type) {
-  return JS('!', '# == # || # == # || # == #', type, Object, type, dynamic,
-      type, void_);
+  if (_jsInstanceOf(type, NullableType))
+    return JS('!', '#.type === #', type, Object);
+
+  return _equalType(type, dynamic) || JS('!', '# === #', type, void_);
+}
+
+/// Wraps the JavaScript `instanceof` operator returning  `true` if [type] is an
+/// instance of [cls].
+///
+/// This method is equivalent to:
+///
+///    JS<bool>('!', '# instanceof #', type, cls);
+///
+/// but the code is generated by the compiler directly (a low-tech way of
+/// inlining).
+@notNull
+external bool _jsInstanceOf(type, cls);
+
+/// Returns `true` if [type] is [cls].
+///
+/// This method is equivalent to:
+///
+///    JS<bool>('!', '# === #', type, unwrapType(cls));
+///
+/// but the code is generated by the compiler directly (a low-tech way of
+/// inlining).
+@notNull
+external bool _equalType(type, cls);
+
+/// Extracts the type argument as an unwrapped type preserving all forms of
+/// nullability.
+///
+/// Acts as a way to bypass extra calls of [wrapType] and [unwrapType]. For
+/// example `typeRep<Object?>()` emits `dart.nullable(core.Object)` directly.
+@notNull
+external Type typeRep<T>();
+
+/// Extracts the type argument as an unwrapped type and performs a shallow
+/// replacement of the nullability to a legacy type.
+///
+/// Acts as a way to bypass extra calls of [wrapType] and [unwrapType]. For
+/// example `legacyTypeRep<Object>()` emits `dart.legacy(core.Object)` directly.
+@notNull
+external Type legacyTypeRep<T>();
+
+@notNull
+bool _isFutureOr(type) {
+  var genericClass = getGenericClass(type);
+  return JS<bool>('!', '# && # === #', genericClass, genericClass,
+      getGenericClass(FutureOr));
 }
 
 @notNull
-bool _isFutureOr(type) =>
-    identical(getGenericClass(type), getGenericClass(FutureOr));
-
-bool _isSubtype(t1, t2) => JS('', '''(() => {
+bool _isSubtype(t1, t2, bool strictMode) => JS<bool>('!', '''(() => {
+  if (!$strictMode) {
+    // Strip nullable types when performing check in weak mode.
+    // TODO(nshahan) Investigate stripping off legacy types as well.
+    if (${_jsInstanceOf(t1, NullableType)}) {
+      t1 = t1.type;
+    }
+    if (${_jsInstanceOf(t2, NullableType)}) {
+      t2 = t2.type;
+    }
+  }
   if ($t1 === $t2) {
     return true;
   }
 
-  // Trivially true.
-  if (${_isTop(t2)} || ${_isBottom(t1)}) {
+  // Trivially true, "Right Top" or "Left Bottom".
+  if (${_isTop(t2)} || ${_isBottom(t1, strictMode)}) {
     return true;
   }
 
-  // Trivially false.
-  if (${_isTop(t1)} || ${_isBottom(t2)}) {
-    return false;
+  // "Left Top".
+  if (${_equalType(t1, dynamic)} || $t1 === $void_) {
+    return $_isSubtype($nullable($Object), $t2, $strictMode);
+  }
+
+  // "Right Object".
+  if (${_equalType(t2, Object)}) {
+    // TODO(nshahan) Need to handle type variables.
+    // https://github.com/dart-lang/sdk/issues/38816
+    if (${_isFutureOr(t1)}) {
+      let t1TypeArg = ${getGenericArgs(t1)}[0];
+      return $_isSubtype(t1TypeArg, $Object, $strictMode);
+    }
+
+    if (${_jsInstanceOf(t1, LegacyType)}) {
+      return $_isSubtype(t1.type, t2, $strictMode);
+    }
+
+    if (${_equalType(t1, Null)} || ${_jsInstanceOf(t1, NullableType)}) {
+      // Checks for t1 is dynamic or void already performed in "Left Top" test.
+      return false;
+    }
+    return true;
+  }
+
+  // "Left Null".
+  if (${_equalType(t1, Null)}) {
+    // TODO(nshahan) Need to handle type variables.
+    // https://github.com/dart-lang/sdk/issues/38816
+    if (${_isFutureOr(t2)}) {
+      let t2TypeArg = ${getGenericArgs(t2)}[0];
+      return $_isSubtype($Null, t2TypeArg, $strictMode);
+    }
+
+    return ${_equalType(t2, Null)} || ${_jsInstanceOf(t2, LegacyType)} ||
+        ${_jsInstanceOf(t2, NullableType)};
+  }
+
+  // "Left Legacy".
+  if (${_jsInstanceOf(t1, LegacyType)}) {
+    return $_isSubtype(t1.type, t2, $strictMode);
+  }
+
+  // "Right Legacy".
+  if (${_jsInstanceOf(t2, LegacyType)}) {
+    return $_isSubtype(t1, $nullable(t2.type), $strictMode);
   }
 
   // Handle FutureOr<T> union type.
@@ -867,14 +1364,22 @@
       // FutureOr<A> <: FutureOr<B> iff A <: B
       // TODO(nshahan): Proven to not actually be true and needs cleanup.
       // https://github.com/dart-lang/sdk/issues/38818
-      return $_isSubtype(t1TypeArg, t2TypeArg);
+      return $_isSubtype(t1TypeArg, t2TypeArg, $strictMode);
     }
 
     // given t1 is Future<A> | A, then:
     // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
     let t1Future = ${getGenericClass(Future)}(t1TypeArg);
     // Known to handle the case FutureOr<Null> <: Future<Null>.
-    return $_isSubtype(t1Future, $t2) && $_isSubtype(t1TypeArg, $t2);
+    return $_isSubtype(t1Future, $t2, $strictMode) &&
+        $_isSubtype(t1TypeArg, $t2, $strictMode);
+  }
+
+  // "Left Nullable".
+  if (${_jsInstanceOf(t1, NullableType)}) {
+    // TODO(nshahan) Need to handle type variables.
+    // https://github.com/dart-lang/sdk/issues/38816
+    return $_isSubtype(t1.type, t2, $strictMode) && $_isSubtype($Null, t2, $strictMode);
   }
 
   if ($_isFutureOr($t2)) {
@@ -882,38 +1387,47 @@
     // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
     let t2TypeArg = ${getGenericArgs(t2)}[0];
     let t2Future = ${getGenericClass(Future)}(t2TypeArg);
-    return $_isSubtype($t1, t2Future) || $_isSubtype($t1, t2TypeArg);
+    // TODO(nshahan) Need to handle type variables on the left.
+    // https://github.com/dart-lang/sdk/issues/38816
+    return $_isSubtype($t1, t2Future, $strictMode) || $_isSubtype($t1, t2TypeArg, $strictMode);
+  }
+
+  // "Right Nullable".
+  if (${_jsInstanceOf(t2, NullableType)}) {
+    // TODO(nshahan) Need to handle type variables.
+    // https://github.com/dart-lang/sdk/issues/38816
+    return $_isSubtype(t1, t2.type, $strictMode) || $_isSubtype(t1, $Null, $strictMode);
   }
 
   // "Traditional" name-based subtype check.  Avoid passing
   // function types to the class subtype checks, since we don't
   // currently distinguish between generic typedefs and classes.
-  if (!($t2 instanceof $AbstractFunctionType)) {
+  if (!${_jsInstanceOf(t2, AbstractFunctionType)}) {
     // t2 is an interface type.
 
-    if ($t1 instanceof $AbstractFunctionType) {
+    if (${_jsInstanceOf(t1, AbstractFunctionType)}) {
       // Function types are only subtypes of interface types `Function` (and top
       // types, handled already above).
-      return $t2 === $Function;
+      return ${_equalType(t2, Function)};
     }
 
     // All JS types are subtypes of anonymous JS types.
-    if ($t1 === $jsobject && $t2 instanceof $AnonymousJSType) {
+    if ($t1 === $jsobject && ${_jsInstanceOf(t2, AnonymousJSType)}) {
       return true;
     }
 
     // Compare two interface types.
-    return ${_isInterfaceSubtype(t1, t2)};
+    return ${_isInterfaceSubtype(t1, t2, strictMode)};
   }
 
   // Function subtyping.
-  if (!($t1 instanceof $AbstractFunctionType)) {
+  if (!${_jsInstanceOf(t1, AbstractFunctionType)}) {
     return false;
   }
 
   // Handle generic functions.
-  if ($t1 instanceof $GenericFunctionType) {
-    if (!($t2 instanceof $GenericFunctionType)) {
+  if (${_jsInstanceOf(t1, GenericFunctionType)}) {
+    if (!${_jsInstanceOf(t2, GenericFunctionType)}) {
       return false;
     }
 
@@ -947,8 +1461,8 @@
       let t2Bounds = $t2.instantiateTypeBounds(fresh);
       for (let i = 0; i < formalCount; i++) {
         if (t1Bounds[i] != t2Bounds[i]) {
-          if (!($_isSubtype(t1Bounds[i], t2Bounds[i])
-              && $_isSubtype(t2Bounds[i], t1Bounds[i]))) {
+          if (!($_isSubtype(t1Bounds[i], t2Bounds[i], $strictMode)
+              && $_isSubtype(t2Bounds[i], t1Bounds[i], $strictMode))) {
             return false;
           }
         }
@@ -957,35 +1471,35 @@
 
     $t1 = $t1.instantiate(fresh);
     $t2 = $t2.instantiate(fresh);
-  } else if ($t2 instanceof $GenericFunctionType) {
+  } else if (${_jsInstanceOf(t2, GenericFunctionType)}) {
     return false;
   }
 
   // Handle non-generic functions.
-  return ${_isFunctionSubtype(t1, t2)};
+  return ${_isFunctionSubtype(t1, t2, strictMode)};
 })()''');
 
-bool _isInterfaceSubtype(t1, t2) => JS('', '''(() => {
+bool _isInterfaceSubtype(t1, t2, strictMode) => JS('', '''(() => {
   // If we have lazy JS types, unwrap them.  This will effectively
   // reduce to a prototype check below.
-  if ($t1 instanceof $LazyJSType) $t1 = $t1.rawJSTypeForCheck();
-  if ($t2 instanceof $LazyJSType) $t2 = $t2.rawJSTypeForCheck();
+  if (${_jsInstanceOf(t1, LazyJSType)}) $t1 = $t1.rawJSTypeForCheck();
+  if (${_jsInstanceOf(t2, LazyJSType)}) $t2 = $t2.rawJSTypeForCheck();
 
   if ($t1 === $t2) {
     return true;
   }
-  if ($t1 === $Object) {
+  if (${_equalType(t1, Object)}) {
     return false;
   }
 
   // Classes cannot subtype `Function` or vice versa.
-  if ($t1 === $Function || $t2 === $Function) {
+  if (${_equalType(t1, Function)} || ${_equalType(t2, Function)}) {
     return false;
   }
 
   // If t1 is a JS Object, we may not hit core.Object.
   if ($t1 == null) {
-    return $t2 == $Object || $t2 == $dynamic;
+    return ${_equalType(t2, Object)} || ${_equalType(t2, dynamic)};
   }
 
   // Check if t1 and t2 have the same raw type.  If so, check covariance on
@@ -1003,16 +1517,16 @@
       // When using implicit variance, variances will be undefined and
       // considered covariant.
       if (variances === void 0 || variances[i] == ${Variance.covariant}) {
-        if (!$_isSubtype(typeArguments1[i], typeArguments2[i])) {
+        if (!$_isSubtype(typeArguments1[i], typeArguments2[i], $strictMode)) {
           return false;
         }
       } else if (variances[i] == ${Variance.contravariant}) {
-        if (!$_isSubtype(typeArguments2[i], typeArguments1[i])) {
+        if (!$_isSubtype(typeArguments2[i], typeArguments1[i], $strictMode)) {
           return false;
         }
       } else if (variances[i] == ${Variance.invariant}) {
-        if (!$_isSubtype(typeArguments1[i], typeArguments2[i]) ||
-            !$_isSubtype(typeArguments2[i], typeArguments1[i])) {
+        if (!$_isSubtype(typeArguments1[i], typeArguments2[i], $strictMode) ||
+            !$_isSubtype(typeArguments2[i], typeArguments1[i], $strictMode)) {
           return false;
         }
       }
@@ -1020,13 +1534,13 @@
     return true;
   }
 
-  if ($_isInterfaceSubtype(t1.__proto__, $t2)) {
+  if ($_isInterfaceSubtype(t1.__proto__, $t2, $strictMode)) {
     return true;
   }
 
   // Check mixin.
   let m1 = $getMixin($t1);
-  if (m1 != null && $_isInterfaceSubtype(m1, $t2)) {
+  if (m1 != null && $_isInterfaceSubtype(m1, $t2, $strictMode)) {
     return true;
   }
 
@@ -1034,7 +1548,7 @@
   let getInterfaces = $getImplements($t1);
   if (getInterfaces) {
     for (let i1 of getInterfaces()) {
-      if ($_isInterfaceSubtype(i1, $t2)) {
+      if ($_isInterfaceSubtype(i1, $t2, $strictMode)) {
         return true;
       }
     }
@@ -1047,6 +1561,9 @@
     throw ArgumentError('Cannot extract type of null instance.');
   }
   var type = unwrapType(T);
+  // Get underlying type from nullability wrappers if needed.
+  type = JS<Object>('!', '#.type || #', type, type);
+
   if (type is AbstractFunctionType || _isFutureOr(type)) {
     throw ArgumentError('Cannot extract from non-class type ($type).');
   }
@@ -1076,7 +1593,7 @@
 
   /// Returns the inferred types based on the current constraints.
   List<Object> getInferredTypes() {
-    var result = List<Object>();
+    var result = <Object>[];
     for (var constraint in _typeVariables.values) {
       // Prefer the known bound, if any.
       if (constraint.lower != null) {
@@ -1144,8 +1661,28 @@
         return false;
       }
     }
+
+    // Named parameter invariants:
+    // 1) All named params in the superclass are named params in the subclass.
+    // 2) All required named params in the subclass are required named params
+    //    in the superclass.
+    // 3) With strict null checking disabled, we treat required named params as
+    //    optional named params.
     var supertypeNamed = supertype.getNamedParameters();
+    var supertypeRequiredNamed = supertype.getRequiredNamedParameters();
     var subtypeNamed = supertype.getNamedParameters();
+    var subtypeRequiredNamed = supertype.getRequiredNamedParameters();
+    if (!_strictSubtypeChecks) {
+      // In weak mode, treat required named params as optional named params.
+      supertypeNamed = {...supertypeNamed, ...supertypeRequiredNamed};
+      subtypeNamed = {...subtypeNamed, ...subtypeRequiredNamed};
+      supertypeRequiredNamed = {};
+      subtypeRequiredNamed = {};
+    }
+    for (var name in subtypeRequiredNamed.keys) {
+      var supertypeParamType = supertypeRequiredNamed[name];
+      if (supertypeParamType == null) return false;
+    }
     for (var name in supertypeNamed.keys) {
       var subtypeParamType = subtypeNamed[name];
       if (subtypeParamType == null) return false;
@@ -1153,6 +1690,12 @@
         return false;
       }
     }
+    for (var name in supertypeRequiredNamed.keys) {
+      var subtypeParamType = subtypeRequiredNamed[name] ?? subtypeNamed[name];
+      if (!_isSubtypeMatch(supertypeRequiredNamed[name], subtypeParamType)) {
+        return false;
+      }
+    }
     return true;
   }
 
@@ -1190,8 +1733,6 @@
     return true;
   }
 
-  bool _isNull(Object type) => identical(type, unwrapType(Null));
-
   /// Attempts to match [subtype] as a subtype of [supertype], gathering any
   /// constraints discovered in the process.
   ///
@@ -1201,6 +1742,7 @@
   /// In the case where `false` is returned, some bogus constraints may have
   /// been added to [_protoConstraints].  It is the caller's responsibility to
   /// discard them if necessary.
+  // TODO(#40326) Update to support null safety subtyping algorithm.
   bool _isSubtypeMatch(Object subtype, Object supertype) {
     // A type variable `T` in `L` is a subtype match for any type schema `Q`:
     // - Under constraint `T <: Q`.
@@ -1224,7 +1766,7 @@
     if (_isTop(supertype)) return true;
     // `Null` is a subtype match for any type `Q` under no constraints.
     // Note that nullable types will change this.
-    if (_isNull(subtype)) return true;
+    if (_equalType(subtype, Null)) return true;
 
     // Handle FutureOr<T> union type.
     if (_isFutureOr(subtype)) {
@@ -1244,7 +1786,8 @@
       //   constraints `C0`.
       // - And `P` is a subtype match for `Q` with respect to `L` under
       //   constraints `C1`.
-      var subtypeFuture = JS('!', '#(#)', getGenericClass(Future), subtypeArg);
+      var subtypeFuture =
+          JS<Object>('!', '#(#)', getGenericClass(Future), subtypeArg);
       return _isSubtypeMatch(subtypeFuture, supertype) &&
           _isSubtypeMatch(subtypeArg, supertype);
     }
@@ -1260,7 +1803,7 @@
       //     constraints `C`
       var supertypeArg = getGenericArgs(supertype)[0];
       var supertypeFuture =
-          JS('!', '#(#)', getGenericClass(Future), supertypeArg);
+          JS<Object>('!', '#(#)', getGenericClass(Future), supertypeArg);
       return _isSubtypeMatch(subtype, supertypeFuture) ||
           _isSubtypeMatch(subtype, supertypeArg);
     }
@@ -1330,8 +1873,7 @@
     // TODO(paulberry): implement this case.
     if (subtype is FunctionType) {
       if (supertype is! FunctionType) {
-        if (identical(supertype, unwrapType(Function)) ||
-            identical(supertype, unwrapType(Object))) {
+        if (_equalType(supertype, Function) || _equalType(supertype, Object)) {
           return true;
         } else {
           return false;
@@ -1347,7 +1889,7 @@
   bool _isTop(Object type) =>
       identical(type, _dynamic) ||
       identical(type, void_) ||
-      identical(type, unwrapType(Object));
+      _equalType(type, Object);
 }
 
 /// A constraint on a type parameter that we're inferring.
@@ -1361,12 +1903,13 @@
   Object upper;
 
   void _constrainLower(Object type) {
-    if (lower != null) {
-      if (isSubtypeOf(lower, type)) {
+    var _lower = lower;
+    if (_lower != null) {
+      if (isSubtypeOf(_lower, type)) {
         // nothing to do, existing lower bound is lower than the new one.
         return;
       }
-      if (!isSubtypeOf(type, lower)) {
+      if (!isSubtypeOf(type, _lower)) {
         // Neither bound is lower and we don't have GLB, so use bottom type.
         type = unwrapType(Null);
       }
@@ -1375,12 +1918,13 @@
   }
 
   void _constrainUpper(Object type) {
-    if (upper != null) {
-      if (isSubtypeOf(type, upper)) {
+    var _upper = upper;
+    if (_upper != null) {
+      if (isSubtypeOf(type, _upper)) {
         // nothing to do, existing upper bound is higher than the new one.
         return;
       }
-      if (!isSubtypeOf(upper, type)) {
+      if (!isSubtypeOf(_upper, type)) {
         // Neither bound is higher and we don't have LUB, so use top type.
         type = unwrapType(Object);
       }
@@ -1395,7 +1939,7 @@
 /// contain different generic type arguments.
 Object _getMatchingSupertype(Object subtype, Object supertype) {
   if (identical(subtype, supertype)) return supertype;
-  if (subtype == null || subtype == unwrapType(Object)) return null;
+  if (subtype == null || _equalType(subtype, Object)) return null;
 
   var subclass = getGenericClass(subtype);
   var superclass = getGenericClass(supertype);
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
index 5d5a251..d202ff0 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
@@ -25,13 +25,13 @@
     bool configurable,
     bool writable}) defineAccessor = JS('', 'Object.defineProperty');
 
-final Function(Object, Object) getOwnPropertyDescriptor =
+final dynamic Function(Object, Object) getOwnPropertyDescriptor =
     JS('', 'Object.getOwnPropertyDescriptor');
 
-final Iterable Function(Object) getOwnPropertyNames =
+final List Function(Object) getOwnPropertyNames =
     JS('', 'Object.getOwnPropertyNames');
 
-final Function(Object) getOwnPropertySymbols =
+final List Function(Object) getOwnPropertySymbols =
     JS('', 'Object.getOwnPropertySymbols');
 
 final Function(Object) getPrototypeOf = JS('', 'Object.getPrototypeOf');
@@ -62,49 +62,6 @@
     return JS<Object>('', '#[#]', obj, name);
 }
 
-/// Defines a lazy static field.
-/// After initial get or set, it will replace itself with a value property.
-// TODO(jmesserly): reusing descriptor objects has been shown to improve
-// performance in other projects (e.g. webcomponents.js ShadowDOM polyfill).
-defineLazyField(to, name, desc) => JS('', '''(() => {
-  const initializer = $desc.get;
-  let init = initializer;
-  let value = null;
-  $desc.get = function() {
-    if (init == null) return value;
-    let f = init;
-    init = $throwCyclicInitializationError;
-    if (f === init) f($name); // throw cycle error
-
-    // On the first (non-cyclic) execution, record the field so we can reset it
-    // later if needed (hot restart).
-    $_resetFields.push(() => {
-      init = initializer;
-      value = null;
-    });
-
-    // Try to evaluate the field, using try+catch to ensure we implement the
-    // correct Dart error semantics.
-    try {
-      value = f();
-      init = null;
-      return value;
-    } catch (e) {
-      init = null;
-      value = null;
-      throw e;
-    }
-  };
-  $desc.configurable = true;
-  if ($desc.set != null) {
-    $desc.set = function(x) {
-      init = null;
-      value = x;
-    };
-  }
-  return ${defineProperty(to, name, desc)};
-})()''');
-
 copyTheseProperties(to, from, names) {
   for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
     var name = JS('', '#[#]', names, i);
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 2148886..20f023e 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -423,8 +423,11 @@
         ? new JSArray<E>.growable(length)
         : new JSArray<E>.fixed(length);
     if (length != 0 && fill != null) {
+      // TODO(sra): Consider using `Array.fill`.
       for (int i = 0; i < result.length; i++) {
-        result[i] = fill;
+        // Unchecked assignment equivalent to `result[i] = fill`;
+        // `fill` is checked statically at call site.
+        JS('', '#[#] = #', result, i, fill);
       }
     }
     return result;
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index e50d821..88b0b38 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -2156,9 +2156,9 @@
   void set multicastHops(int value) =>
       _socket.setOption(SocketOption._ipMulticastHops, value);
 
-  NetworkInterface get multicastInterface => throw "Not implemented";
+  NetworkInterface get multicastInterface => throw UnimplementedError();
   void set multicastInterface(NetworkInterface value) =>
-      throw "Not implemented";
+      throw UnimplementedError();
 
   bool get broadcastEnabled => _socket.getOption(SocketOption._ipBroadcast);
   void set broadcastEnabled(bool value) =>
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 7d62432..3c111f4 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -47,7 +47,7 @@
   }
 
   @pragma("vm:entry-point")
-  void start(f) {
+  void start(void Function() f) {
     f();
     isSync = true;
   }
@@ -58,8 +58,8 @@
 
 // We need to pass the value as first argument and leave the second and third
 // arguments empty (used for error handling).
-// See vm/ast_transformer.cc for usage.
-Function _asyncThenWrapperHelper(continuation) {
+dynamic Function(dynamic) _asyncThenWrapperHelper(
+    dynamic Function(dynamic) continuation) {
   // Any function that is used as an asynchronous callback must be registered
   // in the current Zone. Normally, this is done by the future when a
   // callback is registered (for example with `.then` or `.catchError`). In our
@@ -76,16 +76,18 @@
   // `Future` implementation could potentially invoke the callback with the
   // wrong number of arguments.
   if (Zone.current == Zone.root) return continuation;
-  return Zone.current.registerUnaryCallback(continuation);
+  return Zone.current.registerUnaryCallback<dynamic, dynamic>(continuation);
 }
 
 // We need to pass the exception and stack trace objects as second and third
-// parameter to the continuation.  See vm/ast_transformer.cc for usage.
-Function _asyncErrorWrapperHelper(continuation) {
+// parameter to the continuation.
+dynamic Function(Object, StackTrace) _asyncErrorWrapperHelper(
+    dynamic Function(dynamic, dynamic, StackTrace) continuation) {
   // See comments of `_asyncThenWrapperHelper`.
-  void errorCallback(Object e, StackTrace s) => continuation(null, e, s);
+  dynamic errorCallback(Object e, StackTrace s) => continuation(null, e, s);
   if (Zone.current == Zone.root) return errorCallback;
-  return Zone.current.registerBinaryCallback(errorCallback);
+  return Zone.current
+      .registerBinaryCallback<dynamic, Object, StackTrace>(errorCallback);
 }
 
 /// Registers the [thenCallback] and [errorCallback] on the given [object].
@@ -93,11 +95,14 @@
 /// If [object] is not a future, then it is wrapped into one.
 ///
 /// Returns the result of registering with `.then`.
-Future _awaitHelper(
-    var object, Function thenCallback, Function errorCallback, var awaiter) {
+Future _awaitHelper(var object, dynamic Function(dynamic) thenCallback,
+    dynamic Function(dynamic, StackTrace) errorCallback, Function awaiter) {
+  _Future future;
   if (object is! Future) {
-    object = new _Future().._setValue(object);
-  } else if (object is! _Future) {
+    future = new _Future().._setValue(object);
+  } else if (object is _Future) {
+    future = object;
+  } else {
     return object.then(thenCallback, onError: errorCallback);
   }
   // `object` is a `_Future`.
@@ -108,8 +113,8 @@
   //
   // We can only do this for our internal futures (the default implementation of
   // all futures that are constructed by the `dart:async` library).
-  object._awaiter = awaiter;
-  return object._thenAwait(thenCallback, errorCallback);
+  future._awaiter = awaiter;
+  return future._thenAwait<dynamic>(thenCallback, errorCallback);
 }
 
 // Called as part of the 'await for (...)' construct. Registers the
diff --git a/sdk/lib/_internal/vm/lib/errors_patch.dart b/sdk/lib/_internal/vm/lib/errors_patch.dart
index c29f052..ee0d608 100644
--- a/sdk/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/errors_patch.dart
@@ -598,6 +598,7 @@
 
 class _LateInitializationError extends Error
     implements LateInitializationError {
+  @pragma("vm:entry-point")
   _LateInitializationError(this._name);
 
   @pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/symbol_patch.dart b/sdk/lib/_internal/vm/lib/symbol_patch.dart
index 3671bf7..338b339 100644
--- a/sdk/lib/_internal/vm/lib/symbol_patch.dart
+++ b/sdk/lib/_internal/vm/lib/symbol_patch.dart
@@ -12,7 +12,7 @@
   const Symbol(String name) : this._name = name;
 
   @patch
-  toString() => 'Symbol("${computeUnmangledName(this)}")';
+  String toString() => 'Symbol("${computeUnmangledName(this)}")';
 
   @patch
   static String computeUnmangledName(Symbol symbol) {
diff --git a/sdk/lib/convert/base64.dart b/sdk/lib/convert/base64.dart
index 505ab42..2a8d462 100644
--- a/sdk/lib/convert/base64.dart
+++ b/sdk/lib/convert/base64.dart
@@ -641,10 +641,11 @@
     // all the characters in `charOr` and later validate that all characters
     // were ASCII.
     var charOr = 0;
+    final inverseAlphabet = _Base64Decoder._inverseAlphabet;
     for (var i = start; i < end; i++) {
       var char = input.codeUnitAt(i);
       charOr |= char;
-      var code = _inverseAlphabet[char & asciiMask];
+      var code = inverseAlphabet[char & asciiMask];
       if (code >= 0) {
         bits = ((bits << bitsPerCharacter) | code) & 0xFFFFFF;
         count = (count + 1) & 3;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 3f8332f..73f1e6e 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -11778,6 +11778,10 @@
     }
   }
 
+  void insertAll(int index, Iterable<Element> iterable) {
+    throw new UnimplementedError();
+  }
+
   void setAll(int index, Iterable<Element> iterable) {
     throw new UnimplementedError();
   }
@@ -11796,9 +11800,7 @@
 
   Element removeLast() {
     final result = this.last;
-    if (result != null) {
-      _element._removeChild(result);
-    }
+    _element._removeChild(result);
     return result;
   }
 
@@ -15381,7 +15383,7 @@
 
 // WARNING: Do not edit - generated code.
 
-@Native("Event,InputEvent")
+@Native("Event,InputEvent,SubmitEvent")
 class Event extends Interceptor {
   // In JS, canBubble and cancelable are technically required parameters to
   // init*Event. In practice, though, if they aren't provided they simply
@@ -36052,7 +36054,8 @@
    * after the operation, and returns `false` if [value] is absent after the
    * operation.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To toggle multiple classes, use
@@ -36086,7 +36089,8 @@
    * If this CssClassSet corresponds to one element. Returns true if [value] was
    * added to the set, otherwise false.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To add multiple classes use
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index 486fa31..814829b 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.dart
@@ -110,7 +110,7 @@
     _validateToken(value);
     // TODO - figure out if we need to do any validation here
     // or if the browser natively does enough.
-    return modify((s) => s.add(value));
+    return modify((s) => s.add(value)) ?? false;
   }
 
   /**
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index e6b5547..dd45dbd 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -52,7 +52,7 @@
   * operating system.
   */
 @pragma("vm:entry-point")
-class OSError {
+class OSError implements Exception {
   /** Constant used to indicate that no OS error code is available. */
   static const int noErrorCode = -1;
 
diff --git a/sdk/lib/js_util/js_util.dart b/sdk/lib/js_util/js_util.dart
index 9f2f4cb..a299a30 100644
--- a/sdk/lib/js_util/js_util.dart
+++ b/sdk/lib/js_util/js_util.dart
@@ -76,9 +76,13 @@
 callMethod(o, String method, List args) =>
     JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
 
-bool instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
+/// Check whether [o] is an instance of [type].
+///
+/// The value in [type] is expected to be a JS-interop object that
+/// represents a valid JavaScript constructor function.
+bool instanceof(o, Object type) => JS('bool', '# instanceof #', o, type);
 
-callConstructor(Function constr, List arguments) {
+callConstructor(Object constr, List arguments) {
   if (arguments == null) {
     return JS('Object', 'new #()', constr);
   }
diff --git a/sdk_nnbd/lib/_http/embedder_config.dart b/sdk_nnbd/lib/_http/embedder_config.dart
new file mode 100644
index 0000000..730bc2dd
--- /dev/null
+++ b/sdk_nnbd/lib/_http/embedder_config.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.
+
+part of dart._http;
+
+/// Embedder-specific `dart:_http` configuration.
+
+/// [HttpClient] will disallow HTTP URLs if this value is set to `false`.
+@pragma("vm:entry-point")
+bool _embedderAllowsHttp = true;
diff --git a/sdk_nnbd/lib/_http/http.dart b/sdk_nnbd/lib/_http/http.dart
index 551ab65..e00ae5e 100644
--- a/sdk_nnbd/lib/_http/http.dart
+++ b/sdk_nnbd/lib/_http/http.dart
@@ -23,6 +23,7 @@
 import 'dart:typed_data';
 
 part 'crypto.dart';
+part 'embedder_config.dart';
 part 'http_date.dart';
 part 'http_headers.dart';
 part 'http_impl.dart';
@@ -142,8 +143,7 @@
    *
    * The default value is `null`.
    */
-  String? get serverHeader;
-  void set serverHeader(String? newServerHeader);
+  String? serverHeader;
 
   /**
    * Default set of headers added to all response objects.
@@ -170,8 +170,7 @@
    * The default value is `false` (compression disabled).
    * To enable, set `autoCompress` to `true`.
    */
-  bool get autoCompress;
-  void set autoCompress(bool newAutoCompress);
+  bool autoCompress = false;
 
   /**
    * Gets or sets the timeout used for idle keep-alive connections. If no
@@ -185,8 +184,7 @@
    *
    * To disable, set [idleTimeout] to `null`.
    */
-  Duration? get idleTimeout;
-  void set idleTimeout(Duration? newIdleTimeout);
+  Duration? idleTimeout = const Duration(seconds: 120);
 
   /**
    * Starts listening for HTTP requests on the specified [address] and
@@ -646,22 +644,19 @@
    *
    * The value is negative if there is no content length set.
    */
-  int get contentLength;
-  void set contentLength(int contentLength);
+  int contentLength = -1;
 
   /**
    * Whether the connection is persistent (keep-alive).
    */
-  bool get persistentConnection;
-  void set persistentConnection(bool persistentConnection);
+  late bool persistentConnection;
 
   /**
    * Whether the connection uses chunked transfer encoding.
    *
    * Reflects and modifies the value of the [transferEncodingHeader] header.
    */
-  bool get chunkedTransferEncoding;
-  void set chunkedTransferEncoding(bool chunkedTransferEncoding);
+  late bool chunkedTransferEncoding;
 
   /**
    * The values for the header named [name].
@@ -997,8 +992,7 @@
    * `(`, `)`, `<`, `>`, `@`, `,`, `;`, `:`, `\`, `"`, `/`, `[`, `]`, `?`, `=`,
    * `{`, and `}`.
    */
-  String get name;
-  void set name(String newName);
+  late String name;
 
   /**
    * The value of the cookie.
@@ -1011,46 +1005,39 @@
    * Cookie values may be wrapped in a single pair of double quotes
    * (U+0022, `"`).
    */
-  String get value;
-  void set value(String newValue);
+  late String value;
 
   /**
    * The time at which the cookie expires.
    */
-  DateTime? get expires;
-  void set expires(DateTime? newExpires);
+  DateTime? expires;
 
   /**
    * The number of seconds until the cookie expires. A zero or negative value
    * means the cookie has expired.
    */
-  int? get maxAge;
-  void set maxAge(int? newMaxAge);
+  int? maxAge;
 
   /**
    * The domain that the cookie applies to.
    */
-  String? get domain;
-  void set domain(String? newDomain);
+  String? domain;
 
   /**
    * The path within the [domain] that the cookie applies to.
    */
-  String? get path;
-  void set path(String? newPath);
+  String? path;
 
   /**
    * Whether to only send this cookie on secure connections.
    */
-  bool get secure;
-  void set secure(bool newSecure);
+  bool secure = false;
 
   /**
    * Whether the cookie is only sent in the HTTP request and is not made
    * available to client side scripts.
    */
-  bool get httpOnly;
-  void set httpOnly(bool newHttpOnly);
+  bool httpOnly = false;
 
   /**
    * Creates a new cookie setting the name and value.
@@ -1279,8 +1266,7 @@
    * the response is not known in advance set the content length to
    * -1, which is also the default if not set.
    */
-  int get contentLength;
-  void set contentLength(int contentLength);
+  int contentLength = -1;
 
   /**
    * The status code of the response.
@@ -1294,8 +1280,7 @@
    * to. Setting the status code after writing to the response body or
    * closing the response will throw a `StateError`.
    */
-  int get statusCode;
-  void set statusCode(int statusCode);
+  int statusCode = HttpStatus.ok;
 
   /**
    * The reason phrase for the response.
@@ -1306,16 +1291,14 @@
    * to. Setting the reason phrase after writing to the response body
    * or closing the response will throw a [StateError].
    */
-  String get reasonPhrase;
-  void set reasonPhrase(String reasonPhrase);
+  late String reasonPhrase;
 
   /**
    * Gets and sets the persistent connection state. The initial value
    * of this property is the persistent connection state from the
    * request.
    */
-  bool get persistentConnection;
-  void set persistentConnection(bool persistentConnection);
+  late bool persistentConnection;
 
   /**
    * Set and get the [deadline] for the response. The deadline is timed from the
@@ -1337,8 +1320,7 @@
    * __Note__: Disabling buffering of the output can result in very poor
    * performance, when writing many small chunks.
    */
-  bool get bufferOutput;
-  void set bufferOutput(bool bufferOutput);
+  bool bufferOutput = true;
 
   /**
    * Returns the response headers.
@@ -1507,8 +1489,7 @@
   /// connections.
   ///
   /// The default value is 15 seconds.
-  Duration get idleTimeout;
-  void set idleTimeout(Duration newIdleTimeout);
+  Duration idleTimeout = const Duration(seconds: 15);
 
   /// Gets and sets the connection timeout.
   ///
@@ -1518,8 +1499,7 @@
   ///
   /// When this is `null`, the OS default timeout is used. The default is
   /// `null`.
-  Duration? get connectionTimeout;
-  void set connectionTimeout(Duration? newConnectionTimeout);
+  Duration? connectionTimeout;
 
   /**
    * Gets and sets the maximum number of live connections, to a single host.
@@ -1531,8 +1511,7 @@
    *
    * Default is `null`.
    */
-  int? get maxConnectionsPerHost;
-  void set maxConnectionsPerHost(int? newMaxConnectionsPerHost);
+  int? maxConnectionsPerHost;
 
   /**
    * Gets and sets whether the body of a response will be automatically
@@ -1560,8 +1539,7 @@
    *
    * Default is `true`.
    */
-  bool get autoUncompress;
-  void set autoUncompress(bool newAutoUncompress);
+  bool autoUncompress = true;
 
   /// Gets and sets the default value of the `User-Agent` header for all requests
   /// generated by this [HttpClient].
@@ -1570,8 +1548,7 @@
   ///
   /// If the userAgent is set to `null`, no default `User-Agent` header will be
   /// added to each request.
-  String? get userAgent;
-  void set userAgent(String? newUserAgent);
+  String? userAgent;
 
   factory HttpClient({SecurityContext? context}) {
     HttpOverrides? overrides = HttpOverrides.current;
@@ -1972,8 +1949,7 @@
    * request(s). However, any body send with the request will not be
    * part of the redirection request(s).
    */
-  bool get followRedirects;
-  void set followRedirects(bool followRedirects);
+  bool followRedirects = true;
 
   /**
    * Set this property to the maximum number of redirects to follow
@@ -1982,8 +1958,7 @@
    *
    * The default value is 5.
    */
-  int get maxRedirects;
-  void set maxRedirects(int maxRedirects);
+  int maxRedirects = 5;
 
   /**
    * The method of the request.
@@ -1999,8 +1974,7 @@
   ///
   /// If the size of the request is not known in advance set content length to
   /// -1, which is also the default.
-  int get contentLength;
-  void set contentLength(int contentLength);
+  int contentLength = -1;
 
   /**
    * Gets or sets if the [HttpClientRequest] should buffer output.
@@ -2010,8 +1984,7 @@
    * __Note__: Disabling buffering of the output can result in very poor
    * performance, when writing many small chunks.
    */
-  bool get bufferOutput;
-  void set bufferOutput(bool bufferOutput);
+  bool bufferOutput = true;
 
   /**
    * Returns the client request headers.
diff --git a/sdk_nnbd/lib/_http/http_impl.dart b/sdk_nnbd/lib/_http/http_impl.dart
index 2c50285..cc5e99a 100644
--- a/sdk_nnbd/lib/_http/http_impl.dart
+++ b/sdk_nnbd/lib/_http/http_impl.dart
@@ -1860,7 +1860,8 @@
       // Resume the parser now we have a handler.
       _subscription!.resume();
       return s;
-    }, onError: (e) {
+    });
+    Future<Socket?>.value(_streamFuture).catchError((e) {
       destroy();
     });
     return request;
@@ -2266,6 +2267,32 @@
     });
   }
 
+  /// Whether HTTP requests are currently allowed.
+  ///
+  /// If the [Zone] variable `#dart.library.io.allow_http` is set to a boolean,
+  /// it determines whether the HTTP protocol is allowed. If the zone variable
+  /// is set to any other non-null value, HTTP is not allowed.
+  /// Otherwise, if the `dart.library.io.allow_http` environment flag
+  /// is set to `false`, HTTP is not allowed.
+  /// Otherwise, [_embedderAllowsHttp] determines the result.
+  bool get _isHttpAllowed {
+    final zoneOverride = Zone.current[#dart.library.io.allow_http];
+    if (zoneOverride != null) return true == zoneOverride;
+    bool envOverride =
+        bool.fromEnvironment("dart.library.io.allow_http", defaultValue: true);
+    return envOverride && _embedderAllowsHttp;
+  }
+
+  bool _isLoopback(String host) {
+    if (host.isEmpty) return false;
+    if ("localhost" == host) return true;
+    try {
+      return InternetAddress(host).isLoopback;
+    } on ArgumentError {
+      return false;
+    }
+  }
+
   Future<_HttpClientRequest> _openUrl(String method, Uri uri) {
     if (_closing) {
       throw new StateError("Client is closed");
@@ -2286,7 +2313,12 @@
       }
     }
 
-    bool isSecure = (uri.scheme == "https");
+    bool isSecure = uri.isScheme("https");
+    if (!_isHttpAllowed && !isSecure && !_isLoopback(uri.host)) {
+      throw new StateError(
+          "Insecure HTTP is not allowed by the current platform: $uri");
+    }
+
     int port = uri.port;
     if (port == 0) {
       port =
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 20555fb..bee1a93 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -443,16 +443,17 @@
 }
 
 bool test(bool? obj) {
-  if (obj == null) _throwBooleanConversionError();
-  return obj!;
-}
-
-bool dtest(obj) {
-  if (obj is! bool) booleanConversionFailed(obj);
+  if (obj == null) throw BooleanConversionAssertionError();
   return obj;
 }
 
-void _throwBooleanConversionError() => throw BooleanConversionAssertionError();
+bool dtest(obj) {
+  // Only throw an AssertionError in weak mode for compatibility. Strong mode
+  // should throw a TypeError.
+  if (obj is! bool)
+    booleanConversionFailed(_strictSubtypeChecks ? obj : test(obj));
+  return obj;
+}
 
 void booleanConversionFailed(obj) {
   var actual = typeName(getReifiedType(obj));
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 6bd3820..8f4647c 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -1262,6 +1262,22 @@
 @notNull
 external bool _equalType(type, cls);
 
+/// Extracts the type argument as an unwrapped type preserving all forms of
+/// nullability.
+///
+/// Acts as a way to bypass extra calls of [wrapType] and [unwrapType]. For
+/// example `typeRep<Object?>()` emits `dart.nullable(core.Object)` directly.
+@notNull
+external Type typeRep<T>();
+
+/// Extracts the type argument as an unwrapped type and performs a shallow
+/// replacement of the nullability to a legacy type.
+///
+/// Acts as a way to bypass extra calls of [wrapType] and [unwrapType]. For
+/// example `legacyTypeRep<Object>()` emits `dart.legacy(core.Object)` directly.
+@notNull
+external Type legacyTypeRep<T>();
+
 @notNull
 bool _isFutureOr(type) {
   var genericClass = getGenericClass(type);
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
index 6218ba6..644dba1 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -190,7 +190,6 @@
     if (timerFrequency != 0) return;
     // Start with low-resolution. We overwrite the fields if we find better.
     timerFrequency = 1000;
-    timerTicks = dateNow;
     if (JS<bool>('!', 'typeof window == "undefined"')) return;
     var jsWindow = JS('var', 'window');
     if (jsWindow == null) return;
@@ -203,7 +202,7 @@
 
   /// 0 frequency indicates the default uninitialized state.
   static int timerFrequency = 0;
-  static late int Function() timerTicks;
+  static int Function() timerTicks = dateNow; // Low-resolution version.
 
   static bool get isD8 {
     return JS(
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart
index dfc4707..45c0f03 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart
@@ -578,8 +578,9 @@
 
   T get current {
     var nested = _nestedIterator;
-    var result = nested != null ? nested.current : _current;
-    return result as T;
+    if (nested == null) return _current as T;
+    // Don't merge this with above 'as T', the one above can be optimized.
+    return nested.current as T;
   }
 
   _runBody() {
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
index 10418cf..9d1a8d6 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
@@ -422,8 +422,11 @@
         ? new JSArray<E>.growable(length)
         : new JSArray<E>.fixed(length);
     if (length != 0 && fill != null) {
+      // TODO(sra): Consider using `Array.fill`.
       for (int i = 0; i < result.length; i++) {
-        result[i] = fill;
+        // Unchecked assignment equivalent to `result[i] = fill`;
+        // `fill` is checked statically at call site.
+        JS('', '#[#] = #', result, i, fill);
       }
     }
     return result;
@@ -483,8 +486,12 @@
   @patch
   factory String.fromCharCodes(Iterable<int> charCodes,
       [int start = 0, int? end]) {
-    if (charCodes is JSArray<int>) {
-      return _stringFromJSArray(charCodes as JSArray<int>, start, end);
+    if (charCodes is JSArray) {
+      // Type promotion doesn't work unless the check is `is JSArray<int>`,
+      // which is more expensive.
+      // TODO(41383): Optimize `is JSArray<int>` rather than do weird 'casts'.
+      JSArray array = JS('JSArray', '#', charCodes);
+      return _stringFromJSArray(array, start, end);
     }
     if (charCodes is NativeUint8List) {
       return _stringFromUint8List(charCodes, start, end);
@@ -497,12 +504,11 @@
     return Primitives.stringFromCharCode(charCode);
   }
 
-  static String _stringFromJSArray(
-      JSArray<int> list, int start, int? endOrNull) {
+  static String _stringFromJSArray(JSArray list, int start, int? endOrNull) {
     int len = list.length;
     int end = RangeError.checkValidRange(start, endOrNull, len);
     if (start > 0 || end < len) {
-      list = list.sublist(start, end) as JSArray<int>;
+      list = JS('JSArray', '#.slice(#, #)', list, start, end);
     }
     return Primitives.stringFromCharCodes(list);
   }
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart
index 808be98..fc97282 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart
@@ -184,7 +184,10 @@
 }
 
 // A JS String or Symbol.
-final JS_INTEROP_INTERCEPTOR_TAG = getIsolateAffinityTag(r'_$dart_js');
+dynamic _JS_INTEROP_INTERCEPTOR_TAG = null;
+get JS_INTEROP_INTERCEPTOR_TAG {
+  return _JS_INTEROP_INTERCEPTOR_TAG ??= getIsolateAffinityTag(r'_$dart_js');
+}
 
 lookupInterceptorByConstructor(constructor) {
   return constructor == null
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
index 0aaa85c..994ea2d 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
@@ -661,7 +661,6 @@
     if (timerFrequency != 0) return;
     // Start with low-resolution. We overwrite the fields if we find better.
     timerFrequency = 1000;
-    timerTicks = dateNow;
     if (JS('bool', 'typeof window == "undefined"')) return;
     var window = JS('var', 'window');
     if (window == null) return;
@@ -673,7 +672,7 @@
   }
 
   static int timerFrequency = 0;
-  static late int Function() timerTicks;
+  static int Function() timerTicks = dateNow; // Low-resolution version.
 
   static String? currentUri() {
     requiresPreamble();
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index 40c6a6f..cb06c90 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -35,6 +35,13 @@
 
 import 'dart:_recipe_syntax';
 
+// The top type `Object?` is used throughout this library even when values are
+// not nullable or have narrower types in order to avoid incurring type checks
+// before the type checking infrastructure has been set up.
+// We could use `dynamic`, but this would allow inadvertent implicit downcasts.
+// TODO(fishythefish, dart-lang/language#115): Replace `Object?` with a typedef
+// when possible.
+
 /// An Rti object represents both a type (e.g `Map<int, String>`) and a type
 /// environment (`Map<int, String>` binds `Map.K=int` and `Map.V=String`).
 ///
@@ -51,36 +58,36 @@
   /// JavaScript method for 'as' check. The method is called from generated code,
   /// e.g. `o as T` generates something like `rtiForT._as(o)`.
   @pragma('dart2js:noElision')
-  dynamic _as;
+  Object? _as;
 
   /// JavaScript method for 'is' test.  The method is called from generated
   /// code, e.g. `o is T` generates something like `rtiForT._is(o)`.
   @pragma('dart2js:noElision')
-  dynamic _is;
+  Object? _is;
 
-  static void _setAsCheckFunction(Rti rti, fn) {
+  static void _setAsCheckFunction(Rti rti, Object? fn) {
     rti._as = fn;
   }
 
-  static void _setIsTestFunction(Rti rti, fn) {
+  static void _setIsTestFunction(Rti rti, Object? fn) {
     rti._is = fn;
   }
 
   @pragma('dart2js:tryInline')
-  static bool _asCheck(Rti rti, object) {
+  static bool _asCheck(Rti rti, Object? object) {
     return JS(
         'bool', '#.#(#)', rti, JS_GET_NAME(JsGetName.RTI_FIELD_AS), object);
   }
 
   @pragma('dart2js:tryInline')
-  static bool _isCheck(Rti rti, object) {
+  static bool _isCheck(Rti rti, Object? object) {
     return JS(
         'bool', '#.#(#)', rti, JS_GET_NAME(JsGetName.RTI_FIELD_IS), object);
   }
 
   /// Method called from generated code to evaluate a type environment recipe in
   /// `this` type environment.
-  Rti _eval(recipe) {
+  Rti _eval(Object? recipe) {
     // TODO(sra): Clone the fast-path of _Universe.evalInEnvironment to here.
     return _rtiEval(this, _Utils.asString(recipe));
   }
@@ -88,12 +95,12 @@
   /// Method called from generated code to extend `this` type environment (an
   /// interface or binding Rti) with function type arguments (a singleton
   /// argument or tuple of arguments).
-  Rti _bind(typeOrTuple) => _rtiBind(this, _castToRti(typeOrTuple));
+  Rti _bind(Object? typeOrTuple) => _rtiBind(this, _Utils.asRti(typeOrTuple));
 
   /// Method called from generated code to extend `this` type (as a singleton
   /// type environment) with function type arguments (a singleton argument or
   /// tuple of arguments).
-  Rti _bind1(Rti typeOrTuple) => _rtiBind1(this, typeOrTuple);
+  Rti _bind1(Object? typeOrTuple) => _rtiBind1(this, _Utils.asRti(typeOrTuple));
 
   // Precomputed derived types. These fields are used to hold derived types that
   // are computed eagerly.
@@ -105,17 +112,17 @@
   /// If kind == kindStar, holds T? where T is the base type.
   /// - This case is lazily initialized during subtype checks.
   @pragma('dart2js:noElision')
-  dynamic _precomputed1;
+  Object? _precomputed1;
 
   static Object? _getPrecomputed1(Rti rti) => rti._precomputed1;
 
-  static void _setPrecomputed1(Rti rti, precomputed) {
+  static void _setPrecomputed1(Rti rti, Object? precomputed) {
     rti._precomputed1 = precomputed;
   }
 
-  static Rti _getQuestionFromStar(universe, Rti rti) {
+  static Rti _getQuestionFromStar(Object? universe, Rti rti) {
     assert(_getKind(rti) == kindStar);
-    Rti? question = _castToRtiOrNull(_getPrecomputed1(rti));
+    Rti? question = _Utils.asRtiOrNull(_getPrecomputed1(rti));
     if (question == null) {
       question =
           _Universe._lookupQuestionRti(universe, _getStarArgument(rti), true);
@@ -124,9 +131,9 @@
     return question;
   }
 
-  static Rti _getFutureFromFutureOr(universe, Rti rti) {
+  static Rti _getFutureFromFutureOr(Object? universe, Rti rti) {
     assert(_getKind(rti) == kindFutureOr);
-    Rti? future = _castToRtiOrNull(_getPrecomputed1(rti));
+    Rti? future = _Utils.asRtiOrNull(_getPrecomputed1(rti));
     if (future == null) {
       future = _Universe._lookupFutureRti(universe, _getFutureOrArgument(rti));
       Rti._setPrecomputed1(rti, future);
@@ -134,19 +141,19 @@
     return future;
   }
 
-  dynamic _precomputed2;
-  dynamic _precomputed3;
-  dynamic _precomputed4;
+  Object? _precomputed2;
+  Object? _precomputed3;
+  Object? _precomputed4;
 
   // Data value used by some tests.
   @pragma('dart2js:noElision')
   Object? _specializedTestResource;
 
-  static Object _getSpecializedTestResource(Rti rti) {
-    return rti._specializedTestResource!;
+  static Object? _getSpecializedTestResource(Rti rti) {
+    return rti._specializedTestResource;
   }
 
-  static void _setSpecializedTestResource(Rti rti, Object value) {
+  static void _setSpecializedTestResource(Rti rti, Object? value) {
     rti._specializedTestResource = value;
   }
 
@@ -164,7 +171,7 @@
   ///
   /// The zero initializer ensures dart2js type analysis considers [_kind] is
   /// non-nullable.
-  Object /*int*/ _kind = 0;
+  Object? /*int*/ _kind = 0;
 
   static int _getKind(Rti rti) => _Utils.asInt(rti._kind);
   static void _setKind(Rti rti, int kind) {
@@ -172,27 +179,27 @@
   }
 
   // Terminal terms.
-  static const kindNever = 1;
-  static const kindDynamic = 2;
-  static const kindVoid = 3; // TODO(sra): Use `dynamic` instead?
-  static const kindAny = 4; // Dart1-style 'dynamic' for JS-interop.
-  static const kindErased = 5;
+  static const int kindNever = 1;
+  static const int kindDynamic = 2;
+  static const int kindVoid = 3; // TODO(sra): Use `dynamic` instead?
+  static const int kindAny = 4; // Dart1-style 'dynamic' for JS-interop.
+  static const int kindErased = 5;
   // Unary terms.
-  static const kindStar = 6;
-  static const kindQuestion = 7;
-  static const kindFutureOr = 8;
+  static const int kindStar = 6;
+  static const int kindQuestion = 7;
+  static const int kindFutureOr = 8;
   // More complex terms.
-  static const kindInterface = 9;
+  static const int kindInterface = 9;
   // A vector of type parameters from enclosing functions and closures.
-  static const kindBinding = 10;
-  static const kindFunction = 11;
-  static const kindGenericFunction = 12;
-  static const kindGenericFunctionParameter = 13;
+  static const int kindBinding = 10;
+  static const int kindFunction = 11;
+  static const int kindGenericFunction = 12;
+  static const int kindGenericFunctionParameter = 13;
 
   static bool _isUnionOfFunctionType(Rti rti) {
     int kind = Rti._getKind(rti);
     if (kind == kindStar || kind == kindQuestion || kind == kindFutureOr) {
-      return _isUnionOfFunctionType(_castToRti(_getPrimary(rti)));
+      return _isUnionOfFunctionType(_Utils.asRti(_getPrimary(rti)));
     }
     return kind == kindFunction || kind == kindGenericFunction;
   }
@@ -206,10 +213,10 @@
   /// - Return type of a function type.
   /// - Underlying function type for a generic function.
   /// - de Bruijn index for a generic function parameter.
-  dynamic _primary;
+  Object? _primary;
 
-  static Object _getPrimary(Rti rti) => rti._primary;
-  static void _setPrimary(Rti rti, value) {
+  static Object? _getPrimary(Rti rti) => rti._primary;
+  static void _setPrimary(Rti rti, Object? value) {
     rti._primary = value;
   }
 
@@ -220,10 +227,10 @@
   ///   kindBinding.
   /// - The [_FunctionParameters] of a function type.
   /// - The type parameter bounds of a generic function.
-  dynamic _rest;
+  Object? _rest;
 
-  static Object _getRest(Rti rti) => rti._rest;
-  static void _setRest(Rti rti, value) {
+  static Object? _getRest(Rti rti) => rti._rest;
+  static void _setRest(Rti rti, Object? value) {
     rti._rest = value;
   }
 
@@ -241,7 +248,7 @@
 
   static Rti _getBindingBase(Rti rti) {
     assert(_getKind(rti) == kindBinding);
-    return _castToRti(_getPrimary(rti));
+    return _Utils.asRti(_getPrimary(rti));
   }
 
   static JSArray _getBindingArguments(Rti rti) {
@@ -251,22 +258,22 @@
 
   static Rti _getStarArgument(Rti rti) {
     assert(_getKind(rti) == kindStar);
-    return _castToRti(_getPrimary(rti));
+    return _Utils.asRti(_getPrimary(rti));
   }
 
   static Rti _getQuestionArgument(Rti rti) {
     assert(_getKind(rti) == kindQuestion);
-    return _castToRti(_getPrimary(rti));
+    return _Utils.asRti(_getPrimary(rti));
   }
 
   static Rti _getFutureOrArgument(Rti rti) {
     assert(_getKind(rti) == kindFutureOr);
-    return _castToRti(_getPrimary(rti));
+    return _Utils.asRti(_getPrimary(rti));
   }
 
   static Rti _getReturnType(Rti rti) {
     assert(_getKind(rti) == kindFunction);
-    return _castToRti(_getPrimary(rti));
+    return _Utils.asRti(_getPrimary(rti));
   }
 
   static _FunctionParameters _getFunctionParameters(Rti rti) {
@@ -276,7 +283,7 @@
 
   static Rti _getGenericFunctionBase(Rti rti) {
     assert(_getKind(rti) == kindGenericFunction);
-    return _castToRti(_getPrimary(rti));
+    return _Utils.asRti(_getPrimary(rti));
   }
 
   static JSArray _getGenericFunctionBounds(Rti rti) {
@@ -301,7 +308,7 @@
   Object? _evalCache;
 
   static Object? _getEvalCache(Rti rti) => rti._evalCache;
-  static void _setEvalCache(Rti rti, value) {
+  static void _setEvalCache(Rti rti, Object? value) {
     rti._evalCache = value;
   }
 
@@ -321,7 +328,7 @@
   Object? _bindCache;
 
   static Object? _getBindCache(Rti rti) => rti._bindCache;
-  static void _setBindCache(Rti rti, value) {
+  static void _setBindCache(Rti rti, Object? value) {
     rti._bindCache = value;
   }
 
@@ -332,7 +339,7 @@
   Object? _canonicalRecipe;
 
   static String _getCanonicalRecipe(Rti rti) {
-    Object? s = rti._canonicalRecipe;
+    var s = rti._canonicalRecipe;
     assert(_Utils.isString(s), 'Missing canonical recipe');
     return _Utils.asString(s);
   }
@@ -351,7 +358,7 @@
   static JSArray _getRequiredPositional(_FunctionParameters parameters) =>
       JS('JSUnmodifiableArray', '#', parameters._requiredPositional);
   static void _setRequiredPositional(
-      _FunctionParameters parameters, Object requiredPositional) {
+      _FunctionParameters parameters, Object? requiredPositional) {
     parameters._requiredPositional = requiredPositional;
   }
 
@@ -359,7 +366,7 @@
   static JSArray _getOptionalPositional(_FunctionParameters parameters) =>
       JS('JSUnmodifiableArray', '#', parameters._optionalPositional);
   static void _setOptionalPositional(
-      _FunctionParameters parameters, Object optionalPositional) {
+      _FunctionParameters parameters, Object? optionalPositional) {
     parameters._optionalPositional = optionalPositional;
   }
 
@@ -376,12 +383,12 @@
   static JSArray _getOptionalNamed(_FunctionParameters parameters) =>
       JS('JSUnmodifiableArray', '#', parameters._optionalNamed);
   static void _setOptionalNamed(
-      _FunctionParameters parameters, Object optionalNamed) {
+      _FunctionParameters parameters, Object? optionalNamed) {
     parameters._optionalNamed = optionalNamed;
   }
 }
 
-Object _theUniverse() => JS_EMBEDDED_GLOBAL('', RTI_UNIVERSE);
+Object? _theUniverse() => JS_EMBEDDED_GLOBAL('', RTI_UNIVERSE);
 
 Rti _rtiEval(Rti environment, String recipe) {
   return _Universe.evalInEnvironment(_theUniverse(), environment, recipe);
@@ -410,7 +417,7 @@
 }
 
 /// Evaluate a type recipe in the environment of an instance.
-Rti evalInInstance(instance, String recipe) {
+Rti evalInInstance(Object? instance, String recipe) {
   return _rtiEval(instanceType(instance), recipe);
 }
 
@@ -440,7 +447,7 @@
   }
   String key = Rti._getCanonicalRecipe(instantiationRti);
   var probe = _Utils.mapGet(cache, key);
-  if (probe != null) return _castToRti(probe);
+  if (probe != null) return _Utils.asRti(probe);
   Rti rti = _substitute(_theUniverse(),
       Rti._getGenericFunctionBase(genericFunctionRti), typeArguments, 0);
   _Utils.mapSet(cache, key, rti);
@@ -459,7 +466,7 @@
 /// In order to do a partial substitution - that is, substituting only some
 /// type parameters rather than all of them - we encode the unsubstituted
 /// positions of the argument list as `undefined` or `null`.
-Rti _substitute(universe, Rti rti, Object typeArguments, int depth) {
+Rti _substitute(Object? universe, Rti rti, Object? typeArguments, int depth) {
   int kind = Rti._getKind(rti);
   switch (kind) {
     case Rti.kindErased:
@@ -469,26 +476,26 @@
     case Rti.kindAny:
       return rti;
     case Rti.kindStar:
-      Rti baseType = _castToRti(Rti._getPrimary(rti));
+      Rti baseType = _Utils.asRti(Rti._getPrimary(rti));
       Rti substitutedBaseType =
           _substitute(universe, baseType, typeArguments, depth);
       if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
       return _Universe._lookupStarRti(universe, substitutedBaseType, true);
     case Rti.kindQuestion:
-      Rti baseType = _castToRti(Rti._getPrimary(rti));
+      Rti baseType = _Utils.asRti(Rti._getPrimary(rti));
       Rti substitutedBaseType =
           _substitute(universe, baseType, typeArguments, depth);
       if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
       return _Universe._lookupQuestionRti(universe, substitutedBaseType, true);
     case Rti.kindFutureOr:
-      Rti baseType = _castToRti(Rti._getPrimary(rti));
+      Rti baseType = _Utils.asRti(Rti._getPrimary(rti));
       Rti substitutedBaseType =
           _substitute(universe, baseType, typeArguments, depth);
       if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
       return _Universe._lookupFutureOrRti(universe, substitutedBaseType, true);
     case Rti.kindInterface:
-      Object interfaceTypeArguments = Rti._getInterfaceTypeArguments(rti);
-      Object substitutedInterfaceTypeArguments = _substituteArray(
+      var interfaceTypeArguments = Rti._getInterfaceTypeArguments(rti);
+      var substitutedInterfaceTypeArguments = _substituteArray(
           universe, interfaceTypeArguments, typeArguments, depth);
       if (_Utils.isIdentical(
           substitutedInterfaceTypeArguments, interfaceTypeArguments))
@@ -498,8 +505,8 @@
     case Rti.kindBinding:
       Rti base = Rti._getBindingBase(rti);
       Rti substitutedBase = _substitute(universe, base, typeArguments, depth);
-      Object arguments = Rti._getBindingArguments(rti);
-      Object substitutedArguments =
+      var arguments = Rti._getBindingArguments(rti);
+      var substitutedArguments =
           _substituteArray(universe, arguments, typeArguments, depth);
       if (_Utils.isIdentical(substitutedBase, base) &&
           _Utils.isIdentical(substitutedArguments, arguments)) return rti;
@@ -519,9 +526,9 @@
       return _Universe._lookupFunctionRti(
           universe, substitutedReturnType, substitutedFunctionParameters);
     case Rti.kindGenericFunction:
-      Object bounds = Rti._getGenericFunctionBounds(rti);
+      var bounds = Rti._getGenericFunctionBounds(rti);
       depth += _Utils.arrayLength(bounds);
-      Object substitutedBounds =
+      var substitutedBounds =
           _substituteArray(universe, bounds, typeArguments, depth);
       Rti base = Rti._getGenericFunctionBase(rti);
       Rti substitutedBase = _substitute(universe, base, typeArguments, depth);
@@ -540,19 +547,19 @@
       // positions of the argument list as `undefined` (which will compare equal
       // to `null`).
       if (argument == null) return rti;
-      return _castToRti(argument);
+      return _Utils.asRti(argument);
     default:
       throw AssertionError('Attempted to substitute unexpected RTI kind $kind');
   }
 }
 
-Object _substituteArray(
-    universe, Object rtiArray, Object typeArguments, int depth) {
+Object? _substituteArray(
+    Object? universe, Object? rtiArray, Object? typeArguments, int depth) {
   bool changed = false;
   int length = _Utils.arrayLength(rtiArray);
-  Object result = JS('', '[]');
+  Object? result = JS('', '[]');
   for (int i = 0; i < length; i++) {
-    Rti rti = _castToRti(_Utils.arrayAt(rtiArray, i));
+    Rti rti = _Utils.asRti(_Utils.arrayAt(rtiArray, i));
     Rti substitutedRti = _substitute(universe, rti, typeArguments, depth);
     if (_Utils.isNotIdentical(substitutedRti, rti)) {
       changed = true;
@@ -562,15 +569,15 @@
   return changed ? result : rtiArray;
 }
 
-Object _substituteNamed(
-    universe, Object namedArray, Object typeArguments, int depth) {
+Object? _substituteNamed(
+    Object? universe, Object? namedArray, Object? typeArguments, int depth) {
   bool changed = false;
   int length = _Utils.arrayLength(namedArray);
   assert(length.isEven);
-  Object result = JS('', '[]');
+  Object? result = JS('', '[]');
   for (int i = 0; i < length; i += 2) {
     String name = _Utils.asString(_Utils.arrayAt(namedArray, i));
-    Rti rti = _castToRti(_Utils.arrayAt(namedArray, i + 1));
+    Rti rti = _Utils.asRti(_Utils.arrayAt(namedArray, i + 1));
     Rti substitutedRti = _substitute(universe, rti, typeArguments, depth);
     if (_Utils.isNotIdentical(substitutedRti, rti)) {
       changed = true;
@@ -582,19 +589,18 @@
 }
 
 // TODO(fishythefish): Support required named parameters.
-_FunctionParameters _substituteFunctionParameters(universe,
-    _FunctionParameters functionParameters, Object typeArguments, int depth) {
-  Object requiredPositional =
+_FunctionParameters _substituteFunctionParameters(Object? universe,
+    _FunctionParameters functionParameters, Object? typeArguments, int depth) {
+  var requiredPositional =
       _FunctionParameters._getRequiredPositional(functionParameters);
-  Object substitutedRequiredPositional =
+  var substitutedRequiredPositional =
       _substituteArray(universe, requiredPositional, typeArguments, depth);
-  Object optionalPositional =
+  var optionalPositional =
       _FunctionParameters._getOptionalPositional(functionParameters);
-  Object substitutedOptionalPositional =
+  var substitutedOptionalPositional =
       _substituteArray(universe, optionalPositional, typeArguments, depth);
-  Object optionalNamed =
-      _FunctionParameters._getOptionalNamed(functionParameters);
-  Object substitutedOptionalNamed =
+  var optionalNamed = _FunctionParameters._getOptionalNamed(functionParameters);
+  var substitutedOptionalNamed =
       _substituteNamed(universe, optionalNamed, typeArguments, depth);
   if (_Utils.isIdentical(substitutedRequiredPositional, requiredPositional) &&
       _Utils.isIdentical(substitutedOptionalPositional, optionalPositional) &&
@@ -609,23 +615,23 @@
   return result;
 }
 
-bool _isDartObject(object) => _Utils.instanceOf(object,
+bool _isDartObject(Object? object) => _Utils.instanceOf(object,
     JS_BUILTIN('depends:none;effects:none;', JsBuiltin.dartObjectConstructor));
 
-bool _isClosure(object) => _Utils.instanceOf(object,
+bool _isClosure(Object? object) => _Utils.instanceOf(object,
     JS_BUILTIN('depends:none;effects:none;', JsBuiltin.dartClosureConstructor));
 
 /// Returns the structural function [Rti] of [closure], or `null`.
 /// [closure] must be a subclass of [Closure].
 /// Called from generated code.
-Rti? closureFunctionType(closure) {
+Rti? closureFunctionType(Object? closure) {
   var signatureName = JS_GET_NAME(JsGetName.SIGNATURE_NAME);
   var signature = JS('', '#[#]', closure, signatureName);
   if (signature != null) {
     if (JS('bool', 'typeof # == "number"', signature)) {
       return getTypeFromTypesTable(_Utils.asInt(signature));
     }
-    return _castToRti(JS('', '#[#]()', closure, signatureName));
+    return _Utils.asRti(JS('', '#[#]()', closure, signatureName));
   }
   return null;
 }
@@ -635,7 +641,7 @@
 /// [testRti] to choose the appropriate type.
 ///
 /// Called from generated code.
-Rti instanceOrFunctionType(object, Rti testRti) {
+Rti instanceOrFunctionType(Object? object, Rti testRti) {
   if (Rti._isUnionOfFunctionType(testRti)) {
     if (_isClosure(object)) {
       // If [testRti] is e.g. `FutureOr<Action>` (where `Action` is some
@@ -651,7 +657,7 @@
 /// Returns the Rti type of [object].
 /// This is the general entry for obtaining the interface type of any value.
 /// Called from generated code.
-Rti instanceType(object) {
+Rti instanceType(Object? object) {
   // TODO(sra): Add interceptor-based specializations of this method. Inject a
   // _getRti method into (Dart)Object, JSArray, and Interceptor. Then calls to
   // this method can be generated as `getInterceptor(o)._getRti(o)`, allowing
@@ -674,7 +680,7 @@
 
 /// Returns the Rti type of JavaScript Array [object].
 /// Called from generated code.
-Rti _arrayInstanceType(object) {
+Rti _arrayInstanceType(Object? object) {
   // A JavaScript Array can come from three places:
   //   1. This Dart program.
   //   2. Another Dart program loaded in the JavaScript environment.
@@ -695,40 +701,40 @@
   var defaultRti = getJSArrayInteropRti();
 
   // Case 3.
-  if (rti == null) return _castToRti(defaultRti);
+  if (rti == null) return _Utils.asRti(defaultRti);
 
   // Case 2 and perhaps case 3. Check constructor of extracted type against a
   // known instance of Rti - this is an easy way to get the constructor.
   if (JS('bool', '#.constructor !== #.constructor', rti, defaultRti)) {
-    return _castToRti(defaultRti);
+    return _Utils.asRti(defaultRti);
   }
 
   // Case 1.
-  return _castToRti(rti);
+  return _Utils.asRti(rti);
 }
 
 /// Returns the Rti type of user-defined class [object].
 /// [object] must not be an intercepted class or a closure.
 /// Called from generated code.
-Rti _instanceType(object) {
+Rti _instanceType(Object? object) {
   var rti = JS('', r'#[#]', object, JS_GET_NAME(JsGetName.RTI_NAME));
-  return rti != null ? _castToRti(rti) : _instanceTypeFromConstructor(object);
+  return rti != null ? _Utils.asRti(rti) : _instanceTypeFromConstructor(object);
 }
 
-String instanceTypeName(object) {
+String instanceTypeName(Object? object) {
   Rti rti = instanceType(object);
   return _rtiToString(rti, null);
 }
 
-Rti _instanceTypeFromConstructor(instance) {
+Rti _instanceTypeFromConstructor(Object? instance) {
   var constructor = JS('', '#.constructor', instance);
   var probe = JS('', r'#[#]', constructor, CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME);
-  if (probe != null) return _castToRti(probe);
+  if (probe != null) return _Utils.asRti(probe);
   return _instanceTypeFromConstructorMiss(instance, constructor);
 }
 
 @pragma('dart2js:noInline')
-Rti _instanceTypeFromConstructorMiss(instance, constructor) {
+Rti _instanceTypeFromConstructorMiss(Object? instance, Object? constructor) {
   // Subclasses of Closure are synthetic classes. The synthetic classes all
   // extend a 'normal' class (Closure, BoundClosure, StaticClosure), so make
   // them appear to be the superclass. Instantiations have a `$ti` field so
@@ -750,13 +756,12 @@
 
 /// Returns the structural function type of [object], or `null` if the object is
 /// not a closure.
-Rti? _instanceFunctionType(object) =>
+Rti? _instanceFunctionType(Object? object) =>
     _isClosure(object) ? closureFunctionType(object) : null;
 
 /// Returns Rti from types table. The types table is initialized with recipe
 /// strings.
-Rti getTypeFromTypesTable(/*int*/ _index) {
-  int index = _Utils.asInt(_index);
+Rti getTypeFromTypesTable(int index) {
   var table = JS_EMBEDDED_GLOBAL('', TYPES);
   var type = _Utils.arrayAt(table, index);
   if (_Utils.isString(type)) {
@@ -764,10 +769,10 @@
     _Utils.arraySetAt(table, index, rti);
     return rti;
   }
-  return _castToRti(type);
+  return _Utils.asRti(type);
 }
 
-Type getRuntimeType(object) {
+Type getRuntimeType(Object? object) {
   Rti rti = _instanceFunctionType(object) ?? instanceType(object);
   return createRuntimeType(rti);
 }
@@ -821,10 +826,10 @@
 // (e.g. we lower a check to a direct helper), and (2) `bool` does not flow to a
 // tested type parameter. The trick will be to ensure that `H._isBool` is
 // generated.
-bool _installSpecializedIsTest(object) {
+bool _installSpecializedIsTest(Object? object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
-  Rti testRti = _castToRti(JS('', 'this'));
+  Rti testRti = _Utils.asRti(JS('', 'this'));
 
   if (isObjectType(testRti)) {
     return _finishIsFn(testRti, object, RAW_DART_FUNCTION_REF(_isObject));
@@ -871,7 +876,7 @@
 }
 
 @pragma('dart2js:noInline') // Slightly smaller code.
-bool _finishIsFn(Rti testRti, object, isFn) {
+bool _finishIsFn(Rti testRti, Object? object, Object? isFn) {
   Rti._setIsTestFunction(testRti, isFn);
   return Rti._isCheck(testRti, object);
 }
@@ -896,10 +901,10 @@
 ///
 /// The first time this default `_as` method is called, it replaces itself with
 /// a specialized version.
-bool _installSpecializedAsCheck(object) {
+bool _installSpecializedAsCheck(Object? object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
-  Rti testRti = _castToRti(JS('', 'this'));
+  Rti testRti = _Utils.asRti(JS('', 'this'));
 
   var asFn = RAW_DART_FUNCTION_REF(_generalAsCheckImplementation);
   if (isTopType(testRti)) {
@@ -925,10 +930,10 @@
 }
 
 /// Called from generated code.
-bool _generalIsTestImplementation(object) {
+bool _generalIsTestImplementation(Object? object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
-  Rti testRti = _castToRti(JS('', 'this'));
+  Rti testRti = _Utils.asRti(JS('', 'this'));
   if (JS_GET_FLAG('NNBD') && object == null) {
     return _nullIs(testRti);
   }
@@ -942,20 +947,20 @@
 /// single-step specialization).
 ///
 /// Called from generated code.
-bool _generalNullableIsTestImplementation(object) {
+bool _generalNullableIsTestImplementation(Object? object) {
   if (object == null) return true;
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
-  Rti testRti = _castToRti(JS('', 'this'));
+  Rti testRti = _Utils.asRti(JS('', 'this'));
   Rti baseRti = Rti._getQuestionArgument(testRti);
   return Rti._isCheck(baseRti, object);
 }
 
 /// Called from generated code.
-bool _isTestViaProperty(object) {
+bool _isTestViaProperty(Object? object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
-  Rti testRti = _castToRti(JS('', 'this'));
+  Rti testRti = _Utils.asRti(JS('', 'this'));
   if (JS_GET_FLAG('NNBD') && object == null) {
     return _nullIs(testRti);
   }
@@ -974,10 +979,10 @@
 
 /// General unspecialized 'as' check that works for any type.
 /// Called from generated code.
-_generalAsCheckImplementation(object) {
+Object? _generalAsCheckImplementation(Object? object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
-  Rti testRti = _castToRti(JS('', 'this'));
+  Rti testRti = _Utils.asRti(JS('', 'this'));
   if (object == null) {
     if (JS_GET_FLAG('LEGACY') || isNullable(testRti)) return object;
   } else {
@@ -988,16 +993,16 @@
 
 /// General 'as' check for types that accept `null`.
 /// Called from generated code.
-_generalNullableAsCheckImplementation(object) {
+Object? _generalNullableAsCheckImplementation(Object? object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
-  Rti testRti = _castToRti(JS('', 'this'));
+  Rti testRti = _Utils.asRti(JS('', 'this'));
   if (object == null) return object;
   if (Rti._isCheck(testRti, object)) return object;
   _failedAsCheck(object, testRti);
 }
 
-void _failedAsCheck(object, Rti testRti) {
+void _failedAsCheck(Object? object, Rti testRti) {
   Rti objectRti = instanceOrFunctionType(object, testRti);
   String message =
       _Error.compose(object, objectRti, _rtiToString(testRti, null));
@@ -1005,11 +1010,11 @@
 }
 
 /// Called from generated code.
-checkTypeBound(Rti type, Rti bound, variable, methodName) {
+Rti checkTypeBound(Rti type, Rti bound, String variable, String methodName) {
   if (isSubtype(_theUniverse(), type, bound)) return type;
   String message = "The type argument '${_rtiToString(type, null)}' is not"
       " a subtype of the type variable bound '${_rtiToString(bound, null)}'"
-      " of type variable '${_Utils.asString(variable)}' in '$methodName'.";
+      " of type variable '$variable' in '$methodName'.";
   throw _TypeError.fromMessage(message);
 }
 
@@ -1018,7 +1023,8 @@
   final String _message;
   _Error(this._message);
 
-  static String compose(object, objectRti, checkedTypeDescription) {
+  static String compose(
+      Object? object, Rti? objectRti, String checkedTypeDescription) {
     String objectDescription = Error.safeToString(object);
     objectRti ??= instanceType(object);
     String objectTypeDescription = _rtiToString(objectRti, null);
@@ -1049,38 +1055,40 @@
 
 /// Specialization for 'is Object'.
 /// Called from generated code via Rti `_is` method.
-bool _isObject(object) {
+bool _isObject(Object? object) {
   return !JS_GET_FLAG('NNBD') || object != null;
 }
 
 /// Specialization for 'as Object'.
 /// Called from generated code via Rti `_as` method.
-dynamic _asObject(object) {
+Object? _asObject(Object? object) {
   if (JS_GET_FLAG('LEGACY') || object != null) return object;
   throw _TypeError.forType(object, 'Object');
 }
 
 /// Specialization for 'is dynamic' and other top types.
 /// Called from generated code via Rti `_is` method.
-bool _isTop(object) {
+bool _isTop(Object? object) {
   return true;
 }
 
 /// Specialization for 'as dynamic' and other top types.
 /// Called from generated code via Rti `_as` methods.
-dynamic _asTop(object) {
+Object? _asTop(Object? object) {
   return object;
 }
 
 /// Specialization for 'is bool'.
 /// Called from generated code.
-bool _isBool(object) {
+bool _isBool(Object? object) {
   return true == object || false == object;
 }
 
+// TODO(fishythefish): Change `dynamic` to `Object?` below once promotion works.
+
 /// Specialization for 'as bool?'.
 /// Called from generated code.
-bool? _asBoolNullable(object) {
+bool? _asBoolNullable(dynamic object) {
   if (_isBool(object)) return _Utils.asBool(object);
   if (object == null) return object;
   throw _TypeError.forType(object, 'bool');
@@ -1088,7 +1096,7 @@
 
 /// Specialization for 'as double?'.
 /// Called from generated code.
-double? _asDoubleNullable(object) {
+double? _asDoubleNullable(dynamic object) {
   if (_isNum(object)) return _Utils.asDouble(object);
   if (object == null) return object;
   throw _TypeError.forType(object, 'double');
@@ -1096,14 +1104,14 @@
 
 /// Specialization for 'is int'.
 /// Called from generated code.
-bool _isInt(object) {
+bool _isInt(Object? object) {
   return JS('bool', 'typeof # == "number"', object) &&
       JS('bool', 'Math.floor(#) === #', object, object);
 }
 
 /// Specialization for 'as int?'.
 /// Called from generated code.
-int? _asIntNullable(object) {
+int? _asIntNullable(dynamic object) {
   if (_isInt(object)) return _Utils.asInt(object);
   if (object == null) return object;
   throw _TypeError.forType(object, 'int');
@@ -1111,13 +1119,13 @@
 
 /// Specialization for 'is num' and 'is double'.
 /// Called from generated code.
-bool _isNum(object) {
+bool _isNum(Object? object) {
   return JS('bool', 'typeof # == "number"', object);
 }
 
 /// Specialization for 'as num?'.
 /// Called from generated code.
-num? _asNumNullable(object) {
+num? _asNumNullable(dynamic object) {
   if (_isNum(object)) return _Utils.asNum(object);
   if (object == null) return object;
   throw _TypeError.forType(object, 'num');
@@ -1125,23 +1133,23 @@
 
 /// Specialization for 'is String'.
 /// Called from generated code.
-bool _isString(object) {
+bool _isString(Object? object) {
   return JS('bool', 'typeof # == "string"', object);
 }
 
 /// Specialization for 'as String?'.
 /// Called from generated code.
-String? _asStringNullable(object) {
+String? _asStringNullable(dynamic object) {
   if (_isString(object)) return _Utils.asString(object);
   if (object == null) return object;
   throw _TypeError.forType(object, 'String');
 }
 
-String _rtiArrayToString(Object array, List<String>? genericContext) {
+String _rtiArrayToString(Object? array, List<String>? genericContext) {
   String s = '', sep = '';
   for (int i = 0; i < _Utils.arrayLength(array); i++) {
     s += sep +
-        _rtiToString(_castToRti(_Utils.arrayAt(array, i)), genericContext);
+        _rtiToString(_Utils.asRti(_Utils.arrayAt(array, i)), genericContext);
     sep = ', ';
   }
   return s;
@@ -1169,7 +1177,7 @@
     for (int i = 0; i < boundsLength; i++) {
       typeParametersText += typeSep;
       typeParametersText += genericContext[genericContext.length - 1 - i];
-      Rti boundRti = _castToRti(_Utils.arrayAt(bounds, i));
+      Rti boundRti = _Utils.asRti(_Utils.arrayAt(bounds, i));
       if (!isTopType(boundRti) &&
           (!JS_GET_FLAG('LEGACY') || !isObjectType(boundRti))) {
         typeParametersText +=
@@ -1199,8 +1207,8 @@
   String sep = '';
   for (int i = 0; i < requiredPositionalLength; i++) {
     argumentsText += sep +
-        _rtiToString(
-            _castToRti(_Utils.arrayAt(requiredPositional, i)), genericContext);
+        _rtiToString(_Utils.asRti(_Utils.arrayAt(requiredPositional, i)),
+            genericContext);
     sep = ', ';
   }
 
@@ -1209,7 +1217,7 @@
     sep = '';
     for (int i = 0; i < optionalPositionalLength; i++) {
       argumentsText += sep +
-          _rtiToString(_castToRti(_Utils.arrayAt(optionalPositional, i)),
+          _rtiToString(_Utils.asRti(_Utils.arrayAt(optionalPositional, i)),
               genericContext);
       sep = ', ';
     }
@@ -1221,7 +1229,7 @@
     sep = '';
     for (int i = 0; i < optionalNamedLength; i += 2) {
       argumentsText += sep +
-          _rtiToString(_castToRti(_Utils.arrayAt(optionalNamed, i + 1)),
+          _rtiToString(_Utils.asRti(_Utils.arrayAt(optionalNamed, i + 1)),
               genericContext) +
           ' ' +
           _Utils.asString(_Utils.arrayAt(optionalNamed, i));
@@ -1298,7 +1306,7 @@
 
   if (kind == Rti.kindGenericFunction) {
     Rti baseFunctionType = Rti._getGenericFunctionBase(rti);
-    Object bounds = Rti._getGenericFunctionBounds(rti);
+    var bounds = Rti._getGenericFunctionBounds(rti);
     return _functionRtiToString(baseFunctionType, genericContext,
         bounds: bounds);
   }
@@ -1318,10 +1326,10 @@
   return JS_GET_FLAG('MINIFIED') ? 'minified:$rawClassName' : rawClassName;
 }
 
-String _rtiArrayToDebugString(Object array) {
+String _rtiArrayToDebugString(Object? array) {
   String s = '[', sep = '';
   for (int i = 0; i < _Utils.arrayLength(array); i++) {
-    s += sep + _rtiToDebugString(_castToRti(_Utils.arrayAt(array, i)));
+    s += sep + _rtiToDebugString(_Utils.asRti(_Utils.arrayAt(array, i)));
     sep = ', ';
   }
   return s + ']';
@@ -1342,7 +1350,7 @@
 
   for (int i = 0; i < requiredPositionalLength; i++) {
     s += sep +
-        _rtiToDebugString(_castToRti(_Utils.arrayAt(requiredPositional, i)));
+        _rtiToDebugString(_Utils.asRti(_Utils.arrayAt(requiredPositional, i)));
     sep = ', ';
   }
 
@@ -1351,7 +1359,8 @@
     sep = '';
     for (int i = 0; i < optionalPositionalLength; i++) {
       s += sep +
-          _rtiToDebugString(_castToRti(_Utils.arrayAt(optionalPositional, i)));
+          _rtiToDebugString(
+              _Utils.asRti(_Utils.arrayAt(optionalPositional, i)));
       sep = ', ';
     }
     s += ']';
@@ -1362,7 +1371,8 @@
     sep = '';
     for (int i = 0; i < optionalNamedLength; i += 2) {
       s += sep +
-          _rtiToDebugString(_castToRti(_Utils.arrayAt(optionalNamed, i + 1))) +
+          _rtiToDebugString(
+              _Utils.asRti(_Utils.arrayAt(optionalNamed, i + 1))) +
           ' ' +
           _Utils.asString(_Utils.arrayAt(optionalNamed, i));
       sep = ', ';
@@ -1421,7 +1431,7 @@
 
   if (kind == Rti.kindGenericFunction) {
     Rti baseFunctionType = Rti._getGenericFunctionBase(rti);
-    Object bounds = Rti._getGenericFunctionBounds(rti);
+    var bounds = Rti._getGenericFunctionBounds(rti);
     return 'genericFunction(${_rtiToDebugString(baseFunctionType)}, ${_rtiArrayToDebugString(bounds)})';
   }
 
@@ -1466,38 +1476,38 @@
 
   // Field accessors.
 
-  static evalCache(universe) =>
+  static Object evalCache(Object? universe) =>
       JS('', '#.#', universe, RtiUniverseFieldNames.evalCache);
 
-  static Object typeRules(universe) =>
+  static Object typeRules(Object? universe) =>
       JS('', '#.#', universe, RtiUniverseFieldNames.typeRules);
 
-  static Object erasedTypes(universe) =>
+  static Object erasedTypes(Object? universe) =>
       JS('', '#.#', universe, RtiUniverseFieldNames.erasedTypes);
 
-  static Object typeParameterVariances(universe) =>
+  static Object typeParameterVariances(Object? universe) =>
       JS('', '#.#', universe, RtiUniverseFieldNames.typeParameterVariances);
 
-  static Object? _findRule(universe, String targetType) =>
+  static Object? _findRule(Object? universe, String targetType) =>
       JS('', '#.#', typeRules(universe), targetType);
 
-  static Object? findRule(universe, String targetType) {
-    Object? rule = _findRule(universe, targetType);
+  static Object? findRule(Object? universe, String targetType) {
+    var rule = _findRule(universe, targetType);
     while (_Utils.isString(rule)) {
       rule = _findRule(universe, _Utils.asString(rule));
     }
     return rule;
   }
 
-  static Rti findErasedType(universe, String cls) {
-    Object metadata = erasedTypes(universe);
+  static Rti findErasedType(Object? universe, String cls) {
+    var metadata = erasedTypes(universe);
     var probe = JS('', '#.#', metadata, cls);
     if (probe == null) {
       return eval(universe, cls, false);
     } else if (_Utils.isNum(probe)) {
       int length = _Utils.asInt(probe);
       Rti erased = _lookupErasedRti(universe);
-      Object arguments = JS('', '[]');
+      Object? arguments = JS('', '[]');
       for (int i = 0; i < length; i++) {
         _Utils.arrayPush(arguments, erased);
       }
@@ -1505,58 +1515,58 @@
       JS('', '#.# = #', metadata, cls, interface);
       return interface;
     } else {
-      return _castToRti(probe);
+      return _Utils.asRti(probe);
     }
   }
 
-  static Object? findTypeParameterVariances(universe, String cls) =>
+  static Object? findTypeParameterVariances(Object? universe, String cls) =>
       JS('', '#.#', typeParameterVariances(universe), cls);
 
-  static void addRules(universe, rules) =>
+  static void addRules(Object? universe, Object? rules) =>
       _Utils.objectAssign(typeRules(universe), rules);
 
-  static void addErasedTypes(universe, types) =>
+  static void addErasedTypes(Object? universe, Object? types) =>
       _Utils.objectAssign(erasedTypes(universe), types);
 
-  static void addTypeParameterVariances(universe, variances) =>
+  static void addTypeParameterVariances(Object? universe, Object? variances) =>
       _Utils.objectAssign(typeParameterVariances(universe), variances);
 
-  static Object sharedEmptyArray(universe) =>
+  static JSArray sharedEmptyArray(Object? universe) =>
       JS('JSArray', '#.#', universe, RtiUniverseFieldNames.sharedEmptyArray);
 
   /// Evaluates [recipe] in the global environment.
-  static Rti eval(Object universe, String recipe, bool normalize) {
+  static Rti eval(Object? universe, String recipe, bool normalize) {
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, recipe);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, recipe);
+    if (probe != null) return _Utils.asRti(probe);
     Rti rti = _parseRecipe(universe, null, recipe, normalize);
-    _cacheSet(cache, recipe, rti);
+    _Utils.mapSet(cache, recipe, rti);
     return rti;
   }
 
   static Rti evalInEnvironment(
-      Object universe, Rti environment, String recipe) {
+      Object? universe, Rti environment, String recipe) {
     var cache = Rti._getEvalCache(environment);
     if (cache == null) {
       cache = JS('', 'new Map()');
       Rti._setEvalCache(environment, cache);
     }
-    var probe = _cacheGet(cache, recipe);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, recipe);
+    if (probe != null) return _Utils.asRti(probe);
     Rti rti = _parseRecipe(universe, environment, recipe, true);
-    _cacheSet(cache, recipe, rti);
+    _Utils.mapSet(cache, recipe, rti);
     return rti;
   }
 
-  static Rti bind(Object universe, Rti environment, Rti argumentsRti) {
+  static Rti bind(Object? universe, Rti environment, Rti argumentsRti) {
     var cache = Rti._getBindCache(environment);
     if (cache == null) {
       cache = JS('', 'new Map()');
       Rti._setBindCache(environment, cache);
     }
     String argumentsRecipe = Rti._getCanonicalRecipe(argumentsRti);
-    var probe = _cacheGet(cache, argumentsRecipe);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, argumentsRecipe);
+    if (probe != null) return _Utils.asRti(probe);
     var argumentsArray;
     if (Rti._getKind(argumentsRti) == Rti.kindBinding) {
       argumentsArray = Rti._getBindingArguments(argumentsRti);
@@ -1564,22 +1574,22 @@
       argumentsArray = JS('', '[#]', argumentsRti);
     }
     Rti rti = _lookupBindingRti(universe, environment, argumentsArray);
-    _cacheSet(cache, argumentsRecipe, rti);
+    _Utils.mapSet(cache, argumentsRecipe, rti);
     return rti;
   }
 
-  static Rti bind1(Object universe, Rti environment, Rti argumentsRti) {
+  static Rti bind1(Object? universe, Rti environment, Rti argumentsRti) {
     throw UnimplementedError('_Universe.bind1');
   }
 
-  static Rti evalTypeVariable(Object universe, Rti environment, String name) {
+  static Rti evalTypeVariable(Object? universe, Rti environment, String name) {
     int kind = Rti._getKind(environment);
     if (kind == Rti.kindBinding) {
       environment = Rti._getBindingBase(environment);
     }
 
     String interfaceName = Rti._getInterfaceName(environment);
-    Object? rule = _Universe.findRule(universe, interfaceName);
+    var rule = _Universe.findRule(universe, interfaceName);
     assert(rule != null);
     String? recipe = TypeRule.lookupTypeVariable(rule, name);
     if (recipe == null) {
@@ -1588,20 +1598,14 @@
     return _Universe.evalInEnvironment(universe, environment, recipe);
   }
 
-  static _cacheGet(cache, key) => JS('', '#.get(#)', cache, key);
-  static void _cacheSet(cache, key, value) {
-    JS('', '#.set(#, #)', cache, key, value);
-  }
-
   static Rti _parseRecipe(
-      Object universe, Object? environment, String recipe, bool normalize) {
-    Object parser = _Parser.create(universe, environment, recipe, normalize);
+      Object? universe, Object? environment, String recipe, bool normalize) {
+    var parser = _Parser.create(universe, environment, recipe, normalize);
     Rti rti = _Parser.parse(parser);
-    if (rti != null) return rti;
-    throw UnimplementedError('_Universe._parseRecipe("$recipe")');
+    return rti;
   }
 
-  static Rti _installTypeTests(Object universe, Rti rti) {
+  static Rti _installTypeTests(Object? universe, Rti rti) {
     // Set up methods to perform type tests. The general as-check methods use
     // the is-test method. The is-test method on first use overwrites itself,
     // and possibly the as-check methods, with a specialized version.
@@ -1612,8 +1616,8 @@
     return rti;
   }
 
-  static Rti _installRti(Object universe, String key, Rti rti) {
-    _cacheSet(evalCache(universe), key, rti);
+  static Rti _installRti(Object? universe, String key, Rti rti) {
+    _Utils.mapSet(evalCache(universe), key, rti);
     return rti;
   }
 
@@ -1649,54 +1653,54 @@
   static String _canonicalRecipeOfGenericFunctionParameter(int index) =>
       '$index' + Recipe.genericFunctionTypeParameterIndexString;
 
-  static Rti _lookupErasedRti(universe) {
+  static Rti _lookupErasedRti(Object? universe) {
     return _lookupTerminalRti(
         universe, Rti.kindErased, _canonicalRecipeOfErased());
   }
 
-  static Rti _lookupDynamicRti(universe) {
+  static Rti _lookupDynamicRti(Object? universe) {
     return _lookupTerminalRti(
         universe, Rti.kindDynamic, _canonicalRecipeOfDynamic());
   }
 
-  static Rti _lookupVoidRti(universe) {
+  static Rti _lookupVoidRti(Object? universe) {
     return _lookupTerminalRti(universe, Rti.kindVoid, _canonicalRecipeOfVoid());
   }
 
-  static Rti _lookupNeverRti(universe) {
+  static Rti _lookupNeverRti(Object? universe) {
     return _lookupTerminalRti(
         universe, Rti.kindNever, _canonicalRecipeOfNever());
   }
 
-  static Rti _lookupAnyRti(universe) {
+  static Rti _lookupAnyRti(Object? universe) {
     return _lookupTerminalRti(universe, Rti.kindAny, _canonicalRecipeOfAny());
   }
 
-  static Rti _lookupTerminalRti(universe, int kind, String key) {
+  static Rti _lookupTerminalRti(Object? universe, int kind, String key) {
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(universe, key, _createTerminalRti(universe, kind, key));
   }
 
-  static Rti _createTerminalRti(universe, int kind, String key) {
+  static Rti _createTerminalRti(Object? universe, int kind, String key) {
     Rti rti = Rti.allocate();
     Rti._setKind(rti, kind);
     Rti._setCanonicalRecipe(rti, key);
     return _installTypeTests(universe, rti);
   }
 
-  static Rti _lookupStarRti(universe, Rti baseType, bool normalize) {
+  static Rti _lookupStarRti(Object? universe, Rti baseType, bool normalize) {
     String key = _canonicalRecipeOfStar(baseType);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(
         universe, key, _createStarRti(universe, baseType, key, normalize));
   }
 
   static Rti _createStarRti(
-      universe, Rti baseType, String key, bool normalize) {
+      Object? universe, Rti baseType, String key, bool normalize) {
     if (normalize) {
       int baseKind = Rti._getKind(baseType);
       if (isTopType(baseType) ||
@@ -1713,17 +1717,18 @@
     return _installTypeTests(universe, rti);
   }
 
-  static Rti _lookupQuestionRti(universe, Rti baseType, bool normalize) {
+  static Rti _lookupQuestionRti(
+      Object? universe, Rti baseType, bool normalize) {
     String key = _canonicalRecipeOfQuestion(baseType);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(
         universe, key, _createQuestionRti(universe, baseType, key, normalize));
   }
 
   static Rti _createQuestionRti(
-      universe, Rti baseType, String key, bool normalize) {
+      Object? universe, Rti baseType, String key, bool normalize) {
     if (normalize) {
       int baseKind = Rti._getKind(baseType);
       if (isStrongTopType(baseType) ||
@@ -1753,17 +1758,18 @@
     return _installTypeTests(universe, rti);
   }
 
-  static Rti _lookupFutureOrRti(universe, Rti baseType, bool normalize) {
+  static Rti _lookupFutureOrRti(
+      Object? universe, Rti baseType, bool normalize) {
     String key = _canonicalRecipeOfFutureOr(baseType);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(
         universe, key, _createFutureOrRti(universe, baseType, key, normalize));
   }
 
   static Rti _createFutureOrRti(
-      universe, Rti baseType, String key, bool normalize) {
+      Object? universe, Rti baseType, String key, bool normalize) {
     if (normalize) {
       int baseKind = Rti._getKind(baseType);
       if (isTopType(baseType) || isObjectType(baseType)) {
@@ -1783,17 +1789,17 @@
     return _installTypeTests(universe, rti);
   }
 
-  static Rti _lookupGenericFunctionParameterRti(universe, int index) {
+  static Rti _lookupGenericFunctionParameterRti(Object? universe, int index) {
     String key = _canonicalRecipeOfGenericFunctionParameter(index);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(universe, key,
         _createGenericFunctionParameterRti(universe, index, key));
   }
 
   static Rti _createGenericFunctionParameterRti(
-      universe, int index, String key) {
+      Object? universe, int index, String key) {
     Rti rti = Rti.allocate();
     Rti._setKind(rti, Rti.kindGenericFunctionParameter);
     Rti._setPrimary(rti, index);
@@ -1801,11 +1807,11 @@
     return _installTypeTests(universe, rti);
   }
 
-  static String _canonicalRecipeJoin(Object arguments) {
+  static String _canonicalRecipeJoin(Object? arguments) {
     String s = '', sep = '';
     int length = _Utils.arrayLength(arguments);
     for (int i = 0; i < length; i++) {
-      Rti argument = _castToRti(_Utils.arrayAt(arguments, i));
+      Rti argument = _Utils.asRti(_Utils.arrayAt(arguments, i));
       String subrecipe = Rti._getCanonicalRecipe(argument);
       s += sep + subrecipe;
       sep = Recipe.separatorString;
@@ -1813,13 +1819,13 @@
     return s;
   }
 
-  static String _canonicalRecipeJoinNamed(Object arguments) {
+  static String _canonicalRecipeJoinNamed(Object? arguments) {
     String s = '', sep = '';
     int length = _Utils.arrayLength(arguments);
     assert(length.isEven);
     for (int i = 0; i < length; i += 2) {
       String name = _Utils.asString(_Utils.arrayAt(arguments, i));
-      Rti type = _castToRti(_Utils.arrayAt(arguments, i + 1));
+      Rti type = _Utils.asRti(_Utils.arrayAt(arguments, i + 1));
       String subrecipe = Rti._getCanonicalRecipe(type);
       s += sep + name + Recipe.nameSeparatorString + subrecipe;
       sep = Recipe.separatorString;
@@ -1827,7 +1833,7 @@
     return s;
   }
 
-  static String _canonicalRecipeOfInterface(String name, Object arguments) {
+  static String _canonicalRecipeOfInterface(String name, Object? arguments) {
     assert(_Utils.isString(name));
     String s = _Utils.asString(name);
     int length = _Utils.arrayLength(arguments);
@@ -1840,17 +1846,17 @@
   }
 
   static Rti _lookupInterfaceRti(
-      Object universe, String name, Object arguments) {
+      Object? universe, String name, Object? arguments) {
     String key = _canonicalRecipeOfInterface(name, arguments);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(
         universe, key, _createInterfaceRti(universe, name, arguments, key));
   }
 
   static Rti _createInterfaceRti(
-      Object universe, String name, Object typeArguments, String key) {
+      Object? universe, String name, Object? typeArguments, String key) {
     Rti rti = Rti.allocate();
     Rti._setKind(rti, Rti.kindInterface);
     Rti._setPrimary(rti, name);
@@ -1863,12 +1869,11 @@
     return _installTypeTests(universe, rti);
   }
 
-  static Rti _lookupFutureRti(Object universe, Rti base) => _lookupInterfaceRti(
-      universe,
-      JS_GET_NAME(JsGetName.FUTURE_CLASS_TYPE_NAME),
-      JS('', '[#]', base));
+  static Rti _lookupFutureRti(Object? universe, Rti base) =>
+      _lookupInterfaceRti(universe,
+          JS_GET_NAME(JsGetName.FUTURE_CLASS_TYPE_NAME), JS('', '[#]', base));
 
-  static String _canonicalRecipeOfBinding(Rti base, Object arguments) {
+  static String _canonicalRecipeOfBinding(Rti base, Object? arguments) {
     String s = Rti._getCanonicalRecipe(base);
     s += Recipe
         .toTypeString; // TODO(sra): Omit when base encoding is Rti without ToType.
@@ -1879,9 +1884,9 @@
   }
 
   /// [arguments] becomes owned by the created Rti.
-  static Rti _lookupBindingRti(Object universe, Rti base, Object arguments) {
+  static Rti _lookupBindingRti(Object? universe, Rti base, Object? arguments) {
     Rti newBase = base;
-    Object newArguments = arguments;
+    var newArguments = arguments;
     if (Rti._getKind(base) == Rti.kindBinding) {
       newBase = Rti._getBindingBase(base);
       newArguments =
@@ -1889,14 +1894,14 @@
     }
     String key = _canonicalRecipeOfBinding(newBase, newArguments);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(
         universe, key, _createBindingRti(universe, newBase, newArguments, key));
   }
 
   static Rti _createBindingRti(
-      Object universe, Rti base, Object arguments, String key) {
+      Object? universe, Rti base, Object? arguments, String key) {
     Rti rti = Rti.allocate();
     Rti._setKind(rti, Rti.kindBinding);
     Rti._setPrimary(rti, base);
@@ -1946,16 +1951,16 @@
   }
 
   static Rti _lookupFunctionRti(
-      Object universe, Rti returnType, _FunctionParameters parameters) {
+      Object? universe, Rti returnType, _FunctionParameters parameters) {
     String key = _canonicalRecipeOfFunction(returnType, parameters);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(universe, key,
         _createFunctionRti(universe, returnType, parameters, key));
   }
 
-  static Rti _createFunctionRti(Object universe, Rti returnType,
+  static Rti _createFunctionRti(Object? universe, Rti returnType,
       _FunctionParameters parameters, String key) {
     Rti rti = Rti.allocate();
     Rti._setKind(rti, Rti.kindFunction);
@@ -1966,18 +1971,18 @@
   }
 
   static String _canonicalRecipeOfGenericFunction(
-          Rti baseFunctionType, Object bounds) =>
+          Rti baseFunctionType, Object? bounds) =>
       Rti._getCanonicalRecipe(baseFunctionType) +
       Recipe.startTypeArgumentsString +
       _canonicalRecipeJoin(bounds) +
       Recipe.endTypeArgumentsString;
 
   static Rti _lookupGenericFunctionRti(
-      Object universe, Rti baseFunctionType, Object bounds, bool normalize) {
+      Object? universe, Rti baseFunctionType, Object? bounds, bool normalize) {
     String key = _canonicalRecipeOfGenericFunction(baseFunctionType, bounds);
     var cache = evalCache(universe);
-    var probe = _cacheGet(cache, key);
-    if (probe != null) return _castToRti(probe);
+    var probe = _Utils.mapGet(cache, key);
+    if (probe != null) return _Utils.asRti(probe);
     return _installRti(
         universe,
         key,
@@ -1985,14 +1990,14 @@
             universe, baseFunctionType, bounds, key, normalize));
   }
 
-  static Rti _createGenericFunctionRti(Object universe, Rti baseFunctionType,
-      Object bounds, String key, bool normalize) {
+  static Rti _createGenericFunctionRti(Object? universe, Rti baseFunctionType,
+      Object? bounds, String key, bool normalize) {
     if (normalize) {
       int length = _Utils.arrayLength(bounds);
       int count = 0;
-      Object typeArguments = JS('', 'new Array(#)', length);
+      Object? typeArguments = JS('', 'new Array(#)', length);
       for (int i = 0; i < length; i++) {
-        Rti bound = _castToRti(_Utils.arrayAt(bounds, i));
+        Rti bound = _Utils.asRti(_Utils.arrayAt(bounds, i));
         if (Rti._getKind(bound) == Rti.kindNever) {
           _Utils.arraySetAt(typeArguments, i, bound);
           count++;
@@ -2142,7 +2147,7 @@
   /// Marked as no-inline so the object literal is not cloned by inlining.
   @pragma('dart2js:noInline')
   static Object create(
-      Object universe, Object? environment, String recipe, bool normalize) {
+      Object? universe, Object? environment, String recipe, bool normalize) {
     return JS(
         '',
         '{'
@@ -2160,27 +2165,27 @@
   }
 
   // Field accessors for the parser.
-  static Object universe(Object parser) => JS('', '#.u', parser);
-  static Rti environment(Object parser) => JS('Rti', '#.e', parser);
-  static String recipe(Object parser) => JS('String', '#.r', parser);
-  static Object stack(Object parser) => JS('', '#.s', parser);
-  static int position(Object parser) => JS('int', '#.p', parser);
-  static void setPosition(Object parser, int p) {
+  static Object universe(Object? parser) => JS('', '#.u', parser);
+  static Rti environment(Object? parser) => JS('Rti', '#.e', parser);
+  static String recipe(Object? parser) => JS('String', '#.r', parser);
+  static Object stack(Object? parser) => JS('', '#.s', parser);
+  static int position(Object? parser) => JS('int', '#.p', parser);
+  static void setPosition(Object? parser, int p) {
     JS('', '#.p = #', parser, p);
   }
 
-  static bool normalize(Object parser) => JS('bool', '#.n', parser);
+  static bool normalize(Object? parser) => JS('bool', '#.n', parser);
 
   static int charCodeAt(String s, int i) => JS('int', '#.charCodeAt(#)', s, i);
-  static void push(Object stack, Object value) {
+  static void push(Object? stack, Object? value) {
     JS('', '#.push(#)', stack, value);
   }
 
-  static Object pop(Object stack) => JS('', '#.pop()', stack);
+  static Object? pop(Object? stack) => JS('', '#.pop()', stack);
 
-  static Rti parse(Object parser) {
+  static Rti parse(Object? parser) {
     String source = _Parser.recipe(parser);
-    Object stack = _Parser.stack(parser);
+    var stack = _Parser.stack(parser);
     int i = 0;
     while (i < source.length) {
       int ch = charCodeAt(source, i);
@@ -2234,7 +2239,7 @@
             break;
 
           case Recipe.wrapStar:
-            Object u = universe(parser);
+            var u = universe(parser);
             push(
                 stack,
                 _Universe._lookupStarRti(
@@ -2244,7 +2249,7 @@
             break;
 
           case Recipe.wrapQuestion:
-            Object u = universe(parser);
+            var u = universe(parser);
             push(
                 stack,
                 _Universe._lookupQuestionRti(
@@ -2254,7 +2259,7 @@
             break;
 
           case Recipe.wrapFutureOr:
-            Object u = universe(parser);
+            var u = universe(parser);
             push(
                 stack,
                 _Universe._lookupFutureOrRti(
@@ -2292,16 +2297,16 @@
         }
       }
     }
-    Object item = pop(stack);
+    var item = pop(stack);
     return toType(universe(parser), environment(parser), item);
   }
 
-  static void pushStackFrame(Object parser, Object stack) {
+  static void pushStackFrame(Object? parser, Object? stack) {
     push(stack, position(parser));
     setPosition(parser, _Utils.arrayLength(stack));
   }
 
-  static int handleDigit(int i, int digit, String source, Object stack) {
+  static int handleDigit(int i, int digit, String source, Object? stack) {
     int value = Recipe.digitValue(digit);
     for (; i < source.length; i++) {
       int ch = charCodeAt(source, i);
@@ -2313,7 +2318,7 @@
   }
 
   static int handleIdentifier(
-      Object parser, int start, String source, Object stack, bool hasPeriod) {
+      Object? parser, int start, String source, Object? stack, bool hasPeriod) {
     int i = start + 1;
     for (; i < source.length; i++) {
       int ch = charCodeAt(source, i);
@@ -2338,10 +2343,10 @@
     return i;
   }
 
-  static void handleTypeArguments(Object parser, Object stack) {
-    Object universe = _Parser.universe(parser);
-    Object arguments = collectArray(parser, stack);
-    Object head = pop(stack);
+  static void handleTypeArguments(Object? parser, Object? stack) {
+    var universe = _Parser.universe(parser);
+    var arguments = collectArray(parser, stack);
+    var head = pop(stack);
     if (_Utils.isString(head)) {
       String name = _Utils.asString(head);
       push(stack, _Universe._lookupInterfaceRti(universe, name, arguments));
@@ -2365,13 +2370,13 @@
   static const int optionalPositionalSentinel = -1;
   static const int optionalNamedSentinel = -2;
 
-  static void handleFunctionArguments(Object parser, Object stack) {
-    Object universe = _Parser.universe(parser);
+  static void handleFunctionArguments(Object? parser, Object? stack) {
+    var universe = _Parser.universe(parser);
     _FunctionParameters parameters = _FunctionParameters.allocate();
-    var optionalPositional = _Universe.sharedEmptyArray(universe);
-    var optionalNamed = _Universe.sharedEmptyArray(universe);
+    Object? optionalPositional = _Universe.sharedEmptyArray(universe);
+    Object? optionalNamed = _Universe.sharedEmptyArray(universe);
 
-    Object head = pop(stack);
+    var head = pop(stack);
     if (_Utils.isNum(head)) {
       int sentinel = _Utils.asInt(head);
       switch (sentinel) {
@@ -2399,20 +2404,20 @@
     push(stack, _Universe._lookupFunctionRti(universe, returnType, parameters));
   }
 
-  static void handleOptionalGroup(Object parser, Object stack) {
-    Object parameters = collectArray(parser, stack);
+  static void handleOptionalGroup(Object? parser, Object? stack) {
+    var parameters = collectArray(parser, stack);
     push(stack, parameters);
     push(stack, optionalPositionalSentinel);
   }
 
-  static void handleNamedGroup(Object parser, Object stack) {
-    Object parameters = collectNamed(parser, stack);
+  static void handleNamedGroup(Object? parser, Object? stack) {
+    var parameters = collectNamed(parser, stack);
     push(stack, parameters);
     push(stack, optionalNamedSentinel);
   }
 
-  static void handleExtendedOperations(Object parser, Object stack) {
-    Object top = pop(stack);
+  static void handleExtendedOperations(Object? parser, Object? stack) {
+    var top = pop(stack);
     if (0 == top) {
       push(stack, _Universe._lookupNeverRti(universe(parser)));
       return;
@@ -2424,14 +2429,14 @@
     throw AssertionError('Unexpected extended operation $top');
   }
 
-  static Object collectArray(Object parser, Object stack) {
+  static JSArray collectArray(Object? parser, Object? stack) {
     var array = _Utils.arraySplice(stack, position(parser));
     toTypes(_Parser.universe(parser), environment(parser), array);
     setPosition(parser, _Utils.asInt(pop(stack)));
     return array;
   }
 
-  static Object collectNamed(Object parser, Object stack) {
+  static JSArray collectNamed(Object? parser, Object? stack) {
     var array = _Utils.arraySplice(stack, position(parser));
     toTypesNamed(_Parser.universe(parser), environment(parser), array);
     setPosition(parser, _Utils.asInt(pop(stack)));
@@ -2440,7 +2445,7 @@
 
   /// Coerce a stack item into an Rti object. Strings are converted to interface
   /// types, integers are looked up in the type environment.
-  static Rti toType(Object universe, Rti environment, Object item) {
+  static Rti toType(Object? universe, Rti environment, Object? item) {
     if (_Utils.isString(item)) {
       String name = _Utils.asString(item);
       return _Universe._lookupInterfaceRti(
@@ -2448,11 +2453,11 @@
     } else if (_Utils.isNum(item)) {
       return _Parser.indexToType(universe, environment, _Utils.asInt(item));
     } else {
-      return _castToRti(item);
+      return _Utils.asRti(item);
     }
   }
 
-  static void toTypes(Object universe, Rti environment, Object items) {
+  static void toTypes(Object? universe, Rti environment, Object? items) {
     int length = _Utils.arrayLength(items);
     for (int i = 0; i < length; i++) {
       var item = _Utils.arrayAt(items, i);
@@ -2461,7 +2466,7 @@
     }
   }
 
-  static void toTypesNamed(Object universe, Rti environment, Object items) {
+  static void toTypesNamed(Object? universe, Rti environment, Object? items) {
     int length = _Utils.arrayLength(items);
     assert(length.isEven);
     for (int i = 1; i < length; i += 2) {
@@ -2471,14 +2476,14 @@
     }
   }
 
-  static Rti indexToType(Object universe, Rti environment, int index) {
+  static Rti indexToType(Object? universe, Rti environment, int index) {
     int kind = Rti._getKind(environment);
     if (kind == Rti.kindBinding) {
       if (index == 0) return Rti._getBindingBase(environment);
       var typeArguments = Rti._getBindingArguments(environment);
       int len = _Utils.arrayLength(typeArguments);
       if (index <= len) {
-        return _castToRti(_Utils.arrayAt(typeArguments, index - 1));
+        return _Utils.asRti(_Utils.arrayAt(typeArguments, index - 1));
       }
       // Is index into interface Rti in base.
       index -= len;
@@ -2493,12 +2498,12 @@
     var typeArguments = Rti._getInterfaceTypeArguments(environment);
     int len = _Utils.arrayLength(typeArguments);
     if (index <= len) {
-      return _castToRti(_Utils.arrayAt(typeArguments, index - 1));
+      return _Utils.asRti(_Utils.arrayAt(typeArguments, index - 1));
     }
     throw AssertionError('Bad index $index for $environment');
   }
 
-  static Rti toGenericFunctionParameter(Object universe, Object item) {
+  static Rti toGenericFunctionParameter(Object? universe, Object? item) {
     assert(_Utils.isNum(item));
     return _Universe._lookupGenericFunctionParameterRti(
         universe, _Utils.asInt(item));
@@ -2512,26 +2517,26 @@
     throw UnimplementedError("TypeRule is static methods only.");
   }
 
-  static String? lookupTypeVariable(rule, String typeVariable) =>
+  static String? lookupTypeVariable(Object? rule, String typeVariable) =>
       JS('', '#.#', rule, typeVariable);
 
-  static JSArray? lookupSupertype(rule, String supertype) =>
+  static JSArray? lookupSupertype(Object? rule, String supertype) =>
       JS('', '#.#', rule, supertype);
 }
 
 // This needs to be kept in sync with `Variance` in `entities.dart`.
 class Variance {
   // TODO(fishythefish): Try bitmask representation.
-  static const legacyCovariant = 0;
-  static const covariant = 1;
-  static const contravariant = 2;
-  static const invariant = 3;
+  static const int legacyCovariant = 0;
+  static const int covariant = 1;
+  static const int contravariant = 2;
+  static const int invariant = 3;
 }
 
 // -------- Subtype tests ------------------------------------------------------
 
 // Future entry point from compiled code.
-bool isSubtype(universe, Rti s, Rti t) {
+bool isSubtype(Object? universe, Rti s, Rti t) {
   return _isSubtype(universe, s, null, t, null);
 }
 
@@ -2558,7 +2563,7 @@
 /// the bottom of the type hierarchy, `Object` is treated as nullable, and
 /// `required` is ignored on named parameters. This should provide the same
 /// subtyping results as pre-NNBD Dart.
-bool _isSubtype(universe, Rti s, sEnv, Rti t, tEnv) {
+bool _isSubtype(Object? universe, Rti s, Object? sEnv, Rti t, Object? tEnv) {
   bool isLegacy = JS_GET_FLAG('LEGACY');
 
   // Reflexivity:
@@ -2584,7 +2589,7 @@
   bool leftTypeVariable = sKind == Rti.kindGenericFunctionParameter;
   if (leftTypeVariable) {
     int index = Rti._getGenericFunctionParameterIndex(s);
-    Rti bound = _castToRti(_Utils.arrayAt(sEnv, index));
+    Rti bound = _Utils.asRti(_Utils.arrayAt(sEnv, index));
     if (_isSubtype(universe, bound, sEnv, t, tEnv)) return true;
   }
 
@@ -2693,8 +2698,8 @@
     tEnv = tEnv == null ? tBounds : _Utils.arrayConcat(tBounds, tEnv);
 
     for (int i = 0; i < sLength; i++) {
-      var sBound = _castToRti(_Utils.arrayAt(sBounds, i));
-      var tBound = _castToRti(_Utils.arrayAt(tBounds, i));
+      var sBound = _Utils.asRti(_Utils.arrayAt(sBounds, i));
+      var tBound = _Utils.asRti(_Utils.arrayAt(tBounds, i));
       if (!_isSubtype(universe, sBound, sEnv, tBound, tEnv) ||
           !_isSubtype(universe, tBound, tEnv, sBound, sEnv)) {
         return false;
@@ -2720,7 +2725,8 @@
 }
 
 // TODO(fishythefish): Support required named parameters.
-bool _isFunctionSubtype(universe, Rti s, sEnv, Rti t, tEnv) {
+bool _isFunctionSubtype(
+    Object? universe, Rti s, Object? sEnv, Rti t, Object? tEnv) {
   assert(Rti._getKind(s) == Rti.kindFunction);
   assert(Rti._getKind(t) == Rti.kindFunction);
 
@@ -2753,16 +2759,16 @@
       tRequiredPositionalLength + tOptionalPositionalLength) return false;
 
   for (int i = 0; i < sRequiredPositionalLength; i++) {
-    Rti sParameter = _castToRti(_Utils.arrayAt(sRequiredPositional, i));
-    Rti tParameter = _castToRti(_Utils.arrayAt(tRequiredPositional, i));
+    Rti sParameter = _Utils.asRti(_Utils.arrayAt(sRequiredPositional, i));
+    Rti tParameter = _Utils.asRti(_Utils.arrayAt(tRequiredPositional, i));
     if (!_isSubtype(universe, tParameter, tEnv, sParameter, sEnv)) {
       return false;
     }
   }
 
   for (int i = 0; i < requiredPositionalDelta; i++) {
-    Rti sParameter = _castToRti(_Utils.arrayAt(sOptionalPositional, i));
-    Rti tParameter = _castToRti(
+    Rti sParameter = _Utils.asRti(_Utils.arrayAt(sOptionalPositional, i));
+    Rti tParameter = _Utils.asRti(
         _Utils.arrayAt(tRequiredPositional, sRequiredPositionalLength + i));
     if (!_isSubtype(universe, tParameter, tEnv, sParameter, sEnv)) {
       return false;
@@ -2770,9 +2776,9 @@
   }
 
   for (int i = 0; i < tOptionalPositionalLength; i++) {
-    Rti sParameter = _castToRti(
+    Rti sParameter = _Utils.asRti(
         _Utils.arrayAt(sOptionalPositional, requiredPositionalDelta + i));
-    Rti tParameter = _castToRti(_Utils.arrayAt(tOptionalPositional, i));
+    Rti tParameter = _Utils.asRti(_Utils.arrayAt(tOptionalPositional, i));
     if (!_isSubtype(universe, tParameter, tEnv, sParameter, sEnv)) {
       return false;
     }
@@ -2792,15 +2798,16 @@
       i += 2;
     } while (_Utils.stringLessThan(sName, tName));
     if (_Utils.stringLessThan(tName, sName)) return false;
-    Rti sType = _castToRti(_Utils.arrayAt(sOptionalNamed, i - 1));
-    Rti tType = _castToRti(_Utils.arrayAt(tOptionalNamed, j + 1));
+    Rti sType = _Utils.asRti(_Utils.arrayAt(sOptionalNamed, i - 1));
+    Rti tType = _Utils.asRti(_Utils.arrayAt(tOptionalNamed, j + 1));
     if (!_isSubtype(universe, tType, tEnv, sType, sEnv)) return false;
   }
 
   return true;
 }
 
-bool _isInterfaceSubtype(universe, Rti s, sEnv, Rti t, tEnv) {
+bool _isInterfaceSubtype(
+    Object? universe, Rti s, Object? sEnv, Rti t, Object? tEnv) {
   String sName = Rti._getInterfaceName(s);
   String tName = Rti._getInterfaceName(t);
 
@@ -2820,8 +2827,8 @@
     }
 
     for (int i = 0; i < length; i++) {
-      Rti sArg = _castToRti(_Utils.arrayAt(sArgs, i));
-      Rti tArg = _castToRti(_Utils.arrayAt(tArgs, i));
+      Rti sArg = _Utils.asRti(_Utils.arrayAt(sArgs, i));
+      Rti tArg = _Utils.asRti(_Utils.arrayAt(tArgs, i));
       if (JS_GET_FLAG("VARIANCE")) {
         int sVariance = hasVariances != null
             ? _Utils.asInt(_Utils.arrayAt(sVariances, i))
@@ -2871,7 +2878,7 @@
   // We don't list Object explicitly as a supertype of each interface, so check
   // this trivial case first.
   if (isObjectType(t)) return true;
-  Object? rule = _Universe.findRule(universe, sName);
+  var rule = _Universe.findRule(universe, sName);
   if (rule == null) return false;
   var supertypeArgs = TypeRule.lookupSupertype(rule, tName);
   if (supertypeArgs == null) return false;
@@ -2881,7 +2888,7 @@
   for (int i = 0; i < length; i++) {
     String recipe = _Utils.asString(_Utils.arrayAt(supertypeArgs, i));
     Rti supertypeArg = _Universe.evalInEnvironment(universe, s, recipe);
-    Rti tArg = _castToRti(_Utils.arrayAt(tArgs, i));
+    Rti tArg = _Utils.asRti(_Utils.arrayAt(tArgs, i));
     if (!_isSubtype(universe, supertypeArg, sEnv, tArg, tEnv)) {
       return false;
     }
@@ -2919,30 +2926,29 @@
 bool isJsFunctionType(Rti t) =>
     _Utils.isIdentical(t, TYPE_REF<JavaScriptFunction>());
 
-/// Unchecked cast to Rti.
-Rti _castToRti(s) => JS('Rti', '#', s);
-Rti? _castToRtiOrNull(s) => JS('Rti|Null', '#', s);
-
 class _Utils {
-  static bool asBool(o) => JS('bool', '#', o);
-  static double asDouble(o) => JS('double', '#', o);
-  static int asInt(o) => JS('int', '#', o);
-  static num asNum(o) => JS('num', '#', o);
-  static String asString(o) => JS('String', '#', o);
+  static bool asBool(Object? o) => JS('bool', '#', o);
+  static double asDouble(Object? o) => JS('double', '#', o);
+  static int asInt(Object? o) => JS('int', '#', o);
+  static num asNum(Object? o) => JS('num', '#', o);
+  static String asString(Object? o) => JS('String', '#', o);
+  static Rti asRti(Object? s) => JS('Rti', '#', s);
+  static Rti? asRtiOrNull(Object? s) => JS('Rti|Null', '#', s);
 
-  static bool isString(o) => JS('bool', 'typeof # == "string"', o);
-  static bool isNum(o) => JS('bool', 'typeof # == "number"', o);
+  static bool isString(Object? o) => JS('bool', 'typeof # == "string"', o);
+  static bool isNum(Object? o) => JS('bool', 'typeof # == "number"', o);
 
-  static bool instanceOf(o, Object constructor) =>
+  static bool instanceOf(Object? o, Object? constructor) =>
       JS('bool', '# instanceof #', o, constructor);
 
-  static bool isIdentical(s, t) => JS('bool', '# === #', s, t);
-  static bool isNotIdentical(s, t) => JS('bool', '# !== #', s, t);
+  static bool isIdentical(Object? s, Object? t) => JS('bool', '# === #', s, t);
+  static bool isNotIdentical(Object? s, Object? t) =>
+      JS('bool', '# !== #', s, t);
 
-  static JSArray objectKeys(Object o) =>
+  static JSArray objectKeys(Object? o) =>
       JS('returns:JSArray;new:true;', 'Object.keys(#)', o);
 
-  static void objectAssign(Object o, Object other) {
+  static void objectAssign(Object? o, Object? other) {
     // TODO(fishythefish): Use `Object.assign()` when IE11 is deprecated.
     var keys = objectKeys(other);
     int length = arrayLength(keys);
@@ -2952,26 +2958,26 @@
     }
   }
 
-  static bool isArray(o) => JS('bool', 'Array.isArray(#)', o);
+  static bool isArray(Object? o) => JS('bool', 'Array.isArray(#)', o);
 
-  static int arrayLength(Object array) => JS('int', '#.length', array);
+  static int arrayLength(Object? array) => JS('int', '#.length', array);
 
-  static Object arrayAt(Object array, int i) => JS('', '#[#]', array, i);
+  static Object? arrayAt(Object? array, int i) => JS('', '#[#]', array, i);
 
-  static void arraySetAt(Object array, int i, value) {
+  static void arraySetAt(Object? array, int i, Object? value) {
     JS('', '#[#] = #', array, i, value);
   }
 
-  static JSArray arrayShallowCopy(Object array) =>
+  static JSArray arrayShallowCopy(Object? array) =>
       JS('JSArray', '#.slice()', array);
 
-  static JSArray arraySplice(Object array, int position) =>
+  static JSArray arraySplice(Object? array, int position) =>
       JS('JSArray', '#.splice(#)', array, position);
 
-  static JSArray arrayConcat(Object a1, Object a2) =>
+  static JSArray arrayConcat(Object? a1, Object? a2) =>
       JS('JSArray', '#.concat(#)', a1, a2);
 
-  static void arrayPush(Object array, value) {
+  static void arrayPush(Object? array, Object? value) {
     JS('', '#.push(#)', array, value);
   }
 
@@ -2981,56 +2987,56 @@
   static bool stringLessThan(String s1, String s2) =>
       JS('bool', '# < #', s1, s2);
 
-  static mapGet(cache, key) => JS('', '#.get(#)', cache, key);
+  static Object? mapGet(Object? cache, Object? key) =>
+      JS('', '#.get(#)', cache, key);
 
-  static void mapSet(cache, key, value) {
+  static void mapSet(Object? cache, Object? key, Object? value) {
     JS('', '#.set(#, #)', cache, key, value);
   }
 }
 // -------- Entry points for testing -------------------------------------------
 
-String testingCanonicalRecipe(rti) {
+String testingCanonicalRecipe(Rti rti) {
   return Rti._getCanonicalRecipe(rti);
 }
 
-String testingRtiToString(rti) {
-  return _rtiToString(_castToRti(rti), null);
+String testingRtiToString(Rti rti) {
+  return _rtiToString(rti, null);
 }
 
-String testingRtiToDebugString(rti) {
-  return _rtiToDebugString(_castToRti(rti));
+String testingRtiToDebugString(Rti rti) {
+  return _rtiToDebugString(rti);
 }
 
 Object testingCreateUniverse() {
   return _Universe.create();
 }
 
-void testingAddRules(universe, rules) {
+void testingAddRules(Object? universe, Object? rules) {
   _Universe.addRules(universe, rules);
 }
 
-void testingAddTypeParameterVariances(universe, variances) {
+void testingAddTypeParameterVariances(Object? universe, Object? variances) {
   _Universe.addTypeParameterVariances(universe, variances);
 }
 
-bool testingIsSubtype(universe, rti1, rti2) {
-  return isSubtype(universe, _castToRti(rti1), _castToRti(rti2));
+bool testingIsSubtype(Object? universe, Rti rti1, Rti rti2) {
+  return isSubtype(universe, rti1, rti2);
 }
 
-Object testingUniverseEval(universe, String recipe) {
+Rti testingUniverseEval(Object? universe, String recipe) {
   return _Universe.eval(universe, recipe, true);
 }
 
-void testingUniverseEvalOverride(universe, String recipe, Rti rti) {
+void testingUniverseEvalOverride(Object? universe, String recipe, Rti rti) {
   var cache = _Universe.evalCache(universe);
-  _Universe._cacheSet(cache, recipe, rti);
+  _Utils.mapSet(cache, recipe, rti);
 }
 
-Object testingEnvironmentEval(universe, environment, String recipe) {
-  return _Universe.evalInEnvironment(universe, _castToRti(environment), recipe);
+Rti testingEnvironmentEval(Object? universe, Rti environment, String recipe) {
+  return _Universe.evalInEnvironment(universe, environment, recipe);
 }
 
-Object testingEnvironmentBind(universe, environment, arguments) {
-  return _Universe.bind(
-      universe, _castToRti(environment), _castToRti(arguments));
+Rti testingEnvironmentBind(Object? universe, Rti environment, Rti arguments) {
+  return _Universe.bind(universe, environment, arguments);
 }
diff --git a/sdk_nnbd/lib/_internal/vm/bin/filter_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/filter_patch.dart
index 2bcf5a9..06898f4 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/filter_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/filter_patch.dart
@@ -7,7 +7,7 @@
 class _FilterImpl extends NativeFieldWrapperClass1 implements RawZLibFilter {
   void process(List<int> data, int start, int end) native "Filter_Process";
 
-  List<int> processed({bool flush: true, bool end: false})
+  List<int>? processed({bool flush: true, bool end: false})
       native "Filter_Processed";
 }
 
diff --git a/sdk_nnbd/lib/_internal/vm/bin/secure_socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/secure_socket_patch.dart
index 69cc88a..9a0586d 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/secure_socket_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/secure_socket_patch.dart
@@ -104,7 +104,7 @@
 
   int processBuffer(int bufferIndex) => throw new UnimplementedError();
 
-  String selectedProtocol() native "SecureSocket_GetSelectedProtocol";
+  String? selectedProtocol() native "SecureSocket_GetSelectedProtocol";
 
   void renegotiate(bool useSessionCache, bool requestClientCertificate,
       bool requireClientCertificate) native "SecureSocket_Renegotiate";
diff --git a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
index 8ef06ed..b5ea987 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
@@ -1446,7 +1446,7 @@
         controller.add(_RawSocket(socket));
         if (controller.isPaused) return;
       }
-    }), error: zone.bindBinaryCallbackGuarded((Object e, StackTrace st) {
+    }), error: zone.bindBinaryCallbackGuarded((Object e, StackTrace? st) {
       controller.addError(e, st);
       controller.close();
     }), destroyed: () {
@@ -1560,7 +1560,7 @@
           _controller.add(RawSocketEvent.closed);
           _controller.close();
         },
-        error: zone.bindBinaryCallbackGuarded((Object e, StackTrace st) {
+        error: zone.bindBinaryCallbackGuarded((Object e, StackTrace? st) {
           _controller.addError(e, st);
           _socket.close();
         }));
@@ -2113,7 +2113,7 @@
           _controller.add(RawSocketEvent.closed);
           _controller.close();
         },
-        error: zone.bindBinaryCallbackGuarded((Object e, StackTrace st) {
+        error: zone.bindBinaryCallbackGuarded((Object e, StackTrace? st) {
           _controller.addError(e, st);
           _socket.close();
         }));
@@ -2187,9 +2187,9 @@
   void set multicastHops(int value) =>
       _socket.setOption(SocketOption._ipMulticastHops, value);
 
-  NetworkInterface get multicastInterface => throw "Not implemented";
+  NetworkInterface get multicastInterface => throw UnimplementedError();
   void set multicastInterface(NetworkInterface? value) =>
-      throw "Not implemented";
+      throw UnimplementedError();
 
   bool get broadcastEnabled => _socket.getOption(SocketOption._ipBroadcast);
   void set broadcastEnabled(bool value) =>
diff --git a/sdk_nnbd/lib/_internal/vm/lib/array.dart b/sdk_nnbd/lib/_internal/vm/lib/array.dart
index 1922173..5304841 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/array.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/array.dart
@@ -6,8 +6,8 @@
 
 @pragma("vm:entry-point")
 class _List<E> extends FixedLengthListBase<E> {
-  @pragma(
-      "vm:exact-result-type", [_List, "result-type-uses-passed-type-arguments"])
+  @pragma("vm:exact-result-type",
+      <dynamic>[_List, "result-type-uses-passed-type-arguments"])
   @pragma("vm:prefer-inline")
   factory _List(length) native "List_allocate";
 
diff --git a/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
index a03c772..3020fea 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
@@ -45,7 +45,7 @@
   }
 
   @pragma("vm:entry-point")
-  void start(f) {
+  void start(void Function() f) {
     f();
     isSync = true;
   }
@@ -56,8 +56,8 @@
 
 // We need to pass the value as first argument and leave the second and third
 // arguments empty (used for error handling).
-// See vm/ast_transformer.cc for usage.
-Function _asyncThenWrapperHelper(continuation) {
+dynamic Function(dynamic) _asyncThenWrapperHelper(
+    dynamic Function(dynamic) continuation) {
   // Any function that is used as an asynchronous callback must be registered
   // in the current Zone. Normally, this is done by the future when a
   // callback is registered (for example with `.then` or `.catchError`). In our
@@ -74,16 +74,18 @@
   // `Future` implementation could potentially invoke the callback with the
   // wrong number of arguments.
   if (Zone.current == Zone.root) return continuation;
-  return Zone.current.registerUnaryCallback(continuation);
+  return Zone.current.registerUnaryCallback<dynamic, dynamic>(continuation);
 }
 
 // We need to pass the exception and stack trace objects as second and third
-// parameter to the continuation.  See vm/ast_transformer.cc for usage.
-Function _asyncErrorWrapperHelper(continuation) {
+// parameter to the continuation.
+dynamic Function(Object, StackTrace) _asyncErrorWrapperHelper(
+    dynamic Function(dynamic, dynamic, StackTrace) continuation) {
   // See comments of `_asyncThenWrapperHelper`.
-  void errorCallback(Object e, StackTrace s) => continuation(null, e, s);
+  dynamic errorCallback(Object e, StackTrace s) => continuation(null, e, s);
   if (Zone.current == Zone.root) return errorCallback;
-  return Zone.current.registerBinaryCallback(errorCallback);
+  return Zone.current
+      .registerBinaryCallback<dynamic, Object, StackTrace>(errorCallback);
 }
 
 /// Registers the [thenCallback] and [errorCallback] on the given [object].
@@ -91,11 +93,8 @@
 /// If [object] is not a future, then it is wrapped into one.
 ///
 /// Returns the result of registering with `.then`.
-Future _awaitHelper(
-    var object,
-    FutureOr<dynamic> Function(dynamic) thenCallback,
-    Function errorCallback,
-    var awaiter) {
+Future _awaitHelper(var object, dynamic Function(dynamic) thenCallback,
+    dynamic Function(dynamic, StackTrace) errorCallback, Function awaiter) {
   late _Future future;
   if (object is! Future) {
     future = new _Future().._setValue(object);
@@ -113,7 +112,7 @@
   // We can only do this for our internal futures (the default implementation of
   // all futures that are constructed by the `dart:async` library).
   future._awaiter = awaiter;
-  return future._thenAwait(thenCallback, errorCallback);
+  return future._thenAwait<dynamic>(thenCallback, errorCallback);
 }
 
 // Called as part of the 'await for (...)' construct. Registers the
diff --git a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
index 4060970..3a964d6 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
@@ -201,7 +201,7 @@
   // unresolved method.
   @pragma("vm:entry-point", "call")
   static void _throwNew(Object receiver, String memberName, int invocationType,
-      Object typeArguments, List arguments, List argumentNames) {
+      Object? typeArguments, List? arguments, List? argumentNames) {
     throw new NoSuchMethodError._withType(receiver, memberName, invocationType,
         typeArguments, arguments, argumentNames);
   }
@@ -260,9 +260,9 @@
       this._receiver,
       String memberName,
       int invocationType,
-      Object typeArguments,
-      List arguments,
-      List argumentNames)
+      Object? typeArguments,
+      List? arguments,
+      List? argumentNames)
       : this._invocation = new _InvocationMirror._withType(
             new Symbol(memberName),
             invocationType,
@@ -271,10 +271,10 @@
                 ? _InvocationMirror._unpackTypeArguments(typeArguments, 0)
                 : null,
             argumentNames != null
-                ? arguments.sublist(0, arguments.length - argumentNames.length)
+                ? arguments!.sublist(0, arguments.length - argumentNames.length)
                 : arguments,
             argumentNames != null
-                ? _NamedArgumentsMap(arguments, argumentNames)
+                ? _NamedArgumentsMap(arguments!, argumentNames)
                 : null);
 
   static String? _existingMethodSignature(Object receiver, String methodName,
@@ -596,6 +596,7 @@
 
 class _LateInitializationError extends Error
     implements LateInitializationError {
+  @pragma("vm:entry-point")
   _LateInitializationError(this._name);
 
   @pragma("vm:entry-point")
diff --git a/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart
index d5749b0..d42689c 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart
@@ -64,10 +64,13 @@
 // implementation, since that would pull the callback trampoline into JIT
 // snapshots. The callback trampolines can only be serialized into AOT snapshots
 // because they embed the addresses of runtime routines in JIT mode.
-Object _nativeCallbackFunction<NS extends Function>(Function target,
+//
+// Function objects returned by this native method are not Dart instances,
+// so we need to use top type as a return type to avoid type check.
+dynamic _nativeCallbackFunction<NS extends Function>(Function target,
     Object exceptionalReturn) native "Ffi_nativeCallbackFunction";
 
-Pointer<NS> _pointerFromFunction<NS extends NativeFunction>(Object function)
+Pointer<NS> _pointerFromFunction<NS extends NativeFunction>(dynamic function)
     native "Ffi_pointerFromFunction";
 
 @patch
diff --git a/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
index e4dcee5..bca95ab 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
@@ -108,7 +108,7 @@
   }
 
   @pragma("vm:exact-result-type",
-      [_GrowableList, "result-type-uses-passed-type-arguments"])
+      <dynamic>[_GrowableList, "result-type-uses-passed-type-arguments"])
   factory _GrowableList._withData(_List data) native "GrowableList_allocate";
 
   @pragma("vm:exact-result-type", "dart:core#_Smi")
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
index 6ed550a..a7f1f13 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
@@ -1330,7 +1330,7 @@
   final int _position;
   final bool isOptional;
   final bool isNamed;
-  final List _unmirroredMetadata;
+  final List? _unmirroredMetadata;
 
   _ParameterMirror._(
       reflectee,
diff --git a/sdk_nnbd/lib/_internal/vm/lib/symbol_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/symbol_patch.dart
index 8b78e85..06eb588 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/symbol_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/symbol_patch.dart
@@ -10,7 +10,7 @@
   const Symbol(String name) : this._name = name;
 
   @patch
-  toString() => 'Symbol("${computeUnmangledName(this)}")';
+  String toString() => 'Symbol("${computeUnmangledName(this)}")';
 
   @patch
   static String computeUnmangledName(Symbol symbol) {
diff --git a/sdk_nnbd/lib/async/future.dart b/sdk_nnbd/lib/async/future.dart
index d1273aa..30748ca 100644
--- a/sdk_nnbd/lib/async/future.dart
+++ b/sdk_nnbd/lib/async/future.dart
@@ -223,9 +223,8 @@
       if (result is Future<T>) {
         return result;
       } else {
-        if (result is! T)
-          throw "unreachable"; // TODO(lrn): Remove when type promotion works.
-        return new _Future<T>.value(result);
+        // TODO(40014): Remove cast when type promotion works.
+        return new _Future<T>.value(result as dynamic);
       }
     } catch (error, stackTrace) {
       var future = new _Future<T>();
diff --git a/sdk_nnbd/lib/async/future_impl.dart b/sdk_nnbd/lib/async/future_impl.dart
index b23bfdb0..11c8f26 100644
--- a/sdk_nnbd/lib/async/future_impl.dart
+++ b/sdk_nnbd/lib/async/future_impl.dart
@@ -511,8 +511,11 @@
       }
     } else {
       _FutureListener? listeners = _removeListeners();
-      // TODO(lrn): Remove cast when type promotion works.
-      _setValue(value as T); // Value promoted to T.
+      // TODO(40014): Remove cast when type promotion works.
+      // This would normally be `as T` but we use `as dynamic` to make the
+      // unneeded check be implict to match dart2js unsound optimizations in the
+      // user code.
+      _setValue(value as dynamic); // Value promoted to T.
       _propagateToListeners(this, listeners);
     }
   }
@@ -553,8 +556,11 @@
     }
     _setPendingComplete();
     _zone.scheduleMicrotask(() {
-      // TODO(lrn): Remove cast when type promotion works.
-      _completeWithValue(value as T); // Value promoted to T.
+      // TODO(40014): Remove cast when type promotion works.
+      // This would normally be `as T` but we use `as dynamic` to make the
+      // unneeded check be implict to match dart2js unsound optimizations in the
+      // user code.
+      _completeWithValue(value as dynamic); // Value promoted to T.
     });
   }
 
diff --git a/sdk_nnbd/lib/async/stream.dart b/sdk_nnbd/lib/async/stream.dart
index d504a42..b0d41f4 100644
--- a/sdk_nnbd/lib/async/stream.dart
+++ b/sdk_nnbd/lib/async/stream.dart
@@ -523,10 +523,8 @@
           subscription.pause();
           newValue.then(add, onError: addError).whenComplete(resume);
         } else {
-          if (newValue is! E) {
-            throw "unreachable"; // TODO(lrn): Remove when type promotion works.
-          }
-          controller.add(newValue);
+          // TODO(40014): Remove cast when type promotion works.
+          controller.add(newValue as dynamic);
         }
       });
       controller.onCancel = subscription.cancel;
diff --git a/sdk_nnbd/lib/convert/base64.dart b/sdk_nnbd/lib/convert/base64.dart
index c36ba1a..0955ca1 100644
--- a/sdk_nnbd/lib/convert/base64.dart
+++ b/sdk_nnbd/lib/convert/base64.dart
@@ -651,10 +651,11 @@
     // all the characters in `charOr` and later validate that all characters
     // were ASCII.
     var charOr = 0;
+    final inverseAlphabet = _Base64Decoder._inverseAlphabet;
     for (var i = start; i < end; i++) {
       var char = input.codeUnitAt(i);
       charOr |= char;
-      var code = _inverseAlphabet[char & asciiMask];
+      var code = inverseAlphabet[char & asciiMask];
       if (code >= 0) {
         bits = ((bits << bitsPerCharacter) | code) & 0xFFFFFF;
         count = (count + 1) & 3;
diff --git a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
index c8d19df..d648c04 100644
--- a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
+++ b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
@@ -4049,7 +4049,7 @@
 
   String get cssFloat native;
 
-  set cssFloat(String value) native;
+  set cssFloat(String? value) native;
 
   String get cssText native;
 
@@ -11795,6 +11795,10 @@
     }
   }
 
+  void insertAll(int index, Iterable<Element> iterable) {
+    throw new UnimplementedError();
+  }
+
   void setAll(int index, Iterable<Element> iterable) {
     throw new UnimplementedError();
   }
@@ -11805,6 +11809,7 @@
 
   Element removeAt(int index) {
     final result = this[index];
+    // TODO(41258): Remove null check after unfork/strong mode.
     if (result != null) {
       _element._removeChild(result);
     }
@@ -11813,9 +11818,7 @@
 
   Element removeLast() {
     final result = this.last;
-    if (result != null) {
-      _element._removeChild(result);
-    }
+    _element._removeChild(result);
     return result;
   }
 
@@ -12881,6 +12884,7 @@
 
   @pragma('dart2js:tryInline')
   String? getAttribute(String name) {
+    // TODO(41258): Delete this assertion after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     return _getAttribute(name);
@@ -12888,6 +12892,7 @@
 
   @pragma('dart2js:tryInline')
   String? getAttributeNS(String? namespaceURI, String name) {
+    // TODO(41258): Delete this assertion after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     // [namespaceURI] does not need protecting, both `null` and `undefined` map to `null`.
     assert(name != null, 'Attribute name cannot be null');
@@ -12896,6 +12901,7 @@
 
   @pragma('dart2js:tryInline')
   bool hasAttribute(String name) {
+    // TODO(41258): Delete this assertion after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     return _hasAttribute(name);
@@ -12903,6 +12909,7 @@
 
   @pragma('dart2js:tryInline')
   bool hasAttributeNS(String? namespaceURI, String name) {
+    // TODO(41258): Delete this assertion after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     // [namespaceURI] does not need protecting, both `null` and `undefined` map to `null`.
     assert(name != null, 'Attribute name cannot be null');
@@ -12911,6 +12918,7 @@
 
   @pragma('dart2js:tryInline')
   void removeAttribute(String name) {
+    // TODO(41258): Delete this assertion after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     _removeAttribute(name);
@@ -12918,6 +12926,7 @@
 
   @pragma('dart2js:tryInline')
   void removeAttributeNS(String? namespaceURI, String name) {
+    // TODO(41258): Delete this assertion after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     _removeAttributeNS(namespaceURI, name);
@@ -12925,6 +12934,7 @@
 
   @pragma('dart2js:tryInline')
   void setAttribute(String name, String value) {
+    // TODO(41258): Delete these assertions after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     // TODO(sra): assert(value != null, 'Attribute value cannot be null.');
@@ -12933,6 +12943,7 @@
 
   @pragma('dart2js:tryInline')
   void setAttributeNS(String? namespaceURI, String name, String value) {
+    // TODO(41258): Delete these assertions after forcing strong mode.
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     // TODO(sra): assert(value != null, 'Attribute value cannot be null.');
@@ -13726,7 +13737,7 @@
    * This uses the default sanitization behavior to sanitize the HTML fragment,
    * use [setInnerHtml] to override the default behavior.
    */
-  set innerHtml(String html) {
+  set innerHtml(String? html) {
     this.setInnerHtml(html);
   }
 
@@ -13751,13 +13762,13 @@
    * * [NodeValidator]
    * * [NodeTreeSanitizer]
    */
-  void setInnerHtml(String html,
+  void setInnerHtml(String? html,
       {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     text = null;
     if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
       _innerHtml = html;
     } else {
-      append(createFragment(html,
+      append(createFragment(html!,
           validator: validator, treeSanitizer: treeSanitizer));
     }
   }
@@ -14551,7 +14562,7 @@
   String get _innerHtml native;
 
   @JSName('innerHTML')
-  set _innerHtml(String value) native;
+  set _innerHtml(String? value) native;
 
   @JSName('localName')
   String get _localName native;
@@ -15399,7 +15410,7 @@
 
 // WARNING: Do not edit - generated code.
 
-@Native("Event,InputEvent")
+@Native("Event,InputEvent,SubmitEvent")
 class Event extends Interceptor {
   // In JS, canBubble and cancelable are technically required parameters to
   // init*Event. In practice, though, if they aren't provided they simply
@@ -19185,7 +19196,7 @@
 
   String get value native;
 
-  set value(String value) native;
+  set value(String? value) native;
 
   DateTime get valueAsDate =>
       convertNativeToDart_DateTime(this._get_valueAsDate);
@@ -19266,7 +19277,7 @@
   set name(String value);
 
   String get value;
-  set value(String value);
+  set value(String? value);
 
   List<Node> get labels;
 
@@ -22514,7 +22525,7 @@
         NavigatorOnLine,
         NavigatorAutomationInformation,
         NavigatorID {
-  List<Gamepad> getGamepads() {
+  List<Gamepad?> getGamepads() {
     var gamepadList = _getGamepads();
 
     // If no prototype we need one for the world to hookup to the proper Dart class.
@@ -22666,7 +22677,7 @@
   @JSName('getGamepads')
   @Returns('_GamepadList')
   @Creates('_GamepadList')
-  List<Gamepad> _getGamepads() native;
+  List<Gamepad?> _getGamepads() native;
 
   Future<RelatedApplication> getInstalledRelatedApps() =>
       promiseToFuture<RelatedApplication>(
@@ -27847,7 +27858,7 @@
   String get innerHtml native;
 
   @JSName('innerHTML')
-  set innerHtml(String value) native;
+  set innerHtml(String? value) native;
 
   String get mode native;
 
@@ -29255,7 +29266,7 @@
 
   String get headers native;
 
-  set headers(String value) native;
+  set headers(String? value) native;
 
   int get rowSpan native;
 
@@ -29570,11 +29581,11 @@
    *
    * * <https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin>
    */
-  void setInnerHtml(String html,
+  void setInnerHtml(String? html,
       {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     text = null;
     content.nodes.clear();
-    var fragment = createFragment(html,
+    var fragment = createFragment(html!,
         validator: validator, treeSanitizer: treeSanitizer);
 
     content.append(fragment);
@@ -29712,7 +29723,7 @@
 
   String get value native;
 
-  set value(String value) native;
+  set value(String? value) native;
 
   bool get willValidate native;
 
@@ -35685,7 +35696,7 @@
   _ElementAttributeMap(Element element) : super(element);
 
   bool containsKey(Object? key) {
-    return _element._hasAttribute(key as String);
+    return key is String && _element._hasAttribute(key);
   }
 
   String? operator [](Object? key) {
@@ -35711,8 +35722,8 @@
   // Inline this because almost all call sites of [remove] do not use [value],
   // and the annotations on the `getAttribute` call allow it to be removed.
   @pragma('dart2js:tryInline')
-  static String _remove(Element element, String key) {
-    String value = JS(
+  static String? _remove(Element element, String key) {
+    String? value = JS(
         // throws:null(1) is not accurate since [key] could be malformed, but
         // [key] is checked again by `removeAttributeNS`.
         'returns:String|Null;depends:all;effects:none;throws:null(1)',
@@ -35728,12 +35739,12 @@
  * Wrapper to expose namespaced attributes as a typed map.
  */
 class _NamespacedAttributeMap extends _AttributeMap {
-  final String _namespace;
+  final String? _namespace;
 
   _NamespacedAttributeMap(Element element, this._namespace) : super(element);
 
   bool containsKey(Object? key) {
-    return _element._hasAttributeNS(_namespace, key as String);
+    return key is String && _element._hasAttributeNS(_namespace, key);
   }
 
   String? operator [](Object? key) {
@@ -35761,8 +35772,8 @@
   // returned [value], and the annotations on the `getAttributeNS` call allow it
   // to be removed.
   @pragma('dart2js:tryInline')
-  static String _remove(String namespace, Element element, String key) {
-    String value = JS(
+  static String? _remove(String? namespace, Element element, String key) {
+    String? value = JS(
         // throws:null(1) is not accurate since [key] could be malformed, but
         // [key] is checked again by `removeAttributeNS`.
         'returns:String|Null;depends:all;effects:none;throws:null(1)',
@@ -36097,7 +36108,8 @@
    * after the operation, and returns `false` if [value] is absent after the
    * operation.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To toggle multiple classes, use
@@ -36131,7 +36143,8 @@
    * If this CssClassSet corresponds to one element. Returns true if [value] was
    * added to the set, otherwise false.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To add multiple classes use
@@ -40622,14 +40635,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.
 
-void Function(T)? _wrapZone<T>(void Function(T) callback) {
+void Function(T)? _wrapZone<T>(void Function(T)? callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.root) return callback;
   if (callback == null) return null;
   return Zone.current.bindUnaryCallbackGuarded(callback);
 }
 
-void Function(T1, T2)? _wrapBinaryZone<T1, T2>(void Function(T1, T2) callback) {
+void Function(T1, T2)? _wrapBinaryZone<T1, T2>(
+    void Function(T1, T2)? callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.root) return callback;
   if (callback == null) return null;
@@ -40944,7 +40958,7 @@
   /// important attributes we want to check, remove it if it's not valid
   /// or not allowed, either as a whole or particular attributes.
   void _sanitizeElement(Element element, Node? parent, bool corrupted,
-      String text, String tag, Map attrs, String isAttr) {
+      String text, String tag, Map attrs, String? isAttr) {
     if (false != corrupted) {
       _removeNode(element, parent);
       window.console
diff --git a/sdk_nnbd/lib/html/html_common/css_class_set.dart b/sdk_nnbd/lib/html/html_common/css_class_set.dart
index 3421b75..ff15a4d 100644
--- a/sdk_nnbd/lib/html/html_common/css_class_set.dart
+++ b/sdk_nnbd/lib/html/html_common/css_class_set.dart
@@ -108,7 +108,7 @@
     _validateToken(value);
     // TODO - figure out if we need to do any validation here
     // or if the browser natively does enough.
-    return modify((s) => s.add(value));
+    return modify((s) => s.add(value)) ?? false;
   }
 
   /**
diff --git a/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 4bbd020..4cb159b 100644
--- a/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -1002,7 +1002,7 @@
     request.onError.listen(controller.addError);
 
     request.onSuccess.listen((e) {
-      T cursor = request.result as dynamic;
+      T? cursor = request.result as dynamic;
       if (cursor == null) {
         controller.close();
       } else {
diff --git a/sdk_nnbd/lib/io/common.dart b/sdk_nnbd/lib/io/common.dart
index e6a56bc..dd4e46f 100644
--- a/sdk_nnbd/lib/io/common.dart
+++ b/sdk_nnbd/lib/io/common.dart
@@ -50,7 +50,7 @@
   * operating system.
   */
 @pragma("vm:entry-point")
-class OSError {
+class OSError implements Exception {
   /** Constant used to indicate that no OS error code is available. */
   static const int noErrorCode = -1;
 
diff --git a/sdk_nnbd/lib/io/file_impl.dart b/sdk_nnbd/lib/io/file_impl.dart
index 7be1bf3..eed5268 100644
--- a/sdk_nnbd/lib/io/file_impl.dart
+++ b/sdk_nnbd/lib/io/file_impl.dart
@@ -166,8 +166,8 @@
   _FileStreamConsumer.fromStdio(int fd)
       : _openFuture = new Future.value(_File._openStdioSync(fd));
 
-  Future<File> addStream(Stream<List<int>> stream) {
-    Completer<File> completer = new Completer<File>.sync();
+  Future<File?> addStream(Stream<List<int>> stream) {
+    Completer<File?> completer = new Completer<File?>.sync();
     _openFuture.then((openedFile) {
       late StreamSubscription<List<int>> _subscription;
       void error(e, StackTrace stackTrace) {
diff --git a/sdk_nnbd/lib/io/io_sink.dart b/sdk_nnbd/lib/io/io_sink.dart
index d4a3ec8..622656a 100644
--- a/sdk_nnbd/lib/io/io_sink.dart
+++ b/sdk_nnbd/lib/io/io_sink.dart
@@ -31,8 +31,7 @@
    * The [Encoding] used when writing strings. Depending on the
    * underlying consumer this property might be mutable.
    */
-  Encoding get encoding;
-  void set encoding(Encoding newEncoding);
+  late Encoding encoding;
 
   /**
    * Adds byte [data] to the target consumer, ignoring [encoding].
diff --git a/sdk_nnbd/lib/io/secure_socket.dart b/sdk_nnbd/lib/io/secure_socket.dart
index fef9d16..08e9bf7 100644
--- a/sdk_nnbd/lib/io/secure_socket.dart
+++ b/sdk_nnbd/lib/io/secure_socket.dart
@@ -113,7 +113,7 @@
     return ((socket as dynamic /*_Socket*/)._detachRaw() as Future)
         .then<RawSecureSocket>((detachedRaw) {
       return RawSecureSocket.secure(detachedRaw[0] as RawSocket,
-          subscription: detachedRaw[1] as StreamSubscription<RawSocketEvent>,
+          subscription: detachedRaw[1] as StreamSubscription<RawSocketEvent>?,
           host: host,
           context: context,
           onBadCertificate: onBadCertificate,
@@ -151,7 +151,7 @@
     return ((socket as dynamic /*_Socket*/)._detachRaw() as Future)
         .then<RawSecureSocket>((detachedRaw) {
       return RawSecureSocket.secureServer(detachedRaw[0] as RawSocket, context,
-          subscription: detachedRaw[1] as StreamSubscription<RawSocketEvent>,
+          subscription: detachedRaw[1] as StreamSubscription<RawSocketEvent>?,
           bufferedData: bufferedData,
           requestClientCertificate: requestClientCertificate,
           requireClientCertificate: requireClientCertificate,
@@ -1236,7 +1236,7 @@
       Uint8List protocols);
   void destroy();
   void handshake();
-  String selectedProtocol();
+  String? selectedProtocol();
   void rehandshake();
   void renegotiate(bool useSessionCache, bool requestClientCertificate,
       bool requireClientCertificate);
diff --git a/sdk_nnbd/lib/js_util/js_util.dart b/sdk_nnbd/lib/js_util/js_util.dart
index 86fd582..605f6d6 100644
--- a/sdk_nnbd/lib/js_util/js_util.dart
+++ b/sdk_nnbd/lib/js_util/js_util.dart
@@ -76,10 +76,14 @@
 dynamic callMethod(Object o, String method, List<Object?> args) =>
     JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
 
-bool instanceof(Object? o, Function type) =>
+/// Check whether [o] is an instance of [type].
+///
+/// The value in [type] is expected to be a JS-interop object that
+/// represents a valid JavaScript constructor function.
+bool instanceof(Object? o, Object type) =>
     JS('bool', '# instanceof #', o, type);
 
-dynamic callConstructor(Function constr, List<Object?> arguments) {
+dynamic callConstructor(Object constr, List<Object?> arguments) {
   if (arguments == null) {
     return JS('Object', 'new #()', constr);
   }
diff --git a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
index 8eaabef..3e319cd 100644
--- a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
@@ -3037,7 +3037,7 @@
     return container.innerHtml;
   }
 
-  set innerHtml(String value) {
+  set innerHtml(String? value) {
     this.setInnerHtml(value);
   }
 
diff --git a/tests/compiler/dart2js/end_to_end/output_type_test.dart b/tests/compiler/dart2js/end_to_end/output_type_test.dart
index 150e8f4..9a0a7b6 100644
--- a/tests/compiler/dart2js/end_to_end/output_type_test.dart
+++ b/tests/compiler/dart2js/end_to_end/output_type_test.dart
@@ -90,7 +90,7 @@
       'custom.js_1.part.js', 'custom.js_1.part.js.map',
       'def/deferred.json', // From --deferred-map
       'custom.js.info.json', // From --dump-info
-      'dart.cfg', // From TRACE_FILTER_PATTERN_FOR_TEST
+      'custom.js.cfg', // From TRACE_FILTER_PATTERN_FOR_TEST
     ], groupOutputs: [
       '.dot', // From PRINT_GRAPH
     ]);
diff --git a/tests/compiler/dart2js/generic_methods/generic_method_type_test.dart b/tests/compiler/dart2js/generic_methods/generic_method_type_test.dart
index ef4dfc5..a6a17a0 100644
--- a/tests/compiler/dart2js/generic_methods/generic_method_type_test.dart
+++ b/tests/compiler/dart2js/generic_methods/generic_method_type_test.dart
@@ -34,9 +34,11 @@
     """);
 
     for (FunctionTypeData data in signatures) {
-      FunctionType functionType = env.getElementType('t${data.name}');
+      FunctionType functionType =
+          env.getElementType('t${data.name}').withoutNullability;
       FunctionEntity method = env.getElement('m${data.name}');
-      FunctionType methodType = env.getElementType('m${data.name}');
+      FunctionType methodType =
+          env.getElementType('m${data.name}').withoutNullability;
       ParameterStructure parameterStructure = method.parameterStructure;
       Expect.equals(functionType, methodType, "Type mismatch on $data");
       Expect.equals(
diff --git a/tests/compiler/dart2js/optimization/optimization_test.dart b/tests/compiler/dart2js/optimization/optimization_test.dart
index e2687f6..b5f2987 100644
--- a/tests/compiler/dart2js/optimization/optimization_test.dart
+++ b/tests/compiler/dart2js/optimization/optimization_test.dart
@@ -38,7 +38,7 @@
   const OptimizationDataValidator({this.strict: false});
 
   @override
-  String getText(OptimizationTestLog actualData) {
+  String getText(OptimizationTestLog actualData, [String indentation]) {
     Features features = new Features();
     for (OptimizationLogEntry entry in actualData.entries) {
       features.addElement(
diff --git a/tests/compiler/dart2js_extra/constant_folding2_test.dart b/tests/compiler/dart2js_extra/constant_folding2_test.dart
new file mode 100644
index 0000000..b8fbee4
--- /dev/null
+++ b/tests/compiler/dart2js_extra/constant_folding2_test.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.
+
+import 'dart:async';
+import 'package:expect/expect.dart';
+
+get b => 499;
+@pragma('dart2js:noInline')
+get b_noInline => b;
+const b0 = 499 is FutureOr<int>;
+final b1 = 499 is FutureOr<int>;
+get b2 => 499 is FutureOr<int>;
+get b3 => b is FutureOr<int>;
+get b4 => b_noInline is FutureOr<int>;
+
+get c => 499;
+@pragma('dart2js:noInline')
+get c_noInline => c;
+const c0 = 499 is FutureOr<FutureOr<int>>;
+final c1 = 499 is FutureOr<FutureOr<int>>;
+get c2 => 499 is FutureOr<FutureOr<int>>;
+get c3 => c is FutureOr<FutureOr<int>>;
+get c4 => c_noInline is FutureOr<FutureOr<int>>;
+
+get d => 499.0;
+@pragma('dart2js:noInline')
+get d_noInline => d;
+const d0 = 499.0 is FutureOr<int>;
+final d1 = 499.0 is FutureOr<int>;
+get d2 => 499.0 is FutureOr<int>;
+get d3 => d is FutureOr<int>;
+get d4 => d_noInline is FutureOr<int>;
+
+get e => 499;
+@pragma('dart2js:noInline')
+get e_noInline => e;
+const e0 = 499 is FutureOr<double>;
+final e1 = 499 is FutureOr<double>;
+get e2 => 499 is FutureOr<double>;
+get e3 => e is FutureOr<double>;
+get e4 => e_noInline is FutureOr<double>;
+
+get f => 499;
+@pragma('dart2js:noInline')
+get f_noInline => f;
+const f0 = 499 is FutureOr<FutureOr<double>>;
+final f1 = 499 is FutureOr<FutureOr<double>>;
+get f2 => 499 is FutureOr<FutureOr<double>>;
+get f3 => f is FutureOr<FutureOr<double>>;
+get f4 => f_noInline is FutureOr<FutureOr<double>>;
+
+test(fromConst, fromFinal, fromImplicitConstant, fromInlined, fromRuntime) {
+  Expect.equals(fromRuntime, fromConst);
+  Expect.equals(fromRuntime, fromFinal);
+  Expect.equals(fromRuntime, fromInlined);
+  Expect.equals(fromRuntime, fromImplicitConstant);
+}
+
+main() {
+  test(b0, b1, b2, b3, b4);
+  test(c0, c1, c2, c3, c4);
+  test(d0, d1, d2, d3, d4);
+  test(e0, e1, e2, e3, e4);
+  test(f0, f1, f2, f3, f4);
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js_extra/constant_truncate_test.dart b/tests/compiler/dart2js_extra/constant_truncate_test.dart
new file mode 100644
index 0000000..9d2c4de
--- /dev/null
+++ b/tests/compiler/dart2js_extra/constant_truncate_test.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 a0 = 0 ~/ 0; //# a0: compile-time error
+const a1 = 0.0 ~/ 0; //# a1: compile-time error
+const a2 = -0.0 ~/ 0; //# a2: compile-time error
+const a3 = double.nan ~/ 0; //# a3: compile-time error
+const a4 = double.infinity ~/ 0; //# a4: compile-time error
+const a5 = double.negativeInfinity ~/ 0; //# a5: compile-time error
+
+const b0 = 0 ~/ 0.0; //# b0: compile-time error
+const b1 = 0.0 ~/ 0.0; //# b1: compile-time error
+const b2 = -0.0 ~/ 0.0; //# b2: compile-time error
+const b3 = double.nan ~/ 0.0; //# b3: compile-time error
+const b4 = double.infinity ~/ 0.0; //# b4: compile-time error
+const b5 = double.negativeInfinity ~/ 0.0; //# b5: compile-time error
+
+const c0 = 0 ~/ -0.0; //# c0: compile-time error
+const c1 = 0.0 ~/ -0.0; //# c1: compile-time error
+const c2 = -0.0 ~/ -0.0; //# c2: compile-time error
+const c3 = double.nan ~/ -0.0; //# c3: compile-time error
+const c4 = double.infinity ~/ -0.0; //# c4: compile-time error
+const c5 = double.negativeInfinity ~/ -0.0; //# c5: compile-time error
+
+const d0 = 0 ~/ double.nan; //# d0: compile-time error
+const d1 = 0.0 ~/ double.nan; //# d1: compile-time error
+const d2 = -0.0 ~/ double.nan; //# d2: compile-time error
+const d3 = double.nan ~/ double.nan; //# d3: compile-time error
+const d4 = double.infinity ~/ double.nan; //# d4: compile-time error
+const d5 = double.negativeInfinity ~/ double.nan; //# d5: compile-time error
+
+const e0 = 0 ~/ double.infinity; //# e0: ok
+const e1 = 0.0 ~/ double.infinity; //# e1: ok
+const e2 = -0.0 ~/ double.infinity; //# e2: ok
+const e3 = double.nan ~/ double.infinity; //# e3: compile-time error
+const e4 = double.infinity ~/ double.infinity; //# e4: compile-time error
+const e5 = double.negativeInfinity ~/ double.infinity; //# e5: compile-time error
+
+const f0 = 0 ~/ double.negativeInfinity; //# f0: ok
+const f1 = 0.0 ~/ double.negativeInfinity; //# f1: ok
+const f2 = -0.0 ~/ double.negativeInfinity; //# f2: ok
+const f3 = double.nan ~/ double.negativeInfinity; //# f3: compile-time error
+const f4 = double.infinity ~/ double.negativeInfinity; //# f4: compile-time error
+const f5 = double.negativeInfinity ~/ double.negativeInfinity; //# f5: compile-time error
+
+main() {
+  test(0, 0, () => a0); //# a0: continued
+  test(0.0, 0, () => a1); //# a1: continued
+  test(-0.0, 0, () => a2); //# a2: continued
+  test(double.nan, 0, () => a3); //# a3: continued
+  test(double.infinity, 0, () => a4); //# a4: continued
+  test(double.negativeInfinity, 0, () => a5); //# a5: continued
+
+  test(0, 0.0, () => b0); //# b0: continued
+  test(0.0, 0.0, () => b1); //# b1: continued
+  test(-0.0, 0.0, () => b2); //# b2: continued
+  test(double.nan, 0.0, () => b3); //# b3: continued
+  test(double.infinity, 0.0, () => b4); //# b4: continued
+  test(double.negativeInfinity, 0.0, () => b5); //# b5: continued
+
+  test(0, -0.0, () => c0); //# c0: continued
+  test(0.0, -0.0, () => c1); //# c1: continued
+  test(-0.0, -0.0, () => c2); //# c2: continued
+  test(double.nan, -0.0, () => c3); //# c3: continued
+  test(double.infinity, -0.0, () => c4); //# c4: continued
+  test(double.negativeInfinity, -0.0, () => c5); //# c5: continued
+
+  test(0, double.nan, () => d0); //# d0: continued
+  test(0.0, double.nan, () => d1); //# d1: continued
+  test(-0.0, double.nan, () => d2); //# d2: continued
+  test(double.nan, double.nan, () => d3); //# d3: continued
+  test(double.infinity, double.nan, () => d4); //# d4: continued
+  test(double.negativeInfinity, double.nan, () => d5); //# d5: continued
+
+  test(0, double.infinity, () => e0); //# e0: continued
+  test(0.0, double.infinity, () => e1); //# e1: continued
+  test(-0.0, double.infinity, () => e2); //# e2: continued
+  test(double.nan, double.infinity, () => e3); //# e3: continued
+  test(double.infinity, double.infinity, () => e4); //# e4: continued
+  test(double.negativeInfinity, double.infinity, () => e5); //# e5: continued
+
+  test(0, double.negativeInfinity, () => f0); //# f0: continued
+  test(0.0, double.negativeInfinity, () => f1); //# f1: continued
+  test(-0.0, double.negativeInfinity, () => f2); //# f2: continued
+  test(double.nan, double.negativeInfinity, () => f3); //# f3: continued
+  test(double.infinity, double.negativeInfinity, () => f4); //# f4: continued
+  test(double.negativeInfinity, double.negativeInfinity, () => f5); //# f5: continued
+}
+
+void test(num a, num b, num Function() f) {
+  num result;
+  try {
+    result = a ~/ b;
+    print('$a ~/ $b = $result');
+  } catch (e) {
+    print('$a ~/ $b throws $e');
+    throws(f);
+    return;
+  }
+  expect(f(), result);
+}
+
+void expect(expected, actual) {
+  if (expected != actual) {
+    throw 'Expected $expected, actual $actual';
+  }
+}
+
+void throws(num Function() f) {
+  try {
+    f();
+  } catch (e) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/tests/compiler/dartdevc_native/nnbd_basic_assignment.dart b/tests/compiler/dartdevc_native/nnbd_basic_assignment_test.dart
similarity index 100%
rename from tests/compiler/dartdevc_native/nnbd_basic_assignment.dart
rename to tests/compiler/dartdevc_native/nnbd_basic_assignment_test.dart
diff --git a/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart b/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
index 9bc25d9..e6d5448 100644
--- a/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
+++ b/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
@@ -1,12 +1,18 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for 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-strong
 
-import 'dart:async' show Future;
+import 'dart:_runtime' show typeRep, legacyTypeRep;
+import 'dart:async' show FutureOr;
 
-import 'runtime_utils.dart' show futureOrOf, voidType;
+import 'runtime_utils.dart'
+    show
+        checkSubtype,
+        checkProperSubtype,
+        checkMutualSubtype,
+        checkSubtypeFailure;
 import 'runtime_utils_nnbd.dart';
 
 class A {}
@@ -23,271 +29,259 @@
 
 void main() {
   // Top type symmetry.
-  // Object? <: dynamic
-  checkSubtype(nullable(Object), dynamic);
-  // dynamic <: Object?
-  checkSubtype(dynamic, nullable(Object));
-  // Object? <: void
-  checkSubtype(nullable(Object), voidType);
-  // void <: Object?
-  checkSubtype(voidType, nullable(Object));
-  // void <: dynamic
-  checkSubtype(voidType, dynamic);
-  // dynamic <: void
-  checkSubtype(dynamic, voidType);
+  // Object? <:> dynamic
+  checkMutualSubtype(typeRep<Object?>(), typeRep<dynamic>());
+  // Object? <:> void
+  checkMutualSubtype(typeRep<Object?>(), typeRep<void>());
+  // void <:> dynamic
+  checkMutualSubtype(typeRep<void>(), typeRep<dynamic>());
 
   // Bottom is subtype of top.
-  // never <: dynamic
-  checkProperSubtype(Never, dynamic);
-  // never <: void
-  checkProperSubtype(Never, voidType);
-  // never <: Object?
-  checkProperSubtype(Never, nullable(Object));
+  // Never <: dynamic
+  checkProperSubtype(typeRep<Never>(), typeRep<dynamic>());
+  // Never <: void
+  checkProperSubtype(typeRep<Never>(), typeRep<void>());
+  // Never <: Object?
+  checkProperSubtype(typeRep<Never>(), typeRep<Object?>());
 
   // Object is between top and bottom.
   // Object <: Object?
-  checkProperSubtype(Object, nullable(Object));
-  // never <: Object
-  checkProperSubtype(Never, Object);
+  checkSubtype(typeRep<Object>(), typeRep<Object?>());
+  // Never <: Object
+  checkProperSubtype(typeRep<Never>(), typeRep<Object>());
 
   // Null is between top and bottom.
   // Null <: Object?
-  checkProperSubtype(Null, nullable(Object));
-  // never <: Null
-  checkProperSubtype(Never, Null);
+  checkProperSubtype(typeRep<Null>(), typeRep<Object?>());
+  // Never <: Null
+  checkProperSubtype(typeRep<Never>(), typeRep<Null>());
 
   // Class is between Object and bottom.
   // A <: Object
-  checkProperSubtype(A, dynamic);
-  // never <: A
-  checkProperSubtype(Never, A);
+  checkProperSubtype(typeRep<A>(), typeRep<dynamic>());
+  // Never <: A
+  checkProperSubtype(typeRep<Never>(), typeRep<A>());
 
   // Nullable types are a union of T and Null.
   // A <: A?
-  checkProperSubtype(A, nullable(A));
+  checkProperSubtype(typeRep<A>(), typeRep<A?>());
   // Null <: A?
-  checkProperSubtype(Null, nullable(A));
+  checkProperSubtype(typeRep<Null>(), typeRep<A?>());
   // A? <: Object?
-  checkProperSubtype(nullable(A), nullable(Object));
+  checkProperSubtype(typeRep<A?>(), typeRep<Object?>());
 
   // Legacy types will eventually be migrated to T or T? but until then are
   // symmetric with both.
-  // Object* <: Object
-  checkSubtype(legacy(Object), Object);
-  // Object <: Object*
-  checkSubtype(Object, legacy(Object));
-  // Object* <: Object?
-  checkSubtype(legacy(Object), nullable(Object));
-  // Object? <: Object*
-  checkSubtype(nullable(Object), legacy(Object));
+  // Object* <:> Object
+  checkMutualSubtype(legacyTypeRep<Object>(), typeRep<Object>());
+  // Object* <:> Object?
+  checkMutualSubtype(legacyTypeRep<Object>(), typeRep<Object?>());
+
+  // Bottom Types
   // Null <: Object*
-  checkSubtype(Null, legacy(Object));
-  // never <: Object*
-  checkSubtype(Never, legacy(Object));
-  // A* <: A
-  checkSubtype(legacy(A), A);
-  // A <: A*
-  checkSubtype(A, legacy(A));
-  // A* <: A?
-  checkSubtype(legacy(A), nullable(A));
-  // A? <: A*
-  checkSubtype(nullable(A), legacy(A));
+  checkSubtype(typeRep<Null>(), legacyTypeRep<Object>());
+  // Never <: Object*
+  checkSubtype(typeRep<Never>(), legacyTypeRep<Object>());
+  // A* <:> A
+  checkMutualSubtype(legacyTypeRep<A>(), typeRep<A>());
+  // A* <:> A?
+  checkMutualSubtype(legacyTypeRep<A>(), typeRep<A?>());
   // A* <: Object
-  checkProperSubtype(legacy(A), Object);
+  checkProperSubtype(legacyTypeRep<A>(), typeRep<Object>());
   // A* <: Object?
-  checkProperSubtype(legacy(A), nullable(Object));
+  checkProperSubtype(legacyTypeRep<A>(), typeRep<Object?>());
   // Null <: A*
-  checkProperSubtype(Null, legacy(A));
-  // never <: A*
-  checkProperSubtype(Never, legacy(A));
+  checkProperSubtype(typeRep<Null>(), legacyTypeRep<A>());
+  // Never <: A*
+  checkProperSubtype(typeRep<Never>(), legacyTypeRep<A>());
 
   // Futures.
   // Null <: FutureOr<Object?>
-  checkProperSubtype(Null, futureOrOf(nullable(Object)));
+  checkProperSubtype(typeRep<Null>(), typeRep<FutureOr<Object?>>());
   // Object <: FutureOr<Object?>
-  checkProperSubtype(Object, futureOrOf(nullable(Object)));
-  // Object? <: FutureOr<Object?>
-  checkSubtype(nullable(Object), futureOrOf(nullable(Object)));
-  // Object <: FutureOr<Object>
-  checkSubtype(Object, futureOrOf(Object));
-  // FutureOr<Object> <: Object
-  checkSubtype(futureOrOf(Object), Object);
+  checkProperSubtype(typeRep<Object>(), typeRep<FutureOr<Object?>>());
+  // Object? <:> FutureOr<Object?>
+  checkMutualSubtype(typeRep<Object?>(), typeRep<FutureOr<Object?>>());
+  // Object <:> FutureOr<Object>
+  checkMutualSubtype(typeRep<Object>(), typeRep<FutureOr<Object>>());
   // Object <: FutureOr<dynamic>
-  checkProperSubtype(Object, futureOrOf(dynamic));
+  checkProperSubtype(typeRep<Object>(), typeRep<FutureOr<dynamic>>());
   // Object <: FutureOr<void>
-  checkProperSubtype(Object, futureOrOf(voidType));
+  checkProperSubtype(typeRep<Object>(), typeRep<FutureOr<void>>());
   // Future<Object> <: FutureOr<Object?>
-  checkProperSubtype(generic1(Future, Object), futureOrOf(nullable(Object)));
+  checkProperSubtype(typeRep<Future<Object>>(), typeRep<FutureOr<Object?>>());
   // Future<Object?> <: FutureOr<Object?>
-  checkProperSubtype(
-      generic1(Future, nullable(Object)), futureOrOf(nullable(Object)));
+  checkProperSubtype(typeRep<Future<Object?>>(), typeRep<FutureOr<Object?>>());
   // FutureOr<Never> <: Future<Never>
-  checkSubtype(futureOrOf(Never), generic1(Future, Never));
+  checkSubtype(typeRep<FutureOr<Never>>(), typeRep<Future<Never>>());
   // Future<B> <: FutureOr<A>
-  checkProperSubtype(generic1(Future, B), futureOrOf(A));
+  checkProperSubtype(typeRep<Future<B>>(), typeRep<FutureOr<A>>());
   // B <: <: FutureOr<A>
-  checkProperSubtype(B, futureOrOf(A));
+  checkProperSubtype(typeRep<B>(), typeRep<FutureOr<A>>());
   // Future<B> <: Future<A>
-  checkProperSubtype(generic1(Future, B), generic1(Future, A));
+  checkProperSubtype(typeRep<Future<B>>(), typeRep<Future<A>>());
 
   // Interface subtypes.
   // A <: A
-  checkSubtype(A, A);
+  checkSubtype(typeRep<A>(), typeRep<A>());
   // B <: A
-  checkProperSubtype(B, A);
+  checkProperSubtype(typeRep<B>(), typeRep<A>());
   // C <: B
-  checkProperSubtype(C, B);
+  checkProperSubtype(typeRep<C>(), typeRep<B>());
   // C <: A
-  checkProperSubtype(C, A);
+  checkProperSubtype(typeRep<C>(), typeRep<A>());
 
   // Functions.
   // A -> B <: Function
-  checkProperSubtype(function1(B, A), Function);
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<Function>());
 
   // A -> B <: A -> B
-  checkSubtype(function1(B, A), function1(B, A));
+  checkSubtype(typeRep<B Function(A)>(), typeRep<B Function(A)>());
 
   // A -> B <: B -> B
-  checkProperSubtype(function1(B, A), function1(B, B));
-  // TODO(nshahan) Subtype check with covariant keyword?
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<B Function(B)>());
 
   // A -> B <: A -> A
-  checkSubtype(function1(B, A), function1(A, A));
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<A Function(A)>());
 
   // Generic Function Subtypes.
   // Bound is a built in type.
   // <T extends int> void -> void <: <T extends int> void -> void
-  checkSubtype(genericFunction(int), genericFunction(int));
+  checkSubtype(
+      genericFunction(typeRep<int>()), genericFunction(typeRep<int>()));
 
   // <T extends String> A -> T <: <T extends String> B -> T
-  checkProperSubtype(
-      functionGenericReturn(String, A), functionGenericReturn(String, B));
+  checkProperSubtype(functionGenericReturn(typeRep<String>(), typeRep<A>()),
+      functionGenericReturn(typeRep<String>(), typeRep<B>()));
 
   // <T extends double> T -> B <: <T extends double> T -> A
-  checkProperSubtype(
-      functionGenericArg(double, B), functionGenericArg(double, A));
+  checkProperSubtype(functionGenericArg(typeRep<double>(), typeRep<B>()),
+      functionGenericArg(typeRep<double>(), typeRep<A>()));
 
   // Bound is a function type.
   // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
-  checkSubtype(
-      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
+  checkSubtype(genericFunction(typeRep<A Function(B)>()),
+      genericFunction(typeRep<A Function(B)>()));
 
   // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
-  checkProperSubtype(functionGenericReturn(function1(B, A), A),
-      functionGenericReturn(function1(B, A), B));
+  checkProperSubtype(
+      functionGenericReturn(typeRep<A Function(B)>(), typeRep<A>()),
+      functionGenericReturn(typeRep<A Function(B)>(), typeRep<B>()));
 
   // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
-  checkProperSubtype(functionGenericArg(function1(B, A), B),
-      functionGenericArg(function1(B, A), A));
+  checkProperSubtype(functionGenericArg(typeRep<A Function(B)>(), typeRep<B>()),
+      functionGenericArg(typeRep<A Function(B)>(), typeRep<A>()));
 
   // Bound is a user defined class.
   // <T extends B> void -> void <: <T extends B> void -> void
-  checkSubtype(genericFunction(B), genericFunction(B));
+  checkSubtype(genericFunction(typeRep<B>()), genericFunction(typeRep<B>()));
 
   // <T extends B> A -> T <: <T extends B> B -> T
-  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
+  checkProperSubtype(functionGenericReturn(typeRep<B>(), typeRep<A>()),
+      functionGenericReturn(typeRep<B>(), typeRep<B>()));
 
   // <T extends B> T -> B <: <T extends B> T -> A
-  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
+  checkProperSubtype(functionGenericArg(typeRep<B>(), typeRep<B>()),
+      functionGenericArg(typeRep<B>(), typeRep<A>()));
 
   // Bound is a Future.
   // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
-  checkSubtype(genericFunction(generic1(Future, B)),
-      genericFunction(generic1(Future, B)));
+  checkSubtype(genericFunction(typeRep<Future<B>>()),
+      genericFunction(typeRep<Future<B>>()));
 
   // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
-  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
-      functionGenericReturn(generic1(Future, B), B));
+  checkProperSubtype(functionGenericReturn(typeRep<Future<B>>(), typeRep<A>()),
+      functionGenericReturn(typeRep<Future<B>>(), typeRep<B>()));
 
   // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
-  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
-      functionGenericArg(generic1(Future, B), A));
+  checkProperSubtype(functionGenericArg(typeRep<Future<B>>(), typeRep<B>()),
+      functionGenericArg(typeRep<Future<B>>(), typeRep<A>()));
 
   // Bound is a FutureOr.
   // <T extends FutureOr<B>> void -> void <:
   //    <T extends FutureOr<B>> void -> void
-  checkSubtype(genericFunction(futureOrOf(B)), genericFunction(futureOrOf(B)));
+  checkSubtype(genericFunction(typeRep<FutureOr<B>>()),
+      genericFunction(typeRep<FutureOr<B>>()));
 
   // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
-  checkProperSubtype(functionGenericReturn(futureOrOf(B), A),
-      functionGenericReturn(futureOrOf(B), B));
+  checkProperSubtype(
+      functionGenericReturn(typeRep<FutureOr<B>>(), typeRep<A>()),
+      functionGenericReturn(typeRep<FutureOr<B>>(), typeRep<B>()));
 
   // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
-  checkProperSubtype(functionGenericArg(futureOrOf(B), B),
-      functionGenericArg(futureOrOf(B), A));
+  checkProperSubtype(functionGenericArg(typeRep<FutureOr<B>>(), typeRep<B>()),
+      functionGenericArg(typeRep<FutureOr<B>>(), typeRep<A>()));
 
   // Generics.
-  // D <: D<B>
-  checkSubtype(D, generic1(D, B));
-  // D<B> <: D
-  checkSubtype(generic1(D, B), D);
+  // D <:> D<B>
+  checkMutualSubtype(typeRep<D>(), typeRep<D<B>>());
   // D<C> <: D<B>
-  checkProperSubtype(generic1(D, C), generic1(D, B));
+  checkProperSubtype(typeRep<D<C>>(), typeRep<D<B>>());
 
   // F <: E
-  checkProperSubtype(F, E);
+  checkProperSubtype(typeRep<F>(), typeRep<E>());
   // F <: E<A, A>
-  checkProperSubtype(F, generic2(E, A, A));
+  checkProperSubtype(typeRep<F>(), typeRep<E<A, A>>());
+  // E<B, B> <: E
+  checkProperSubtype(typeRep<E<B, B>>(), typeRep<E>());
   // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), E);
-  // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
+  checkProperSubtype(typeRep<E<B, B>>(), typeRep<E<A, A>>());
 
   // Nullable interface subtypes.
   // B <: A?
-  checkProperSubtype(B, nullable(A));
+  checkProperSubtype(typeRep<B>(), typeRep<A?>());
   // C <: A?
-  checkProperSubtype(C, nullable(A));
+  checkProperSubtype(typeRep<C>(), typeRep<A?>());
   // B? <: A?
-  checkProperSubtype(nullable(B), nullable(A));
+  checkProperSubtype(typeRep<B?>(), typeRep<A?>());
   // C? <: A?
-  checkProperSubtype(nullable(C), nullable(A));
+  checkProperSubtype(typeRep<C?>(), typeRep<A?>());
 
   // Mixed mode.
   // B* <: A
-  checkProperSubtype(legacy(B), A);
+  checkProperSubtype(legacyTypeRep<B>(), typeRep<A>());
   // B* <: A?
-  checkProperSubtype(legacy(B), nullable(A));
+  checkProperSubtype(legacyTypeRep<B>(), typeRep<A?>());
   // A* <\: B
-  checkSubtypeFailure(legacy(A), B);
+  checkSubtypeFailure(legacyTypeRep<A>(), typeRep<B>());
   // B? <: A*
-  checkProperSubtype(nullable(B), legacy(A));
+  checkProperSubtype(typeRep<B?>(), legacyTypeRep<A>());
   // B <: A*
-  checkProperSubtype(B, legacy(A));
+  checkProperSubtype(typeRep<B>(), legacyTypeRep<A>());
   // A <: B*
-  checkSubtypeFailure(A, legacy(B));
+  checkSubtypeFailure(typeRep<A>(), legacyTypeRep<B>());
   // A? <: B*
-  checkSubtypeFailure(nullable(A), legacy(B));
+  checkSubtypeFailure(typeRep<A?>(), legacyTypeRep<B>());
 
   // Allowed in weak mode.
   // dynamic <\: Object
-  checkSubtypeFailure(dynamic, Object);
+  checkSubtypeFailure(typeRep<dynamic>(), typeRep<Object>());
   // void <\: Object
-  checkSubtypeFailure(voidType, Object);
+  checkSubtypeFailure(typeRep<void>(), typeRep<Object>());
   // Object? <\: Object
-  checkSubtypeFailure(nullable(Object), Object);
+  checkSubtypeFailure(typeRep<Object?>(), typeRep<Object>());
   // A? <\: Object
-  checkSubtypeFailure(nullable(A), Object);
+  checkSubtypeFailure(typeRep<A?>(), typeRep<Object>());
   // A? <\: A
-  checkSubtypeFailure(nullable(A), A);
-  // Null <\: never
-  checkSubtypeFailure(Null, Never);
+  checkSubtypeFailure(typeRep<A?>(), typeRep<A>());
+  // Null <\: Never
+  checkSubtypeFailure(typeRep<Null>(), typeRep<Never>());
   // Null <\: Object
-  checkSubtypeFailure(Null, Object);
+  checkSubtypeFailure(typeRep<Null>(), typeRep<Object>());
   // Null <\: A
-  checkSubtypeFailure(Null, A);
+  checkSubtypeFailure(typeRep<Null>(), typeRep<A>());
   // Null <\: FutureOr<A>
-  checkSubtypeFailure(Null, futureOrOf(A));
+  checkSubtypeFailure(typeRep<Null>(), typeRep<FutureOr<A>>());
   // Null <\: Future<A>
-  checkSubtypeFailure(Null, generic1(Future, A));
+  checkSubtypeFailure(typeRep<Null>(), typeRep<Future<A>>());
   // FutureOr<Null> <\: Future<Null>
-  checkSubtypeFailure(futureOrOf(Null), generic1(Future, Null));
+  checkSubtypeFailure(typeRep<FutureOr<Null>>(), typeRep<Future<Null>>());
   // Null <\: Future<A?>
-  checkSubtypeFailure(Null, generic1(Future, nullable(A)));
+  checkSubtypeFailure(typeRep<Null>(), typeRep<Future<A?>>());
   // FutureOr<Object?> <\: Object
-  checkSubtypeFailure(futureOrOf(nullable(Object)), Object);
+  checkSubtypeFailure(typeRep<FutureOr<Object?>>(), typeRep<Object>());
   // FutureOr<dynamic> <\: Object
-  checkSubtypeFailure(futureOrOf(dynamic), Object);
+  checkSubtypeFailure(typeRep<FutureOr<dynamic>>(), typeRep<Object>());
   // FutureOr<void> <\: Object
-  checkSubtypeFailure(futureOrOf(voidType), Object);
+  checkSubtypeFailure(typeRep<FutureOr<void>>(), typeRep<Object>());
 }
diff --git a/tests/compiler/dartdevc_native/nnbd_type_normalization_test.dart b/tests/compiler/dartdevc_native/nnbd_type_normalization_test.dart
index 6946585..2ae889c 100644
--- a/tests/compiler/dartdevc_native/nnbd_type_normalization_test.dart
+++ b/tests/compiler/dartdevc_native/nnbd_type_normalization_test.dart
@@ -4,35 +4,34 @@
 
 // Requirements=nnbd
 
-import 'dart:_runtime' as dart;
+import 'dart:_runtime' show legacy, nullable, typeRep, legacyTypeRep;
 
 import 'package:expect/expect.dart';
 
-import 'runtime_utils_nnbd.dart';
-
 class A {}
 
 void main() {
   // A?? == A?
-  Expect.identical(nullable(nullable(A)), nullable(A));
+  Expect.identical(nullable(typeRep<A?>()), typeRep<A?>());
   // A?* == A?
-  Expect.identical(legacy(nullable(A)), nullable(A));
+  Expect.identical(legacy(typeRep<A?>()), typeRep<A?>());
   // A*? == A?
-  Expect.identical(nullable(legacy(A)), nullable(A));
+  Expect.identical(nullable(legacyTypeRep<A>()), typeRep<A?>());
   // A** == A*
-  Expect.identical(legacy(legacy(A)), legacy(A));
+  Expect.identical(legacy(legacyTypeRep<A>()), legacyTypeRep<A>());
+
+  // The tests below need explicit wrapping in nullable and legacy to ensure
+  // they appear at runtime and the runtime library normalizes them correctly.
   // Null? == Null
-  Expect.identical(nullable(Null), Null);
+  Expect.identical(nullable(typeRep<Null>()), typeRep<Null>());
   // Never? == Null
-  Expect.identical(nullable(Never), Null);
+  Expect.identical(nullable(typeRep<Never>()), typeRep<Null>());
   // dynamic? == dynamic
-  Expect.identical(nullable(dynamic), dynamic);
+  Expect.identical(nullable(typeRep<dynamic>()), typeRep<dynamic>());
   // void? == void
-  Expect.identical(
-      nullable(dart.wrapType(dart.void_)), dart.wrapType(dart.void_));
+  Expect.identical(nullable(typeRep<void>()), typeRep<void>());
   // dynamic* == dynamic
-  Expect.identical(legacy(dynamic), dynamic);
+  Expect.identical(legacy(typeRep<dynamic>()), typeRep<dynamic>());
   // void* == void
-  Expect.identical(
-      legacy(dart.wrapType(dart.void_)), dart.wrapType(dart.void_));
+  Expect.identical(legacy(typeRep<void>()), typeRep<void>());
 }
diff --git a/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart b/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
index 9160e7a..205d2f1 100644
--- a/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
+++ b/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
@@ -1,12 +1,18 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for 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
 
+import 'dart:_runtime' show typeRep, legacyTypeRep;
 import 'dart:async';
 
-import 'runtime_utils.dart' show futureOrOf, voidType;
+import 'runtime_utils.dart'
+    show
+        checkSubtype,
+        checkProperSubtype,
+        checkMutualSubtype,
+        checkSubtypeFailure;
 import 'runtime_utils_nnbd.dart';
 
 class A {}
@@ -23,271 +29,259 @@
 
 void main() {
   // Top type symmetry.
-  // Object? <: dynamic
-  checkSubtype(nullable(Object), dynamic);
-  // dynamic <: Object?
-  checkSubtype(dynamic, nullable(Object));
-  // Object? <: void
-  checkSubtype(nullable(Object), voidType);
-  // void <: Object?
-  checkSubtype(voidType, nullable(Object));
-  // void <: dynamic
-  checkSubtype(voidType, dynamic);
-  // dynamic <: void
-  checkSubtype(dynamic, voidType);
+  // Object? <:> dynamic
+  checkMutualSubtype(typeRep<Object?>(), typeRep<dynamic>());
+  // Object? <:> void
+  checkMutualSubtype(typeRep<Object?>(), typeRep<void>());
+  // void <:> dynamic
+  checkMutualSubtype(typeRep<void>(), typeRep<dynamic>());
 
   // Bottom is subtype of top.
-  // never <: dynamic
-  checkProperSubtype(Never, dynamic);
-  // never <: void
-  checkProperSubtype(Never, voidType);
-  // never <: Object?
-  checkProperSubtype(Never, nullable(Object));
+  // Never <: dynamic
+  checkProperSubtype(typeRep<Never>(), typeRep<dynamic>());
+  // Never <: void
+  checkProperSubtype(typeRep<Never>(), typeRep<void>());
+  // Never <: Object?
+  checkProperSubtype(typeRep<Never>(), typeRep<Object?>());
 
   // Object is between top and bottom.
   // Object <: Object?
-  checkSubtype(Object, nullable(Object));
-  // never <: Object
-  checkProperSubtype(Never, Object);
+  checkSubtype(typeRep<Object>(), typeRep<Object?>());
+  // Never <: Object
+  checkProperSubtype(typeRep<Never>(), typeRep<Object>());
 
   // Null is between top and bottom.
   // Null <: Object?
-  checkProperSubtype(Null, nullable(Object));
-  // never <: Null
-  checkSubtype(Never, Null);
+  checkProperSubtype(typeRep<Null>(), typeRep<Object?>());
+  // Never <: Null
+  checkSubtype(typeRep<Never>(), typeRep<Null>());
 
   // Class is between Object and bottom.
   // A <: Object
-  checkProperSubtype(A, dynamic);
-  // never <: A
-  checkProperSubtype(Never, A);
+  checkProperSubtype(typeRep<A>(), typeRep<dynamic>());
+  // Never <: A
+  checkProperSubtype(typeRep<Never>(), typeRep<A>());
 
   // Nullable types are a union of T and Null.
   // A <: A?
-  checkSubtype(A, nullable(A));
+  checkSubtype(typeRep<A>(), typeRep<A?>());
   // Null <: A?
-  checkProperSubtype(Null, nullable(A));
+  checkProperSubtype(typeRep<Null>(), typeRep<A?>());
   // A? <: Object?
-  checkProperSubtype(nullable(A), nullable(Object));
+  checkProperSubtype(typeRep<A?>(), typeRep<Object?>());
 
   // Legacy types will eventually be migrated to T or T? but until then are
   // symmetric with both.
-  // Object* <: Object
-  checkSubtype(legacy(Object), Object);
-  // Object <: Object*
-  checkSubtype(Object, legacy(Object));
-  // Object* <: Object?
-  checkSubtype(legacy(Object), nullable(Object));
-  // Object? <: Object*
-  checkSubtype(nullable(Object), legacy(Object));
+  // Object* <:> Object
+  checkMutualSubtype(legacyTypeRep<Object>(), typeRep<Object>());
+  // Object* <:> Object?
+  checkMutualSubtype(legacyTypeRep<Object>(), typeRep<Object?>());
+
+  // Bottom Types
   // Null <: Object*
-  checkSubtype(Null, legacy(Object));
-  // never <: Object*
-  checkSubtype(Never, legacy(Object));
-  // A* <: A
-  checkSubtype(legacy(A), A);
-  // A <: A*
-  checkSubtype(A, legacy(A));
-  // A* <: A?
-  checkSubtype(legacy(A), nullable(A));
-  // A? <: A*
-  checkSubtype(nullable(A), legacy(A));
+  checkSubtype(typeRep<Null>(), legacyTypeRep<Object>());
+  // Never <: Object*
+  checkSubtype(typeRep<Never>(), legacyTypeRep<Object>());
+  // A* <:> A
+  checkMutualSubtype(legacyTypeRep<A>(), typeRep<A>());
+  // A* <:> A?
+  checkMutualSubtype(legacyTypeRep<A>(), typeRep<A?>());
   // A* <: Object
-  checkProperSubtype(legacy(A), Object);
+  checkProperSubtype(legacyTypeRep<A>(), typeRep<Object>());
   // A* <: Object?
-  checkProperSubtype(legacy(A), nullable(Object));
+  checkProperSubtype(legacyTypeRep<A>(), typeRep<Object?>());
   // Null <: A*
-  checkProperSubtype(Null, legacy(A));
-  // never <: A*
-  checkProperSubtype(Never, legacy(A));
+  checkProperSubtype(typeRep<Null>(), legacyTypeRep<A>());
+  // Never <: A*
+  checkProperSubtype(typeRep<Never>(), legacyTypeRep<A>());
 
   // Futures.
   // Null <: FutureOr<Object?>
-  checkProperSubtype(Null, futureOrOf(nullable(Object)));
+  checkProperSubtype(typeRep<Null>(), typeRep<FutureOr<Object?>>());
   // Object <: FutureOr<Object?>
-  checkSubtype(Object, futureOrOf(nullable(Object)));
-  // Object? <: FutureOr<Object?>
-  checkSubtype(nullable(Object), futureOrOf(nullable(Object)));
-  // Object <: FutureOr<Object>
-  checkSubtype(Object, futureOrOf(Object));
-  // FutureOr<Object> <: Object
-  checkSubtype(futureOrOf(Object), Object);
-  // Object <: FutureOr<dynamic>
-  checkSubtype(Object, futureOrOf(dynamic));
-  // Object <: FutureOr<void>
-  checkSubtype(Object, futureOrOf(voidType));
+  checkSubtype(typeRep<Object>(), typeRep<FutureOr<Object?>>());
+  // Object? <:> FutureOr<Object?>
+  checkMutualSubtype(typeRep<Object?>(), typeRep<FutureOr<Object?>>());
+  // Object <:> FutureOr<Object>
+  checkMutualSubtype(typeRep<Object>(), typeRep<FutureOr<Object>>());
+  // Object <:> FutureOr<dynamic>
+  checkMutualSubtype(typeRep<Object>(), typeRep<FutureOr<dynamic>>());
+  // Object <:> FutureOr<void>
+  checkMutualSubtype(typeRep<Object>(), typeRep<FutureOr<void>>());
   // Future<Object> <: FutureOr<Object?>
-  checkProperSubtype(generic1(Future, Object), futureOrOf(nullable(Object)));
+  checkProperSubtype(typeRep<Future<Object>>(), typeRep<FutureOr<Object?>>());
   // Future<Object?> <: FutureOr<Object?>
-  checkProperSubtype(
-      generic1(Future, nullable(Object)), futureOrOf(nullable(Object)));
+  checkProperSubtype(typeRep<Future<Object?>>(), typeRep<FutureOr<Object?>>());
   // FutureOr<Never> <: Future<Never>
-  checkSubtype(futureOrOf(Never), generic1(Future, Never));
+  checkSubtype(typeRep<FutureOr<Never>>(), typeRep<Future<Never>>());
   // Future<B> <: FutureOr<A>
-  checkProperSubtype(generic1(Future, B), futureOrOf(A));
+  checkProperSubtype(typeRep<Future<B>>(), typeRep<FutureOr<A>>());
   // B <: <: FutureOr<A>
-  checkProperSubtype(B, futureOrOf(A));
+  checkProperSubtype(typeRep<B>(), typeRep<FutureOr<A>>());
   // Future<B> <: Future<A>
-  checkProperSubtype(generic1(Future, B), generic1(Future, A));
+  checkProperSubtype(typeRep<Future<B>>(), typeRep<Future<A>>());
 
   // Interface subtypes.
   // A <: A
-  checkSubtype(A, A);
+  checkSubtype(typeRep<A>(), typeRep<A>());
   // B <: A
-  checkProperSubtype(B, A);
+  checkProperSubtype(typeRep<B>(), typeRep<A>());
   // C <: B
-  checkProperSubtype(C, B);
+  checkProperSubtype(typeRep<C>(), typeRep<B>());
   // C <: A
-  checkProperSubtype(C, A);
+  checkProperSubtype(typeRep<C>(), typeRep<A>());
 
   // Functions.
   // A -> B <: Function
-  checkProperSubtype(function1(B, A), Function);
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<Function>());
 
   // A -> B <: A -> B
-  checkSubtype(function1(B, A), function1(B, A));
+  checkSubtype(typeRep<B Function(A)>(), typeRep<B Function(A)>());
 
   // A -> B <: B -> B
-  checkProperSubtype(function1(B, A), function1(B, B));
-  // TODO(nshahan) Subtype check with covariant keyword?
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<B Function(B)>());
 
   // A -> B <: A -> A
-  checkSubtype(function1(B, A), function1(A, A));
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<A Function(A)>());
 
   // Generic Function Subtypes.
   // Bound is a built in type.
   // <T extends int> void -> void <: <T extends int> void -> void
-  checkSubtype(genericFunction(int), genericFunction(int));
+  checkSubtype(
+      genericFunction(typeRep<int>()), genericFunction(typeRep<int>()));
 
   // <T extends String> A -> T <: <T extends String> B -> T
-  checkProperSubtype(
-      functionGenericReturn(String, A), functionGenericReturn(String, B));
+  checkProperSubtype(functionGenericReturn(typeRep<String>(), typeRep<A>()),
+      functionGenericReturn(typeRep<String>(), typeRep<B>()));
 
   // <T extends double> T -> B <: <T extends double> T -> A
-  checkProperSubtype(
-      functionGenericArg(double, B), functionGenericArg(double, A));
+  checkProperSubtype(functionGenericArg(typeRep<double>(), typeRep<B>()),
+      functionGenericArg(typeRep<double>(), typeRep<A>()));
 
   // Bound is a function type.
   // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
-  checkSubtype(
-      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
+  checkSubtype(genericFunction(typeRep<A Function(B)>()),
+      genericFunction(typeRep<A Function(B)>()));
 
   // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
-  checkProperSubtype(functionGenericReturn(function1(B, A), A),
-      functionGenericReturn(function1(B, A), B));
+  checkProperSubtype(
+      functionGenericReturn(typeRep<A Function(B)>(), typeRep<A>()),
+      functionGenericReturn(typeRep<A Function(B)>(), typeRep<B>()));
 
   // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
-  checkProperSubtype(functionGenericArg(function1(B, A), B),
-      functionGenericArg(function1(B, A), A));
+  checkProperSubtype(functionGenericArg(typeRep<A Function(B)>(), typeRep<B>()),
+      functionGenericArg(typeRep<A Function(B)>(), typeRep<A>()));
 
   // Bound is a user defined class.
   // <T extends B> void -> void <: <T extends B> void -> void
-  checkSubtype(genericFunction(B), genericFunction(B));
+  checkSubtype(genericFunction(typeRep<B>()), genericFunction(typeRep<B>()));
 
   // <T extends B> A -> T <: <T extends B> B -> T
-  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
+  checkProperSubtype(functionGenericReturn(typeRep<B>(), typeRep<A>()),
+      functionGenericReturn(typeRep<B>(), typeRep<B>()));
 
   // <T extends B> T -> B <: <T extends B> T -> A
-  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
+  checkProperSubtype(functionGenericArg(typeRep<B>(), typeRep<B>()),
+      functionGenericArg(typeRep<B>(), typeRep<A>()));
 
   // Bound is a Future.
   // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
-  checkSubtype(genericFunction(generic1(Future, B)),
-      genericFunction(generic1(Future, B)));
+  checkSubtype(genericFunction(typeRep<Future<B>>()),
+      genericFunction(typeRep<Future<B>>()));
 
   // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
-  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
-      functionGenericReturn(generic1(Future, B), B));
+  checkProperSubtype(functionGenericReturn(typeRep<Future<B>>(), typeRep<A>()),
+      functionGenericReturn(typeRep<Future<B>>(), typeRep<B>()));
 
   // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
-  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
-      functionGenericArg(generic1(Future, B), A));
+  checkProperSubtype(functionGenericArg(typeRep<Future<B>>(), typeRep<B>()),
+      functionGenericArg(typeRep<Future<B>>(), typeRep<A>()));
 
   // Bound is a FutureOr.
   // <T extends FutureOr<B>> void -> void <:
   //    <T extends FutureOr<B>> void -> void
-  checkSubtype(genericFunction(futureOrOf(B)), genericFunction(futureOrOf(B)));
+  checkSubtype(genericFunction(typeRep<FutureOr<B>>()),
+      genericFunction(typeRep<FutureOr<B>>()));
 
   // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
-  checkProperSubtype(functionGenericReturn(futureOrOf(B), A),
-      functionGenericReturn(futureOrOf(B), B));
+  checkProperSubtype(
+      functionGenericReturn(typeRep<FutureOr<B>>(), typeRep<A>()),
+      functionGenericReturn(typeRep<FutureOr<B>>(), typeRep<B>()));
 
   // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
-  checkProperSubtype(functionGenericArg(futureOrOf(B), B),
-      functionGenericArg(futureOrOf(B), A));
+  checkProperSubtype(functionGenericArg(typeRep<FutureOr<B>>(), typeRep<B>()),
+      functionGenericArg(typeRep<FutureOr<B>>(), typeRep<A>()));
 
   // Generics.
-  // D <: D<B>
-  checkSubtype(D, generic1(D, B));
-  // D<B> <: D
-  checkSubtype(generic1(D, B), D);
+  // D <:> D<B>
+  checkMutualSubtype(typeRep<D>(), typeRep<D<B>>());
   // D<C> <: D<B>
-  checkProperSubtype(generic1(D, C), generic1(D, B));
+  checkProperSubtype(typeRep<D<C>>(), typeRep<D<B>>());
 
   // F <: E
-  checkProperSubtype(F, E);
+  checkProperSubtype(typeRep<F>(), typeRep<E>());
   // F <: E<A, A>
-  checkProperSubtype(F, generic2(E, A, A));
+  checkProperSubtype(typeRep<F>(), typeRep<E<A, A>>());
+  // E<B, B> <: E
+  checkProperSubtype(typeRep<E<B, B>>(), typeRep<E>());
   // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), E);
-  // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
+  checkProperSubtype(typeRep<E<B, B>>(), typeRep<E<A, A>>());
 
   // Nullable interface subtypes.
   // B <: A?
-  checkProperSubtype(B, nullable(A));
+  checkProperSubtype(typeRep<B>(), typeRep<A?>());
   // C <: A?
-  checkProperSubtype(C, nullable(A));
+  checkProperSubtype(typeRep<C>(), typeRep<A?>());
   // B? <: A?
-  checkProperSubtype(nullable(B), nullable(A));
+  checkProperSubtype(typeRep<B?>(), typeRep<A?>());
   // C? <: A?
-  checkProperSubtype(nullable(C), nullable(A));
+  checkProperSubtype(typeRep<C?>(), typeRep<A?>());
 
   // Mixed mode.
   // B* <: A
-  checkProperSubtype(legacy(B), A);
+  checkProperSubtype(legacyTypeRep<B>(), typeRep<A>());
   // B* <: A?
-  checkProperSubtype(legacy(B), nullable(A));
+  checkProperSubtype(legacyTypeRep<B>(), typeRep<A?>());
   // A* <\: B
-  checkSubtypeFailure(legacy(A), B);
+  checkSubtypeFailure(legacyTypeRep<A>(), typeRep<B>());
   // B? <: A*
-  checkProperSubtype(nullable(B), legacy(A));
+  checkProperSubtype(typeRep<B?>(), legacyTypeRep<A>());
   // B <: A*
-  checkProperSubtype(B, legacy(A));
+  checkProperSubtype(typeRep<B>(), legacyTypeRep<A>());
   // A <: B*
-  checkSubtypeFailure(A, legacy(B));
+  checkSubtypeFailure(typeRep<A>(), legacyTypeRep<B>());
   // A? <: B*
-  checkSubtypeFailure(nullable(A), legacy(B));
+  checkSubtypeFailure(typeRep<A?>(), legacyTypeRep<B>());
 
   // Allowed in weak mode.
   // dynamic <: Object
-  checkSubtype(dynamic, Object);
+  checkSubtype(typeRep<dynamic>(), typeRep<Object>());
   // void <: Object
-  checkSubtype(voidType, Object);
+  checkSubtype(typeRep<void>(), typeRep<Object>());
   // Object? <: Object
-  checkSubtype(nullable(Object), Object);
+  checkSubtype(typeRep<Object?>(), typeRep<Object>());
   // A? <: Object
-  checkProperSubtype(nullable(A), Object);
+  checkProperSubtype(typeRep<A?>(), typeRep<Object>());
   // A? <: A
-  checkSubtype(nullable(A), A);
-  // Null <: never
-  checkSubtype(Null, Never);
+  checkSubtype(typeRep<A?>(), typeRep<A>());
+  // Null <: Never
+  checkSubtype(typeRep<Null>(), typeRep<Never>());
   // Null <: Object
-  checkProperSubtype(Null, Object);
+  checkProperSubtype(typeRep<Null>(), typeRep<Object>());
   // Null <: A
-  checkProperSubtype(Null, A);
+  checkProperSubtype(typeRep<Null>(), typeRep<A>());
   // Null <: FutureOr<A>
-  checkProperSubtype(Null, futureOrOf(A));
+  checkProperSubtype(typeRep<Null>(), typeRep<FutureOr<A>>());
   // Null <: Future<A>
-  checkProperSubtype(Null, generic1(Future, A));
+  checkProperSubtype(typeRep<Null>(), typeRep<Future<A>>());
   // FutureOr<Null> <: Future<Null>
-  checkSubtype(futureOrOf(Null), generic1(Future, Null));
+  checkSubtype(typeRep<FutureOr<Null>>(), typeRep<Future<Null>>());
   // Null <: Future<A?>
-  checkProperSubtype(Null, generic1(Future, nullable(A)));
+  checkProperSubtype(typeRep<Null>(), typeRep<Future<A?>>());
   // FutureOr<Object?> <: Object
-  checkSubtype(futureOrOf(nullable(Object)), Object);
+  checkSubtype(typeRep<FutureOr<Object?>>(), typeRep<Object>());
   // FutureOr<dynamic> <: Object
-  checkSubtype(futureOrOf(dynamic), Object);
+  checkSubtype(typeRep<FutureOr<dynamic>>(), typeRep<Object>());
   // FutureOr<void> <: Object
-  checkSubtype(futureOrOf(voidType), Object);
+  checkSubtype(typeRep<FutureOr<void>>(), typeRep<Object>());
 }
diff --git a/tests/compiler/dartdevc_native/runtime_utils.dart b/tests/compiler/dartdevc_native/runtime_utils.dart
index b5a32c0..5b14053 100644
--- a/tests/compiler/dartdevc_native/runtime_utils.dart
+++ b/tests/compiler/dartdevc_native/runtime_utils.dart
@@ -2,101 +2,50 @@
 // for details. 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:_foreign_helper' show JS;
-import 'dart:_runtime' as dart;
+import 'dart:_runtime' show gFnType, typeRep, isSubtypeOf;
 
-import 'dart:async' show FutureOr;
 import 'package:expect/expect.dart';
 
-// Function type used to extract the FutureOr now that a raw FutureOr gets
-// normalized away.
-typedef _futureOrReturn = FutureOr<int> Function();
-
-// The runtime representation of the void type.
-final voidType = dart.wrapType(dart.void_);
-
-/// Unwrap the user code type representation to expose the runtime
-/// representation of [t].
+/// Returns an unwrapped generic function type with a bounded type argument in
+/// the form: <T extends [bound]> void -> void.
 ///
-/// Generic functions are unchanged, as they have a separate runtime type object representation.
-Object unwrap(Type t) {
-  if (t is dart.GenericFunctionType) {
-    return t;
-  }
-  return dart.unwrapType(t);
-}
+// TODO(nshahan): The generic function type is created as a legacy type.
+genericFunction(bound) => gFnType((T) => [typeRep<void>(), []], (T) => [bound]);
 
-Type futureOrOf(Type tWrapped) {
-  var t = unwrap(tWrapped);
-  var f = unwrap(_futureOrReturn);
-  // Extract a raw FutureOr from an existing use.
-  var futureOrGeneric = dart.getGenericClass(JS('', '#.returnType', f));
-  return dart.wrapType(JS('', '#(#)', futureOrGeneric, t));
-}
-
-// Returns sWrapped<tWrapped> as a wrapped type.
-Type generic1(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#)', sGeneric, t));
-}
-
-// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
-Type generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  var r = unwrap(rWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
-}
-
-// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
-Type function1(Type returnWrapped, Type argWrapped) {
-  var returnType = unwrap(returnWrapped);
-  var argType = unwrap(argWrapped);
-  var fun = dart.fnType(returnType, [argType]);
-  return dart.wrapType(fun);
-}
-
-// Returns a function type with a bounded type argument that takes no argument
-// and returns void as a wrapped type.
-Type genericFunction(Type boundWrapped) =>
-    dart.gFnType((T) => [dart.VoidType, []], (T) => [unwrap(boundWrapped)]);
-
-// Returns a function type with a bounded generic return type of
-// <T extends boundWrapped> argWrapped -> T as a wrapped type.
-Type functionGenericReturn(Type boundWrapped, Type argWrapped) => dart.gFnType(
+/// Returns an unwrapped generic function type with a bounded type argument in
+/// the form: <T extends [bound]> [argumentType] -> T.
+///
+// TODO(nshahan): The generic function type is created as a legacy type.
+functionGenericReturn(bound, argumentType) => gFnType(
     (T) => [
           T,
-          [unwrap(argWrapped)]
+          [argumentType]
         ],
-    (T) => [unwrap(boundWrapped)]);
+    (T) => [bound]);
 
-// Returns a function with a bounded generic argument type of
-// <T extends boundWrapped> T -> returnWrapped as a wrapped type.
-Type functionGenericArg(Type boundWrapped, Type returnWrapped) => dart.gFnType(
+/// Returns an unwrapped generic function type with a bounded type argument in
+/// the form: <T extends [bound]> T -> [returnType].
+///
+// TODO(nshahan): The generic function type is created as a legacy type.
+functionGenericArg(bound, returnType) => gFnType(
     (T) => [
-          unwrap(returnWrapped),
+          returnType,
           [T]
         ],
-    (T) => [unwrap(boundWrapped)]);
+    (T) => [bound]);
 
-void checkSubtype(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+void checkSubtype(s, t) =>
+    Expect.isTrue(isSubtypeOf(s, t), '$s should be subtype of $t.');
+
+void checkProperSubtype(s, t) {
+  Expect.isTrue(isSubtypeOf(s, t), '$s should be subtype of $t.');
+  checkSubtypeFailure(t, s);
 }
 
-void checkProperSubtype(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
-  checkSubtypeFailure(tWrapped, sWrapped);
+void checkMutualSubtype(Object s, Object t) {
+  Expect.isTrue(isSubtypeOf(s, t), '$s should be subtype of $t.');
+  Expect.isTrue(isSubtypeOf(t, s), '$t should be subtype of $s.');
 }
 
-void checkSubtypeFailure(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  Expect.isFalse(dart.isSubtypeOf(s, t), '$s should not be subtype of $t.');
-}
+void checkSubtypeFailure(s, t) =>
+    Expect.isFalse(isSubtypeOf(s, t), '$s should not be subtype of $t.');
diff --git a/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart b/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
index 47dd2bc..3d10655 100644
--- a/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
+++ b/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
@@ -3,110 +3,27 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:_foreign_helper' show JS;
-import 'dart:_runtime' as dart;
+import 'dart:_runtime' show gFnType, typeRep;
 
-import 'package:expect/expect.dart';
+/// Returns an unwrapped generic function type with a bounded type argument in
+/// the form: <T extends [bound]> void -> void.
+Object genericFunction(Object bound) =>
+    gFnType((T) => [typeRep<void>(), []], (T) => [bound]);
 
-/// Unwrap the user code type representation to expose the runtime
-/// representation of [t].
-///
-/// Legacy types (produced by the legacy helper below) are returned unchanged
-/// because they are created unwrapped since wrapping will strip the legacy from
-/// them by design.
-/// Generic functions are also unchanged, as they have a separate runtime type object representation.
-Object unwrap(Type t) {
-  if (JS<bool>('!', '# instanceof #', t, dart.LegacyType) ||
-      JS<bool>('!', '# instanceof #', t, dart.GenericFunctionType)) {
-    return t;
-  }
-  return dart.unwrapType(t);
-}
-
-/// Returns tWrapped? as a wrapped type.
-Type nullable(Type tWrapped) {
-  var t = unwrap(tWrapped);
-  var tNullable = dart.nullable(t);
-  return dart.wrapType(tNullable);
-}
-
-/// Returns tWrapped* as an *unwrapped* type when it produces a legacy type, and
-/// a *wrapped* type when the legacy has been normalized away.
-///
-/// For example DDC does not create a legacy dynamic type, only dynamic.
-///
-/// This is the only helper to return an unwrapped version of a type because
-/// wrapping a legacy type will strip off the legacy by design.
-Type legacy(Type tWrapped) {
-  var t = unwrap(tWrapped);
-  var tLegacy = dart.legacy(t);
-  // During normalization some types never get created as legacy versions.
-  // Ex: dynamic.
-  return tLegacy is dart.LegacyType ? tLegacy : dart.wrapType(tLegacy);
-}
-
-// Returns sWrapped<tWrapped> as a wrapped type.
-Type generic1(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#)', sGeneric, t));
-}
-
-// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
-Type generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  var r = unwrap(rWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
-}
-
-// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
-Type function1(Type returnWrapped, Type argWrapped) {
-  var returnType = unwrap(returnWrapped);
-  var argType = unwrap(argWrapped);
-  var fun = dart.fnType(returnType, [argType]);
-  return dart.wrapType(fun);
-}
-
-// Returns a function type with a bounded type argument that takes no argument
-// and returns void as a wrapped type.
-Type genericFunction(Type boundWrapped) =>
-    dart.gFnType((T) => [dart.VoidType, []], (T) => [unwrap(boundWrapped)]);
-
-// Returns a function type with a bounded generic return type of
-// <T extends boundWrapped> argWrapped -> T as a wrapped type.
-Type functionGenericReturn(Type boundWrapped, Type argWrapped) => dart.gFnType(
+/// Returns an unwrapped generic function type with a bounded type argument in
+/// the form: <T extends [bound]> [argumentType] -> T.
+Object functionGenericReturn(Object bound, Object argType) => gFnType(
     (T) => [
           T,
-          [unwrap(argWrapped)]
+          [argType]
         ],
-    (T) => [unwrap(boundWrapped)]);
+    (T) => [bound]);
 
-// Returns a function with a bounded generic argument type of
-// <T extends boundWrapped> T -> returnWrapped as a wrapped type.
-Type functionGenericArg(Type boundWrapped, Type returnWrapped) => dart.gFnType(
+/// Returns an unwrapped generic function type with a bounded type argument in
+/// the form: <T extends [bound]> T -> [returnType].
+Object functionGenericArg(Object bound, Object returnType) => gFnType(
     (T) => [
-          unwrap(returnWrapped),
+          returnType,
           [T]
         ],
-    (T) => [unwrap(boundWrapped)]);
-
-void checkSubtype(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
-}
-
-void checkProperSubtype(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
-  checkSubtypeFailure(tWrapped, sWrapped);
-}
-
-void checkSubtypeFailure(Type sWrapped, Type tWrapped) {
-  var s = unwrap(sWrapped);
-  var t = unwrap(tWrapped);
-  Expect.isFalse(dart.isSubtypeOf(s, t), '$s should not be subtype of $t.');
-}
+    (T) => [bound]);
diff --git a/tests/compiler/dartdevc_native/subtype_test.dart b/tests/compiler/dartdevc_native/subtype_test.dart
index 93d7ebc7..51e0c75 100644
--- a/tests/compiler/dartdevc_native/subtype_test.dart
+++ b/tests/compiler/dartdevc_native/subtype_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.6
 
-import 'dart:async';
+import 'dart:_runtime' show typeRep;
+import 'dart:async' show FutureOr;
 
 import 'runtime_utils.dart';
 
@@ -22,122 +23,128 @@
 
 void main() {
   // A <: dynamic
-  checkProperSubtype(A, dynamic);
+  checkProperSubtype(typeRep<A>(), typeRep<dynamic>());
   // A <: Object
-  checkProperSubtype(A, Object);
-  // TODO(nshahan) Test void as top? A <: void
+  checkProperSubtype(typeRep<A>(), typeRep<Object>());
+  // A <: Object
+  checkProperSubtype(typeRep<A>(), typeRep<void>());
 
   // Null <: A
-  checkProperSubtype(Null, A);
+  checkProperSubtype(typeRep<Null>(), typeRep<A>());
 
   // FutureOr<Null> <: Future<Null>
-  checkSubtype(futureOrOf(Null), generic1(Future, Null));
+  checkSubtype(typeRep<FutureOr<Null>>(), typeRep<Future<Null>>());
   // Future<Null> <: FutureOr<Null>
-  checkSubtype(generic1(Future, Null), futureOrOf(Null));
+  checkSubtype(typeRep<Future<Null>>(), typeRep<FutureOr<Null>>());
   // Future<B> <: FutureOr<A>
-  checkProperSubtype(generic1(Future, B), futureOrOf(A));
+  checkProperSubtype(typeRep<Future<B>>(), typeRep<FutureOr<A>>());
   // B <: <: FutureOr<A>
-  checkProperSubtype(B, futureOrOf(A));
+  checkProperSubtype(typeRep<B>(), typeRep<FutureOr<A>>());
   // Future<B> <: Future<A>
-  checkProperSubtype(generic1(Future, B), generic1(Future, A));
+  checkProperSubtype(typeRep<Future<B>>(), typeRep<Future<A>>());
   // B <: A
-  checkProperSubtype(B, A);
+  checkProperSubtype(typeRep<B>(), typeRep<A>());
 
   // A <: A
-  checkSubtype(A, A);
+  checkSubtype(typeRep<A>(), typeRep<A>());
   // C <: B
-  checkProperSubtype(C, B);
+  checkProperSubtype(typeRep<C>(), typeRep<B>());
   // C <: A
-  checkProperSubtype(C, A);
+  checkProperSubtype(typeRep<C>(), typeRep<A>());
 
   // A -> B <: Function
-  checkProperSubtype(function1(B, A), Function);
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<Function>());
 
   // A -> B <: A -> B
-  checkSubtype(function1(B, A), function1(B, A));
+  checkSubtype(typeRep<B Function(A)>(), typeRep<B Function(A)>());
 
   // A -> B <: B -> B
-  checkProperSubtype(function1(B, A), function1(B, B));
-  // TODO(nshahan) Subtype check with covariant keyword?
+  checkProperSubtype(typeRep<B Function(A)>(), typeRep<B Function(B)>());
 
   // A -> B <: A -> A
-  checkSubtype(function1(B, A), function1(A, A));
+  checkSubtype(typeRep<B Function(A)>(), typeRep<A Function(A)>());
 
   // Generic Function Subtypes.
   // Bound is a built in type.
   // <T extends int> void -> void <: <T extends int> void -> void
-  checkSubtype(genericFunction(int), genericFunction(int));
+  checkSubtype(
+      genericFunction(typeRep<int>()), genericFunction(typeRep<int>()));
 
   // <T extends String> A -> T <: <T extends String> B -> T
-  checkProperSubtype(
-      functionGenericReturn(String, A), functionGenericReturn(String, B));
+  checkProperSubtype(functionGenericReturn(typeRep<String>(), typeRep<A>()),
+      functionGenericReturn(typeRep<String>(), typeRep<B>()));
 
   // <T extends double> T -> B <: <T extends double> T -> A
-  checkProperSubtype(
-      functionGenericArg(double, B), functionGenericArg(double, A));
+  checkProperSubtype(functionGenericArg(typeRep<double>(), typeRep<B>()),
+      functionGenericArg(typeRep<double>(), typeRep<A>()));
 
   // Bound is a function type.
   // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
-  checkSubtype(
-      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
+  checkSubtype(genericFunction(typeRep<B Function(A)>()),
+      genericFunction(typeRep<B Function(A)>()));
 
   // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
-  checkProperSubtype(functionGenericReturn(function1(B, A), A),
-      functionGenericReturn(function1(B, A), B));
+  checkProperSubtype(
+      functionGenericReturn(typeRep<B Function(A)>(), typeRep<A>()),
+      functionGenericReturn(typeRep<B Function(A)>(), typeRep<B>()));
 
   // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
-  checkProperSubtype(functionGenericArg(function1(B, A), B),
-      functionGenericArg(function1(B, A), A));
+  checkProperSubtype(functionGenericArg(typeRep<B Function(A)>(), typeRep<B>()),
+      functionGenericArg(typeRep<B Function(A)>(), typeRep<A>()));
 
   // Bound is a user defined class.
   // <T extends B> void -> void <: <T extends B> void -> void
-  checkSubtype(genericFunction(B), genericFunction(B));
+  checkSubtype(genericFunction(typeRep<B>()), genericFunction(typeRep<B>()));
 
   // <T extends B> A -> T <: <T extends B> B -> T
-  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
+  checkProperSubtype(functionGenericReturn(typeRep<B>(), typeRep<A>()),
+      functionGenericReturn(typeRep<B>(), typeRep<B>()));
 
   // <T extends B> T -> B <: <T extends B> T -> A
-  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
+  checkProperSubtype(functionGenericArg(typeRep<B>(), typeRep<B>()),
+      functionGenericArg(typeRep<B>(), typeRep<A>()));
 
   // Bound is a Future.
   // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
-  checkSubtype(genericFunction(generic1(Future, B)),
-      genericFunction(generic1(Future, B)));
+  checkSubtype(genericFunction(typeRep<Future<B>>()),
+      genericFunction(typeRep<Future<B>>()));
 
   // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
-  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
-      functionGenericReturn(generic1(Future, B), B));
+  checkProperSubtype(functionGenericReturn(typeRep<Future<B>>(), typeRep<A>()),
+      functionGenericReturn(typeRep<Future<B>>(), typeRep<B>()));
 
   // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
-  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
-      functionGenericArg(generic1(Future, B), A));
+  checkProperSubtype(functionGenericArg(typeRep<Future<B>>(), typeRep<B>()),
+      functionGenericArg(typeRep<Future<B>>(), typeRep<A>()));
 
   // Bound is a FutureOr.
   // <T extends FutureOr<B>> void -> void <:
   //    <T extends FutureOr<B>> void -> void
-  checkSubtype(genericFunction(futureOrOf(B)), genericFunction(futureOrOf(B)));
+  checkSubtype(genericFunction(typeRep<FutureOr<B>>()),
+      genericFunction(typeRep<FutureOr<B>>()));
 
   // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
-  checkProperSubtype(functionGenericReturn(futureOrOf(B), A),
-      functionGenericReturn(futureOrOf(B), B));
+  checkProperSubtype(
+      functionGenericReturn(typeRep<FutureOr<B>>(), typeRep<A>()),
+      functionGenericReturn(typeRep<FutureOr<B>>(), typeRep<B>()));
 
   // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
-  checkProperSubtype(functionGenericArg(futureOrOf(B), B),
-      functionGenericArg(futureOrOf(B), A));
+  checkProperSubtype(functionGenericArg(typeRep<FutureOr<B>>(), typeRep<B>()),
+      functionGenericArg(typeRep<FutureOr<B>>(), typeRep<A>()));
 
   // D <: D<B>
-  checkSubtype(D, generic1(D, B));
+  checkSubtype(typeRep<D>(), typeRep<D<B>>());
   // D<B> <: D
-  checkSubtype(generic1(D, B), D);
+  checkSubtype(typeRep<D<B>>(), typeRep<D>());
   // D<C> <: D<B>
-  checkProperSubtype(generic1(D, C), generic1(D, B));
+  checkSubtype(typeRep<D<C>>(), typeRep<D<B>>());
 
   // F <: E
-  checkProperSubtype(F, E);
+  checkProperSubtype(typeRep<F>(), typeRep<E>());
   // F <: E<A, A>
-  checkProperSubtype(F, generic2(E, A, A));
+  checkProperSubtype(typeRep<F>(), typeRep<E<A, A>>());
+  // E<B, B> <: E
+  checkProperSubtype(typeRep<E<B, B>>(), typeRep<E>());
   // // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), E);
-  // // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
+  checkProperSubtype(typeRep<E<B, B>>(), typeRep<E<A, A>>());
 }
diff --git a/tests/compiler/dartdevc_native/variance_subtype_test.dart b/tests/compiler/dartdevc_native/variance_subtype_test.dart
index 96090bb..b930484 100644
--- a/tests/compiler/dartdevc_native/variance_subtype_test.dart
+++ b/tests/compiler/dartdevc_native/variance_subtype_test.dart
@@ -8,143 +8,184 @@
 
 // Tests runtime subtyping with explicit variance modifiers.
 
-import 'dart:async';
+import 'dart:_runtime' show typeRep;
+import 'dart:async' show FutureOr;
 
 import 'runtime_utils.dart';
 
 class Upper {}
+
 class Middle extends Upper {}
+
 class Lower extends Middle {}
 
 class Covariant<out T> {}
+
 class Contravariant<in T> {}
+
 class Invariant<inout T> {}
+
 class LegacyCovariant<T> {}
 
 void main() {
   // Covariant<Lower> <: Covariant<Middle>
-  checkProperSubtype(generic1(Covariant, Lower), generic1(Covariant, Middle));
+  checkProperSubtype(typeRep<Covariant<Lower>>(), typeRep<Covariant<Middle>>());
 
   // Covariant<Middle> <: Covariant<Middle>
-  checkSubtype(generic1(Covariant, Middle), generic1(Covariant, Middle));
+  checkSubtype(typeRep<Covariant<Middle>>(), typeRep<Covariant<Middle>>());
 
   // Contravariant<Upper> <: Contravariant<Middle>
-  checkProperSubtype(generic1(Contravariant, Upper), generic1(Contravariant, Middle));
+  checkProperSubtype(
+      typeRep<Contravariant<Upper>>(), typeRep<Contravariant<Middle>>());
 
   // Contravariant<Middle> <: Contravariant<Middle>
-  checkSubtype(generic1(Contravariant, Middle), generic1(Contravariant, Middle));
+  checkSubtype(
+      typeRep<Contravariant<Middle>>(), typeRep<Contravariant<Middle>>());
 
   // Invariant<Middle> <: Invariant<Middle>
-  checkSubtype(generic1(Invariant, Middle), generic1(Invariant, Middle));
+  checkSubtype(typeRep<Invariant<Middle>>(), typeRep<Invariant<Middle>>());
 
   // Invariant<dynamic> <:> Invariant<Object>
-  checkSubtype(generic1(Invariant, dynamic), generic1(Invariant, Object));
-  checkSubtype(generic1(Invariant, Object), generic1(Invariant, dynamic));
+  checkMutualSubtype(
+      typeRep<Invariant<dynamic>>(), typeRep<Invariant<Object>>());
 
   // Invariant<FutureOr<dynamic>> <:> Invariant<dynamic>
-  checkSubtype(generic1(Invariant, futureOrOf(dynamic)), generic1(Invariant, dynamic));
-  checkSubtype(generic1(Invariant, dynamic), generic1(Invariant, futureOrOf(dynamic)));
+  checkMutualSubtype(
+      typeRep<Invariant<FutureOr<dynamic>>>(), typeRep<Invariant<dynamic>>());
 
   // Invariant<FutureOr<Null>> <:> Invariant<Future<Null>>
-  checkSubtype(generic1(Invariant, futureOrOf(Null)), generic1(Invariant, generic1(Future, Null)));
-  checkSubtype(generic1(Invariant, generic1(Future, Null)), generic1(Invariant, futureOrOf(Null)));
+  checkMutualSubtype(
+      typeRep<Invariant<FutureOr<Null>>>(), typeRep<Invariant<Future<Null>>>());
 
   // LegacyCovariant<Lower> <: LegacyCovariant<Middle>
-  checkProperSubtype(generic1(LegacyCovariant, Lower), generic1(LegacyCovariant, Middle));
+  checkProperSubtype(
+      typeRep<LegacyCovariant<Lower>>(), typeRep<LegacyCovariant<Middle>>());
 
   // List<Covariant<Lower>> <: Iterable<Covariant<Middle>>
-  checkProperSubtype(generic1(List, generic1(Covariant, Lower)), generic1(Iterable, generic1(Covariant, Middle)));
+  checkProperSubtype(typeRep<List<Covariant<Lower>>>(),
+      typeRep<Iterable<Covariant<Middle>>>());
 
   // List<Contravariant<Upper>> <: Iterable<Contravariant<Middle>>
-  checkProperSubtype(generic1(List, generic1(Contravariant, Upper)), generic1(Iterable, generic1(Contravariant, Middle)));
+  checkProperSubtype(typeRep<List<Contravariant<Upper>>>(),
+      typeRep<Iterable<Contravariant<Middle>>>());
 
   // List<Invariant<Middle>> <: Iterable<Invariant<Middle>>
-  checkProperSubtype(generic1(List, generic1(Invariant, Middle)), generic1(Iterable, generic1(Invariant, Middle)));
+  checkProperSubtype(typeRep<List<Invariant<Middle>>>(),
+      typeRep<Iterable<Invariant<Middle>>>());
 
   // List<LegacyCovariant<Lower>> <: Iterable<LegacyCovariant<Middle>>
-  checkProperSubtype(generic1(List, generic1(LegacyCovariant, Lower)), generic1(Iterable, generic1(LegacyCovariant, Middle)));
+  checkProperSubtype(typeRep<List<LegacyCovariant<Lower>>>(),
+      typeRep<Iterable<LegacyCovariant<Middle>>>());
 
   // String -> Covariant<Lower> <: String -> Covariant<Middle>
-  checkProperSubtype(function1(generic1(Covariant, Lower), String), function1(generic1(Covariant, Middle), String));
+  checkProperSubtype(typeRep<Covariant<Lower> Function(String)>(),
+      typeRep<Covariant<Middle> Function(String)>());
 
   // Covariant<Upper> -> String <: Covariant<Middle> -> String
-  checkProperSubtype(function1(String, generic1(Covariant, Upper)), function1(String, generic1(Covariant, Middle)));
+  checkProperSubtype(typeRep<String Function(Covariant<Upper>)>(),
+      typeRep<String Function(Covariant<Middle>)>());
 
   // String -> Contravariant<Upper> <: String -> Contravariant<Middle>
-  checkProperSubtype(function1(generic1(Contravariant, Upper), String), function1(generic1(Contravariant, Middle), String));
+  checkProperSubtype(typeRep<Contravariant<Upper> Function(String)>(),
+      typeRep<Contravariant<Middle> Function(String)>());
 
   // Contravariant<Lower> -> String <: Contravariant<Middle> -> String
-  checkProperSubtype(function1(String, generic1(Contravariant, Lower)), function1(String, generic1(Contravariant, Middle)));
+  checkProperSubtype(typeRep<String Function(Contravariant<Lower>)>(),
+      typeRep<String Function(Contravariant<Middle>)>());
 
   // String -> Invariant<Middle> <: String -> Invariant<Middle>
-  checkSubtype(function1(generic1(Invariant, Middle), String), function1(generic1(Invariant, Middle), String));
+  checkSubtype(typeRep<String Function(Invariant<Middle>)>(),
+      typeRep<String Function(Invariant<Middle>)>());
 
   // Invariant<Middle> -> String <: Invariant<Middle> -> String
-  checkSubtype(function1(String, generic1(Invariant, Middle)), function1(String, generic1(Invariant, Middle)));
+  checkSubtype(typeRep<String Function(Invariant<Middle>)>(),
+      typeRep<String Function(Invariant<Middle>)>());
 
   // String -> LegacyCovariant<Lower> <: String -> LegacyCovariant<Middle>
-  checkProperSubtype(function1(generic1(LegacyCovariant, Lower), String), function1(generic1(LegacyCovariant, Middle), String));
+  checkProperSubtype(typeRep<LegacyCovariant<Lower> Function(String)>(),
+      typeRep<LegacyCovariant<Middle> Function(String)>());
 
   // LegacyCovariant<Upper> -> String <: LegacyCovariant<Middle> -> String
-  checkProperSubtype(function1(String, generic1(LegacyCovariant, Upper)), function1(String, generic1(LegacyCovariant, Middle)));
+  checkProperSubtype(typeRep<String Function(LegacyCovariant<Upper>)>(),
+      typeRep<String Function(LegacyCovariant<Middle>)>());
 
   // Covariant<Upper> </: Covariant<Middle>
-  checkSubtypeFailure(generic1(Covariant, Upper), generic1(Covariant, Middle));
+  checkSubtypeFailure(
+      typeRep<Covariant<Upper>>(), typeRep<Covariant<Middle>>());
 
   // Contravariant<Lower> </: Contravariant<Middle>
-  checkSubtypeFailure(generic1(Contravariant, Lower), generic1(Contravariant, Middle));
+  checkSubtypeFailure(
+      typeRep<Contravariant<Lower>>(), typeRep<Contravariant<Middle>>());
 
   // Invariant<Upper> </: Invariant<Middle>
-  checkSubtypeFailure(generic1(Invariant, Upper), generic1(Invariant, Middle));
+  checkSubtypeFailure(
+      typeRep<Invariant<Upper>>(), typeRep<Invariant<Middle>>());
 
   // Invariant<Lower> </: Invariant<Middle>
-  checkSubtypeFailure(generic1(Invariant, Lower), generic1(Invariant, Middle));
+  checkSubtypeFailure(
+      typeRep<Invariant<Lower>>(), typeRep<Invariant<Middle>>());
 
   // LegacyCovariant<Upper> </: LegacyCovariant<Middle>
-  checkSubtypeFailure(generic1(LegacyCovariant, Upper), generic1(LegacyCovariant, Middle));
+  checkSubtypeFailure(
+      typeRep<LegacyCovariant<Upper>>(), typeRep<LegacyCovariant<Middle>>());
 
   // List<Covariant<Upper>> </: Iterable<Covariant<Middle>>
-  checkSubtypeFailure(generic1(List, generic1(Covariant, Upper)), generic1(Iterable, generic1(Covariant, Middle)));
+  checkSubtypeFailure(typeRep<List<Covariant<Upper>>>(),
+      typeRep<Iterable<Covariant<Middle>>>());
 
   // List<Contravariant<Lower>> </: Iterable<Contravariant<Middle>>
-  checkSubtypeFailure(generic1(List, generic1(Contravariant, Lower)), generic1(Iterable, generic1(Contravariant, Middle)));
+  checkSubtypeFailure(typeRep<List<Contravariant<Lower>>>(),
+      typeRep<Iterable<Contravariant<Middle>>>());
 
   // List<Invariant<Upper>> </: Iterable<Invariant<Middle>>
-  checkSubtypeFailure(generic1(List, generic1(Invariant, Upper)), generic1(Iterable, generic1(Invariant, Middle)));
+  checkSubtypeFailure(typeRep<List<Invariant<Upper>>>(),
+      typeRep<Iterable<Invariant<Middle>>>());
 
   // List<Invariant<Lower>> </: Iterable<Invariant<Middle>>
-  checkSubtypeFailure(generic1(List, generic1(Invariant, Lower)), generic1(Iterable, generic1(Invariant, Middle)));
+  checkSubtypeFailure(typeRep<List<Invariant<Lower>>>(),
+      typeRep<Iterable<Invariant<Middle>>>());
 
   // List<LegacyCovariant<Upper>> </: Iterable<LegacyCovariant<Middle>>
-  checkSubtypeFailure(generic1(List, generic1(LegacyCovariant, Upper)), generic1(Iterable, generic1(LegacyCovariant, Middle)));
+  checkSubtypeFailure(typeRep<List<LegacyCovariant<Upper>>>(),
+      typeRep<Iterable<LegacyCovariant<Middle>>>());
 
   // String -> Covariant<Upper> </: String -> Covariant<Middle>
-  checkSubtypeFailure(function1(generic1(Covariant, Upper), String), function1(generic1(Covariant, Middle), String));
+  checkSubtypeFailure(typeRep<Covariant<Upper> Function(String)>(),
+      typeRep<Covariant<Middle> Function(String)>());
 
   // Covariant<Lower> -> String </: Covariant<Middle> -> String
-  checkSubtypeFailure(function1(String, generic1(Covariant, Lower)), function1(String, generic1(Covariant, Middle)));
+  checkSubtypeFailure(typeRep<String Function(Covariant<Lower>)>(),
+      typeRep<String Function(Covariant<Middle>)>());
 
   // String -> Contravariant<Lower> </: String -> Contravariant<Middle>
-  checkSubtypeFailure(function1(generic1(Contravariant, Lower), String), function1(generic1(Contravariant, Middle), String));
+  checkSubtypeFailure(typeRep<Contravariant<Lower> Function(String)>(),
+      typeRep<Contravariant<Middle> Function(String)>());
 
   // Contravariant<Upper> -> String </: Contravariant<Middle> -> String
-  checkSubtypeFailure(function1(String, generic1(Contravariant, Upper)), function1(String, generic1(Contravariant, Middle)));
+  checkSubtypeFailure(typeRep<String Function(Contravariant<Upper>)>(),
+      typeRep<String Function(Contravariant<Middle>)>());
 
   // String -> Invariant<Upper> </: String -> Invariant<Middle>
-  checkSubtypeFailure(function1(generic1(Invariant, Upper), String), function1(generic1(Invariant, Middle), String));
+  checkSubtypeFailure(typeRep<Invariant<Upper> Function(String)>(),
+      typeRep<Invariant<Middle> Function(String)>());
 
   // Invariant<Upper> -> String </: Invariant<Middle> -> String
-  checkSubtypeFailure(function1(String, generic1(Invariant, Upper)), function1(String, generic1(Invariant, Middle)));
+  checkSubtypeFailure(typeRep<String Function(Invariant<Upper>)>(),
+      typeRep<String Function(Invariant<Middle>)>());
 
   // String -> Invariant<Lower> </: String -> Invariant<Middle>
-  checkSubtypeFailure(function1(generic1(Invariant, Lower), String), function1(generic1(Invariant, Middle), String));
+  checkSubtypeFailure(typeRep<Invariant<Lower> Function(String)>(),
+      typeRep<Invariant<Middle> Function(String)>());
 
   // Invariant<Lower> -> String <: Invariant<Middle> -> String
-  checkSubtypeFailure(function1(String, generic1(Invariant, Lower)), function1(String, generic1(Invariant, Middle)));
+  checkSubtypeFailure(typeRep<String Function(Invariant<Lower>)>(),
+      typeRep<String Function(Invariant<Middle>)>());
 
   // String -> LegacyCovariant<Upper> </: String -> LegacyCovariant<Middle>
-  checkSubtypeFailure(function1(generic1(LegacyCovariant, Upper), String), function1(generic1(LegacyCovariant, Middle), String));
+  checkSubtypeFailure(typeRep<LegacyCovariant<Upper> Function(String)>(),
+      typeRep<LegacyCovariant<Middle> Function(String)>());
 
   // LegacyCovariant<Lower> -> String </: LegacyCovariant<Middle> -> String
-  checkSubtypeFailure(function1(String, generic1(LegacyCovariant, Lower)), function1(String, generic1(LegacyCovariant, Middle)));
+  checkSubtypeFailure(typeRep<String Function(LegacyCovariant<Lower>)>(),
+      typeRep<String Function(LegacyCovariant<Middle>)>());
 }
diff --git a/tests/compiler/dartdevc_native/variance_test.dart b/tests/compiler/dartdevc_native/variance_test.dart
index b649ca3..ac2e683 100644
--- a/tests/compiler/dartdevc_native/variance_test.dart
+++ b/tests/compiler/dartdevc_native/variance_test.dart
@@ -8,7 +8,8 @@
 
 // Tests the emission of explicit variance modifiers.
 
-import 'dart:_runtime' as dart;
+import 'dart:_runtime'
+    show wrapType, unwrapType, getGenericArgVariances, Variance, typeRep;
 
 import 'package:expect/expect.dart';
 
@@ -26,31 +27,27 @@
 
 class G<inout T> = Object with F<T>;
 
-List getVariances(Type typeWrapped) {
-  var type = dart.unwrapType(typeWrapped);
-  return dart.getGenericArgVariances(type);
-}
-
-void checkVariances(List v1, List v2) {
-  Expect.equals(v1.length, v2.length);
-  for (int i = 0; i < v1.length; i++) {
-    Expect.equals(v1[i], v2[i]);
-  }
+List getVariances(Object t) {
+  // TODO(nshahan) Update to handle legacy wrapper when we unfork dart:_runtime.
+  var type = unwrapType(wrapType(t));
+  return getGenericArgVariances(type);
 }
 
 main() {
-  checkVariances(getVariances(A), [dart.Variance.contravariant]);
+  Expect.listEquals([Variance.contravariant], getVariances(typeRep<A>()));
 
-  checkVariances(getVariances(B), [dart.Variance.covariant]);
+  Expect.listEquals([Variance.covariant], getVariances(typeRep<B>()));
 
-  checkVariances(getVariances(C), [dart.Variance.invariant]);
+  Expect.listEquals([Variance.invariant], getVariances(typeRep<C>()));
 
   // Implicit variance is not emitted into the generated code.
-  Expect.isNull(getVariances(D));
+  Expect.isNull(getVariances(typeRep<D>()));
 
-  checkVariances(getVariances(E), [dart.Variance.invariant, dart.Variance.covariant, dart.Variance.contravariant]);
+  Expect.listEquals(
+      [Variance.invariant, Variance.covariant, Variance.contravariant],
+      getVariances(typeRep<E>()));
 
-  checkVariances(getVariances(F), [dart.Variance.contravariant]);
+  Expect.listEquals([Variance.contravariant], getVariances(typeRep<F>()));
 
-  checkVariances(getVariances(G), [dart.Variance.invariant]);
+  Expect.listEquals([Variance.invariant], getVariances(typeRep<G>()));
 }
diff --git a/tests/corelib/apply_generic_function_test.dart b/tests/corelib/apply_generic_function_test.dart
index b9e6e3e..ad75ee1 100644
--- a/tests/corelib/apply_generic_function_test.dart
+++ b/tests/corelib/apply_generic_function_test.dart
@@ -13,7 +13,7 @@
 
 main() {
   test(res, func, list, map) {
-    map = symbolMapToStringMap(map);
+    map = symbolToStringMap(map);
     Expect.equals(res, Function.apply(func, list, map));
   }
 
diff --git a/tests/corelib/apply_test.dart b/tests/corelib/apply_test.dart
index 0958dab..364f2f4 100644
--- a/tests/corelib/apply_test.dart
+++ b/tests/corelib/apply_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import "symbol_map_helper.dart";
 
 // Testing Function.apply calls correctly.
 // This test is not testing error handling, only that correct parameters
diff --git a/tests/corelib/collection_length_test.dart b/tests/corelib/collection_length_test.dart
index 27dae6e..984f30e 100644
--- a/tests/corelib/collection_length_test.dart
+++ b/tests/corelib/collection_length_test.dart
@@ -70,7 +70,7 @@
   testCollection(new LinkedHashSet(), N);
   testCollection(new ListQueue(), N);
   testCollection(new DoubleLinkedQueue(), N);
-  testList(new List()..length = N, N);
-  testList(new List(N), N);
+  testList([]..length = N, N);
+  testList(new List.filled(N, null), N);
   testString(N);
 }
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 00d80ea6..4ed80aa 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -13,7 +13,7 @@
 
 [ $builder_tag == obfuscated && $runtime == dart_precompiled ]
 apply_generic_function_test: SkipByDesign # Function.apply with named args
-apply_test: Skip # Uses new Symbol via symbolMapToStringMap helper
+apply_test: Skip # Uses new Symbol via symbolToStringMap helper
 dynamic_nosuchmethod_test: SkipByDesign # Expects names in NSM
 error_stack_trace1_test: SkipByDesign # Expects unobfuscated stack trace
 type_tostring_test: SkipByDesign # Expects names in Type.toString()
diff --git a/tests/corelib/error_stack_trace2_test.dart b/tests/corelib/error_stack_trace2_test.dart
index 47f6a7d..2b3d302 100644
--- a/tests/corelib/error_stack_trace2_test.dart
+++ b/tests/corelib/error_stack_trace2_test.dart
@@ -15,6 +15,20 @@
   return cyclicStatic;
 }
 
+// Helper method to detect whether [errorType] is an overflow error.
+//
+// TODO(41308): Use `is StackOverflowError` once DDC converts overflow errors
+// from JavaSript.
+bool isOverflowError(Type errorType) {
+  void detectOverflowError() => detectOverflowError();
+  try {
+    detectOverflowError();
+  } catch (e) {
+    return errorType == e.runtimeType;
+  }
+  return false;
+}
+
 main() {
   bool hasThrown = false;
   try {
@@ -22,7 +36,8 @@
   } catch (e2) {
     var e = e2;
     hasThrown = true;
-    Expect.isTrue(e is StackOverflowError);
+    Expect.isTrue(isOverflowError(e.runtimeType),
+        "Got '$e' instead of StackOverflowError");
   }
   Expect.isTrue(hasThrown);
 }
diff --git a/tests/corelib/expando_test.dart b/tests/corelib/expando_test.dart
index 04d6ad4..02810bc 100644
--- a/tests/corelib/expando_test.dart
+++ b/tests/corelib/expando_test.dart
@@ -10,7 +10,7 @@
   static testMain() {
     var legal = [
       new Object(),
-      new List(),
+      new List.filled(0, null),
       [1, 2, 3],
       const [1, 2, 3],
       new Map(),
diff --git a/tests/corelib/growable_list_test.dart b/tests/corelib/growable_list_test.dart
index 4c095f0..2f030f4 100644
--- a/tests/corelib/growable_list_test.dart
+++ b/tests/corelib/growable_list_test.dart
@@ -51,8 +51,9 @@
     }
     _current = _nextIndex;
     _nextIndex++;
-    if (_current == _iterable.callbackIndex) {
-      _iterable.callback();
+    var tempCallback = _iterable.callback;
+    if (_current == _iterable.callbackIndex && tempCallback != null) {
+      tempCallback();
     }
     return true;
   }
@@ -83,21 +84,19 @@
     Expect.throws(fn, (_) => true, name);
   }
 
-  testFixedLength(new List<int?>(0));
-  testFixedLength(new List<int?>(5));
+  testFixedLength(new List<int?>.empty());
   testFixedLength(new List<int?>.filled(5, null)); // default growable: false.
-  testGrowable(new List<int?>());
-  testGrowable(new List<int?>()..length = 5);
+  testGrowable(<int?>[]);
+  testGrowable(<int?>[]..length = 5);
   testGrowable(new List<int?>.filled(5, null, growable: true));
-  Expect.throwsArgumentError(() => new List<int?>(-1), "-1");
+  Expect.throwsArgumentError(() => new List<int?>.filled(-1, null), "-1");
   // There must be limits. Fix this test if we ever allow 2^63 elements.
-  Expect.throws(() => new List<int?>(0x7ffffffffffff000),
+  Expect.throws(() => new List<int?>.filled(0x7ffffffffffff000, null),
       (e) => e is OutOfMemoryError || e is ArgumentError, "bignum");
-  Expect.throwsArgumentError(() => new List<int?>(null), "null");
   testThrowsOrTypeError(
-      () => new List([] as dynamic), // Cast to avoid warning.
+      () => new List.filled([] as dynamic, null), // Cast to avoid warning.
       'list');
-  testThrowsOrTypeError(() => new List([42] as dynamic), "list2");
+  testThrowsOrTypeError(() => new List.filled([42] as dynamic, null), "list2");
 }
 
 void testConcurrentModification() {
diff --git a/tests/corelib/iterable_contains_test.dart b/tests/corelib/iterable_contains_test.dart
index 760a104..08b1c23 100644
--- a/tests/corelib/iterable_contains_test.dart
+++ b/tests/corelib/iterable_contains_test.dart
@@ -15,8 +15,8 @@
     Expect.isFalse(list.contains(notInList), "!$list.contains($notInList)");
   }
 
-  List fixedList = new List(list.length);
-  List growList = new List();
+  List fixedList = new List.filled(list.length, null);
+  List growList = [];
   for (int i = 0; i < list.length; i++) {
     fixedList[i] = list[i];
     growList.add(list[i]);
diff --git a/tests/corelib/iterable_fold_test.dart b/tests/corelib/iterable_fold_test.dart
index b531ccc..a6ee921 100644
--- a/tests/corelib/iterable_fold_test.dart
+++ b/tests/corelib/iterable_fold_test.dart
@@ -25,7 +25,7 @@
   for (dynamic iterable in [
     const [1, 2, 3],
     [1, 2, 3],
-    new List(3)
+    new List<int?>.filled(3, null)
       ..[0] = 1
       ..[1] = 2
       ..[2] = 3,
@@ -86,7 +86,7 @@
   for (var iterable in [
     const [],
     [],
-    new List(0),
+    new List.empty(),
     {}.keys,
     {}.values,
     new Iterable.generate(0, (x) => x + 1),
@@ -116,7 +116,7 @@
   for (dynamic iterable in [
     const [1],
     [1],
-    new List(1)..[0] = 1,
+    new List.filled(1, 1),
     {1: 1}.keys,
     {1: 1}.values,
     new Iterable.generate(1, (x) => x + 1),
diff --git a/tests/corelib/iterable_reduce_test.dart b/tests/corelib/iterable_reduce_test.dart
index 6ee66d0..4425c96 100644
--- a/tests/corelib/iterable_reduce_test.dart
+++ b/tests/corelib/iterable_reduce_test.dart
@@ -26,7 +26,7 @@
   for (dynamic iterable in [
     const [1, 2, 3],
     [1, 2, 3],
-    new List(3)
+    new List<int?>.filled(3, null)
       ..[0] = 1
       ..[1] = 2
       ..[2] = 3,
@@ -88,7 +88,7 @@
   for (var iterable in [
     const [],
     [],
-    new List(0),
+    new List.empty(),
     {}.keys,
     {}.values,
     new Iterable.generate(0, (x) => x + 1),
@@ -119,7 +119,7 @@
   for (dynamic iterable in [
     const [1],
     [1],
-    new List(1)..[0] = 1,
+    new List.filled(1, 1),
     {1: 1}.keys,
     {1: 1}.values,
     new Iterable.generate(1, (x) => x + 1),
diff --git a/tests/corelib/map_test.dart b/tests/corelib/map_test.dart
index 09b9311..30618b0 100644
--- a/tests/corelib/map_test.dart
+++ b/tests/corelib/map_test.dart
@@ -55,14 +55,17 @@
   testNumericKeys(new MapBaseMap<num, String>());
   testNumericKeys(new MapMixinMap<num, String>());
 
+  // NaN maps need to have nullable value types because the forEach method
+  // cannot look up the value and therefore might find `null` instead of the
+  // actuall value. See MapMixin.forEach in dart:collection/maps.dart
   testNaNKeys(new Map());
-  testNaNKeys(new Map<num, String>());
+  testNaNKeys(new Map<num, String?>());
   testNaNKeys(new HashMap());
-  testNaNKeys(new HashMap<num, String>());
+  testNaNKeys(new HashMap<num, String?>());
   testNaNKeys(new LinkedHashMap());
-  testNaNKeys(new LinkedHashMap<num, String>());
-  testNaNKeys(new MapBaseMap<num, String>());
-  testNaNKeys(new MapMixinMap<num, String>());
+  testNaNKeys(new LinkedHashMap<num, String?>());
+  testNaNKeys(new MapBaseMap<num, String?>());
+  testNaNKeys(new MapMixinMap<num, String?>());
   // Identity maps fail the NaN-keys tests because the test assumes that
   // NaN is not equal to NaN.
 
@@ -160,7 +163,7 @@
 
 void testMap<K, V>(
     Map<K, V> typedMap, key1, key2, key3, key4, key5, key6, key7, key8) {
-  var map = typedMap;
+  dynamic map = typedMap;
   int value1 = 10;
   int value2 = 20;
   int value3 = 30;
@@ -379,7 +382,7 @@
 }
 
 void testMapLiteral() {
-  Map m = {"a": 1, "b": 2, "c": 3};
+  var m = {"a": 1, "b": 2, "c": 3};
   Expect.equals(3, m.length);
   int sum = 0;
   m.forEach((a, b) {
diff --git a/tests/corelib/queue_test.dart b/tests/corelib/queue_test.dart
index 0729bf6..a34038e 100644
--- a/tests/corelib/queue_test.dart
+++ b/tests/corelib/queue_test.dart
@@ -420,12 +420,12 @@
     }
     Expect.equals(null, entry2);
 
-    var firstEntry = queue1.firstEntry();
-    var secondEntry = queue1.firstEntry().nextEntry();
-    var thirdEntry = queue1.lastEntry();
+    var firstEntry = queue1.firstEntry()!;
+    var secondEntry = queue1.firstEntry()!.nextEntry()!;
+    var thirdEntry = queue1.lastEntry()!;
     firstEntry.prepend(4);
     firstEntry.append(5);
-    secondEntry!.prepend(6);
+    secondEntry.prepend(6);
     secondEntry.append(7);
     thirdEntry.prepend(8);
     thirdEntry.append(9);
@@ -446,11 +446,11 @@
 
   entry.append(37);
   entry.prepend(87);
-  var prev = entry.previousEntry();
-  var next = entry.nextEntry();
+  var prev = entry.previousEntry()!;
+  var next = entry.nextEntry()!;
   Expect.equals(42, entry.element);
-  Expect.equals(37, next!.element);
-  Expect.equals(87, prev!.element);
+  Expect.equals(37, next.element);
+  Expect.equals(87, prev.element);
   Expect.identical(entry, prev.nextEntry());
   Expect.identical(entry, next.previousEntry());
   Expect.equals(null, next.nextEntry());
diff --git a/tests/corelib/regexp/global_test.dart b/tests/corelib/regexp/global_test.dart
index 2ca88ce..2722ef5 100644
--- a/tests/corelib/regexp/global_test.dart
+++ b/tests/corelib/regexp/global_test.dart
@@ -52,6 +52,7 @@
     if (m.group(1) != null) return "-";
     if (m.group(2) != null) return "+";
     if (m.group(3) != null) return "=";
+    throw 'Unexpected match $m';
   });
   assertEquals("= -. +, or + -. There is - =.", str);
 
@@ -88,6 +89,7 @@
     if (m.group(1) != null) return "-";
     if (m.group(2) != null) return "+";
     if (m.group(3) != null) return "=";
+    throw 'Unexpected match $m';
   });
   assertEquals("= -. +, or + -. There is - =.", str);
 
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index 18deeb3..117f35a 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -177,7 +177,7 @@
   }
 
   // Test Set.addAll.
-  List list = new List(10);
+  List list = new List.filled(10, null);
   for (int i = 0; i < 10; i++) {
     list[i] = i + 10;
   }
diff --git a/tests/corelib/sort_helper.dart b/tests/corelib/sort_helper.dart
index 6b8307b..657fe12 100644
--- a/tests/corelib/sort_helper.dart
+++ b/tests/corelib/sort_helper.dart
@@ -27,7 +27,7 @@
   }
 
   void testSortIntLists() {
-    var a = new List<int>(40);
+    var a = new List<int>.filled(40, -1);
 
     for (int i = 0; i < a.length; i++) {
       a[i] = i;
@@ -83,11 +83,10 @@
     a[33] = 1;
     testSort(a);
 
-    var a2 = new List<int>(0);
+    var a2 = new List<int>.empty();
     testSort(a2);
 
-    var a3 = new List<int>(1);
-    a3[0] = 1;
+    var a3 = new List<int>.filled(1, 1);
     testSort(a3);
 
     // --------
@@ -124,7 +123,7 @@
   }
 
   void testInsertionSort(int i1, int i2, int i3, int i4) {
-    var a = new List<int>(4);
+    var a = new List<int>.filled(4, -1);
     a[0] = i1;
     a[1] = i2;
     a[2] = i3;
@@ -133,7 +132,7 @@
   }
 
   void testSortDoubleLists() {
-    var a = new List<double>(40);
+    var a = new List<double>.filled(40, -1);
     for (int i = 0; i < a.length; i++) {
       a[i] = 1.0 * i + 0.5;
     }
diff --git a/tests/corelib/symbol_map_helper.dart b/tests/corelib/symbol_map_helper.dart
index da9e7e5..2fe69f6 100644
--- a/tests/corelib/symbol_map_helper.dart
+++ b/tests/corelib/symbol_map_helper.dart
@@ -5,7 +5,7 @@
 library dart.test.symbol_map_helper;
 
 // TODO(ahe): Update map literals to avoid this method.
-Map<Symbol, dynamic> symbolMapToStringMap(Map<String, dynamic> map) {
+Map<Symbol, dynamic>? symbolToStringMap(Map<String, dynamic> map) {
   if (map == null) return null;
   Map<Symbol, dynamic> result = new Map<Symbol, dynamic>();
   map.forEach((name, value) {
diff --git a/tests/corelib/symbol_operator_test.dart b/tests/corelib/symbol_operator_test.dart
index ac79499..c32837f 100644
--- a/tests/corelib/symbol_operator_test.dart
+++ b/tests/corelib/symbol_operator_test.dart
@@ -76,6 +76,6 @@
 }
 
 class Symbolize {
-  Symbol lastMember;
+  Symbol? lastMember;
   noSuchMethod(m) => lastMember = m.memberName;
 }
diff --git a/tests/corelib/weak_mode/README b/tests/corelib/weak_mode/README
new file mode 100644
index 0000000..9da48ae
--- /dev/null
+++ b/tests/corelib/weak_mode/README
@@ -0,0 +1,2 @@
+This directory contains tests specific to null safety weak mode
+behavior.
\ No newline at end of file
diff --git a/tests/corelib/weak_mode/asyncMap_accepts_null.dart b/tests/corelib/weak_mode/asyncMap_accepts_null.dart
new file mode 100644
index 0000000..d25a21a
--- /dev/null
+++ b/tests/corelib/weak_mode/asyncMap_accepts_null.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.
+
+// @dart = 2.7
+
+import "dart:async";
+import "package:expect/expect.dart";
+
+// Regression test for https://github.com/dart-lang/sdk/issues/41465
+
+void main() {
+  var stream = Stream.fromIterable([1, 2, 3, 4]);
+  var eventsStream =
+      stream.asyncMap((i) => i % 2 == 0 ? i : null).where((i) => i != null);
+  eventsStream.listen(Expect.isNotNull);
+}
diff --git a/tests/corelib/weak_mode/future_sync_accepts_null.dart b/tests/corelib/weak_mode/future_sync_accepts_null.dart
new file mode 100644
index 0000000..79ac038
--- /dev/null
+++ b/tests/corelib/weak_mode/future_sync_accepts_null.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.7
+
+import "dart:async";
+import "package:expect/expect.dart";
+
+// Regression test for https://github.com/dart-lang/sdk/issues/41465
+
+void main() async {
+  var f = Future<int>.sync(() => null);
+  Expect.isNull(await f);
+}
diff --git a/tests/language/assert/assignable_type_test.dart b/tests/language/assert/assignable_type_test.dart
index 06b1c8d..d769352 100644
--- a/tests/language/assert/assignable_type_test.dart
+++ b/tests/language/assert/assignable_type_test.dart
@@ -15,7 +15,7 @@
 }
 
 testInt64List() {
-  var array = new List(10);
+  var array = new List<int?>.filled(10, null);
   testInt64ListImpl(array);
 }
 
diff --git a/tests/language/assert/with_type_test_or_cast_test.dart b/tests/language/assert/with_type_test_or_cast_test.dart
index 85a18ec..f494804 100644
--- a/tests/language/assert/with_type_test_or_cast_test.dart
+++ b/tests/language/assert/with_type_test_or_cast_test.dart
@@ -12,7 +12,7 @@
 // VMOptions=--enable_asserts
 
 main() {
-  var names = new List<int>();
+  var names = <int>[];
 
   // Generic type test.
   assert(names is List<int>);
diff --git a/tests/language/async/return_types_test.dart b/tests/language/async/return_types_test.dart
index 473150f..9adba85 100644
--- a/tests/language/async/return_types_test.dart
+++ b/tests/language/async/return_types_test.dart
@@ -41,8 +41,6 @@
 // [error line 40, column 1]
 // [cfe] Functions marked 'async' must have a return type assignable to 'Future'.
   return 3;
-  //     ^
-  // [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
 }
 
 Future<int> foo6() async {
diff --git a/tests/language/closure/bound_closure_equality_test.dart b/tests/language/closure/bound_closure_equality_test.dart
new file mode 100644
index 0000000..6ed96db
--- /dev/null
+++ b/tests/language/closure/bound_closure_equality_test.dart
@@ -0,0 +1,76 @@
+// 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 "package:expect/expect.dart";
+
+class A {
+  const A();
+  foo() => 42;
+}
+
+class B {
+  foo() => 42;
+}
+
+main() {
+  // Use an array to defeat type inferencing.
+  var array = <dynamic>[new A(), new A(), new B(), new B()];
+  var set = new Set.from(array.map((a) => a.foo));
+  Expect.equals(array.length, set.length);
+  set.addAll(array.map((a) => a.foo));
+  Expect.equals(array.length, set.length);
+
+  for (int i = 0; i < array.length; i += 2) {
+    Expect.isTrue(set.contains(array[i].foo));
+    Expect.equals(array[i], array[i]);
+    Expect.equals(array[i].foo, array[i].foo);
+    Expect.equals(array[i].foo.hashCode, array[i].foo.hashCode);
+    for (int j = 0; j < array.length; j++) {
+      if (i == j) continue;
+      Expect.notEquals(array[i].foo, array[j].foo);
+    }
+  }
+
+  // Try with dart2js intercepted types.
+  array = <dynamic>['foo', 'bar', [], [], const []];
+  set = new Set.from(array.map((a) => a.indexOf));
+  Expect.equals(array.length, set.length);
+  set.addAll(array.map((a) => a.indexOf));
+  Expect.equals(array.length, set.length);
+
+  for (int i = 0; i < array.length; i += 2) {
+    Expect.isTrue(set.contains(array[i].indexOf));
+    Expect.equals(array[i], array[i]);
+    Expect.equals(array[i].indexOf, array[i].indexOf);
+    Expect.equals(array[i].indexOf.hashCode, array[i].indexOf.hashCode);
+    for (int j = 0; j < array.length; j++) {
+      if (i == j) continue;
+      Expect.notEquals(array[i].indexOf, array[j].indexOf);
+    }
+  }
+
+  array = <dynamic>[const A(), const A()];
+  set = new Set.from(array.map((a) => a.foo));
+  Expect.equals(1, set.length);
+  set.addAll(array.map((a) => a.foo));
+  Expect.equals(1, set.length);
+
+  Expect.isTrue(set.contains(array[0].foo));
+  Expect.equals(array[0].foo, array[0].foo);
+  Expect.equals(array[0].foo.hashCode, array[0].foo.hashCode);
+  Expect.equals(array[0].foo, array[1].foo);
+  Expect.equals(array[0].foo.hashCode, array[1].foo.hashCode);
+
+  array = <dynamic>[const [], const []];
+  set = new Set.from(array.map((a) => a.indexOf));
+  Expect.equals(1, set.length);
+  set.addAll(array.map((a) => a.indexOf));
+  Expect.equals(1, set.length);
+
+  Expect.isTrue(set.contains(array[0].indexOf));
+  Expect.equals(array[0].indexOf, array[0].indexOf);
+  Expect.equals(array[0].indexOf.hashCode, array[0].indexOf.hashCode);
+  Expect.equals(array[0].indexOf, array[1].indexOf);
+  Expect.equals(array[0].indexOf.hashCode, array[1].indexOf.hashCode);
+}
diff --git a/tests/language/closure/bound_closure_primitives_test.dart b/tests/language/closure/bound_closure_primitives_test.dart
new file mode 100644
index 0000000..cd5bdfe
--- /dev/null
+++ b/tests/language/closure/bound_closure_primitives_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Test to make sure dart2js does not try to use the same
+// BoundClosureClass between an intercepted method and a
+// non-intercepted method.
+
+import "package:expect/expect.dart";
+
+class A {
+  // Make dart2js try to share a bound closure for [foo] with a bound
+  // closure for [List.add], by having same number of arguments.
+  foo(a) => a;
+}
+
+main() {
+  var array = <dynamic>[[], new A()];
+  var method = array[0].add;
+  method(42);
+
+  method = array[1].foo;
+  Expect.equals(42, method(42));
+
+  Expect.equals(1, array[0].length);
+  Expect.isTrue(array[0].contains(42));
+}
diff --git a/tests/language/closure/break1_test.dart b/tests/language/closure/break1_test.dart
new file mode 100644
index 0000000..8522fae
--- /dev/null
+++ b/tests/language/closure/break1_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test for closures.
+
+import "package:expect/expect.dart";
+
+class ClosureBreak1 {
+  ClosureBreak1(this.field);
+  int field;
+}
+
+class ClosureBreak1Test {
+  static testMain() {
+    var o1 = new ClosureBreak1(3);
+    String newstr = "abcdefgh";
+    foo() {
+      o1.field++;
+      Expect.equals(8, newstr.length);
+    }
+
+    bool loop = true;
+    L:
+    while (loop) {
+      String newstr1 = "abcd";
+      var o2 = new ClosureBreak1(3);
+      foo1() {
+        o2.field++;
+        Expect.equals(4, newstr1.length);
+      }
+
+      Expect.equals(4, newstr1.length);
+      while (loop) {
+        int newint = 0;
+        var o3 = new ClosureBreak1(3);
+        foo2() {
+          o3.field++;
+          Expect.equals(0, newint);
+        }
+
+        foo2();
+        break L;
+      }
+    }
+    foo();
+    Expect.equals(4, o1.field);
+  }
+}
+
+main() {
+  ClosureBreak1Test.testMain();
+}
diff --git a/tests/language/closure/break2_test.dart b/tests/language/closure/break2_test.dart
new file mode 100644
index 0000000..5742620
--- /dev/null
+++ b/tests/language/closure/break2_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test for closures.
+
+import "package:expect/expect.dart";
+
+class ClosureBreak2 {
+  ClosureBreak2(this.field);
+  int field;
+}
+
+class ClosureBreak2Test {
+  static testMain() {
+    var o1 = new ClosureBreak2(3);
+    String newstr = "abcdefgh";
+    foo() {
+      o1.field++;
+      Expect.equals(8, newstr.length);
+    }
+
+    bool loop = true;
+    L:
+    while (loop) {
+      String newstr1 = "abcd";
+      Expect.equals(4, newstr1.length);
+      while (loop) {
+        int newint = 0;
+        Expect.equals(4, newstr1.length);
+        break L;
+      }
+    }
+    foo();
+    Expect.equals(4, o1.field);
+  }
+}
+
+main() {
+  ClosureBreak2Test.testMain();
+}
diff --git a/tests/language/closure/break_test.dart b/tests/language/closure/break_test.dart
new file mode 100644
index 0000000..ae99035
--- /dev/null
+++ b/tests/language/closure/break_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test for closures.
+
+import "package:expect/expect.dart";
+
+class ClosureBreak {
+  ClosureBreak(this.field);
+  int field;
+}
+
+class ClosureBreakTest {
+  static testMain() {
+    var o1 = new ClosureBreak(3);
+    String newstr = "abcdefgh";
+    foo() {
+      o1.field++;
+      Expect.equals(8, newstr.length);
+    }
+
+    bool loop = true;
+    L1:
+    while (loop) {
+      String newstr1 = "abcd";
+      var o2 = new ClosureBreak(3);
+      foo1() {
+        o2.field++;
+        Expect.equals(4, newstr1.length);
+      }
+
+      Expect.equals(4, newstr1.length);
+      L2:
+      while (loop) {
+        int newint = 0;
+        var o3 = new ClosureBreak(3);
+        foo2() {
+          o3.field++;
+          Expect.equals(0, newint);
+        }
+
+        foo2();
+        break L2;
+      }
+      foo1();
+      Expect.equals(4, newstr1.length);
+      break L1;
+    }
+    foo();
+    Expect.equals(4, o1.field);
+  }
+}
+
+main() {
+  ClosureBreakTest.testMain();
+}
diff --git a/tests/language/closure/call_wrong_argument_count_test.dart b/tests/language/closure/call_wrong_argument_count_test.dart
new file mode 100644
index 0000000..ef9f964
--- /dev/null
+++ b/tests/language/closure/call_wrong_argument_count_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Test mismatch in argument counts.
+import 'package:expect/expect.dart';
+
+int melke(f) {
+  return f(1, 2, 3);
+}
+
+main() {
+  kuh(int a, int b) {
+    return a + b;
+  }
+
+  Expect.throws(() {
+    melke(kuh);
+  });
+}
diff --git a/tests/language/closure/closure2_test.dart b/tests/language/closure/closure2_test.dart
new file mode 100644
index 0000000..bf3cf01
--- /dev/null
+++ b/tests/language/closure/closure2_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test for closures.
+
+import "package:expect/expect.dart";
+
+bounce(fn) {
+  return fn();
+}
+
+demo(s) {
+  var i, a = bounce(() => s);
+  return a;
+}
+
+main() {
+  Expect.equals("Bounce!", demo("Bounce!"));
+}
diff --git a/tests/language/closure/closure3_test.dart b/tests/language/closure/closure3_test.dart
new file mode 100644
index 0000000..8841d375
--- /dev/null
+++ b/tests/language/closure/closure3_test.dart
@@ -0,0 +1,18 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that a NoSuchMethodError is thrown even when an expression
+// seems to be free of side-effects.
+
+test(x, y) {
+  (() {
+    x - y;
+  })();
+}
+
+main() {
+  Expect.throwsNoSuchMethodError(() => test(null, 2));
+}
diff --git a/tests/language/closure/closure4_test.dart b/tests/language/closure/closure4_test.dart
new file mode 100644
index 0000000..5445b7d
--- /dev/null
+++ b/tests/language/closure/closure4_test.dart
@@ -0,0 +1,21 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart2js failed when a declared function was captured inside itself.
+
+foo(f) => f(499);
+
+main() {
+  fun(x) {
+    if (x < 3) {
+      return foo((x) => fun(x));
+    } else {
+      return x;
+    }
+  }
+
+  Expect.equals(499, fun(499));
+}
diff --git a/tests/language/closure/closure5_test.dart b/tests/language/closure/closure5_test.dart
new file mode 100644
index 0000000..bf698b6
--- /dev/null
+++ b/tests/language/closure/closure5_test.dart
@@ -0,0 +1,21 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart2js failed when a declared function was captured inside itself.
+
+foo(f) => f(499);
+
+main() {
+  fun(x) {
+    if (x < 3) {
+      return foo((x) => fun(x));
+    } else {
+      return x;
+    }
+  }
+
+  Expect.equals(499, foo((x) => fun(x)));
+}
diff --git a/tests/language/closure/closure6_test.dart b/tests/language/closure/closure6_test.dart
new file mode 100644
index 0000000..ea37454
--- /dev/null
+++ b/tests/language/closure/closure6_test.dart
@@ -0,0 +1,23 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that captured final variables are correctly mangled.
+
+class A {
+  foo() {
+    length() => 400;
+    final box_0 = 28;
+    var x = 29;
+    var f = () => length() + box_0 + x + bar();
+    return f();
+  }
+
+  bar() => 42;
+}
+
+main() {
+  Expect.equals(499, new A().foo());
+}
diff --git a/tests/language/closure/closure7_test.dart b/tests/language/closure/closure7_test.dart
new file mode 100644
index 0000000..91b8f7b
--- /dev/null
+++ b/tests/language/closure/closure7_test.dart
@@ -0,0 +1,97 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that implicitly bound closures work correctly
+
+class A {
+  foo() => 499;
+  fooo() => 4999; // Implicit closure class can be shared with foo.
+  bar(x, {y: 8, z: 10}) => "1 $x $y $z";
+  gee(x, {y: 9, z: 11}) => "2 $x $y $z"; // Must not be shared with "bar".
+  toto(x, {y: 8, z: 10}) => "3 $x $y $z"; // Could be shared with "bar".
+
+  fisk(x, {y: 8, zz: 10}) => "4 $x $y $zz";
+  titi(x, {y: 8, zz: 77}) => "5 $x $y $zz"; // Could be shared with "fisk",
+  // because default-val is never used.
+}
+
+class B {
+  // All implicit closures of B can be shared with their equivalent functions
+  // of A.
+  foo() => 4990;
+  fooo() => 49990;
+  bar(x, {y: 8, z: 10}) => "1B $x $y $z";
+  gee(x, {y: 9, z: 11}) => "2B $x $y $z";
+  toto(x, {y: 8, z: 10}) => "3B $x $y $z";
+  fisk(x, {y: 8, zz: 10}) => "4B $x $y $zz";
+  titi(x, {y: 8, zz: 77}) => "5B $x $y $zz";
+}
+
+tearOffFoo(o) => o.foo;
+tearOffFooo(o) => o.fooo;
+tearOffBar(o) => o.bar;
+tearOffGee(o) => o.gee;
+tearOffToto(o) => o.toto;
+tearOffFisk(o) => o.fisk;
+tearOffTiti(o) => o.titi;
+
+main() {
+  var a = new A();
+  var b = new B();
+  Expect.equals(499, tearOffFoo(a)());
+  Expect.equals(4990, tearOffFoo(b)());
+  Expect.equals(4999, tearOffFooo(a)());
+  Expect.equals(49990, tearOffFooo(b)());
+
+  var barA = tearOffBar(a);
+  var barB = tearOffBar(b);
+  var geeA = tearOffGee(a);
+  var geeB = tearOffGee(b);
+  var totoA = tearOffToto(a);
+  var totoB = tearOffToto(b);
+  Expect.equals("1 33 8 10", barA(33));
+  Expect.equals("1B 33 8 10", barB(33));
+  Expect.equals("2 33 9 11", geeA(33));
+  Expect.equals("2B 33 9 11", geeB(33));
+  Expect.equals("3 33 8 10", totoA(33));
+  Expect.equals("3B 33 8 10", totoB(33));
+
+  Expect.equals("1 35 8 10", barA(35));
+  Expect.equals("1B 35 8 10", barB(35));
+  Expect.equals("2 35 9 11", geeA(35));
+  Expect.equals("2B 35 9 11", geeB(35));
+  Expect.equals("3 35 8 10", totoA(35));
+  Expect.equals("3B 35 8 10", totoB(35));
+
+  Expect.equals("1 35 8 77", barA(35, z: 77));
+  Expect.equals("1B 35 8 77", barB(35, z: 77));
+  Expect.equals("2 35 9 77", geeA(35, z: 77));
+  Expect.equals("2B 35 9 77", geeB(35, z: 77));
+  Expect.equals("3 35 8 77", totoA(35, z: 77));
+  Expect.equals("3B 35 8 77", totoB(35, z: 77));
+
+  Expect.equals("1 35 8 77", barA(35, z: 77));
+  Expect.equals("1B 35 8 77", barB(35, z: 77));
+  Expect.equals("2 35 9 77", geeA(35, z: 77));
+  Expect.equals("2B 35 9 77", geeB(35, z: 77));
+  Expect.equals("3 35 8 77", totoA(35, z: 77));
+  Expect.equals("3B 35 8 77", totoB(35, z: 77));
+
+  var fiskA = tearOffFisk(a);
+  var fiskB = tearOffFisk(b);
+  var titiA = tearOffTiti(a);
+  var titiB = tearOffTiti(b);
+
+  Expect.equals("4 311 8 987", fiskA(311, zz: 987));
+  Expect.equals("4B 311 8 987", fiskB(311, zz: 987));
+  Expect.equals("5 311 8 987", titiA(311, zz: 987));
+  Expect.equals("5B 311 8 987", titiB(311, zz: 987));
+
+  Expect.equals("4 311 765 987", fiskA(311, y: 765, zz: 987));
+  Expect.equals("4B 311 765 987", fiskB(311, y: 765, zz: 987));
+  Expect.equals("5 311 765 987", titiA(311, y: 765, zz: 987));
+  Expect.equals("5B 311 765 987", titiB(311, y: 765, zz: 987));
+}
diff --git a/tests/language/closure/closure8_test.dart b/tests/language/closure/closure8_test.dart
new file mode 100644
index 0000000..211c722
--- /dev/null
+++ b/tests/language/closure/closure8_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 for issue 6353.
+
+class A<E> {}
+
+class C<E> extends A<E> {
+  forEach(callback(E element)) {}
+}
+
+class D<E> {
+  lala(E element) {}
+}
+
+main() {
+  var c = new C<int>();
+  c.forEach(new D<int>().lala);
+}
diff --git a/tests/language/closure/closure_test.dart b/tests/language/closure/closure_test.dart
new file mode 100644
index 0000000..9dc3a90
--- /dev/null
+++ b/tests/language/closure/closure_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test for closures.
+
+import "package:expect/expect.dart";
+
+class A {
+  var field;
+  A(this.field) {}
+}
+
+class ClosureTest {
+  static testMain() {
+    var o = new A(3);
+    foo() => o.field++;
+    Expect.equals(3, foo());
+    Expect.equals(4, o.field);
+  }
+}
+
+main() {
+  ClosureTest.testMain();
+}
diff --git a/tests/language/closure/closures_initializer2_test.dart b/tests/language/closure/closures_initializer2_test.dart
new file mode 100644
index 0000000..337639b
--- /dev/null
+++ b/tests/language/closure/closures_initializer2_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+class A<T> {
+  var t;
+  A() : t = (() => T);
+}
+
+expect(result, expected) {
+  if (result != expected) {
+    throw 'Expected $expected, got $result';
+  }
+}
+
+main() {
+  for (var i = 0; i < int.parse("1"); i++) {
+    expect(new A<int>().t() is Type, true);
+  }
+}
diff --git a/tests/language/closure/closures_initializer_test.dart b/tests/language/closure/closures_initializer_test.dart
new file mode 100644
index 0000000..0d60490
--- /dev/null
+++ b/tests/language/closure/closures_initializer_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+class A<T> {
+  var t;
+  A() : t = (() => <T>[]);
+}
+
+class B<T> {
+  var t;
+  B() : t = (() => T);
+}
+
+expect(result, expected) {
+  if (result != expected) {
+    throw 'Expected $expected, got $result';
+  }
+}
+
+main() {
+  expect(new A<int>().t() is List<int>, true);
+  expect(new A<String>().t() is List<int>, false);
+  expect(new B<int>().t() is Type, true);
+  expect(new B<int>().t(), int);
+}
diff --git a/tests/language/closure/closures_with_complex_params_test.dart b/tests/language/closure/closures_with_complex_params_test.dart
new file mode 100644
index 0000000..175999a
--- /dev/null
+++ b/tests/language/closure/closures_with_complex_params_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 for parsing closures with complex parameter types.
+const defaultPair = Pair<int, Pair<int, int>>(-1, Pair(-2, -3));
+
+main() {
+  test1();
+  test2();
+  test3();
+}
+
+class Pair<A, B> {
+  final A fst;
+  final B snd;
+  const Pair(A this.fst, B this.snd);
+}
+
+test1() {
+  // Closures with nested parameterized types.
+  var cdar1 = (Pair<int, Pair<int, int>> pr) => pr.snd.fst;
+  var cdar2 = (Pair<int, Pair<int, int>> pr) => pr.snd.fst;
+
+  var e = new Pair<int, Pair<int, int>>(100, new Pair<int, int>(200, 300));
+
+  Expect.equals(200, cdar1(e));
+  Expect.equals(200, cdar2(e));
+}
+
+test2() {
+  // Closures with nested parameterized types in optional position
+  var cdar1 = ([Pair<int, Pair<int, int>> pr = defaultPair]) => pr.snd.fst;
+  var cdar2 = ([Pair<int, Pair<int, int>> pr = defaultPair]) => pr.snd.fst;
+
+  var e = new Pair<int, Pair<int, int>>(100, new Pair<int, int>(200, 300));
+
+  Expect.equals(200, cdar1(e));
+  Expect.equals(200, cdar2(e));
+}
+
+test3() {
+  // Closures with nested parameterized types.
+  var f1 = (Pair<int, Pair<int, int>> pr) => pr.snd.fst + 1;
+  var f2 = (Pair<int, Pair<int, int>> pr) => pr.snd.fst + 2;
+
+  // Closures with function type with nested parameterized types.
+  var ap1 = (f(Pair<int, Pair<int, int>> pr1), Pair<int, Pair<int, int>> pr) =>
+      f(pr) * 10;
+  var ap2 = (f(Pair<int, Pair<int, int>> pr1), Pair<int, Pair<int, int>> pr) =>
+      f(pr) * 100;
+
+  var e = new Pair<int, Pair<int, int>>(100, new Pair<int, int>(200, 300));
+
+  Expect.equals(2010, ap1(f1, e));
+  Expect.equals(2020, ap1(f2, e));
+  Expect.equals(20100, ap2(f1, e));
+  Expect.equals(20200, ap2(f2, e));
+}
diff --git a/tests/language/closure/cycles_test.dart b/tests/language/closure/cycles_test.dart
new file mode 100644
index 0000000..7ad7dae
--- /dev/null
+++ b/tests/language/closure/cycles_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Based on dartbug.com/7681
+// Verify that context chains do not lead to unintended memory being held.
+
+library closure_cycles_test;
+
+import "dart:async";
+
+class X {
+  late Function onX;
+  X() {
+    Timer.run(() => onX(new Y()));
+  }
+}
+
+class Y {
+  late Function onY;
+  var heavyMemory;
+  static var count = 0;
+  Y() {
+    // Consume large amounts of memory per iteration to fail/succeed quicker.
+    heavyMemory = new List.filled(10 * 1024 * 1024, null);
+    // Terminate the test if we allocated enough memory without running out.
+    if (count++ > 100) return;
+    Timer.run(() => onY());
+  }
+}
+
+void doIt() {
+  var x = new X();
+  x.onX = (y) {
+    y.onY = () {
+      y; // Capturing y can lead to endless context chains!
+      doIt();
+    };
+  };
+}
+
+void main() {
+  doIt();
+}
diff --git a/tests/language/closure/forwarding_stub_tearoff_generic_test.dart b/tests/language/closure/forwarding_stub_tearoff_generic_test.dart
new file mode 100644
index 0000000..1bccc6e
--- /dev/null
+++ b/tests/language/closure/forwarding_stub_tearoff_generic_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 "package:expect/expect.dart";
+
+class A {}
+
+class B extends A {}
+
+class C {
+  void f(B x) {}
+}
+
+abstract class I<T> {
+  void f(T x);
+}
+
+// D contains a forwarding stub for f which ensures that `x` is type checked.
+class D extends C implements I<B> {}
+
+void checkStubTearoff(dynamic tearoff) {
+  // Since the stub's parameter is covariant, its type should be reified as
+  // Object.
+  Expect.isTrue(tearoff is void Function(Object));
+
+  // Verify that the appropriate runtime check occurs.
+  tearoff(new B()); // No error
+  Expect.throwsTypeError(() {
+    tearoff(new A());
+  });
+}
+
+main() {
+  // The same forwarding stub should be torn off from D regardless of what
+  // interface is used to tear it off.
+  D d = new D();
+  C c = d;
+  I i = d;
+  checkStubTearoff(d.f);
+  checkStubTearoff(c.f);
+  checkStubTearoff(i.f);
+}
diff --git a/tests/language/closure/forwarding_stub_tearoff_test.dart b/tests/language/closure/forwarding_stub_tearoff_test.dart
new file mode 100644
index 0000000..12aa7bf
--- /dev/null
+++ b/tests/language/closure/forwarding_stub_tearoff_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 "package:expect/expect.dart";
+
+class A {}
+
+class B extends A {}
+
+class C {
+  void f(B x) {}
+}
+
+abstract class I {
+  void f(covariant A x);
+}
+
+// D contains a forwarding stub for f which ensures that `x` is type checked.
+class D extends C implements I {}
+
+void checkStubTearoff(dynamic tearoff) {
+  // Since the stub's parameter is covariant, its type should be reified as
+  // Object.
+  Expect.isTrue(tearoff is void Function(Object));
+
+  // Verify that the appropriate runtime check occurs.
+  tearoff(new B()); // No error
+  Expect.throwsTypeError(() {
+    tearoff(new A());
+  });
+}
+
+main() {
+  // The same forwarding stub should be torn off from D regardless of what
+  // interface is used to tear it off.
+  D d = new D();
+  C c = d;
+  I i = d;
+  checkStubTearoff(d.f);
+  checkStubTearoff(c.f);
+  checkStubTearoff(i.f);
+}
diff --git a/tests/language/closure/implicit1_test.dart b/tests/language/closure/implicit1_test.dart
new file mode 100644
index 0000000..4a8a4f4
--- /dev/null
+++ b/tests/language/closure/implicit1_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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=--enable_type_checks --enable_asserts
+
+typedef Handler(bool e);
+
+class Hello {
+  Hello() {}
+  void handler2(bool e) {
+    print('handler2');
+  }
+
+  static void handler1(bool e) {
+    print('handler1');
+  }
+
+  void addEventListener(String s, Handler handler, bool status) {
+    handler(status);
+  }
+
+  static void main() {
+    final h = new Hello();
+    h.addEventListener('click', handler1, false);
+    h.addEventListener('click', h.handler2, false);
+  }
+}
+
+main() {
+  Hello.main();
+}
diff --git a/tests/language/closure/implicit2_test.dart b/tests/language/closure/implicit2_test.dart
new file mode 100644
index 0000000..a03f458
--- /dev/null
+++ b/tests/language/closure/implicit2_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class B {
+  foo(i) => 499 + i;
+}
+
+class A {
+  var b;
+  A() : b = new B();
+
+  foo(i) {
+    return (() => b.foo(i))();
+  }
+}
+
+main() {
+  var a = new A();
+  Expect.equals(510, a.foo(11));
+  var f = a.foo;
+  Expect.equals(521, f(22));
+}
diff --git a/tests/language/closure/implicit_closure_test.dart b/tests/language/closure/implicit_closure_test.dart
new file mode 100644
index 0000000..a9ea617
--- /dev/null
+++ b/tests/language/closure/implicit_closure_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing invocation of implicit closures.
+// VMOptions=
+// VMOptions=--use_slow_path
+
+import "package:expect/expect.dart";
+
+class First {
+  First(this.i) {}
+  var b;
+  int foo() {
+    return i;
+  }
+
+  Function foo1() {
+    local() {
+      return i;
+    }
+
+    return local;
+  }
+
+  int i;
+}
+
+class ImplicitClosureTest {
+  static void testMain() {
+    First obj = new First(20);
+
+    Function func = () => obj.i;
+    obj.b = func;
+    Expect.equals(20, obj.b());
+
+    var ib1 = obj.foo1();
+    Expect.equals(obj.i, ib1());
+
+    var ib = obj.foo;
+    Expect.equals(obj.i, ib());
+  }
+}
+
+main() {
+  ImplicitClosureTest.testMain();
+}
diff --git a/tests/language/closure/in_constructor_test.dart b/tests/language/closure/in_constructor_test.dart
new file mode 100644
index 0000000..4c768a3
--- /dev/null
+++ b/tests/language/closure/in_constructor_test.dart
@@ -0,0 +1,26 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  var closure;
+
+  factory A.factory() => new A(() => <T>[]);
+
+  A([this.closure]) {
+    if (closure == null) {
+      closure = () => <T>[];
+    }
+  }
+}
+
+main() {
+  Expect.isTrue((new A.factory()).closure() is List);
+  Expect.isTrue((new A()).closure() is List);
+  Expect.isTrue((new A<int>.factory()).closure() is List<int>);
+  Expect.isTrue((new A<int>()).closure() is List<int>);
+  Expect.isFalse((new A<int>.factory()).closure() is List<String>);
+  Expect.isFalse((new A<int>()).closure() is List<String>);
+}
diff --git a/tests/language/closure/in_field_initializer_test.dart b/tests/language/closure/in_field_initializer_test.dart
new file mode 100644
index 0000000..e2dbc5b
--- /dev/null
+++ b/tests/language/closure/in_field_initializer_test.dart
@@ -0,0 +1,14 @@
+// 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 "package:expect/expect.dart";
+
+class Foo {
+  var closures = {'a': (int x, int y) => x + y};
+}
+
+main() {
+  var closures = new Foo().closures;
+  Expect.equals(6, closures['a']!(4, 2));
+}
diff --git a/tests/language/closure/in_initializer2_test.dart b/tests/language/closure/in_initializer2_test.dart
new file mode 100644
index 0000000..a782c64
--- /dev/null
+++ b/tests/language/closure/in_initializer2_test.dart
@@ -0,0 +1,27 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a parameter used in a closure is properly boxed.
+
+import "package:expect/expect.dart";
+
+abstract class S {
+  S() {
+    Expect.equals(2, this.f());
+  }
+
+  get f;
+}
+
+class A extends S {
+  var f;
+  A(a) : f = (() => ++a) {
+    Expect.equals(a, 2);
+  }
+}
+
+main() {
+  var a = new A(1);
+  Expect.equals(a.f(), 3);
+}
diff --git a/tests/language/closure/in_initializer_test.dart b/tests/language/closure/in_initializer_test.dart
new file mode 100644
index 0000000..3556649
--- /dev/null
+++ b/tests/language/closure/in_initializer_test.dart
@@ -0,0 +1,51 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a parameter used in two different closures defined in a
+// constructor initializer, is properly boxed.
+
+import "package:expect/expect.dart";
+
+class A {
+  var f;
+  var g;
+  A(a)
+      : f = (() => 42 + a),
+        g = (() => ++a) {
+    a = 4;
+  }
+}
+
+class B extends A {
+  B() : super(42);
+}
+
+class C extends A {
+  var h;
+  C(a)
+      : h = (() => ++a),
+        super(42);
+}
+
+main() {
+  dynamic a = new A(1);
+  Expect.equals(46, a.f());
+  Expect.equals(5, a.g());
+  Expect.equals(47, a.f());
+
+  a = new B();
+  Expect.equals(46, a.f());
+  Expect.equals(5, a.g());
+  Expect.equals(47, a.f());
+
+  a = new C(0);
+  Expect.equals(46, a.f());
+  Expect.equals(5, a.g());
+  Expect.equals(47, a.f());
+  Expect.equals(1, a.h());
+  Expect.equals(2, a.h());
+  Expect.equals(47, a.f());
+  Expect.equals(6, a.g());
+  Expect.equals(48, a.f());
+}
diff --git a/tests/language/closure/internals_runtime_test.dart b/tests/language/closure/internals_runtime_test.dart
new file mode 100644
index 0000000..1b52d32
--- /dev/null
+++ b/tests/language/closure/internals_runtime_test.dart
@@ -0,0 +1,19 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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 "package:expect/expect.dart";
+
+class C {
+  foo() => 123;
+}
+
+main() {
+  var f = new C().foo;
+
+
+
+}
diff --git a/tests/language/closure/internals_test.dart b/tests/language/closure/internals_test.dart
new file mode 100644
index 0000000..78f04ab
--- /dev/null
+++ b/tests/language/closure/internals_test.dart
@@ -0,0 +1,25 @@
+// 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 "package:expect/expect.dart";
+
+class C {
+  foo() => 123;
+}
+
+main() {
+  var f = new C().foo;
+  var target = f.target;
+  //             ^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'target' isn't defined for the class 'dynamic Function()'.
+  var self = f.self;
+  //           ^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'self' isn't defined for the class 'dynamic Function()'.
+  var receiver = f.receiver;
+  //               ^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'receiver' isn't defined for the class 'dynamic Function()'.
+}
diff --git a/tests/language/closure/invoked_through_interface_target_field_test.dart b/tests/language/closure/invoked_through_interface_target_field_test.dart
new file mode 100644
index 0000000..a60f495
--- /dev/null
+++ b/tests/language/closure/invoked_through_interface_target_field_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.
+
+// Note: this test expects a compile error (getter overrides a method), but it
+// contains more code than necessary to provoke the compile error.  The reason
+// for the extra code is to document the complications that would arise if we
+// decided to eliminate the compile error (and allow getters to override
+// methods).
+
+import "package:expect/expect.dart";
+
+typedef void F<T>(T t);
+
+abstract class A {
+  void foo(Object n);
+}
+
+class C implements A {
+  F<Object> foo;
+  //        ^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_FIELD_AND_METHOD
+  // [cfe] Can't declare a member that conflicts with an inherited one.
+  C(this.foo);
+}
+
+class D<T> {
+  void m(T t) {}
+}
+
+F<Object> bar(D<int> d) => d.m as dynamic;
+void baz(A a) {
+  Expect.throws(() {
+    // This call looks like it doesn't require any runtime type checking, since
+    // it is a call to a regular method with no covariant parameters.  However,
+    // if we decide to allow getters to override methods, then it's possible
+    // that it's actually invoking a getter that returns a closure, and that
+    // closure might have covariant parameters that need runtime type checks.
+    a.foo('hi');
+  });
+  // This call is ok because the types match up at runtime.
+  a.foo(1);
+}
+
+main() {
+  baz(new C(bar(new D<int>())));
+}
diff --git a/tests/language/closure/invoked_through_interface_target_getter_test.dart b/tests/language/closure/invoked_through_interface_target_getter_test.dart
new file mode 100644
index 0000000..05edef8
--- /dev/null
+++ b/tests/language/closure/invoked_through_interface_target_getter_test.dart
@@ -0,0 +1,46 @@
+// 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.
+
+// Note: this test expects a compile error (getter overrides a method), but it
+// contains more code than necessary to provoke the compile error.  The reason
+// for the extra code is to document the complications that would arise if we
+// decided to eliminate the compile error (and allow getters to override
+// methods).
+
+import "package:expect/expect.dart";
+
+typedef void F<T>(T t);
+
+abstract class A {
+  void foo(Object n);
+}
+
+class C implements A {
+  F<Object> get foo => bar(new D<int>());
+  //            ^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_FIELD_AND_METHOD
+  // [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+class D<T> {
+  void m(T t) {}
+}
+
+F<Object> bar(D<int> d) => d.m as dynamic;
+void baz(A a) {
+  Expect.throws(() {
+    // This call looks like it doesn't require any runtime type checking, since
+    // it is a call to a regular method with no covariant parameters.  However,
+    // if we decide to allow getters to override methods, then it's possible
+    // that it's actually invoking a getter that returns a closure, and that
+    // closure might have covariant parameters that need runtime type checks.
+    a.foo('hi');
+  });
+  // This call is ok because the types match up at runtime.
+  a.foo(1);
+}
+
+main() {
+  baz(new C());
+}
diff --git a/tests/language/closure/minify_closure_variable_collision_test.dart b/tests/language/closure/minify_closure_variable_collision_test.dart
new file mode 100644
index 0000000..282acef
--- /dev/null
+++ b/tests/language/closure/minify_closure_variable_collision_test.dart
@@ -0,0 +1,45 @@
+// 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.
+
+// Regression test for dart2js, that used to minify a captured
+// variable's name to the same name as inherited Object methods.
+
+var array = [new A()];
+
+class A {
+  operator ==(other) {
+    return true;
+  }
+}
+
+foo() {
+  // Use lots of variables, to maximize the chance of collisions.
+  var a = 42;
+  var b = 42;
+  var c = 42;
+  var d = 42;
+  var e = 42;
+  var f = 42;
+  var g = 42;
+  var h = 42;
+  var i = 42;
+  var j = 42;
+  var k = 42;
+  var l = 42;
+  var m = 42;
+  var n = 42;
+  array[0] = () {
+    return a + b + c + d + e + f + g + h + i + j + k + l + m + n;
+  };
+}
+
+main() {
+  foo();
+  if (array[0] == new A()) {
+    throw 'Test failed';
+  }
+  if (array[0]() != 42 * 14) {
+    throw 'Test failed';
+  }
+}
diff --git a/tests/language/closure/nested_generic_closure_test.dart b/tests/language/closure/nested_generic_closure_test.dart
new file mode 100644
index 0000000..53fd1f9
--- /dev/null
+++ b/tests/language/closure/nested_generic_closure_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 'package:expect/expect.dart';
+
+void foo(F f<F>(F f)) {}
+
+B bar<B>(B g<F>(F f)) => throw "uncalled";
+
+Function baz<B>() {
+  B foo<F>(B b, F f) => throw "uncalled";
+  return foo;
+}
+
+class C<T> {
+  void foo(F f<F>(T t, F f)) => null;
+  B bar<B>(B g<F>(T t, F f)) => throw "uncalled";
+  Function baz<B>() {
+    B foo<F>(T t, F f) => throw "uncalled";
+    return foo;
+  }
+}
+
+main() {
+  // Check the run-time type of the functions with generic parameters.
+
+  Expect.type<void Function(X Function<X>(X))>(foo);
+
+  Expect.isTrue(bar is X1 Function<X1>(X1 Function<X2>(X2)));
+
+  Expect.isTrue(baz<int>() is int Function<X1>(int, X1));
+  Expect.isTrue(baz<Object>() is Object Function<X1>(Object, X1));
+  Expect.isTrue(baz<Null>() is Null Function<X1>(Null, X1));
+
+  void testC<T>() {
+    var c = new C<T>();
+
+    Expect.type<void Function(F Function<F>(T, F))>(c.foo);
+
+    Expect.isTrue(c.bar is X1 Function<X1>(X1 Function<X2>(T, X2)));
+
+    Expect.isTrue(c.baz<int>() is int Function<X1>(T, X1));
+  }
+
+  testC<bool>();
+  testC<Object>();
+  testC<Null>();
+}
diff --git a/tests/language/closure/param_null_to_object_test.dart b/tests/language/closure/param_null_to_object_test.dart
new file mode 100644
index 0000000..e34f400
--- /dev/null
+++ b/tests/language/closure/param_null_to_object_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+// Requirements=nnbd-strong
+import "package:expect/expect.dart";
+
+main() {
+  // Pre-NNBD bottom type.
+  int Function(Null) f = (x) => 1; // Runtime type is int Function(Object?)
+  Expect.isTrue(f is int Function(Null));
+  Expect.isTrue(f is int Function(Never));
+  Expect.isTrue(f is int Function(String));
+  Expect.isTrue(f is int Function(Object));
+  Expect.isTrue(f is int Function(Object?));
+
+  // NNBD bottom type.
+  int Function(Never) g = (x) => 1; // Runtime type is int Function(Object?)
+  Expect.isTrue(g is int Function(Null));
+  Expect.isTrue(g is int Function(Never));
+  Expect.isTrue(g is int Function(String));
+  Expect.isTrue(g is int Function(Object));
+  Expect.isTrue(g is int Function(Object?));
+
+  int Function(String) h = (x) => 1; // Runtime type is int Function(String)
+  Expect.isFalse(h is int Function(Null));
+  Expect.isTrue(h is int Function(Never));
+  Expect.isTrue(h is int Function(String));
+  Expect.isFalse(h is int Function(Object));
+  Expect.isFalse(h is int Function(Object?));
+}
diff --git a/tests/language/closure/param_null_to_object_weak_test.dart b/tests/language/closure/param_null_to_object_weak_test.dart
new file mode 100644
index 0000000..31b8208
--- /dev/null
+++ b/tests/language/closure/param_null_to_object_weak_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+// Requirements=nnbd-weak
+import "package:expect/expect.dart";
+
+main() {
+  // Pre-NNBD bottom type.
+  int Function(Null) f = (x) => 1; // Runtime type is int Function(Object?)
+  Expect.isTrue(f is int Function(Null));
+  Expect.isTrue(f is int Function(Never));
+  Expect.isTrue(f is int Function(String));
+  Expect.isTrue(f is int Function(Object));
+  Expect.isTrue(f is int Function(Object?));
+
+  // NNBD bottom type.
+  int Function(Never) g = (x) => 1; // Runtime type is int Function(Object?)
+  Expect.isTrue(g is int Function(Null));
+  Expect.isTrue(g is int Function(Never));
+  Expect.isTrue(g is int Function(String));
+  Expect.isTrue(g is int Function(Object));
+  Expect.isTrue(g is int Function(Object?));
+
+  int Function(String) h = (x) => 1; // Runtime type is int Function(String)
+  Expect.isTrue(h is int Function(Null));
+  Expect.isTrue(h is int Function(Never));
+  Expect.isTrue(h is int Function(String));
+  Expect.isFalse(h is int Function(Object));
+  Expect.isFalse(h is int Function(Object?));
+}
diff --git a/tests/language/closure/parameter_types_test.dart b/tests/language/closure/parameter_types_test.dart
new file mode 100644
index 0000000..3fa1521
--- /dev/null
+++ b/tests/language/closure/parameter_types_test.dart
@@ -0,0 +1,27 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Regression test for dart2js, where the optimizer was too aggressive
+// about parameter types of closures.
+
+class A {
+  Function f;
+  A(this.f);
+  _do() => f(1);
+}
+
+main() {
+  int invokeCount = 0;
+  closure(a) {
+    if (invokeCount++ == 1) {
+      Expect.isTrue(a is int);
+    }
+  }
+
+  closure('s');
+  new A(closure)._do();
+  Expect.equals(2, invokeCount);
+}
diff --git a/tests/language/closure/parse_closures_in_initializers_test.dart b/tests/language/closure/parse_closures_in_initializers_test.dart
new file mode 100644
index 0000000..9fc7eda
--- /dev/null
+++ b/tests/language/closure/parse_closures_in_initializers_test.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.
+
+import 'package:expect/expect.dart';
+
+// Test that function literals are parsed correctly in initializers.
+
+class A {
+  final x;
+  static foo(f) => f();
+
+  A.parenthesized(y) : x = (() => y);
+  A.stringLiteral(y) : x = "**${() => y}--";
+  A.listLiteral(y) : x = [() => y];
+  A.mapLiteral(y) : x = {"fun": () => y};
+  A.arg(y) : x = foo(() => y);
+}
+
+main() {
+  var a, f;
+  a = new A.parenthesized(499);
+  f = a.x;
+  Expect.isTrue(f is Function);
+  Expect.equals(499, f());
+
+  // The toString of closures is not specified. Just make sure that there is no
+  // crash.
+  a = new A.stringLiteral(42);
+  Expect.isTrue(a.x.startsWith("**"));
+  Expect.isTrue(a.x.endsWith("--"));
+
+  a = new A.listLiteral(99);
+  f = a.x[0];
+  Expect.isTrue(f is Function);
+  Expect.equals(99, f());
+
+  a = new A.mapLiteral(314);
+  f = a.x["fun"];
+  Expect.isTrue(f is Function);
+  Expect.equals(314, f());
+
+  a = new A.arg(123);
+  Expect.equals(123, a.x);
+}
diff --git a/tests/language/closure/partial_instantiation_eager_bounds_check_test.dart b/tests/language/closure/partial_instantiation_eager_bounds_check_test.dart
new file mode 100644
index 0000000..d20a83e
--- /dev/null
+++ b/tests/language/closure/partial_instantiation_eager_bounds_check_test.dart
@@ -0,0 +1,21 @@
+// 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.
+//
+// This test checks that necessary type argument bounds checks are performed
+// eagerly during partial instantiation, rather than being delayed until the
+// partially instantiated closure is invoked.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+  void foo<S extends T>(S x) {}
+}
+
+void main() {
+  C<Object> c = C<int>();
+  void Function(String) fn;
+  Expect.throwsTypeError(() {
+    fn = c.foo;
+  });
+}
diff --git a/tests/language/closure/partial_instantiation_static_bounds_check_runtime_test.dart b/tests/language/closure/partial_instantiation_static_bounds_check_runtime_test.dart
new file mode 100644
index 0000000..4596750
--- /dev/null
+++ b/tests/language/closure/partial_instantiation_static_bounds_check_runtime_test.dart
@@ -0,0 +1,31 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+topFn<T extends num>(T x) {
+  print(T);
+}
+
+class C<T> {
+  instanceFn<S extends T>(S x) {
+    print(S);
+  }
+}
+
+class D<T> extends C<T> {
+  void foo() {
+
+  }
+}
+
+void main() {
+  localFn<T extends num>(T x) {
+    print(T);
+  }
+
+
+
+}
diff --git a/tests/language/closure/partial_instantiation_static_bounds_check_test.dart b/tests/language/closure/partial_instantiation_static_bounds_check_test.dart
new file mode 100644
index 0000000..38192ba
--- /dev/null
+++ b/tests/language/closure/partial_instantiation_static_bounds_check_test.dart
@@ -0,0 +1,34 @@
+// 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.
+
+topFn<T extends num>(T x) {
+  print(T);
+}
+
+class C<T> {
+  instanceFn<S extends T>(S x) {
+    print(S);
+  }
+}
+
+class D<T> extends C<T> {
+  void foo() {
+    void Function(int) k = instanceFn;
+    //                     ^^^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+  }
+}
+
+void main() {
+  localFn<T extends num>(T x) {
+    print(T);
+  }
+
+  void Function(String) k0 = localFn;
+  //                         ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+  void Function(String) k1 = topFn;
+  //                         ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+}
diff --git a/tests/language/closure/partial_tearoff_instantiation_test.dart b/tests/language/closure/partial_tearoff_instantiation_test.dart
new file mode 100644
index 0000000..629b3bd
--- /dev/null
+++ b/tests/language/closure/partial_tearoff_instantiation_test.dart
@@ -0,0 +1,121 @@
+// 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:expect/expect.dart";
+
+typedef F1 = void Function<T>(T);
+typedef void F2<T>(T v);
+
+dynamic defaultFLatest;
+
+void defaultF<T>(T v) {
+  defaultFLatest = v;
+}
+
+class X1 {
+  final F1 f;
+  const X1({this.f: defaultF});
+}
+
+class X2 {
+  final F2 f;
+  const X2({this.f: defaultF});
+}
+
+class Y1 {
+  F1 f = defaultF;
+}
+
+class Y2 {
+  F2 f = defaultF;
+}
+
+dynamic foo() {
+  if (defaultFLatest == -1) return -1;
+  return "not -1";
+}
+
+void main() {
+  {
+    var x = const X1();
+
+    // OK with implicit dynamic type argument.
+    x.f("hello1");
+    Expect.equals("hello1", defaultFLatest);
+
+    // OK with explicit dynamic type argument.
+    x.f<dynamic>("hello2");
+    Expect.equals("hello2", defaultFLatest);
+
+    // OK with correctly given argument type.
+    x.f<String>("hello3");
+    Expect.equals("hello3", defaultFLatest);
+
+    // OK with correctly given argument type.
+    x.f<int>(42);
+    Expect.equals(42, defaultFLatest);
+
+    // Not OK with incorrectly given argument type.
+    x.f<int>("hello"); //# 01: compile-time error
+
+    // Not OK with incorrectly given argument type.
+    x.f<int>(foo()); //# 02: runtime error
+
+    var y = new Y1();
+    y.f = defaultF;
+
+    // OK with implicit dynamic type argument.
+    y.f("hello4");
+    Expect.equals("hello4", defaultFLatest);
+
+    // OK with explicit dynamic type argument.
+    y.f<dynamic>("hello5");
+    Expect.equals("hello5", defaultFLatest);
+
+    // OK with correctly given argument type.
+    y.f<String>("hello6");
+    Expect.equals("hello6", defaultFLatest);
+
+    // OK with correctly given argument type.
+    y.f<int>(43);
+    Expect.equals(43, defaultFLatest);
+
+    // Not OK with incorrectly given argument type.
+    y.f<int>("hello"); //# 03: compile-time error
+
+    // Not OK with incorrectly given argument type.
+    y.f<int>(foo()); //# 04: runtime error
+  }
+  {
+    var x = const X2();
+
+    // OK with no type arguments.
+    x.f("hello1");
+    Expect.equals("hello1", defaultFLatest);
+
+    // Not OK with a type argument.
+    x.f<dynamic>("hello2"); //# 05: compile-time error
+
+    // Not OK with a type argument.
+    x.f<String>("hello3"); //# 06: compile-time error
+
+    var y = new Y2();
+    y.f = defaultF;
+
+    // OK with no type argument.
+    y.f("hello4");
+    Expect.equals("hello4", defaultFLatest);
+
+    // Not OK with a type argument.
+    y.f<dynamic>("hello5"); //# 07: compile-time error
+
+    // Not OK with a type argument.
+    y.f<String>("hello6"); //# 08: compile-time error
+
+    // Correct runtime type of x.f.
+    void instantiatedFType(dynamic _) {}
+    Expect.equals(x.f.runtimeType.toString(),
+        instantiatedFType.runtimeType.toString()); // #09: ok
+  }
+}
diff --git a/tests/language/closure/self_reference_test.dart b/tests/language/closure/self_reference_test.dart
new file mode 100644
index 0000000..a47b1bf
--- /dev/null
+++ b/tests/language/closure/self_reference_test.dart
@@ -0,0 +1,23 @@
+// 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:expect/expect.dart';
+
+// Tests a self-reference of a closure inside a try/catch.
+// Dart2js must not try to box the closure-reference.
+
+main() {
+  var counter = 0;
+  inner(value) {
+    if (value == 0) return 0;
+    try {
+      return inner(value - 1);
+    } finally {
+      counter++;
+    }
+  }
+
+  Expect.equals(0, inner(199));
+  Expect.equals(199, counter);
+}
diff --git a/tests/language/closure/shared_state_test.dart b/tests/language/closure/shared_state_test.dart
new file mode 100644
index 0000000..85c9908
--- /dev/null
+++ b/tests/language/closure/shared_state_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 for closures sharing mutable bindings.
+
+var f;
+var g;
+
+setupPlain() {
+  int j = 1000;
+  // Two closures sharing variable 'j'; j initially is 1000.
+  f = (int x) {
+    var q = j;
+    j = x;
+    return q;
+  };
+  g = (int x) {
+    var q = j;
+    j = x;
+    return q;
+  };
+}
+
+setupLoop() {
+  for (int i = 0; i < 2; i++) {
+    int j = i * 1000; // The last stored closure has j initially 1000.
+    // Two closures sharing variable 'j'.
+    f = (int x) {
+      var q = j;
+      j = x;
+      return q;
+    };
+    g = (int x) {
+      var q = j;
+      j = x;
+      return q;
+    };
+  }
+}
+
+setupNestedLoop() {
+  for (int outer = 0; outer < 2; outer++) {
+    int j = outer * 1000;
+    for (int i = 0; i < 2; i++) {
+      // Two closures sharing variable 'j' in a loop at different nesting.
+      f = (int x) {
+        var q = j;
+        j = x;
+        return q;
+      };
+      g = (int x) {
+        var q = j;
+        j = x;
+        return q;
+      };
+    }
+  }
+}
+
+test(setup) {
+  setup();
+  Expect.equals(1000, f(100));
+  Expect.equals(100, f(200));
+  Expect.equals(200, f(300));
+  Expect.equals(300, g(400));
+  Expect.equals(400, g(500));
+}
+
+main() {
+  test(setupPlain);
+  test(setupLoop);
+  test(setupNestedLoop);
+}
diff --git a/tests/language/closure/side_effect_test.dart b/tests/language/closure/side_effect_test.dart
new file mode 100644
index 0000000..a7b0f50
--- /dev/null
+++ b/tests/language/closure/side_effect_test.dart
@@ -0,0 +1,47 @@
+// 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 "package:expect/expect.dart";
+
+typedef void VoidToVoid();
+
+var b;
+VoidToVoid a = () {
+  b = 42;
+};
+
+var c = [new C()];
+
+class C {
+  nonInlinable1() {
+    a();
+  }
+
+  nonInlinable2() {
+    var a = () {
+      b = 42;
+    };
+    a();
+  }
+}
+
+testClosureInStaticField() {
+  var temp = c[0];
+  Expect.isNull(b);
+  temp.nonInlinable1();
+  Expect.equals(42, b);
+  b = null;
+}
+
+testLocalClosure() {
+  var temp = c[0];
+  Expect.isNull(b);
+  temp.nonInlinable2();
+  Expect.equals(42, b);
+}
+
+main() {
+  testClosureInStaticField();
+  testLocalClosure();
+}
diff --git a/tests/language/closure/tearoff_bounds_instantiation_test.dart b/tests/language/closure/tearoff_bounds_instantiation_test.dart
new file mode 100644
index 0000000..b823c64
--- /dev/null
+++ b/tests/language/closure/tearoff_bounds_instantiation_test.dart
@@ -0,0 +1,20 @@
+// 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.
+//
+// This test checks that the type parameter bounds on tearoffs from generic
+// classes are properly instantiated in the signature of the tearoff.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+  void foo<S extends T>(S x) {}
+}
+
+void foo<S extends int>(S x) {}
+
+void main() {
+  dynamic c = C<int>();
+  dynamic fn = c.foo;
+  Expect.equals("${fn.runtimeType}", "${foo.runtimeType}");
+}
diff --git a/tests/language/closure/tearoff_dynamic_test.dart b/tests/language/closure/tearoff_dynamic_test.dart
new file mode 100644
index 0000000..08b9091
--- /dev/null
+++ b/tests/language/closure/tearoff_dynamic_test.dart
@@ -0,0 +1,170 @@
+// 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:expect/expect.dart';
+
+class C {
+  dynamic f(int x) => x + 1;
+  dynamic g(int x) => x + 2;
+}
+
+class D extends C {
+  f(int x) => x + 41;
+  get superF => super.f;
+  get superG => super.g;
+}
+
+tearoffEquals(f1, f2) {
+  Expect.equals(f1, f2);
+  Expect.equals(f1.hashCode, f2.hashCode);
+}
+
+tearoffNotEquals(f1, f2) {
+  Expect.notEquals(f1, f2);
+  Expect.notEquals(f1.hashCode, f2.hashCode);
+}
+
+testDynamic() {
+  C c = new C();
+
+  dynamic f1 = c.f;
+  Expect.throws(() => f1(2.5));
+  Expect.equals(f1(41), 42);
+
+  dynamic f2 = (c as dynamic).f;
+  Expect.throws(() => f2(2.5));
+  Expect.equals(f2(41), 42);
+
+  tearoffEquals(f1, f1);
+  tearoffEquals(f1, f2);
+  tearoffEquals(f1, c.f);
+  tearoffEquals(c.g, (c as dynamic).g);
+
+  tearoffNotEquals(f1, new C().f);
+  tearoffNotEquals(f1, (new C() as dynamic).f);
+  tearoffNotEquals(f1, c.g);
+  tearoffNotEquals(f1, (c as dynamic).g);
+  tearoffNotEquals(null, f1);
+  tearoffNotEquals(f1, null);
+}
+
+testSuper() {
+  D d = new D();
+  dynamic superF1 = d.superF;
+  dynamic superF2 = (d as dynamic).superF;
+
+  Expect.throws(() => superF1(2.5));
+  Expect.throws(() => superF2(2.5));
+  Expect.equals(superF1(41), 42);
+  Expect.equals(superF2(41), 42);
+
+  tearoffEquals(superF1, superF1);
+  tearoffEquals(superF1, superF2);
+  tearoffEquals(superF1, d.superF);
+  tearoffEquals(d.f, (d as dynamic).f);
+
+  tearoffNotEquals(superF1, d.f);
+  tearoffNotEquals(superF1, (d as dynamic).f);
+  tearoffNotEquals(superF1, new D().superF);
+  tearoffNotEquals(superF1, (new D() as dynamic).superF);
+  tearoffNotEquals(superF1, d.superG);
+  tearoffNotEquals(superF1, (d as dynamic).superG);
+
+  tearoffEquals(d.superG, (d as dynamic).superG);
+  tearoffEquals(d.g, d.superG);
+}
+
+class S {
+  final int id;
+  S(this.id);
+  toString() => 'S#$id';
+}
+
+testToString() {
+  testType<T>(T c) {
+    dynamic d = c;
+    Object? o = c;
+    tearoffEquals(c.toString, d.toString);
+    tearoffEquals(c.toString, o.toString);
+
+    var expected = c.toString();
+    dynamic f = d.toString;
+    tearoffEquals(f(), expected);
+    f = o.toString;
+    tearoffEquals(f(), expected);
+    var g = c.toString;
+    tearoffEquals(g(), expected);
+  }
+
+  testType(new C());
+  testType(new D());
+  testType(new S(1));
+  testType(new S(2));
+  testType(new Object());
+  testType(null);
+  testType(Object); // Type
+  testType(C); // Type
+  testType(42);
+  testType('hi');
+  testType(true);
+  testType([1, 2, 3]);
+  testType({'a': 'b'});
+  testType((x) => x + 1);
+  testType(testType as dynamic); // illegal inferred type for T otherwise
+}
+
+class N {
+  noSuchMethod(i) => i;
+}
+
+testNoSuchMethod() {
+  // Create an invocation.
+  Invocation i = (new N() as dynamic).foo(1, bar: 2);
+  tearoffEquals(i.memberName, #foo);
+
+  testType<T>(T c) {
+    dynamic d = c;
+    Object? o = c;
+    tearoffEquals(c.noSuchMethod, d.noSuchMethod);
+    tearoffEquals(c.noSuchMethod, o.noSuchMethod);
+
+    var expected;
+    try {
+      c.noSuchMethod(i);
+    } on NoSuchMethodError catch (error) {
+      var nsm = '$error';
+      Expect.isTrue(nsm.startsWith("NoSuchMethodError: "));
+      Expect.isTrue(nsm.contains("'foo'"));
+      expected = (e) => e is NoSuchMethodError && '$e' == nsm;
+    }
+    dynamic f = d.noSuchMethod;
+    Expect.throws(() => f(i), expected);
+    f = o.noSuchMethod;
+    Expect.throws(() => f(i), expected);
+    var g = c.noSuchMethod;
+    Expect.throws(() => g(i), expected);
+  }
+
+  testType(new C());
+  testType(new D());
+  testType(new S(1));
+  testType(new S(2));
+  testType(new Object());
+  testType(null);
+  testType(Object); // Type
+  testType(C); // Type
+  testType(42);
+  testType('hi');
+  testType(true);
+  testType([1, 2, 3]);
+  testType({'a': 'b'});
+  testType((x) => x + 1);
+  testType(testType as dynamic); // illegal inferred type for T otherwise
+}
+
+main() {
+  testDynamic();
+  testSuper();
+  testToString();
+  testNoSuchMethod();
+}
diff --git a/tests/language/closure/type_arguments_test.dart b/tests/language/closure/type_arguments_test.dart
new file mode 100644
index 0000000..f046f83
--- /dev/null
+++ b/tests/language/closure/type_arguments_test.dart
@@ -0,0 +1,42 @@
+// 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:expect/expect.dart";
+
+typedef MapFunc<S1, S2> = void Function(Map<S1, S2>? arg);
+
+class A<P> {
+  final List barTypeArguments = [];
+
+  void foo<Q, Q1 extends P, Q2 extends Q, Q3 extends P, Q4 extends Q>() {
+    void bar<T1 extends P, T2 extends Q>(Map<T1, T2>? arg) {
+      barTypeArguments..add(T1)..add(T2);
+    }
+
+    // Call with explicit type arguments.
+    bar<Q1, Q2>(null);
+
+    // No explicit type arguments - should be instantiated to bounds.
+    bar(null);
+
+    // Partial tear-off instantiation.
+    MapFunc<Q3, Q4> instantiated = bar;
+    instantiated(null);
+  }
+}
+
+abstract class MyIterable implements Iterable {}
+
+main() {
+  final a = new A<num>();
+  a.foo<Iterable, int, List, double, MyIterable>();
+  Expect.listEquals(
+      [int, List, num, Iterable, double, MyIterable], a.barTypeArguments);
+
+  // Test instantiation to bounds in the enclosing method.
+  dynamic b = new A<int>();
+  b.foo();
+  Expect.listEquals(
+      [int, dynamic, int, dynamic, int, dynamic], b.barTypeArguments);
+}
diff --git a/tests/language/closure/type_test.dart b/tests/language/closure/type_test.dart
new file mode 100644
index 0000000..90ba188
--- /dev/null
+++ b/tests/language/closure/type_test.dart
@@ -0,0 +1,33 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Dart test for a closure result type test that cannot be eliminated at compile
+// time.
+
+import "package:expect/expect.dart";
+
+void test(A func(String value), String value) {
+  Expect.throwsTypeError(() {
+    func(value) as B;
+  });
+}
+
+
+class A {
+}
+
+class B extends A {
+}
+
+class C {
+  static A a(String x) => new A();
+}
+
+A aclosure(String x) => C.a(x);
+A bclosure() => new A();
+
+main() {
+  test(aclosure, "foo");
+  test((bar) => bclosure(), "baz");
+}
diff --git a/tests/language/closure/type_variable_test.dart b/tests/language/closure/type_variable_test.dart
new file mode 100644
index 0000000..2ed61c2
--- /dev/null
+++ b/tests/language/closure/type_variable_test.dart
@@ -0,0 +1,18 @@
+// 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.
+
+// Test that the type argument is available inside a closure.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  foo() {
+    bar() => T;
+    return bar();
+  }
+}
+
+main() {
+  Expect.equals(new A<int>().foo(), int);
+}
diff --git a/tests/language/closure/type_variables_test.dart b/tests/language/closure/type_variables_test.dart
new file mode 100644
index 0000000..2fe276c
--- /dev/null
+++ b/tests/language/closure/type_variables_test.dart
@@ -0,0 +1,45 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import "package:expect/expect.dart";
+
+// Test that type variables are available in closures.
+
+class A<T> {
+  A();
+
+  A.bar() {
+    g() {
+      new A<T>();
+    }
+
+    g();
+  }
+
+  foo() {
+    g() {
+      return new A<T>();
+    }
+
+    return g();
+  }
+}
+
+class B<K> {
+  makeBaz() {
+    return (K key) async {
+      return null;
+    };
+  }
+}
+
+typedef Future<Null> aBaz(int a);
+
+main() {
+  Expect.isTrue(new A<int>().foo() is A<int>);
+  Expect.isTrue(new A<int>.bar().foo() is A<int>);
+  Expect.isTrue(new B<int>().makeBaz() is aBaz);
+}
diff --git a/tests/language/closure/unnamed_closure_test.dart b/tests/language/closure/unnamed_closure_test.dart
new file mode 100644
index 0000000..49fa570
--- /dev/null
+++ b/tests/language/closure/unnamed_closure_test.dart
@@ -0,0 +1,22 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+getNonArray() => new A();
+
+class A {
+  operator [](index) => index;
+}
+
+main() {
+  Expect.equals(42, () {
+    var res;
+    do {
+      var a = getNonArray();
+      res = a[42];
+    } while (false);
+    return res;
+  }());
+}
diff --git a/tests/language/closure/variable_shadow_test.dart b/tests/language/closure/variable_shadow_test.dart
new file mode 100644
index 0000000..4b1edb4
--- /dev/null
+++ b/tests/language/closure/variable_shadow_test.dart
@@ -0,0 +1,21 @@
+// 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:expect/expect.dart";
+
+// The intermediate variable 'y' must either be preserved
+// or parameters must be renamed.
+
+foo(x) {
+  var y = x;
+  bar(x) {
+    return y - x;
+  }
+
+  return bar;
+}
+
+main() {
+  Expect.equals(-10, foo(10)(20));
+}
diff --git a/tests/language/closure/with_super_field_test.dart b/tests/language/closure/with_super_field_test.dart
new file mode 100644
index 0000000..68cc3be
--- /dev/null
+++ b/tests/language/closure/with_super_field_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "package:meta/meta.dart" show virtual;
+
+class A {
+  @virtual
+  int a;
+  A() : a = 42;
+}
+
+class B extends A {
+  int get a => 54;
+  returnSuper() => super.a;
+  returnSuperInClosure() => () => super.a;
+}
+
+main() {
+  B b = new B();
+  Expect.equals(54, b.a);
+  Expect.equals(42, b.returnSuper());
+  Expect.equals(42, b.returnSuperInClosure()());
+}
diff --git a/tests/language/closure/with_super_send_test.dart b/tests/language/closure/with_super_send_test.dart
new file mode 100644
index 0000000..bcaae49
--- /dev/null
+++ b/tests/language/closure/with_super_send_test.dart
@@ -0,0 +1,27 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test a closurized super send.
+
+class Super {
+  m() => "super";
+}
+
+class Sub extends Super {
+  m() => "sub";
+
+  test() {
+    var x;
+    [0].forEach((e) => x = super.m());
+    return x;
+  }
+}
+
+main() {
+  Expect.equals("super", new Sub().test());
+  Expect.equals("super", new Super().m());
+  Expect.equals("sub", new Sub().m());
+}
diff --git a/tests/language/const/cast1_test.dart b/tests/language/const/cast1_test.dart
new file mode 100644
index 0000000..2363f3f
--- /dev/null
+++ b/tests/language/const/cast1_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+/// Implicit casts in constants are supported and treated as compile-time errors
+/// if they are not valid.
+
+class A {
+  final int n;
+  const A(dynamic input) : n = input;
+}
+
+main() {
+  print(const A(2)); //# 01: ok
+  print(const A('2')); //# 02: compile-time error
+}
diff --git a/tests/language/const/cast2_test.dart b/tests/language/const/cast2_test.dart
new file mode 100644
index 0000000..326a884
--- /dev/null
+++ b/tests/language/const/cast2_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+/// Explicit casts in constants are supported and treated as compile-time errors
+/// if they are not valid.
+
+class A {
+  final int n;
+  const A(dynamic input) : n = input as int;
+}
+
+main() {
+  print(const A(2)); //# 01: ok
+  print(const A('2')); //# 02: compile-time error
+}
diff --git a/tests/language/const/cast3_test.dart b/tests/language/const/cast3_test.dart
new file mode 100644
index 0000000..f7d7354
--- /dev/null
+++ b/tests/language/const/cast3_test.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/// Casts in constants correctly substitute type variables.
+
+class A {
+  const A();
+}
+
+class B implements A {
+  const B();
+}
+
+class M<T extends A> {
+  final T a;
+  const M(dynamic t) : a = t; // adds implicit cast `as T`
+}
+
+main() {
+  print(const M<B>(const B()));
+}
diff --git a/tests/language/const/cast4_test.dart b/tests/language/const/cast4_test.dart
new file mode 100644
index 0000000..cb7a250
--- /dev/null
+++ b/tests/language/const/cast4_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+/// Casts in constants correctly substitute type variables.
+
+class A {
+  const A();
+}
+
+class B implements A {
+  const B();
+}
+
+class M<T extends A> {
+  final T a;
+  const M(dynamic t) : a = t; // adds implicit cast `as T`
+}
+
+class N<S extends A> extends M<S> {
+  const N(dynamic t) : super(t);
+}
+
+main() {
+  print(const N<B>(const B()));
+}
diff --git a/tests/language/const/conditional_runtime_test.dart b/tests/language/const/conditional_runtime_test.dart
new file mode 100644
index 0000000..5b9d8c8
--- /dev/null
+++ b/tests/language/const/conditional_runtime_test.dart
@@ -0,0 +1,59 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test for conditionals as compile-time constants.
+
+import 'package:expect/expect.dart';
+
+class Marker {
+  final field;
+  const Marker(this.field);
+}
+
+var var0 = const Marker(0);
+var var1 = const Marker(1);
+const const0 = const Marker(0);
+const const1 = const Marker(1);
+
+const trueConst = true;
+const falseConst = false;
+var nonConst = true;
+const zeroConst = 0;
+
+const cond1 = trueConst ? const0 : const1;
+
+
+
+const cond2 = falseConst ? const0 : const1;
+
+
+
+
+
+
+
+
+
+
+
+void main() {
+  Expect.identical(var0, cond1);
+
+
+
+  Expect.identical(var1, cond2);
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/const/conditional_test.dart b/tests/language/const/conditional_test.dart
new file mode 100644
index 0000000..33aec86
--- /dev/null
+++ b/tests/language/const/conditional_test.dart
@@ -0,0 +1,110 @@
+// 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.
+
+// Test for conditionals as compile-time constants.
+
+import 'package:expect/expect.dart';
+
+class Marker {
+  final field;
+  const Marker(this.field);
+}
+
+var var0 = const Marker(0);
+var var1 = const Marker(1);
+const const0 = const Marker(0);
+const const1 = const Marker(1);
+
+const trueConst = true;
+const falseConst = false;
+var nonConst = true;
+const zeroConst = 0;
+
+const cond1 = trueConst ? const0 : const1;
+const cond1a = trueConst ? nonConst : const1;
+//                       ^
+// [cfe] Constant evaluation error:
+//                         ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Not a constant expression.
+const cond1b = trueConst ? const0 : nonConst;
+//                                  ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Not a constant expression.
+
+const cond2 = falseConst ? const0 : const1;
+const cond2a = falseConst ? nonConst : const1;
+//                          ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Not a constant expression.
+const cond2b = falseConst ? const0 : nonConst;
+//                        ^
+// [cfe] Constant evaluation error:
+//                                   ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Not a constant expression.
+
+const cond3 = nonConst ? const0 : const1;
+//            ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Not a constant expression.
+//                     ^
+// [cfe] Constant evaluation error:
+const cond3a = nonConst ? nonConst : const1;
+//             ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Not a constant expression.
+//                      ^
+// [cfe] Constant evaluation error:
+//                        ^
+// [cfe] Not a constant expression.
+const cond3b = nonConst ? const0 : nonConst;
+//             ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Not a constant expression.
+//                      ^
+// [cfe] Constant evaluation error:
+//                                 ^
+// [cfe] Not a constant expression.
+
+const cond4 = zeroConst ? const0 : const1;
+//            ^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_TYPE_BOOL
+// [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
+//            ^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+const cond4a = zeroConst ? nonConst : const1;
+//             ^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_TYPE_BOOL
+// [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
+//             ^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+//                         ^
+// [cfe] Not a constant expression.
+const cond4b = zeroConst ? const0 : nonConst;
+//             ^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_TYPE_BOOL
+// [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
+//             ^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+//                                  ^
+// [cfe] Not a constant expression.
+
+void main() {
+  Expect.identical(var0, cond1);
+  Expect.identical(nonConst, cond1a);
+  Expect.identical(var0, cond1b);
+
+  Expect.identical(var1, cond2);
+  Expect.identical(var1, cond2a);
+  Expect.identical(nonConst, cond2b);
+
+  Expect.identical(var0, cond3);
+  Expect.identical(nonConst, cond3a);
+  Expect.identical(var0, cond3b);
+
+  Expect.identical(var1, cond4);
+  Expect.identical(var1, cond4a);
+  Expect.identical(nonConst, cond4b);
+}
diff --git a/tests/language/const/const2_test.dart b/tests/language/const/const2_test.dart
new file mode 100644
index 0000000..6a9f94e
--- /dev/null
+++ b/tests/language/const/const2_test.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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=--compile_all
+
+// Exercises language constructs that require compile time constants
+
+// Initialize with different literal types
+const b = true;
+const s = "apple";
+const i = 1;
+const d = 3.3;
+const h = 0xf;
+const n = null;
+const aList = const [1, 2, 3]; // array literal
+const aMap = const {"1": "one", "2": "banana"}; // map literal
+
+const INT_LIT = 5;
+const INT_LIT_REF = INT_LIT;
+const DOUBLE_LIT = 1.5;
+const BOOL_LIT = true;
+const STRING_LIT = "Hello";
+
+const BOP1_0 = INT_LIT + 1;
+const BOP1_1 = 1 + INT_LIT;
+const BOP1_2 = INT_LIT - 1;
+const BOP1_3 = 1 - INT_LIT;
+const BOP1_4 = INT_LIT * 1;
+const BOP1_5 = 1 * INT_LIT;
+const BOP1_6 = INT_LIT / 1;
+const BOP1_7 = 1 / INT_LIT;
+const BOP2_0 = DOUBLE_LIT + 1.5;
+const BOP2_1 = 1.5 + DOUBLE_LIT;
+const BOP2_2 = DOUBLE_LIT - 1.5;
+const BOP2_3 = 1.5 - DOUBLE_LIT;
+const BOP2_4 = DOUBLE_LIT * 1.5;
+const BOP2_5 = 1.5 * DOUBLE_LIT;
+const BOP2_6 = DOUBLE_LIT / 1.5;
+const BOP2_7 = 1.5 / DOUBLE_LIT;
+const BOP3_0 = 2 < INT_LIT;
+const BOP3_1 = INT_LIT < 2;
+const BOP3_2 = 2 > INT_LIT;
+const BOP3_3 = INT_LIT > 2;
+const BOP3_4 = 2 < DOUBLE_LIT;
+const BOP3_5 = DOUBLE_LIT < 2;
+const BOP3_6 = 2 > DOUBLE_LIT;
+const BOP3_7 = DOUBLE_LIT > 2;
+const BOP3_8 = 2 <= INT_LIT;
+const BOP3_9 = INT_LIT <= 2;
+const BOP3_10 = 2 >= INT_LIT;
+const BOP3_11 = INT_LIT >= 2;
+const BOP3_12 = 2.0 <= DOUBLE_LIT;
+const BOP3_13 = DOUBLE_LIT <= 2.0;
+const BOP3_14 = 2.0 >= DOUBLE_LIT;
+const BOP3_15 = DOUBLE_LIT >= 2;
+const BOP4_0 = 5 % INT_LIT;
+const BOP4_1 = INT_LIT % 5;
+const BOP4_2 = 5.0 % DOUBLE_LIT;
+const BOP4_3 = DOUBLE_LIT % 5.0;
+const BOP5_0 = 0x80 & 0x04;
+const BOP5_1 = 0x80 | 0x04;
+const BOP5_2 = 0x80 << 0x04;
+const BOP5_3 = 0x80 >> 0x04;
+const BOP5_4 = 0x80 ~/ 0x04;
+const BOP5_5 = 0x80 ^ 0x04;
+const BOP6 = BOOL_LIT && true;
+const BOP7 = false || BOOL_LIT;
+const BOP8 = STRING_LIT == "World!";
+const BOP9 = "Hello" != STRING_LIT;
+const BOP10 = INT_LIT == INT_LIT_REF;
+const BOP11 = BOOL_LIT != true;
+
+// Multiple binary expressions
+const BOP20 = 1 * INT_LIT / 3 + INT_LIT + 9;
+
+// Parenthised expressions
+const BOP30 = (1 > 2);
+const BOP31 = (1 * 2) + 3;
+const BOP32 = 3 + (1 * 2);
+
+// Unary expressions
+const UOP1_0 = !BOOL_LIT;
+const UOP1_1 = BOOL_LIT || !true;
+const UOP1_2 = !BOOL_LIT || true;
+const UOP1_3 = !(BOOL_LIT && true);
+const UOP2_0 = ~0xf0;
+const UOP2_1 = ~INT_LIT;
+const UOP2_2 = ~INT_LIT & 123;
+const UOP2_3 = ~(INT_LIT | 0xff);
+const UOP3_0 = -0xf0;
+const UOP3_1 = -INT_LIT;
+const UOP3_2 = -INT_LIT + 123;
+const UOP3_3 = -(INT_LIT * 0xff);
+const UOP3_4 = -0xf0;
+const UOP3_5 = -DOUBLE_LIT;
+const UOP3_6 = -DOUBLE_LIT + 123;
+const UOP3_7 = -(DOUBLE_LIT * 0xff);
+
+class A {
+  const A();
+  static const a = const A(); // Assignment from Constant constructor OK
+}
+
+main() {}
diff --git a/tests/language/const/const3_test.dart b/tests/language/const/const3_test.dart
new file mode 100644
index 0000000..8872c57
--- /dev/null
+++ b/tests/language/const/const3_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that initializers of const fields can be declared out of order.
+
+import "package:expect/expect.dart";
+
+const P = 2 * (O - N);
+const N = 1;
+const O = 1 + 3;
+
+void main() {
+  Expect.equals(1, N);
+  Expect.equals(4, O);
+  Expect.equals(6, P);
+}
diff --git a/tests/language/const/const4_lib.dart b/tests/language/const/const4_lib.dart
new file mode 100644
index 0000000..c9d2840
--- /dev/null
+++ b/tests/language/const/const4_lib.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 CTConst4Test.dart
+
+library CTConst4Lib;
+
+const B = 1;
diff --git a/tests/language/const/const4_test.dart b/tests/language/const/const4_test.dart
new file mode 100644
index 0000000..c47f33c
--- /dev/null
+++ b/tests/language/const/const4_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 compile-time constant library references with prefixes
+
+library CTConst4Test;
+
+import "package:expect/expect.dart";
+import "const4_lib.dart" as mylib;
+
+const A = mylib.B;
+
+main() {
+  Expect.equals(1, A);
+}
diff --git a/tests/language/const/const_locals_constant_locals_test.dart b/tests/language/const/const_locals_constant_locals_test.dart
new file mode 100644
index 0000000..9f937df
--- /dev/null
+++ b/tests/language/const/const_locals_constant_locals_test.dart
@@ -0,0 +1,50 @@
+// 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.
+
+// Test that constant local variables have constant initializers.
+
+import "package:expect/expect.dart";
+
+void main() {
+  const c1;
+  //    ^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_NOT_INITIALIZED
+  //      ^
+  // [cfe] The const variable ';' must be initialized.
+  const c2 = 0;
+  const c3 = field;
+  //         ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+  // [cfe] Constant evaluation error:
+  //         ^
+  // [cfe] Not a constant expression.
+  const c4 = finalField;
+  //         ^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+  // [cfe] Constant evaluation error:
+  //         ^
+  // [cfe] Not a constant expression.
+  const c5 = constField;
+  const c6 = method();
+  //         ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+  // [cfe] Method invocation is not a constant expression.
+  const c7 = new Class();
+  //         ^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+  // [cfe] New expression is not a constant expression.
+  const c8 = const Class();
+}
+
+var field = 0;
+
+final finalField = 0;
+
+const constField = 0;
+
+method() => 0;
+
+class Class {
+  const Class();
+}
diff --git a/tests/language/const/const_locals_runtime_test.dart b/tests/language/const/const_locals_runtime_test.dart
new file mode 100644
index 0000000..efabff5
--- /dev/null
+++ b/tests/language/const/const_locals_runtime_test.dart
@@ -0,0 +1,33 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test that constant local variables have constant initializers.
+
+import "package:expect/expect.dart";
+
+void main() {
+
+  const c2 = 0;
+
+
+  const c5 = constField;
+
+
+  const c8 = const Class();
+}
+
+var field = 0;
+
+final finalField = 0;
+
+const constField = 0;
+
+method() => 0;
+
+class Class {
+  const Class();
+}
diff --git a/tests/language/const/const_test.dart b/tests/language/const/const_test.dart
new file mode 100644
index 0000000..d97f547
--- /dev/null
+++ b/tests/language/const/const_test.dart
@@ -0,0 +1,43 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Check const classes.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+class AConst {
+  const AConst() : b_ = 3;
+  final int b_;
+}
+
+class BConst {
+  const BConst();
+  set foo(value) {}
+  get foo {
+    return 5;
+  }
+
+  operator [](ix) {
+    return ix;
+  }
+
+  operator []=(ix, value) {}
+}
+
+testMain() {
+  var o = const AConst();
+  Expect.equals(3, o.b_);
+
+  var x = (const BConst()).foo++;
+  Expect.equals(5, x);
+
+  var y = (const BConst())[5]++;
+  Expect.equals(5, y);
+}
+
+main() {
+  for (int i = 0; i < 20; i++) {
+    testMain();
+  }
+}
diff --git a/tests/language/const/constants_test.dart b/tests/language/const/constants_test.dart
new file mode 100644
index 0000000..5864dbe
--- /dev/null
+++ b/tests/language/const/constants_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.
+
+class C {
+  factory C() => C._();
+
+  C._();
+}
+
+const
+// [error line 11, column 1, length 5]
+// [analyzer] SYNTACTIC_ERROR.EXTRANEOUS_MODIFIER
+// [cfe] Can't have modifier 'const' here.
+t() => null;
+
+const
+// [error line 17, column 1, length 5]
+// [analyzer] SYNTACTIC_ERROR.EXTRANEOUS_MODIFIER
+// [cfe] Can't have modifier 'const' here.
+get v => null;
+
+main() {
+  const
+      dynamic x = t();
+      //          ^^^
+      // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+      // [cfe] Method invocation is not a constant expression.
+  const y = const C();
+  //        ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+  //        ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONST
+  //              ^
+  // [cfe] Cannot invoke a non-'const' factory where a const expression is expected.
+  const
+      dynamic z = v;
+      //          ^
+      // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+      // [cfe] Constant evaluation error:
+}
diff --git a/tests/language/const/constructor2_test.dart b/tests/language/const/constructor2_test.dart
new file mode 100644
index 0000000..e8a5d63
--- /dev/null
+++ b/tests/language/const/constructor2_test.dart
@@ -0,0 +1,83 @@
+// 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.
+
+// Regression test for issue 14348.
+
+class A<T> {
+  const A();
+}
+
+class B<S> extends A<S> {
+  const B();
+}
+
+class C<U> {
+  final A<U> a;
+
+  const C(A<U> this.a);
+  const C.optional([A<U> this.a = const A()]);
+  const C.named({A<U> this.a = const A()});
+  const C.untyped(this.a);
+  const C.subtyped(B<U> this.a);
+  const factory C.redirecting(B<U> a) = D<U>;
+}
+
+class D<U> extends C<U> {
+  const D(B<U> b) : super(b);
+}
+
+class E {
+  const factory E.redirecting1(int a) = F<int>;
+  const factory E.redirecting2(int a) = F<int>.redirecting;
+  const factory E.redirecting3(double a) = F<double>.redirecting;
+}
+
+class F<V> implements E {
+  final V field;
+
+  const F(this.field);
+  const factory F.redirecting(V field) = G<V>;
+}
+
+class G<W> implements F<W> {
+  final W field;
+  const G(W field) : this.field = field;
+}
+
+main() {
+  const A<int> a = const B<int>();
+
+  const C(a); //# 01: ok
+  const C.optional(a); //# 02: ok
+  const C.named(a: a); //# 03: ok
+  const C.untyped(a); //# 04: ok
+
+  // Can't infer type argument U for C since a has type A and the argument has
+  // type B<U>, not A<U>. So tries to assign A<int> to B<dynamic> which fails.
+  const C.subtyped(a); //# 05: compile-time error
+  const C.redirecting(a); //# 06: compile-time error
+
+  const C<int>(a); //# 07: ok
+  const C<int>.optional(a); //# 08: ok
+  const C<int>.named(a: a); //# 09: ok
+  const C<int>.untyped(a); //# 10: ok
+
+  // These are compile-time errors with NNBD because of the implicit downcasts.
+  const C<int>.subtyped(a); //# 11: compile-time error
+  const C<int>.redirecting(a); //# 12: compile-time error
+
+  const C<double>(a); //# 13: compile-time error
+  const C<double>.optional(a); //# 14: compile-time error
+  const C<double>.named(a: a); //# 15: compile-time error
+  const C<double>.untyped(a); //# 16: compile-time error
+  const C<double>.subtyped(a); //# 17: compile-time error
+  const C<double>.redirecting(a); //# 18: compile-time error
+
+  const E.redirecting1(0); //# 19: ok
+  const E.redirecting1(''); //# 20: compile-time error
+  const E.redirecting2(0); //# 21: ok
+  const E.redirecting2(''); //# 22: compile-time error
+  const E.redirecting3(0.0); //# 23: ok
+  const E.redirecting3(''); //# 24: compile-time error
+}
diff --git a/tests/language/const/constructor3_runtime_1_test.dart b/tests/language/const/constructor3_runtime_1_test.dart
new file mode 100644
index 0000000..2a970db
--- /dev/null
+++ b/tests/language/const/constructor3_runtime_1_test.dart
@@ -0,0 +1,28 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class C {
+  final double d;
+  const C(this.d);
+}
+
+class D extends C {
+  const D(var d) : super(d);
+}
+
+const intValue = 0;
+const c = const C(0.0);
+
+
+
+
+main() {
+  print(c);
+
+
+
+}
diff --git a/tests/language/const/constructor3_runtime_2_test.dart b/tests/language/const/constructor3_runtime_2_test.dart
new file mode 100644
index 0000000..799f5d7
--- /dev/null
+++ b/tests/language/const/constructor3_runtime_2_test.dart
@@ -0,0 +1,28 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class C {
+  final double d;
+  const C(this.d);
+}
+
+class D extends C {
+  const D(var d) : super(d);
+}
+
+const intValue = 0;
+
+
+const e = const D(0.0);
+
+
+main() {
+
+
+  print(e);
+
+}
diff --git a/tests/language/const/constructor3_runtime_test.dart b/tests/language/const/constructor3_runtime_test.dart
new file mode 100644
index 0000000..5c2e771
--- /dev/null
+++ b/tests/language/const/constructor3_runtime_test.dart
@@ -0,0 +1,28 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class C {
+  final double d;
+  const C(this.d);
+}
+
+class D extends C {
+  const D(var d) : super(d);
+}
+
+const intValue = 0;
+
+
+
+
+
+main() {
+
+
+
+
+}
diff --git a/tests/language/const/constructor3_test.dart b/tests/language/const/constructor3_test.dart
new file mode 100644
index 0000000..54191d1
--- /dev/null
+++ b/tests/language/const/constructor3_test.dart
@@ -0,0 +1,34 @@
+// 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.
+
+class C {
+  final double d;
+  const C(this.d);
+}
+
+class D extends C {
+  const D(var d) : super(d);
+}
+
+const intValue = 0;
+const c = const C(0.0);
+const d = const C(intValue);
+//                ^^^^^^^^
+// [analyzer] CHECKED_MODE_COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
+// [cfe] The argument type 'int' can't be assigned to the parameter type 'double'.
+//                ^^^^^^^^
+// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+const e = const D(0.0);
+const f = const D(intValue);
+//        ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//              ^
+// [cfe] Constant evaluation error:
+
+main() {
+  print(c);
+  print(d);
+  print(e);
+  print(f);
+}
diff --git a/tests/language/const/constructor_mixin2_runtime_test.dart b/tests/language/const/constructor_mixin2_runtime_test.dart
new file mode 100644
index 0000000..5ca87e9
--- /dev/null
+++ b/tests/language/const/constructor_mixin2_runtime_test.dart
@@ -0,0 +1,25 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Mixin {
+  var nonFinalField;
+}
+
+class A {
+  const A(foo);
+}
+
+class B extends A
+
+{
+  const B(foo) : super(foo);
+}
+
+main() {
+  var a = const B(42);
+
+}
diff --git a/tests/language/const/constructor_mixin2_test.dart b/tests/language/const/constructor_mixin2_test.dart
new file mode 100644
index 0000000..a7bc863
--- /dev/null
+++ b/tests/language/const/constructor_mixin2_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+class Mixin {
+  var nonFinalField;
+}
+
+class A {
+  const A(foo);
+}
+
+class B extends A
+    with Mixin
+{
+  const B(foo) : super(foo);
+//      ^
+// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
+//      ^
+// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD
+//               ^
+// [cfe] A constant constructor can't call a non-constant super constructor.
+}
+
+main() {
+  var a = const B(42);
+  a.nonFinalField = 54;
+}
diff --git a/tests/language/const/constructor_mixin3_test.dart b/tests/language/const/constructor_mixin3_test.dart
new file mode 100644
index 0000000..9eb4d76
--- /dev/null
+++ b/tests/language/const/constructor_mixin3_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+class Mixin {}
+
+class A {
+  const A();
+}
+
+class B extends A with Mixin {
+  const B();
+}
+
+main() {
+  var a = const B();
+}
diff --git a/tests/language/const/constructor_mixin_test.dart b/tests/language/const/constructor_mixin_test.dart
new file mode 100644
index 0000000..a177ce1
--- /dev/null
+++ b/tests/language/const/constructor_mixin_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+class Mixin {}
+
+class A {
+  const A(foo);
+}
+
+class B extends A with Mixin {
+  const B(foo) : super(foo);
+}
+
+main() {
+  var a = const B(42);
+}
diff --git a/tests/language/const/constructor_nonconst_field_runtime_test.dart b/tests/language/const/constructor_nonconst_field_runtime_test.dart
new file mode 100644
index 0000000..a08abbe
--- /dev/null
+++ b/tests/language/const/constructor_nonconst_field_runtime_test.dart
@@ -0,0 +1,22 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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:expect/expect.dart";
+
+class A {
+
+  final int j = 1;
+  const A();
+}
+
+int f() {
+  return 3;
+}
+
+main() {
+  const A().j;
+}
diff --git a/tests/language/const/constructor_nonconst_field_test.dart b/tests/language/const/constructor_nonconst_field_test.dart
new file mode 100644
index 0000000..d2e7030
--- /dev/null
+++ b/tests/language/const/constructor_nonconst_field_test.dart
@@ -0,0 +1,23 @@
+// 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:expect/expect.dart";
+
+class A {
+  final int i = f();
+  //            ^
+  // [cfe] Method invocation is not a constant expression.
+  final int j = 1;
+  const A();
+//^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST
+}
+
+int f() {
+  return 3;
+}
+
+main() {
+  const A().j;
+}
diff --git a/tests/language/const/constructor_nonconst_param_runtime_test.dart b/tests/language/const/constructor_nonconst_param_runtime_test.dart
new file mode 100644
index 0000000..5ba2bf7
--- /dev/null
+++ b/tests/language/const/constructor_nonconst_param_runtime_test.dart
@@ -0,0 +1,21 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class A {
+  const A(int a);
+}
+
+class B {
+
+  const B(dynamic v) //
+
+  ;
+}
+
+void main() {
+  const B("");
+}
diff --git a/tests/language/const/constructor_nonconst_param_test.dart b/tests/language/const/constructor_nonconst_param_test.dart
new file mode 100644
index 0000000..bca1b3e
--- /dev/null
+++ b/tests/language/const/constructor_nonconst_param_test.dart
@@ -0,0 +1,25 @@
+// 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.
+
+class A {
+  const A(int a);
+}
+
+class B {
+  final a;
+  const B(dynamic v) //
+      : a = A(v)
+      //    ^^^^
+      // [analyzer] COMPILE_TIME_ERROR.INVALID_CONSTANT
+      // [cfe] Constant evaluation error:
+      //    ^
+      // [cfe] Constant expression expected.
+  ;
+}
+
+void main() {
+  const B("");
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+}
diff --git a/tests/language/const/constructor_runtime_test.dart b/tests/language/const/constructor_runtime_test.dart
new file mode 100644
index 0000000..3317ec1
--- /dev/null
+++ b/tests/language/const/constructor_runtime_test.dart
@@ -0,0 +1,20 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  final int x;
+  const A.named() : x = 42;
+  A() : x = -1;
+}
+
+main() {
+  Expect.equals(42, (const A<int>.named()).x);
+  Expect.equals(42, (new A<int>.named()).x);
+
+}
diff --git a/tests/language/const/constructor_super2_test.dart b/tests/language/const/constructor_super2_test.dart
new file mode 100644
index 0000000..f922769
--- /dev/null
+++ b/tests/language/const/constructor_super2_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:expect/expect.dart';
+
+class A {
+  final a;
+
+  const A(this.a);
+}
+
+class B extends A {
+  final b;
+
+  const B(a, this.b) : super(a);
+}
+
+@pragma('dart2js:noInline')
+foo() => const B(1, 2);
+
+@pragma('dart2js:noInline')
+bar() => const B(2, 2);
+
+void main() {
+  Expect.notEquals(foo(), bar());
+  Expect.notEquals(foo().a, bar().a);
+  Expect.equals(foo().b, bar().b);
+}
diff --git a/tests/language/const/constructor_super_runtime_test.dart b/tests/language/const/constructor_super_runtime_test.dart
new file mode 100644
index 0000000..aa555a62
--- /dev/null
+++ b/tests/language/const/constructor_super_runtime_test.dart
@@ -0,0 +1,36 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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 "package:expect/expect.dart";
+
+class A {
+  final a;
+  A(this.a); // Not const.
+  const A.five() : a = 5;
+}
+
+class B extends A {
+  final b;
+  B(x)
+      : b = x + 1,
+        super(x);
+
+  // Const constructor cannot call non-const super constructor.
+
+}
+
+class C extends A {
+  C() : super(0);
+  // Implicit call to non-const constructor A(x).
+
+}
+
+main() {
+
+  var b1 = new B(0);
+
+}
diff --git a/tests/language/const/constructor_super_test.dart b/tests/language/const/constructor_super_test.dart
new file mode 100644
index 0000000..f710d15
--- /dev/null
+++ b/tests/language/const/constructor_super_test.dart
@@ -0,0 +1,41 @@
+// 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 "package:expect/expect.dart";
+
+class A {
+  final a;
+  A(this.a); // Not const.
+  const A.five() : a = 5;
+}
+
+class B extends A {
+  final b;
+  B(x)
+      : b = x + 1,
+        super(x);
+
+  // Const constructor cannot call non-const super constructor.
+  const B.zerofive() : b = 0, super(5);
+  //                          ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER
+  // [cfe] A constant constructor can't call a non-constant super constructor.
+}
+
+class C extends A {
+  C() : super(0);
+  // Implicit call to non-const constructor A(x).
+  const C.named(x);
+  //    ^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER
+  // [cfe] The superclass, 'A', has no unnamed constructor that takes no arguments.
+  //    ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.NO_DEFAULT_SUPER_CONSTRUCTOR
+}
+
+main() {
+  var b = new B.zerofive();
+  var b1 = new B(0);
+  var c = new C.named("");
+}
diff --git a/tests/language/const/constructor_syntax_runtime_test.dart b/tests/language/const/constructor_syntax_runtime_test.dart
new file mode 100644
index 0000000..bccb4a8
--- /dev/null
+++ b/tests/language/const/constructor_syntax_runtime_test.dart
@@ -0,0 +1,38 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+
+
+  var c1 = const C1();
+
+  var c3 = const C3();
+}
+
+abstract class I0 {
+  factory I0() = C0;
+}
+
+class C0 implements I0 {
+  C0();
+}
+
+class C1 {
+  const C1();
+
+}
+
+class C2 {
+  C2();
+}
+
+class C3 {
+  const C3()
+
+  ;
+  final field = null;
+}
diff --git a/tests/language/const/constructor_syntax_test.dart b/tests/language/const/constructor_syntax_test.dart
new file mode 100644
index 0000000..99a420e
--- /dev/null
+++ b/tests/language/const/constructor_syntax_test.dart
@@ -0,0 +1,62 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  var c0 = const C0();
+  //       ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONST
+  //             ^
+  // [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
+  var i0 = const I0();
+  //       ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONST
+  //             ^
+  // [cfe] Cannot invoke a non-'const' factory where a const expression is expected.
+  var c1 = const C1();
+  var c2 = const C2();
+  //       ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONST
+  //             ^
+  // [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
+  var c3 = const C3();
+  //       ^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+}
+
+abstract class I0 {
+  factory I0() = C0;
+}
+
+class C0 implements I0 {
+  C0();
+}
+
+class C1 {
+  const C1();
+//      ^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
+//      ^
+// [cfe] Constructor is marked 'const' so all fields must be final.
+  var modifiable;
+}
+
+class C2 {
+  C2();
+}
+
+class C3 {
+  const C3()
+      : field = new C0()
+      //^^^^^
+      // [analyzer] STATIC_WARNING.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION
+      //      ^
+      // [cfe] 'field' is a final instance variable that has already been initialized.
+      //      ^
+      // [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
+      //        ^^^^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.INVALID_CONSTANT
+      // [cfe] New expression is not a constant expression.
+  ;
+  final field = null;
+}
diff --git a/tests/language/const/constructor_test.dart b/tests/language/const/constructor_test.dart
new file mode 100644
index 0000000..6873889
--- /dev/null
+++ b/tests/language/const/constructor_test.dart
@@ -0,0 +1,21 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  final int x;
+  const A.named() : x = 42;
+  A() : x = -1;
+}
+
+main() {
+  Expect.equals(42, (const A<int>.named()).x);
+  Expect.equals(42, (new A<int>.named()).x);
+  const A<int>();
+//^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONST
+//      ^
+// [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
+}
diff --git a/tests/language/const/counter_runtime_test.dart b/tests/language/const/counter_runtime_test.dart
new file mode 100644
index 0000000..dd8251f
--- /dev/null
+++ b/tests/language/const/counter_runtime_test.dart
@@ -0,0 +1,22 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Bug: 4254106 Constant constructors must have (implicit) const parameters.
+
+class ConstCounter {
+  const ConstCounter(int i)
+      : nextValue_ = (
+            // Incorrect assignment of a non-const function to a final field.
+
+                i + 1);
+
+  final nextValue_;
+}
+
+main() {
+  const ConstCounter(3);
+}
diff --git a/tests/language/const/counter_test.dart b/tests/language/const/counter_test.dart
new file mode 100644
index 0000000..0ca474f
--- /dev/null
+++ b/tests/language/const/counter_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Bug: 4254106 Constant constructors must have (implicit) const parameters.
+
+class ConstCounter {
+  const ConstCounter(int i)
+      : nextValue_ = (
+      //             ^
+      // [cfe] Can't find ')' to match '('.
+
+            // Incorrect assignment of a non-const function to a final field.
+            () => i + 1;
+//          ^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_CONSTANT
+// [cfe] Not a constant expression.
+//                     ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  final nextValue_;
+}
+
+main() {
+  const ConstCounter(3);
+//^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+}
diff --git a/tests/language/const/ct_const_test.dart b/tests/language/const/ct_const_test.dart
new file mode 100644
index 0000000..defab06
--- /dev/null
+++ b/tests/language/const/ct_const_test.dart
@@ -0,0 +1,134 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test of apparent compile-time nature of constant evaluation. Constant Lists,
+// Maps and other objects should be identical independent of formation.
+
+import "package:expect/expect.dart";
+
+abstract class Roman {
+  static const I = 1;
+  static const II = 2;
+  static const III = 3;
+  static const IV = 4;
+  static const V = 5;
+
+  static const VivaItalia = const {"green": 1, "red": 3, "white": 2};
+}
+
+class Point {
+  static const int zero = 0;
+
+  static const origin = const Point(0, 0);
+  static const origin2 = const Point(zero, Roman.IV - 4);
+
+  const Point(x, y)
+      : x_ = x,
+        y_ = y;
+  const Point.X(x)
+      : x_ = x,
+        y_ = Roman.V - Roman.II - 3;
+
+  bool operator ==(final dynamic other) {
+    return (this.x_ == other.x_) && (this.y_ == other.y_);
+  }
+
+  final int x_, y_;
+}
+
+class Line {
+  const Line(Point begin, Point end)
+      : beg_ = begin,
+        end_ = end;
+  final Point beg_;
+  final Point end_;
+}
+
+class CTConstTest {
+  static int getZero() {
+    return 0;
+  }
+
+  static const naught = null;
+
+  static testMain() {
+    Expect.equals(0, Point.zero);
+    Expect.equals(0, Point.origin.x_);
+    Expect.equals(true, identical(Point.origin, Point.origin2));
+    var p1 = const Point(0, 0);
+    Expect.equals(true, identical(Point.origin, p1));
+
+    Expect.equals(false, Point.origin == const Point(1, 1));
+    Expect.equals(false, identical(Point.origin, const Point(1, 1)));
+
+    var p2 = new Point(0, getZero());
+    Expect.equals(true, Point.origin == p2); // Point.operator==
+
+    Expect.equals(true, identical(const Point.X(5), const Point(5, 0)));
+    Line l1 = const Line(Point.origin, const Point(1, 1));
+    Line l2 = const Line(const Point(0, 0), const Point(1, 1));
+    Line l3 = new Line(const Point(0, 0), const Point(1, 1));
+    Expect.equals(true, identical(l1, l2));
+
+    final evenNumbers = const <int>[2, 2 * 2, 2 * 3, 2 * 4, 2 * 5];
+    Expect.equals(true, identical(evenNumbers, const <int>[2, 4, 6, 8, 10]));
+    Expect.equals(
+        true, !identical(evenNumbers, const <dynamic>[2, 4, 6, 8, 10]));
+
+    final c11dGermany1 = const {"black": 1, "red": 2, "yellow": 3};
+    Expect.equals(true,
+        identical(c11dGermany1, const {"black": 1, "red": 2, "yellow": 3}));
+
+    final c11dGermany2 = const {"black": 1, "red": 2, "yellow": 3};
+    Expect.equals(true, identical(c11dGermany1, c11dGermany2));
+
+    final c11dBelgium = const {"black": 1, "yellow": 2, "red": 3};
+    Expect.equals(false, c11dGermany1 == c11dBelgium);
+    Expect.equals(false, identical(c11dGermany1, c11dBelgium));
+
+    final c11dItaly = const {"green": 1, "red": 3, "white": 2};
+    Expect.equals(
+        true, identical(c11dItaly, const {"green": 1, "red": 3, "white": 2}));
+    Expect.equals(true, identical(c11dItaly, Roman.VivaItalia));
+
+    Expect.equals(3, c11dItaly.length);
+    Expect.equals(3, c11dItaly.keys.length);
+    Expect.equals(true, c11dItaly.containsKey("white"));
+    Expect.equals(false, c11dItaly.containsKey("black"));
+
+    // Make sure the map object is immutable.
+    bool caughtException = false;
+    try {
+      c11dItaly["green"] = 0;
+    } on UnsupportedError catch (e) {
+      caughtException = true;
+    }
+    Expect.equals(true, caughtException);
+    Expect.equals(1, c11dItaly["green"]);
+
+    caughtException = false;
+    try {
+      c11dItaly.clear();
+    } on UnsupportedError catch (e) {
+      caughtException = true;
+    }
+    Expect.equals(true, caughtException);
+    Expect.equals(1, c11dItaly["green"]);
+
+    caughtException = false;
+    try {
+      c11dItaly.remove("orange");
+    } on UnsupportedError catch (e) {
+      caughtException = true;
+    }
+    Expect.equals(true, caughtException);
+    Expect.equals(1, c11dItaly["green"]);
+
+    Expect.equals(true, null == naught);
+  }
+}
+
+main() {
+  CTConstTest.testMain();
+}
diff --git a/tests/language/const/double_in_int_op_test.dart b/tests/language/const/double_in_int_op_test.dart
new file mode 100644
index 0000000..ed12305
--- /dev/null
+++ b/tests/language/const/double_in_int_op_test.dart
@@ -0,0 +1,40 @@
+// 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.
+
+// SharedOptions=--enable-experiment=triple-shift
+
+main() {
+  const dynamic i1 = 3;
+  const dynamic i2 = 2;
+  const dynamic d1 = 3.3;
+  const dynamic d2 = 2.2;
+
+  const sum = 0 + //
+      (i1 | i2) + //# ii1: ok
+      (i1 & i2) + //# ii2: ok
+      (i1 ^ i2) + //# ii3: ok
+      (i1 << i2) + //# ii4: ok
+      (i1 >> i2) + //# ii5: ok
+      (i1 >>> i2) + //# ii6: ok
+      (i1 | d2) + //# id1: compile-time error
+      (i1 & d2) + //# id2: compile-time error
+      (i1 ^ d2) + //# id3: compile-time error
+      (i1 << d2) + //# id4: compile-time error
+      (i1 >> d2) + //# id5: compile-time error
+      (i1 >>> d2) + //# id6: compile-time error
+      (d1 | i2) + //# di1: compile-time error
+      (d1 & i2) + //# di2: compile-time error
+      (d1 ^ i2) + //# di3: compile-time error
+      (d1 << i2) + //# di4: compile-time error
+      (d1 >> i2) + //# di5: compile-time error
+      (d1 >>> i2) + //# di6: compile-time error
+      (d1 | d2) + //# dd1: compile-time error
+      (d1 & d2) + //# dd2: compile-time error
+      (d1 ^ d2) + //# dd3: compile-time error
+      (d1 << d2) + //# dd4: compile-time error
+      (d1 >> d2) + //# dd5: compile-time error
+      (d1 >>> d2) + //# dd6: compile-time error
+      0;
+  print(sum);
+}
diff --git a/tests/language/const/dynamic_type_literal_runtime_1_test.dart b/tests/language/const/dynamic_type_literal_runtime_1_test.dart
new file mode 100644
index 0000000..8f56bb6
--- /dev/null
+++ b/tests/language/const/dynamic_type_literal_runtime_1_test.dart
@@ -0,0 +1,21 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test that 'dynamic' can be used in const expressions and has the expected
+// behavior.
+
+import "package:expect/expect.dart";
+
+const d = dynamic;
+const i = int;
+
+void main() {
+  Expect.isTrue(identical(d, dynamic));
+  // Duplicate key error.
+
+
+}
diff --git a/tests/language/const/dynamic_type_literal_runtime_2_test.dart b/tests/language/const/dynamic_type_literal_runtime_2_test.dart
new file mode 100644
index 0000000..478a9ed
--- /dev/null
+++ b/tests/language/const/dynamic_type_literal_runtime_2_test.dart
@@ -0,0 +1,21 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test that 'dynamic' can be used in const expressions and has the expected
+// behavior.
+
+import "package:expect/expect.dart";
+
+const d = dynamic;
+const i = int;
+
+void main() {
+
+  // Duplicate key error.
+
+  Expect.equals(2, const { d: 1, i: 2 }.length);
+}
diff --git a/tests/language/const/dynamic_type_literal_runtime_test.dart b/tests/language/const/dynamic_type_literal_runtime_test.dart
new file mode 100644
index 0000000..05cb59a
--- /dev/null
+++ b/tests/language/const/dynamic_type_literal_runtime_test.dart
@@ -0,0 +1,21 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test that 'dynamic' can be used in const expressions and has the expected
+// behavior.
+
+import "package:expect/expect.dart";
+
+const d = dynamic;
+const i = int;
+
+void main() {
+
+  // Duplicate key error.
+
+
+}
diff --git a/tests/language/const/dynamic_type_literal_test.dart b/tests/language/const/dynamic_type_literal_test.dart
new file mode 100644
index 0000000..e69bb8f
--- /dev/null
+++ b/tests/language/const/dynamic_type_literal_test.dart
@@ -0,0 +1,22 @@
+// 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.
+
+// Test that 'dynamic' can be used in const expressions and has the expected
+// behavior.
+
+import "package:expect/expect.dart";
+
+const d = dynamic;
+const i = int;
+
+void main() {
+  Expect.isTrue(identical(d, dynamic));
+  // Duplicate key error.
+  Expect.equals(1, const { d: 1, d: 2 }.length);
+  //               ^
+  // [cfe] Constant evaluation error:
+  //                             ^
+  // [analyzer] COMPILE_TIME_ERROR.EQUAL_KEYS_IN_CONST_MAP
+  Expect.equals(2, const { d: 1, i: 2 }.length);
+}
diff --git a/tests/language/const/error_multiply_initialized_test.dart b/tests/language/const/error_multiply_initialized_test.dart
new file mode 100644
index 0000000..490ea0f
--- /dev/null
+++ b/tests/language/const/error_multiply_initialized_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.
+
+// If a constant constructor contains an initializer, or an initializing
+// formal, for a final field which itself has an initializer at its
+// declaration, then a compile-time error should be reported regardless of
+// whether the constructor is called with "const" or "new".
+
+import "package:expect/expect.dart";
+
+class C {
+  final x = 1;
+  const C() : x = 2; //# 01: compile-time error
+  const C() : x = 2; //# 02: compile-time error
+  const C(this.x); //# 03: compile-time error
+  const C(this.x); //# 04: compile-time error
+}
+
+main() {
+  const C(); //# 01: continued
+  new C(); //# 02: continued
+  const C(2); //# 03: continued
+  new C(2); //# 04: continued
+}
diff --git a/tests/language/const/escape_frog_test.dart b/tests/language/const/escape_frog_test.dart
new file mode 100644
index 0000000..0380058
--- /dev/null
+++ b/tests/language/const/escape_frog_test.dart
@@ -0,0 +1,19 @@
+// 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.
+// Test division by power of two.
+// Test that results before and after optimization are the same.
+
+import "package:expect/expect.dart";
+
+class Foo {
+  final Bar<Foo> bar = const Bar /* comment here use to trigger bug 323 */ ();
+}
+
+class Bar<T extends Foo> {
+  const Bar();
+}
+
+main() {
+  Expect.equals(new Foo().bar, const Bar());
+}
diff --git a/tests/language/const/evaluation_test.dart b/tests/language/const/evaluation_test.dart
new file mode 100644
index 0000000..cd0353e
--- /dev/null
+++ b/tests/language/const/evaluation_test.dart
@@ -0,0 +1,44 @@
+// 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.
+
+// Check that compile-time evaluation of constants is consistent with runtime
+// evaluation.
+
+import 'package:expect/expect.dart';
+
+const top_const = identical(-0.0, 0);
+final top_final = identical(-0.0, 0);
+var top_var = identical(-0.0, 0);
+
+@top_const
+class C {
+  static const static_const = identical(-0.0, 0);
+  static final static_final = identical(-0.0, 0);
+  static var static_var = identical(-0.0, 0);
+
+  final instance_final = identical(-0.0, 0);
+  var instance_var = identical(-0.0, 0);
+
+  void test() {
+    const local_const = identical(-0.0, 0);
+    final local_final = identical(-0.0, 0);
+    var local_var = identical(-0.0, 0);
+
+    Expect.equals(identical(-0.0, 0), top_const);
+    Expect.equals(top_const, top_final);
+    Expect.equals(top_final, top_var);
+    Expect.equals(top_var, static_const);
+    Expect.equals(static_const, static_final);
+    Expect.equals(static_final, static_var);
+    Expect.equals(static_var, instance_final);
+    Expect.equals(instance_final, instance_var);
+    Expect.equals(instance_var, local_const);
+    Expect.equals(local_const, local_final);
+    Expect.equals(local_final, local_var);
+  }
+}
+
+void main() {
+  new C().test();
+}
diff --git a/tests/language/const/factory_redirection_test.dart b/tests/language/const/factory_redirection_test.dart
new file mode 100644
index 0000000..e1cc36d
--- /dev/null
+++ b/tests/language/const/factory_redirection_test.dart
@@ -0,0 +1,28 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that factory redirections work for compile-time constants, and
+// that abstract classes can redirect.
+
+abstract class C {
+  const factory C(int x) = D;
+}
+
+class D implements C {
+  final int i;
+  const D(this.i);
+  m() => 'called m';
+}
+
+main() {
+  const C c = const C(42);
+  D d = c as D;
+  Expect.equals(42, d.i);
+  Expect.equals('called m', d.m());
+  d = new C(42) as D;
+  Expect.equals(42, d.i);
+  Expect.equals('called m', d.m());
+}
diff --git a/tests/language/const/factory_with_body_runtime_test.dart b/tests/language/const/factory_with_body_runtime_test.dart
new file mode 100644
index 0000000..559defc
--- /dev/null
+++ b/tests/language/const/factory_with_body_runtime_test.dart
@@ -0,0 +1,16 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 a "const factory" with body produces a compile-time error.
+
+class ConstFactoryWithBody {
+
+}
+
+main() {
+
+}
diff --git a/tests/language/const/factory_with_body_test.dart b/tests/language/const/factory_with_body_test.dart
new file mode 100644
index 0000000..a9577bb
--- /dev/null
+++ b/tests/language/const/factory_with_body_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 a "const factory" with body produces a compile-time error.
+
+class ConstFactoryWithBody {
+  const ConstFactoryWithBody();
+
+  const factory ConstFactoryWithBody.one() { return ConstFactoryWithBody(); }
+//^^^^^
+// [analyzer] SYNTACTIC_ERROR.CONST_FACTORY
+// [cfe] Only redirecting factory constructors can be declared to be 'const'.
+}
+
+main() {
+  const ConstFactoryWithBody.one();
+}
diff --git a/tests/language/const/for_in_variable_test.dart b/tests/language/const/for_in_variable_test.dart
new file mode 100644
index 0000000..2eb63b7
--- /dev/null
+++ b/tests/language/const/for_in_variable_test.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.
+
+main() {
+  for (
+      const //# 01: compile-time error
+      final //# 02: ok
+      int x in const [1, 2, 3]) {
+    break;
+  }
+}
diff --git a/tests/language/const/getter_runtime_test.dart b/tests/language/const/getter_runtime_test.dart
new file mode 100644
index 0000000..4d32485
--- /dev/null
+++ b/tests/language/const/getter_runtime_test.dart
@@ -0,0 +1,25 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Check that const getters are not allowed.
+
+import 'package:expect/expect.dart';
+
+class C {
+  const C();
+
+
+  get x => 1;
+}
+
+
+get y => 2;
+
+main() {
+  const C().x;
+  y;
+}
diff --git a/tests/language/const/getter_test.dart b/tests/language/const/getter_test.dart
new file mode 100644
index 0000000..c843529
--- /dev/null
+++ b/tests/language/const/getter_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+// Check that const getters are not allowed.
+
+import 'package:expect/expect.dart';
+
+class C {
+  const C();
+
+  const
+//^^^^^
+// [analyzer] SYNTACTIC_ERROR.EXTRANEOUS_MODIFIER
+// [cfe] Can't have modifier 'const' here.
+  get x => 1;
+}
+
+const
+// [error line 19, column 1, length 5]
+// [analyzer] SYNTACTIC_ERROR.EXTRANEOUS_MODIFIER
+// [cfe] Can't have modifier 'const' here.
+get y => 2;
+
+main() {
+  const C().x;
+  y;
+}
diff --git a/tests/language/const/global_test.dart b/tests/language/const/global_test.dart
new file mode 100644
index 0000000..99143d4
--- /dev/null
+++ b/tests/language/const/global_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 a = 1;
+
+main() {
+  Expect.equals(1, a);
+  Expect.equals(1, const A(a).a);
+  Expect.equals(1, const [const A(a)][0].a);
+}
+
+class A {
+  final a;
+  const A(this.a);
+}
diff --git a/tests/language/const/inference_test.dart b/tests/language/const/inference_test.dart
new file mode 100644
index 0000000..77b20ec
--- /dev/null
+++ b/tests/language/const/inference_test.dart
@@ -0,0 +1,140 @@
+// 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:expect/expect.dart";
+
+R constFunction<T, R>(T _) => throw "uncalled";
+
+C<T> getC<T>() => const C(constFunction);
+
+List<T> getList<T>() => const [];
+
+Set<T> getSet<T>() => const {};
+
+Map<K, V> getMap<K, V>() => const {};
+
+R Function(T) getFunction<T, R>() {
+  List<R Function(T)> list = const [constFunction];
+  return list[0];
+}
+
+C<T> getImplicitConstC<T>() {
+  List<C<T>> list = const [C(constFunction)];
+  return list[0];
+}
+
+List<T> getImplicitConstList<T>() {
+  List<List<T>> list = const [[]];
+  return list[0];
+}
+
+Set<T> getImplicitConstSet<T>() {
+  List<Set<T>> list = const [{}];
+  return list[0];
+}
+
+Map<K, V> getImplicitConstMap<K, V>() {
+  List<Map<K, V>> list = const [{}];
+  return list[0];
+}
+
+class C<T> {
+  final Object fn;
+  const C(T Function(T) this.fn);
+}
+
+void expectOfType<T>(Object obj) {
+  // An exact type test would be better, but since `Never` is a subtype of all
+  // types that can be written in Dart, it should not matter in practice.
+  //
+  // (`obj.runtimeType == T` does not work for List/Map/Sets because the runtime
+  // type is an implementation-specific subtype of those interfaces.)
+  Expect.isTrue(obj is T, "`$obj` should be of type `$T`");
+}
+
+testClassInstance() {
+  expectOfType<C<Never>>(getC<int>());
+  expectOfType<C<Never>>(getC<String>());
+  expectOfType<C<Never>>(getC());
+}
+
+testImplicitConstClassInstance() {
+  expectOfType<C<Never>>(getImplicitConstC<int>());
+  expectOfType<C<Never>>(getImplicitConstC<String>());
+  expectOfType<C<Never>>(getImplicitConstC());
+}
+
+testDownwardsClassInference() {
+  expectOfType<Never Function(Never)>(getC<int>().fn);
+  expectOfType<Never Function(Never)>(getC<String>().fn);
+  expectOfType<Never Function(Never)>(getC().fn);
+}
+
+testList() {
+  expectOfType<List<Never>>(getList<int>());
+  expectOfType<List<Never>>(getList<String>());
+  expectOfType<List<Never>>(getList());
+}
+
+testImplicitConstList() {
+  expectOfType<List<Never>>(getImplicitConstList<int>());
+  expectOfType<List<Never>>(getImplicitConstList<String>());
+  expectOfType<List<Never>>(getImplicitConstList());
+}
+
+testImplicitConstSet() {
+  expectOfType<Set<Never>>(getImplicitConstSet<int>());
+  expectOfType<Set<Never>>(getImplicitConstSet<String>());
+  expectOfType<Set<Never>>(getImplicitConstSet());
+}
+
+testSet() {
+  expectOfType<Set<Never>>(getSet<int>());
+  expectOfType<Set<Never>>(getSet<String>());
+  expectOfType<Set<Never>>(getSet());
+}
+
+testMap() {
+  expectOfType<Map<Never, Never>>(getMap<int, int>());
+  expectOfType<Map<Never, Never>>(getMap<int, String>());
+  expectOfType<Map<Never, Never>>(getMap<String, int>());
+  expectOfType<Map<Never, Never>>(getMap<String, String>());
+  expectOfType<Map<Never, Never>>(getMap<Never, Never>());
+  expectOfType<Map<Never, Never>>(getMap());
+}
+
+testImplicitConstMap() {
+  expectOfType<Map<Never, Never>>(getImplicitConstMap<int, int>());
+  expectOfType<Map<Never, Never>>(getImplicitConstMap<int, String>());
+  expectOfType<Map<Never, Never>>(getImplicitConstMap<String, int>());
+  expectOfType<Map<Never, Never>>(getImplicitConstMap<String, String>());
+  expectOfType<Map<Never, Never>>(getImplicitConstMap<Never, Never>());
+  expectOfType<Map<Never, Never>>(getImplicitConstMap());
+}
+
+testFunction() {
+  expectOfType<Never Function(Object?)>(getFunction<int, int>());
+  expectOfType<Never Function(Object?)>(getFunction<int, String>());
+  expectOfType<Never Function(Object?)>(getFunction<String, int>());
+  expectOfType<Never Function(Object?)>(getFunction<String, String>());
+  expectOfType<Never Function(Object?)>(getFunction<Never, Never>());
+  expectOfType<Never Function(Object?)>(getFunction());
+}
+
+/// Tests that use type inference for constants do not reference the type
+/// parameter. Instead, free type parameters are substituted to obtain the
+/// least closure (e.g. `List<T>` becomes `List<Never>` and `R Function(T)`
+/// becomes `Never Function(Object)`).
+main() {
+  testClassInstance();
+  testImplicitConstClassInstance();
+  testDownwardsClassInference();
+  testList();
+  testImplicitConstList();
+  testSet();
+  testImplicitConstSet();
+  testMap();
+  testImplicitConstMap();
+  testFunction();
+}
diff --git a/tests/language/const/init2_runtime_1_test.dart b/tests/language/const/init2_runtime_1_test.dart
new file mode 100644
index 0000000..7338f45
--- /dev/null
+++ b/tests/language/const/init2_runtime_1_test.dart
@@ -0,0 +1,15 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+const intValue = 0;
+const double c = 0.0;
+
+
+main() {
+  print(c);
+
+}
diff --git a/tests/language/const/init2_runtime_test.dart b/tests/language/const/init2_runtime_test.dart
new file mode 100644
index 0000000..5970f29
--- /dev/null
+++ b/tests/language/const/init2_runtime_test.dart
@@ -0,0 +1,15 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+const intValue = 0;
+
+
+
+main() {
+
+
+}
diff --git a/tests/language/const/init2_test.dart b/tests/language/const/init2_test.dart
new file mode 100644
index 0000000..7f5e1a3
--- /dev/null
+++ b/tests/language/const/init2_test.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.
+
+const intValue = 0;
+const double c = 0.0;
+const double d = intValue;
+//               ^^^^^^^^
+// [analyzer] CHECKED_MODE_COMPILE_TIME_ERROR.VARIABLE_TYPE_MISMATCH
+// [cfe] A value of type 'int' can't be assigned to a variable of type 'double'.
+//               ^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+
+main() {
+  print(c);
+  print(d);
+}
diff --git a/tests/language/const/init_test.dart b/tests/language/const/init_test.dart
new file mode 100644
index 0000000..714f9e1
--- /dev/null
+++ b/tests/language/const/init_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that initializers of static const fields are compile time constants.
+
+import "package:expect/expect.dart";
+
+class Point {
+  final x_;
+  final y_;
+  const Point(x, y)
+      : x_ = x,
+        y_ = y;
+}
+
+class ConstInitTest {
+  static const N = 1;
+  static const O = 1 + 3;
+  static const P = 2 * (O - N);
+  static const Q = const Point(0, 0);
+
+  static const Q2 = const Point(0, 0);
+  static const P2 = 2 * (O - N);
+  static const O2 = 1 + 3;
+  static const N2 = 1;
+
+  static testMain() {
+    Expect.equals(1, N);
+    Expect.equals(4, O);
+    Expect.equals(6, P);
+    Expect.equals(0, Q.x_);
+    Expect.equals(0, Q.y_);
+  }
+}
+
+main() {
+  ConstInitTest.testMain();
+}
diff --git a/tests/language/const/instance_field_runtime_test.dart b/tests/language/const/instance_field_runtime_test.dart
new file mode 100644
index 0000000..697b231
--- /dev/null
+++ b/tests/language/const/instance_field_runtime_test.dart
@@ -0,0 +1,16 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test that const instance fields are compile-time errors.
+
+class C {
+
+}
+
+void main() {
+  new C();
+}
diff --git a/tests/language/const/instance_field_test.dart b/tests/language/const/instance_field_test.dart
new file mode 100644
index 0000000..f80551a
--- /dev/null
+++ b/tests/language/const/instance_field_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// Test that const instance fields are compile-time errors.
+
+class C {
+  const field = 0;
+//^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INSTANCE_FIELD
+// [cfe] Only static fields can be declared as const.
+}
+
+void main() {
+  new C();
+}
diff --git a/tests/language/const/list_test.dart b/tests/language/const/list_test.dart
new file mode 100644
index 0000000..b34be30
--- /dev/null
+++ b/tests/language/const/list_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 ConstListTest {
+  static testConstructors() {
+    List fixedList = List.filled(4, -1, growable: false);
+    List fixedList2 = List.filled(4, -1, growable: false);
+    List growableList = List.filled(0, -1, growable: true);
+    List growableList2 = List.filled(0, -1, growable: true);
+    for (int i = 0; i < 4; i++) {
+      fixedList[i] = i;
+      fixedList2[i] = i;
+      growableList.add(i);
+      growableList2.add(i);
+    }
+    Expect.equals(growableList, growableList);
+    Expect.notEquals(growableList, growableList2);
+    Expect.equals(fixedList, fixedList);
+    Expect.notEquals(fixedList, fixedList2);
+    Expect.notEquals(fixedList, growableList);
+    growableList.add(4);
+    Expect.notEquals(fixedList, growableList);
+    Expect.equals(4, growableList.removeLast());
+    Expect.notEquals(fixedList, growableList);
+    fixedList[3] = 0;
+    Expect.notEquals(fixedList, growableList);
+  }
+
+  static testLiterals() {
+    dynamic a = [1, 2, 3.1];
+    dynamic b = [1, 2, 3.1];
+    Expect.notEquals(a, b);
+    a = const [1, 2, 3.1];
+    b = const [1, 2, 3.1];
+    Expect.identical(a, b);
+    a = const <num>[1, 2, 3.1];
+    b = const [1, 2, 3.1];
+    Expect.identical(a, b);
+    a = const <dynamic>[1, 2, 3.1];
+    b = const [1, 2, 3.1];
+    Expect.notEquals(a, b);
+  }
+}
+
+main() {
+  ConstListTest.testConstructors();
+  ConstListTest.testLiterals();
+}
diff --git a/tests/language/const/local_test.dart b/tests/language/const/local_test.dart
new file mode 100644
index 0000000..f5288ed
--- /dev/null
+++ b/tests/language/const/local_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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() {
+  const a = 1;
+  Expect.equals(1, a);
+  Expect.equals(1, const A(a).a);
+  Expect.equals(1, const [const A(a)][0].a);
+}
+
+class A {
+  final a;
+  const A(this.a);
+}
diff --git a/tests/language/const/locals_test.dart b/tests/language/const/locals_test.dart
new file mode 100644
index 0000000..00fc637
--- /dev/null
+++ b/tests/language/const/locals_test.dart
@@ -0,0 +1,31 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test of compile time constant local variables.
+
+const N = 8;
+
+class ConstFoo {
+  final x;
+  const ConstFoo(this.x);
+}
+
+main() {
+  const MIN = 2 - 1;
+  const MAX = N * 2;
+  const MASK = (1 << (MAX - MIN + 1)) - 1; // 65535.
+  Expect.equals(1, MIN);
+  Expect.equals(16, MAX);
+  Expect.equals(65535, MASK);
+  const s = 'MIN = $MIN  MAX = $MAX  MASK = $MASK';
+  Expect.identical(s, 'MIN = $MIN  MAX = $MAX  MASK = $MASK');
+  Expect.equals("MIN = 1  MAX = 16  MASK = 65535", s);
+  var cf1 = const ConstFoo(MASK);
+  var cf2 = const ConstFoo(s);
+  var cf3 = const ConstFoo('MIN = $MIN  MAX = $MAX  MASK = $MASK');
+  Expect.identical(cf2, cf3);
+  Expect.isFalse(identical(cf2, cf1));
+}
diff --git a/tests/language/const/map2_runtime_test.dart b/tests/language/const/map2_runtime_test.dart
new file mode 100644
index 0000000..9e1fe97
--- /dev/null
+++ b/tests/language/const/map2_runtime_test.dart
@@ -0,0 +1,32 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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:expect/expect.dart";
+
+class A {
+  const factory A() = B;
+}
+
+class B implements A {
+  const B();
+
+
+}
+
+confuse(x) {
+  if (new DateTime.now() == 42) return confuse(2);
+  return x;
+}
+
+main() {
+  // It is a compile-time error if the key type overrides operator ==.
+  dynamic m = const {const A(): 42};
+  Expect.equals(42, m[confuse(const B())]);
+
+  m = const {"foo": 99, const A(): 499};
+  Expect.equals(499, m[confuse(const B())]);
+}
diff --git a/tests/language/const/map2_test.dart b/tests/language/const/map2_test.dart
new file mode 100644
index 0000000..a5f3798
--- /dev/null
+++ b/tests/language/const/map2_test.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.
+
+import "package:expect/expect.dart";
+
+class A {
+  const factory A() = B;
+}
+
+class B implements A {
+  const B();
+
+  operator ==(o) => true;
+}
+
+confuse(x) {
+  if (new DateTime.now() == 42) return confuse(2);
+  return x;
+}
+
+main() {
+  // It is a compile-time error if the key type overrides operator ==.
+  dynamic m = const {const A(): 42};
+  //          ^
+  // [cfe] Constant evaluation error:
+  //                 ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
+  Expect.equals(42, m[confuse(const B())]);
+
+  m = const {"foo": 99, const A(): 499};
+  //  ^
+  // [cfe] Constant evaluation error:
+  //                    ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
+  Expect.equals(499, m[confuse(const B())]);
+}
diff --git a/tests/language/const/map3_runtime_test.dart b/tests/language/const/map3_runtime_test.dart
new file mode 100644
index 0000000..4416774
--- /dev/null
+++ b/tests/language/const/map3_runtime_test.dart
@@ -0,0 +1,27 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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:expect/expect.dart";
+
+class A {
+  static const b = const B();
+}
+
+class B implements A {
+  const B();
+
+
+}
+
+main() {
+  // It is a compile-time error if the key type overrides operator ==.
+  dynamic m = const {A.b: 42};
+  Expect.equals(42, m[const B()]);
+
+  m = const {"foo": 99, A.b: 499};
+  Expect.equals(499, m[const B()]);
+}
diff --git a/tests/language/const/map3_test.dart b/tests/language/const/map3_test.dart
new file mode 100644
index 0000000..b7ee989
--- /dev/null
+++ b/tests/language/const/map3_test.dart
@@ -0,0 +1,32 @@
+// 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:expect/expect.dart";
+
+class A {
+  static const b = const B();
+}
+
+class B implements A {
+  const B();
+
+  operator ==(o) => true;
+}
+
+main() {
+  // It is a compile-time error if the key type overrides operator ==.
+  dynamic m = const {A.b: 42};
+  //          ^
+  // [cfe] Constant evaluation error:
+  //                 ^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
+  Expect.equals(42, m[const B()]);
+
+  m = const {"foo": 99, A.b: 499};
+  //  ^
+  // [cfe] Constant evaluation error:
+  //                    ^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
+  Expect.equals(499, m[const B()]);
+}
diff --git a/tests/language/const/map4_test.dart b/tests/language/const/map4_test.dart
new file mode 100644
index 0000000..397672c
--- /dev/null
+++ b/tests/language/const/map4_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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() {
+  dynamic a = {1: 'a', 2: 'b', 3: 'c'};
+  dynamic b = {1: 'a', 2: 'b', 3: 'c'};
+  Expect.equals(false, a == b);
+
+  a = const {1: 'a', 2: 'b', 3: 'c'};
+  b = const {1: 'a', 2: 'b', 3: 'c'};
+  Expect.equals(true, a == b);
+
+  a = const <int, String>{1: 'a', 2: 'b', 3: 'c'};
+  b = const {1: 'a', 2: 'b', 3: 'c'};
+  Expect.equals(true, a == b);
+
+  a = const <num, String>{1: 'a', 2: 'b', 3: 'c'};
+  b = const {1: 'a', 2: 'b', 3: 'c'};
+  Expect.equals(false, a == b);
+
+  a = const <dynamic, dynamic>{1: 'a', 2: 'b', 3: 'c'};
+  b = const {1: 'a', 2: 'b', 3: 'c'};
+  Expect.equals(false, a == b);
+}
diff --git a/tests/language/const/map_test.dart b/tests/language/const/map_test.dart
new file mode 100644
index 0000000..19ced31
--- /dev/null
+++ b/tests/language/const/map_test.dart
@@ -0,0 +1,38 @@
+// 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:expect/expect.dart";
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+getValueNonOptimized(x) {
+  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
+  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+  return x;
+}
+
+main() {
+  // TODO(terry): Should check:
+  //   - const map is immutable
+  //   - simple expressions are const e.g., 2 + 3, true && !false, etc.
+  //   - const with final and/or static with same const attributes
+  //     Additionally new class instances with a static const same identity
+  //   - const for all types (int, num, double, String, boolean, and objects)
+  //   - canonicalization - const created only once same identity e.g.,
+  //
+  //     getConstMap() => const [1, 2];
+  //     var a = getConstMap();
+  //     var b = getConstMap();
+  //     Expect.equals(a.hashCode, b.hashCode);
+
+  // Make sure that const maps use the == operator and not object identity. The
+  // specification does not explicitly require it, otherwise ints and Strings
+  // wouldn't make much sense as keys.
+  var m = const {1: 42, "foo": 499, 2: "bar"};
+  Expect.equals(42, m[getValueNonOptimized(1.0)]);
+  Expect.equals(
+      499, m[getValueNonOptimized(new String.fromCharCodes("foo".runes))]);
+  Expect.equals('bar', m[getValueNonOptimized(2)]);
+}
diff --git a/tests/language/const/named_test.dart b/tests/language/const/named_test.dart
new file mode 100644
index 0000000..94b5598
--- /dev/null
+++ b/tests/language/const/named_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that const constructors work with named arguments.
+
+import "package:expect/expect.dart";
+
+main() {
+  var d = const Duration(milliseconds: 499);
+  Expect.equals(499, d.inMilliseconds);
+}
diff --git a/tests/language/const/native_factory_test.dart b/tests/language/const/native_factory_test.dart
new file mode 100644
index 0000000..13d398f
--- /dev/null
+++ b/tests/language/const/native_factory_test.dart
@@ -0,0 +1,14 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+class Cake {
+  final name;
+  const Cake(this.name);
+  const factory Cake.BakeMeACake()
+      native "Cake_BakeMeACake"; /*@compile-error=unspecified*/
+}
+
+main() {
+  var c = const Cake("Sacher");
+}
diff --git a/tests/language/const/nested_test.dart b/tests/language/const/nested_test.dart
new file mode 100644
index 0000000..bf52d67
--- /dev/null
+++ b/tests/language/const/nested_test.dart
@@ -0,0 +1,42 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test of compile time constant local variables in outer function levels.
+
+const N = 8;
+
+class ConstFoo {
+  final x;
+  const ConstFoo(this.x);
+}
+
+getClosure() {
+  const MIN = 2 - 1;
+  const MAX = N * 2;
+  const MASK = (1 << (MAX - MIN + 1)) - 1; // 65535.
+
+  void foo() {
+    Expect.equals(1, MIN);
+    Expect.equals(16, MAX);
+    Expect.equals(65535, MASK);
+    // Refer to compile time constant local variables in outer scope.
+    const s = 'MIN = $MIN  MAX = $MAX  MASK = $MASK';
+    Expect.isTrue(identical(s, 'MIN = $MIN  MAX = $MAX  MASK = $MASK'));
+    Expect.equals("MIN = 1  MAX = 16  MASK = 65535", s);
+    var cf1 = const ConstFoo(MASK);
+    var cf2 = const ConstFoo(s);
+    var cf3 = const ConstFoo('MIN = $MIN  MAX = $MAX  MASK = $MASK');
+    Expect.isTrue(identical(cf2, cf3));
+    Expect.isFalse(identical(cf2, cf1));
+  }
+
+  return foo;
+}
+
+main() {
+  var f = getClosure();
+  f();
+}
diff --git a/tests/language/const/objects_are_immutable_test.dart b/tests/language/const/objects_are_immutable_test.dart
new file mode 100644
index 0000000..7633716
--- /dev/null
+++ b/tests/language/const/objects_are_immutable_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that const objects (including literals) are immutable.
+
+import "package:expect/expect.dart";
+
+class A {
+  const A(this.x, this.y);
+  final num x, y;
+}
+
+main() {
+  dynamic list = const [1, 2];
+  Expect.throws(() => list[0] = 3);
+  Expect.equals(1, list[0]);
+
+  dynamic m = const {'foo': 499};
+  Expect.throws(() => m['foo'] = 42);
+  Expect.equals(499, m['foo']);
+
+  dynamic a1 = const A(1, 2);
+  Expect.throws(() => a1.x = 499);
+  Expect.equals(1, a1.x);
+
+  dynamic a2 = const A(1, 2);
+  Expect.throws(() => a2.x = 499);
+  Expect.equals(1, a2.x);
+}
diff --git a/tests/language/const/optional_args_runtime_test.dart b/tests/language/const/optional_args_runtime_test.dart
new file mode 100644
index 0000000..46d23f9
--- /dev/null
+++ b/tests/language/const/optional_args_runtime_test.dart
@@ -0,0 +1,20 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Check that const objects (including literals) are immutable.
+
+// Must be 'const {}' to be valid.
+invalid(
+    [var p =
+
+    const
+
+    {}]) {}
+
+main() {
+  invalid();
+}
diff --git a/tests/language/const/optional_args_test.dart b/tests/language/const/optional_args_test.dart
new file mode 100644
index 0000000..3d7c779
--- /dev/null
+++ b/tests/language/const/optional_args_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Check that const objects (including literals) are immutable.
+
+// Must be 'const {}' to be valid.
+invalid(
+    [var p =
+    /*
+    const
+    */
+    {}]) {}
+//  ^^
+// [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_DEFAULT_VALUE
+// [cfe] Constant expression expected.
+
+main() {
+  invalid();
+}
diff --git a/tests/language/const/qq_test.dart b/tests/language/const/qq_test.dart
new file mode 100644
index 0000000..9b27099
--- /dev/null
+++ b/tests/language/const/qq_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.
+
+// Check that ?? is compile-time constant.
+
+import "package:expect/expect.dart";
+
+// These are typed `Object?` to avoid warnings that the "??" are unnecessary
+// when the LHS is non-nullable.
+const Object? theNull = null;
+const Object? notNull = const Object();
+
+// Top-level const field initializer.
+const test1 = theNull ?? notNull;
+const test2 = notNull ?? theNull;
+const test3 = theNull ?? theNull ?? notNull;
+const test4 = theNull ?? theNull ?? theNull;
+
+class P {
+  final v;
+  const P(this.v);
+}
+
+// Annotation parameter (not checked by test!)
+@P(theNull ?? notNull)
+@P(notNull ?? theNull)
+@P(theNull ?? theNull ?? notNull)
+@P(theNull ?? theNull ?? theNull)
+class C {
+  // Static const field initializer.
+  static const test5 = theNull ?? notNull;
+  static const test6 = notNull ?? theNull;
+  static const test7 = theNull ?? theNull ?? notNull;
+  static const test8 = theNull ?? theNull ?? theNull;
+
+  // (Constructor) parameter defaults.
+  final test9;
+  final test10;
+  final test11;
+  final test12;
+
+  // Const constructor initializer list.
+  final test13;
+  final test14;
+  final test15;
+  final test16;
+  final test17;
+
+  const C(x,
+      [this.test9 = theNull ?? notNull,
+      this.test10 = notNull ?? theNull,
+      this.test11 = theNull ?? theNull ?? notNull,
+      this.test12 = theNull ?? theNull ?? theNull])
+      : test13 = theNull ?? x,
+        test14 = notNull ?? x,
+        test15 = x ?? notNull,
+        test16 = theNull ?? theNull ?? x,
+        test17 = theNull ?? x ?? notNull;
+
+  List methodLocal() {
+    // Method local const variable initializer.
+    const test18 = theNull ?? notNull;
+    const test19 = notNull ?? theNull;
+    const test20 = theNull ?? theNull ?? notNull;
+    const test21 = theNull ?? theNull ?? theNull;
+
+    return const [test18, test19, test20, test21];
+  }
+
+  List expressionLocal() {
+    // Constant expression sub-expression.
+    return const [
+      theNull ?? notNull,
+      notNull ?? theNull,
+      theNull ?? theNull ?? notNull,
+      theNull ?? theNull ?? theNull
+    ];
+  }
+}
+
+main() {
+  Expect.identical(notNull, test1, "test1");
+  Expect.identical(notNull, test2, "test2");
+  Expect.identical(notNull, test3, "test3");
+  Expect.identical(theNull, test4, "test4");
+
+  Expect.identical(notNull, C.test5, "test5");
+  Expect.identical(notNull, C.test6, "test6");
+  Expect.identical(notNull, C.test7, "test7");
+  Expect.identical(theNull, C.test8, "test8");
+
+  const c1 = const C(null);
+  Expect.identical(notNull, c1.test9, "test9");
+  Expect.identical(notNull, c1.test10, "test10");
+  Expect.identical(notNull, c1.test11, "test11");
+  Expect.identical(theNull, c1.test12, "test12");
+
+  Expect.identical(theNull, c1.test13, "test13");
+  Expect.identical(notNull, c1.test14, "test14");
+  Expect.identical(notNull, c1.test15, "test15");
+  Expect.identical(theNull, c1.test16, "test16");
+  Expect.identical(notNull, c1.test17, "test17");
+
+  var list = c1.methodLocal();
+  Expect.identical(notNull, list[0], "test18");
+  Expect.identical(notNull, list[1], "test19");
+  Expect.identical(notNull, list[2], "test20");
+  Expect.identical(theNull, list[3], "test21");
+
+  list = c1.expressionLocal();
+  Expect.identical(notNull, list[0], "test22");
+  Expect.identical(notNull, list[1], "test23");
+  Expect.identical(notNull, list[2], "test24");
+  Expect.identical(theNull, list[3], "test25");
+
+  const c2 = const C(42);
+  Expect.identical(notNull, c2.test9, "test26");
+  Expect.identical(notNull, c2.test10, "test27");
+  Expect.identical(notNull, c2.test11, "test28");
+  Expect.identical(theNull, c2.test12, "test29");
+
+  Expect.identical(42, c2.test13, "test30");
+  Expect.identical(notNull, c2.test14, "test31");
+  Expect.identical(42, c2.test15, "test32");
+  Expect.identical(42, c2.test16, "test33");
+  Expect.identical(42, c2.test17, "test34");
+
+  list = c2.methodLocal();
+  Expect.identical(notNull, list[0], "test35");
+  Expect.identical(notNull, list[1], "test36");
+  Expect.identical(notNull, list[2], "test37");
+  Expect.identical(theNull, list[3], "test38");
+
+  list = c2.expressionLocal();
+  Expect.identical(notNull, list[0], "test39");
+  Expect.identical(notNull, list[1], "test40");
+  Expect.identical(notNull, list[2], "test41");
+  Expect.identical(theNull, list[3], "test42");
+}
diff --git a/tests/language/const/redirect_skips_supertype_test.dart b/tests/language/const/redirect_skips_supertype_test.dart
new file mode 100644
index 0000000..f79ad5a
--- /dev/null
+++ b/tests/language/const/redirect_skips_supertype_test.dart
@@ -0,0 +1,23 @@
+// 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.
+
+// Since C redirects to C.named, it doesn't implicitly refer to B's
+// unnamed constructor.  Therefore there is no cycle.
+
+class B {
+  final x;
+  const B() : x = y;
+  const B.named() : x = null;
+}
+
+class C extends B {
+  const C() : this.named();
+  const C.named() : super.named();
+}
+
+const y = const C();
+
+main() {
+  print(y);
+}
diff --git a/tests/language/const/redirecting_factory_test.dart b/tests/language/const/redirecting_factory_test.dart
new file mode 100644
index 0000000..c7f8bf2
--- /dev/null
+++ b/tests/language/const/redirecting_factory_test.dart
@@ -0,0 +1,58 @@
+// 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:expect/expect.dart';
+
+class K implements L {
+  final field1;
+  final field2;
+  const K({this.field1: 42, this.field2: true});
+}
+
+class L {
+  const factory L() = K;
+  const factory L.named1({field1, field2}) = K;
+  const factory L.named2({field2, field1}) = K;
+}
+
+const K l1 = const L() as K;
+
+const K l2a = const L.named1() as K;
+const K l2b = const L.named1(field1: 87) as K;
+const K l2c = const L.named1(field2: false) as K;
+const K l2d = const L.named1(field1: 87, field2: false) as K;
+const K l2e = const L.named1(field2: false, field1: 87) as K;
+
+const K l3a = const L.named2() as K;
+const K l3b = const L.named2(field1: 87) as K;
+const K l3c = const L.named2(field2: false) as K;
+const K l3d = const L.named2(field1: 87, field2: false) as K;
+const K l3e = const L.named2(field2: false, field1: 87) as K;
+
+main() {
+  Expect.equals(42, l1.field1);
+  Expect.equals(true, l1.field2);
+
+  Expect.equals(42, l2a.field1);
+  Expect.equals(true, l2a.field2);
+  Expect.equals(87, l2b.field1);
+  Expect.equals(true, l2b.field2);
+  Expect.equals(42, l2c.field1);
+  Expect.equals(false, l2c.field2);
+  Expect.equals(87, l2d.field1);
+  Expect.equals(false, l2d.field2);
+  Expect.equals(87, l2e.field1);
+  Expect.equals(false, l2e.field2);
+
+  Expect.equals(42, l3a.field1);
+  Expect.equals(true, l3a.field2);
+  Expect.equals(87, l3b.field1);
+  Expect.equals(true, l3b.field2);
+  Expect.equals(42, l3c.field1);
+  Expect.equals(false, l3c.field2);
+  Expect.equals(87, l3d.field1);
+  Expect.equals(false, l3d.field2);
+  Expect.equals(87, l3e.field1);
+  Expect.equals(false, l3e.field2);
+}
diff --git a/tests/language/const/string_test.dart b/tests/language/const/string_test.dart
new file mode 100644
index 0000000..13f1a9c
--- /dev/null
+++ b/tests/language/const/string_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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";
+
+// Exercises compile-time string constants
+
+const yz = "y" + "z";
+
+main() {
+  // Constant comparisons are independent of the quotes used.
+  Expect.isTrue(identical("abcd", 'abcd'));
+  Expect.isTrue(identical('abcd', "abcd"));
+  Expect.isTrue(identical("ab\"cd", 'ab"cd'));
+  Expect.isTrue(identical('ab\'cd', "ab'cd"));
+
+  // String concatenation works even when quotes are different.
+  Expect.isTrue(identical("abcd", "ab" "cd"));
+  Expect.isTrue(identical("abcd", "ab" 'cd'));
+  Expect.isTrue(identical("abcd", 'ab' 'cd'));
+  Expect.isTrue(identical("abcd", 'ab' "cd"));
+
+  // Or when there are more than 2 contatenations.
+  Expect.isTrue(identical("abcd", "a" "b" "cd"));
+  Expect.isTrue(identical("abcd", "a" "b" "c" "d"));
+  Expect.isTrue(identical('abcd', 'a' 'b' 'c' 'd'));
+  Expect.isTrue(identical("abcd", "a" "b" 'c' "d"));
+  Expect.isTrue(identical("abcd", 'a' 'b' 'c' 'd'));
+  Expect.isTrue(identical("abcd", 'a' "b" 'c' "d"));
+
+  Expect.isTrue(identical("a'b'cd", "a" "'b'" 'c' "d"));
+  Expect.isTrue(identical("a\"b\"cd", "a" '"b"' 'c' "d"));
+  Expect.isTrue(identical("a\"b\"cd", "a" '"b"' 'c' "d"));
+  Expect.isTrue(identical("a'b'cd", 'a' "'b'" 'c' "d"));
+  Expect.isTrue(identical('a\'b\'cd', "a" "'b'" 'c' "d"));
+  Expect.isTrue(identical('a"b"cd', 'a' '"b"' 'c' "d"));
+  Expect.isTrue(identical("a\"b\"cd", 'a' '"b"' 'c' "d"));
+
+  const a = identical("ab", "a" + "b");
+  Expect.isTrue(a);
+
+  const b = identical("xyz", "x" + yz);
+  Expect.isTrue(b);
+
+  const c = identical("12", "1" "2");
+  Expect.isTrue(c);
+
+  const d = identical("zyz", "z$yz");
+  Expect.isTrue(d);
+}
diff --git a/tests/language/const/switch2_runtime_test.dart b/tests/language/const/switch2_runtime_test.dart
new file mode 100644
index 0000000..38657b1
--- /dev/null
+++ b/tests/language/const/switch2_runtime_test.dart
@@ -0,0 +1,19 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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:expect/expect.dart';
+
+void main() {
+  var a = [1, 2, 3][2];
+  switch (a) {
+
+
+
+    case 1:
+      print("OK");
+  }
+}
diff --git a/tests/language/const/switch2_test.dart b/tests/language/const/switch2_test.dart
new file mode 100644
index 0000000..7d784f1
--- /dev/null
+++ b/tests/language/const/switch2_test.dart
@@ -0,0 +1,24 @@
+// 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:expect/expect.dart';
+
+void main() {
+  var a = [1, 2, 3][2];
+  switch (a) {
+    case 0.0:
+    //   ^^^
+    // [analyzer] COMPILE_TIME_ERROR.CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE
+    //   ^^^
+    // [analyzer] COMPILE_TIME_ERROR.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
+    //   ^
+    // [cfe] Type 'double' of the case expression is not a subtype of type 'int' of this switch expression.
+    //   ^
+    // [cfe] Case expression '0.0' does not have a primitive operator '=='.
+      print("illegal");
+      break;
+    case 1:
+      print("OK");
+  }
+}
diff --git a/tests/language/const/switch_test.dart b/tests/language/const/switch_test.dart
new file mode 100644
index 0000000..c4048c7
--- /dev/null
+++ b/tests/language/const/switch_test.dart
@@ -0,0 +1,36 @@
+// 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:expect/expect.dart';
+
+class C {
+  final field;
+  const C(this.field);
+}
+
+const c1 = const C(0.0);
+const c2 = const C(0);
+const c3 = const C(0.5 + 0.5);
+const c4 = const C(1);
+
+main() {
+  Expect.equals('0.0', test(c1)); //# 01: ok
+  Expect.equals('0', test(c2)); //# 02: ok
+  Expect.equals('1.0', test(c3)); //# 03: ok
+  Expect.equals('1', test(c4)); //# 04: ok
+}
+
+String test(C c) {
+  switch (c) {
+    case const C(0.0):
+      return '0.0';
+    case const C(0):
+      return '0';
+    case const C(1.0):
+      return '1.0';
+    case const C(1):
+      return '1';
+  }
+  return '';
+}
diff --git a/tests/language/const/syntax_runtime_test.dart b/tests/language/const/syntax_runtime_test.dart
new file mode 100644
index 0000000..93d1f48
--- /dev/null
+++ b/tests/language/const/syntax_runtime_test.dart
@@ -0,0 +1,92 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  const f0 = 42;
+
+  const int f2 = 87;
+
+  Expect.equals(42, f0);
+  Expect.equals(87, f2);
+
+  Expect.equals(42, F0);
+
+  Expect.equals(87, F2);
+
+
+  Expect.isTrue(P0 is Point);
+
+
+
+
+  Expect.isTrue(A0 is int);
+  Expect.isTrue(A1 is int);
+
+
+
+  Expect.isTrue(C0.X is C1);
+
+
+  Expect.equals("Hello 42", B2);
+
+
+  const cf1 = identical(const Point(1, 2), const Point(1, 2));
+
+
+
+
+  var f5 = B5;
+}
+
+const F0 = 42;
+
+const int F2 = 87;
+
+
+class Point {
+  final x, y;
+  const Point(this.x, this.y);
+  operator +(int other) => x;
+}
+
+// Check that compile time expressions can include invocations of
+// user-defined const constructors.
+const P0 = const Point(0, 0);
+
+
+
+
+// Check that we cannot have cyclic references in compile time
+// expressions.
+const A0 = 42;
+const A1 = A0 + 1;
+
+
+
+class C0 {
+  static const X = const C1();
+}
+
+class C1 {
+  const C1()
+
+  ;
+  final x = null;
+}
+
+// Check that sub-expressions of binary + are numeric.
+const B0 = 42;
+const B1 = "Hello";
+const B2 = "$B1 $B0";
+
+
+// Check identical.
+
+
+const B5 = identical(1, const Point(1, 2));
diff --git a/tests/language/const/syntax_test.dart b/tests/language/const/syntax_test.dart
new file mode 100644
index 0000000..e9ccc4e
--- /dev/null
+++ b/tests/language/const/syntax_test.dart
@@ -0,0 +1,144 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  const f0 = 42;
+  const f1;
+  //    ^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_NOT_INITIALIZED
+  //      ^
+  // [cfe] The const variable ';' must be initialized.
+  const int f2 = 87;
+  const int f3;
+  //        ^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_NOT_INITIALIZED
+  //          ^
+  // [cfe] The const variable ';' must be initialized.
+  Expect.equals(42, f0);
+  Expect.equals(87, f2);
+
+  Expect.equals(42, F0);
+  Expect.equals(null, F1);
+  Expect.equals(87, F2);
+  Expect.equals(null, F3);
+
+  Expect.isTrue(P0 is Point);
+  Expect.isTrue(P1 is int);
+  Expect.isTrue(P2 is Point);
+  Expect.isTrue(P3 is int);
+
+  Expect.isTrue(A0 is int);
+  Expect.isTrue(A1 is int);
+  Expect.isTrue(A2 is int);
+  Expect.isTrue(A3 is int);
+
+  Expect.isTrue(C0.X is C1);
+  Expect.isTrue(C0.X.x is C1);
+
+  Expect.equals("Hello 42", B2);
+  Expect.equals("42Hello", B3);
+
+  const cf1 = identical(const Point(1, 2), const Point(1, 2));
+
+  const cf2 = identical(const Point(1, 2), new Point(1, 2));
+  //                                       ^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+  // [cfe] New expression is not a constant expression.
+
+  var f4 = B4;
+  var f5 = B5;
+}
+
+const F0 = 42;
+const F1;
+//    ^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_NOT_INITIALIZED
+// [cfe] The const variable 'F1' must be initialized.
+const int F2 = 87;
+const int F3;
+//        ^
+// [cfe] The const variable 'F3' must be initialized.
+//        ^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_NOT_INITIALIZED
+
+class Point {
+  final x, y;
+  const Point(this.x, this.y);
+  operator +(int other) => x;
+}
+
+// Check that compile time expressions can include invocations of
+// user-defined const constructors.
+const P0 = const Point(0, 0);
+const P1 = const Point(0, 0) + 1;
+//         ^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_TYPE_NUM
+//                           ^
+// [cfe] Constant evaluation error:
+const P2 = new Point(0, 0);
+//         ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] New expression is not a constant expression.
+const P3 = new Point(0, 0) + 1;
+//         ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] New expression is not a constant expression.
+
+// Check that we cannot have cyclic references in compile time
+// expressions.
+const A0 = 42;
+const A1 = A0 + 1;
+const A2 = A3 + 1;
+//    ^^
+// [analyzer] COMPILE_TIME_ERROR.RECURSIVE_COMPILE_TIME_CONSTANT
+// [cfe] Can't infer the type of 'A2': circularity found during type inference.
+//         ^^
+// [analyzer] COMPILE_TIME_ERROR.TOP_LEVEL_CYCLE
+//            ^
+// [cfe] Constant evaluation error:
+const A3 = A2 + 1;
+//    ^^
+// [analyzer] COMPILE_TIME_ERROR.RECURSIVE_COMPILE_TIME_CONSTANT
+//         ^^
+// [analyzer] COMPILE_TIME_ERROR.TOP_LEVEL_CYCLE
+
+class C0 {
+  static const X = const C1();
+  //           ^
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_COMPILE_TIME_CONSTANT
+}
+
+class C1 {
+  const C1()
+      : x = C0.X
+      //^
+      // [analyzer] STATIC_WARNING.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION
+      //  ^
+      // [cfe] 'x' is a final instance variable that has already been initialized.
+      //  ^
+      // [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
+  ;
+  final x = null;
+}
+
+// Check that sub-expressions of binary + are numeric.
+const B0 = 42;
+const B1 = "Hello";
+const B2 = "$B1 $B0";
+const B3 = B0 + B1;
+//         ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_TYPE_NUM
+//              ^^
+// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] A value of type 'String' can't be assigned to a variable of type 'num'.
+
+// Check identical.
+
+const B4 = identical(1, new Point(1, 2));
+//                      ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] New expression is not a constant expression.
+const B5 = identical(1, const Point(1, 2));
diff --git a/tests/language/const/tree_test.dart b/tests/language/const/tree_test.dart
new file mode 100644
index 0000000..7c0cd28
--- /dev/null
+++ b/tests/language/const/tree_test.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.
+
+class A {
+  final List<A> children;
+  const A({this.children: const []});
+}
+
+const a = const A();
+const b = const A(children: const [a]);
+
+main() {
+  print(b);
+}
diff --git a/tests/language/const/types_test.dart b/tests/language/const/types_test.dart
new file mode 100644
index 0000000..3199c0c
--- /dev/null
+++ b/tests/language/const/types_test.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.
+
+// Test handling of malformed types in constant expressions.
+
+use(x) {}
+
+class Class<T> implements Supertype, GenericSupertype<T> {
+  const Class();
+  const Class.named();
+
+  void test() {
+    use(const []);
+    use(const <Class>[]);
+    use(const <Class<int>>[]);
+    use(const <Class<Unresolved>>[]); //# 01: compile-time error
+    use(const <Unresolved>[]); //# 02: compile-time error
+
+    use(const {});
+    use(const <Class>{});
+    use(const <String, Class>{});
+    use(const <String, Class<int>>{});
+    use(const <String, Class<Unresolved>>{}); //# 04: compile-time error
+    use(const <String, Unresolved>{}); //# 05: compile-time error
+
+    use(const Class());
+    use(const Class<int>());
+    use(const Class<Unresolved>()); //# 06: compile-time error
+    use(const Class<T>()); //# 07: compile-time error
+    use(const Class<Class<T>>()); //# 08: compile-time error
+
+    use(const Unresolved()); //# 09: compile-time error
+    use(const Unresolved<int>()); //# 10: compile-time error
+    use(const prefix.Unresolved()); //# 11: compile-time error
+    use(const prefix.Unresolved<int>()); //# 12: compile-time error
+
+    use(const Class.named());
+    use(const Class<int>.named());
+    use(const Class<Unresolved>.named()); //# 13: compile-time error
+    use(const Class<T>.named()); //# 14: compile-time error
+    use(const Class<Class<T>>.named()); //# 15: compile-time error
+
+    use(const Class.nonamed()); //# 16: compile-time error
+    use(const Class<int>.nonamed()); //# 17: compile-time error
+    use(const Class<Unresolved>.nonamed()); //# 18: compile-time error
+    use(const Class<T>.nonamed()); //# 19: compile-time error
+    use(const Class<Class<T>>.nonamed()); //# 20: compile-time error
+
+    use(const Unresolved.named()); //# 21: compile-time error
+    use(const Unresolved<int>.named()); //# 22: compile-time error
+  }
+}
+
+class Supertype {
+  const factory Supertype() = Unresolved; //# 23: compile-time error
+  const factory Supertype() = Unresolved<int>; //# 24: compile-time error
+  const factory Supertype() = Unresolved.named; //# 25: compile-time error
+  const factory Supertype() = Unresolved<int>.named; //# 26: compile-time error
+
+  const factory Supertype() = prefix.Unresolved; //# 27: compile-time error
+  const factory Supertype() = prefix.Unresolved<int>; //# 28: compile-time error
+  const factory Supertype() = prefix.Unresolved.named; //# 29: compile-time error
+  const factory Supertype() = prefix.Unresolved<int>.named; //# 30: compile-time error
+
+  const factory Supertype() = Class; //# 31: ok
+  const factory Supertype() = Class<int>; //# 32: ok
+  const factory Supertype() = Class<Unresolved>; //# 35: compile-time error
+
+  const factory Supertype() = Class.named; //# 36: ok
+  const factory Supertype() = Class<int>.named; //# 37: ok
+  const factory Supertype() = Class<Unresolved>.named; //# 40: compile-time error
+}
+
+class GenericSupertype<T> {
+  const factory GenericSupertype() = Class<T>; //# 33: ok
+  const factory GenericSupertype() = Class<Class<T>>; //# 34: compile-time error
+
+  const factory GenericSupertype() = Class<T>.named; //# 38: ok
+  const factory GenericSupertype() = Class<Class<T>>.named; //# 39: compile-time error
+
+  const factory GenericSupertype() = T; //# 41: compile-time error
+}
+
+void main() {
+  new Class().test();
+  new Supertype();
+  new GenericSupertype();
+}
diff --git a/tests/language/const/var_helper.dart b/tests/language/const/var_helper.dart
new file mode 100644
index 0000000..ad3806c
--- /dev/null
+++ b/tests/language/const/var_helper.dart
@@ -0,0 +1,11 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// All things regarding constant variables.
+
+/** Helper library for 'var_test.dart' */
+library const_var_helper;
+
+class Foo<E> {
+  const Foo();
+}
diff --git a/tests/language/const/var_test.dart b/tests/language/const/var_test.dart
new file mode 100644
index 0000000..60557f6
--- /dev/null
+++ b/tests/language/const/var_test.dart
@@ -0,0 +1,30 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// All things regarding constant variables.
+
+library const_var;
+
+import 'var_helper.dart' as foo;
+
+const untypedTopLevel = 1;
+const int typedTopLevel = 2;
+const Map<String, String> genericTopLevel = const <String, String>{};
+
+main() {
+  const untypedLocal = 3;
+  const int typedLocal = 4;
+  const Map<String, String> genericLocal = const <String, String>{};
+  const [];
+  const {};
+  const <int>[];
+  const <String, int>{};
+  const Foo();
+  const Foo<int>();
+  const foo.Foo();
+  const foo.Foo<int>();
+}
+
+class Foo<E> {
+  const Foo();
+}
diff --git a/tests/language/constants_2018/const_type_test.dart b/tests/language/constants_2018/const_type_test.dart
new file mode 100644
index 0000000..c6c3f33
--- /dev/null
+++ b/tests/language/constants_2018/const_type_test.dart
@@ -0,0 +1,100 @@
+// 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.
+
+// Tests that types do matter when an expression is evaluated as constant.
+
+main() {
+  const C c = C();
+  const T.test01(c); //# 01: compile-time error
+  const T.test02(c, c); //# 02: compile-time error
+  const T.test03(c, c); //# 03: compile-time error
+  const T.test04(c, c); //# 04: compile-time error
+  const T.test05(c, c); //# 05: compile-time error
+  const T.test06(c, c); //# 06: compile-time error
+  const T.test07(c, c); //# 07: compile-time error
+  const T.test08(c, c); //# 08: compile-time error
+  const T.test09(c, c); //# 09: compile-time error
+  const T.test10(c, c); //# 10: compile-time error
+  const T.test11(c, c); //# 11: compile-time error
+  const T.test12(c, c); //# 12: compile-time error
+  const T.test13(c, c); //# 13: compile-time error
+  const T.test14(c); //# 14: compile-time error
+  const T.test15(c, c); //# 15: compile-time error
+  const T.test16(c, c); //# 16: compile-time error
+  const T.test17(c, c); //# 17: compile-time error
+  const T.test18(c, c); //# 18: compile-time error
+  const T.test19(c); //# 19: compile-time error
+
+  const v01 = false ? c : -c; //# 20: compile-time error
+  const v02 = false ? c : c + c; //# 21: compile-time error
+  const v03 = false ? c : c - c; //# 22: compile-time error
+  const v04 = false ? c : c * c; //# 23: compile-time error
+  const v05 = false ? c : c / c; //# 24: compile-time error
+  const v06 = false ? c : c ~/ c; //# 25: compile-time error
+  const v07 = false ? c : c % c; //# 26: compile-time error
+  const v08 = false ? c : c << c; //# 27: compile-time error
+  const v09 = false ? c : c >> c; //# 28: compile-time error
+  const v10 = false ? c : c >>> c; //# 29: compile-time error
+  const v11 = false ? c : c & c; //# 30: compile-time error
+  const v12 = false ? c : c | c; //# 31: compile-time error
+  const v13 = false ? c : c ^ c; //# 32: compile-time error
+  const v14 = false ? c : ~c; //# 33: compile-time error
+  const v15 = false ? c : c < c; //# 34: compile-time error
+  const v16 = false ? c : c > c; //# 35: compile-time error
+  const v17 = false ? c : c <= c; //# 36: compile-time error
+  const v18 = false ? c : c >= c; //# 37: compile-time error
+  const v19 = false ? c : c.length; //# 38: compile-time error
+}
+
+// Each expression in the forwarding generative constructors must be
+// potentially constant. They are only checked for being actually
+// constant when the constructor is invoked.
+class T {
+  const T(C o);
+  const T.test01(C x) : this(-x);
+  const T.test02(C x, C y) : this(x + y);
+  const T.test03(C x, C y) : this(x - y);
+  const T.test04(C x, C y) : this(x * y);
+  const T.test05(C x, C y) : this(x / y);
+  const T.test06(C x, C y) : this(x ~/ y);
+  const T.test07(C x, C y) : this(x % y);
+  const T.test08(C x, C y) : this(x << y);
+  const T.test09(C x, C y) : this(x >> y);
+  const T.test10(C x, C y) : this(x >>> y); //# 10: continued
+  const T.test11(C x, C y) : this(x & y);
+  const T.test12(C x, C y) : this(x | y);
+  const T.test13(C x, C y) : this(x ^ y);
+  const T.test14(C x) : this(~x);
+  const T.test15(C x, C y) : this(x < y);
+  const T.test16(C x, C y) : this(x > y);
+  const T.test17(C x, C y) : this(x <= y);
+  const T.test18(C x, C y) : this(x >= y);
+  const T.test19(C x) : this(x.length);
+}
+
+class C {
+  const C();
+  C operator -() => this;
+  C operator +(C other) => this;
+  C operator -(C other) => this;
+  C operator *(C other) => this;
+  C operator /(C other) => this;
+  C operator ~/(C other) => this;
+  C operator %(C other) => this;
+  C operator <<(C other) => this;
+  C operator >>(C other) => this;
+  // Remove the multi-test markers and one of the lines below,
+  // when `>>>` is implemented.
+  C operator >>>(C other) => this;  //# 10: continued
+  C operator >>>(C other) => this;  //# 29: continued
+  C operator &(C other) => this;
+  C operator |(C other) => this;
+  C operator ^(C other) => this;
+  C operator ~() => this;
+  C operator <(C other) => this;
+  C operator >(C other) => this;
+  C operator <=(C other) => this;
+  C operator >=(C other) => this;
+  C get length => this;
+}
\ No newline at end of file
diff --git a/tests/language/constants_2018/constant_type_literal_test.dart b/tests/language/constants_2018/constant_type_literal_test.dart
new file mode 100644
index 0000000..b886d77
--- /dev/null
+++ b/tests/language/constants_2018/constant_type_literal_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.
+
+// Tests that non-deferred type literals are constant expressions.
+
+import "dart:core";
+import "dart:core" as core;
+// No reloading support for deferred loading.
+// See https://github.com/dart-lang/sdk/issues/33118.
+import "dart:core" deferred as dcore; //# 01: compile-time error
+
+// Declares F function type alias, M mixin and C class.
+import "constant_type_literal_types.dart";
+import "constant_type_literal_types.dart" as p;
+// No reloading support for deferred loading.
+// See https://github.com/dart-lang/sdk/issues/33118.
+import "constant_type_literal_types.dart" //# 02: compile-time error
+    deferred as d; //# 02: continued
+
+main() {
+  const Test(int, core.int);
+  const Test(C, p.C);
+  const Test(M, p.M);
+  const Test(F, p.F);
+  const c1 = //
+      dcore. //# 01: continued
+          int;
+  const Test(c1, int);
+  const c2 = //
+      d. //# 02: continued
+          C;
+  const Test(c2, C);
+}
+
+class Test {
+  const Test(Type t1, Type t2) : assert(identical(t1, t2));
+}
diff --git a/tests/language/constants_2018/constant_type_literal_types.dart b/tests/language/constants_2018/constant_type_literal_types.dart
new file mode 100644
index 0000000..d3f5f2c
--- /dev/null
+++ b/tests/language/constants_2018/constant_type_literal_types.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Helper file for constant_type_literal_test.dart.
+// Tests that non-deferred type literals are constant expressions.
+
+typedef F = void Function();
+
+class C {}
+
+mixin M {}
diff --git a/tests/language/constants_2018/constant_types_test.dart b/tests/language/constants_2018/constant_types_test.dart
new file mode 100644
index 0000000..2c8dee1
--- /dev/null
+++ b/tests/language/constants_2018/constant_types_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+// Tests that in some positions only constant types are allowed, so not
+// type parameters. But in other positions potentially constant types are
+// allowed, so type parameters.
+
+import "package:expect/expect.dart";
+
+class T<X> {
+  final Object? value;
+  const T.test1()
+      : value = const //
+            <X> //# 01: compile-time error
+            [];
+  const T.test2(Object o)
+      : value = o //
+            as X //# 02: ok
+  ;
+  const T.test3(Object o)
+      : value = o //
+            is X //# 03: ok
+  ;
+  const T.test4()
+      : value = null //
+            ?? X //# 04: compile-time error
+  ;
+}
+
+class T2 {
+  final Object value;
+  const T2.test1() : value = const <int>[];
+  const T2.test2(Object o) : value = o as int;
+  const T2.test3(Object o) : value = o is int;
+  const T2.test4() : value = int;
+}
+
+main() {
+  // The errors in class T are errors independently of whether the
+  // constructor is invoked or not.
+
+  // Constant type expressions are allowed.
+  Expect.equals(const <int>[], const T2.test1().value);
+  Expect.equals(2, const T2.test2(2).value);
+  Expect.isTrue(const T2.test3(2).value);
+  Expect.equals(int, const T2.test4().value);
+}
diff --git a/tests/language/constants_2018/equals_test.dart b/tests/language/constants_2018/equals_test.dart
new file mode 100644
index 0000000..9e50b76
--- /dev/null
+++ b/tests/language/constants_2018/equals_test.dart
@@ -0,0 +1,63 @@
+// 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.
+
+// Tests that equality is allowed for receivers of specific types.
+
+import "package:expect/expect.dart";
+
+main() {
+  const c = C(); // Does not override operator==.
+  const d = D(); // Overrides operator==.
+
+  // Allowed if receiver is int, double, String, bool or Null, ...
+  Expect.isTrue(const T.eq(1, 1).value);
+  Expect.isTrue(const T.eq(1.5, 1.5).value);
+  Expect.isTrue(const T.eq("", "").value);
+  Expect.isTrue(const T.eq(true, true).value);
+  Expect.isTrue(const T.eq(null, null).value);
+
+  Expect.isFalse(const T.eq(1, c).value);
+  Expect.isFalse(const T.eq(1.5, c).value);
+  Expect.isFalse(const T.eq("", c).value);
+  Expect.isFalse(const T.eq(true, c).value);
+  Expect.isFalse(const T.eq(null, c).value);
+
+  Expect.isFalse(const T.eq(1, d).value);
+  Expect.isFalse(const T.eq(1.5, d).value);
+  Expect.isFalse(const T.eq("", d).value);
+  Expect.isFalse(const T.eq(true, d).value);
+  Expect.isFalse(const T.eq(null, d).value);
+
+  // ... or if second operand is Null.
+  Expect.isFalse(const T.eq(1, null).value);
+  Expect.isFalse(const T.eq(1.5, null).value);
+  Expect.isFalse(const T.eq("", null).value);
+  Expect.isFalse(const T.eq(false, null).value);
+  Expect.isFalse(const T.eq(c, null).value);
+  Expect.isFalse(const T.eq(d, null).value);
+
+  // Otherwise not allowed.
+  const T.eq(c, c); //# 01: compile-time error
+  const T.eq(c, 1); //# 02: compile-time error
+  const T.eq(c, ""); //# 03: compile-time error
+  const T.eq(E.value1, E.value2); //# 04: compile-time error
+}
+
+class T {
+  final Object value;
+  const T.eq(Object? o1, Object? o2) : value = o1 == o2;
+}
+
+/// Class that does not override operator==.
+class C {
+  const C();
+}
+
+/// Class that overrides operator==.
+class D {
+  const D();
+  bool operator ==(Object other) => identical(this, other);
+}
+
+enum E { value1, value2 }
diff --git a/tests/language/constants_2018/potential_const_dynamic_test.dart b/tests/language/constants_2018/potential_const_dynamic_test.dart
new file mode 100644
index 0000000..90de32f
--- /dev/null
+++ b/tests/language/constants_2018/potential_const_dynamic_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.
+
+// Tests that a dynamic type does not affect whether an expression is
+// potentially constant, the actual type of the value of an experssion
+// only matters if the expression is evaluated as a constant.
+
+main() {
+  Object c = C();
+  T.test01(c);
+  T.test02(c, c);
+  T.test03(c, c);
+  T.test04(c, c);
+  T.test05(c, c);
+  T.test06(c, c);
+  T.test07(c, c);
+  T.test08(c, c);
+  T.test09(c, c);
+  T.test10(c, c); //# sh3: ok
+  T.test11(c, c);
+  T.test12(c, c);
+  T .test13(c, c);
+  T.test14(c);
+  T.test15(c, c);
+  T.test16(c, c);
+  T.test17(c, c);
+  T.test18(c, c);
+  T.test19(c);
+}
+
+class T {
+  const T(Object o);
+  const T.test01(dynamic x) : this(-x);
+  const T.test02(dynamic x, dynamic y) : this(x + y);
+  const T.test03(dynamic x, dynamic y) : this(x - y);
+  const T.test04(dynamic x, dynamic y) : this(x * y);
+  const T.test05(dynamic x, dynamic y) : this(x / y);
+  const T.test06(dynamic x, dynamic y) : this(x ~/ y);
+  const T.test07(dynamic x, dynamic y) : this(x % y);
+  const T.test08(dynamic x, dynamic y) : this(x << y);
+  const T.test09(dynamic x, dynamic y) : this(x >> y);
+  const T.test10(dynamic x, dynamic y) : this(x >>> y); //# sh3: continued
+  const T.test11(dynamic x, dynamic y) : this(x & y);
+  const T.test12(dynamic x, dynamic y) : this(x | y);
+  const T.test13(dynamic x, dynamic y) : this(x ^ y);
+  const T.test14(dynamic x) : this(~x);
+  const T.test15(dynamic x, dynamic y) : this(x < y);
+  const T.test16(dynamic x, dynamic y) : this(x > y);
+  const T.test17(dynamic x, dynamic y) : this(x <= y);
+  const T.test18(dynamic x, dynamic y) : this(x >= y);
+  const T.test19(dynamic x) : this(x.length);
+}
+
+class C {
+  const C();
+  dynamic operator -() => this;
+  dynamic operator +(dynamic other) => this;
+  dynamic operator -(dynamic other) => this;
+  dynamic operator *(dynamic other) => this;
+  dynamic operator /(dynamic other) => this;
+  dynamic operator ~/(dynamic other) => this;
+  dynamic operator %(dynamic other) => this;
+  dynamic operator <<(dynamic other) => this;
+  dynamic operator >>(dynamic other) => this;
+  dynamic operator >>>(dynamic other) => this; //# sh3: continued
+  dynamic operator &(dynamic other) => this;
+  dynamic operator |(dynamic other) => this;
+  dynamic operator ^(dynamic other) => this;
+  dynamic operator ~() => this;
+  dynamic operator <(dynamic other) => this;
+  dynamic operator >(dynamic other) => this;
+  dynamic operator <=(dynamic other) => this;
+  dynamic operator >=(dynamic other) => this;
+  dynamic get length => this;
+}
\ No newline at end of file
diff --git a/tests/language/constants_2018/potential_const_shortcircuit_test.dart b/tests/language/constants_2018/potential_const_shortcircuit_test.dart
new file mode 100644
index 0000000..2ce656c
--- /dev/null
+++ b/tests/language/constants_2018/potential_const_shortcircuit_test.dart
@@ -0,0 +1,57 @@
+// 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.
+
+// Tests that short-circuit operators do not care about the unevaluated part.
+
+import "package:expect/expect.dart";
+
+main() {
+  const c = C();
+  // Short-circuited operations.
+  // Non-taken branch of ?:.
+  const c1 = true ? c : c + c;
+  const c2 = false ? c + c : c;
+  // Non-taken part of &&, ||, ??.
+  const c3 = (c != null) || c < c;
+  const c4 = (c == null) && c < c;
+  const c5 = (c as dynamic) ?? c + c;
+  Expect.identical(c, c1);
+  Expect.identical(c, c2);
+  Expect.isTrue(c3);
+  Expect.isFalse(c4);
+  Expect.identical(c, c5);
+  // Nested short-circuiting.
+  const c6 = true ? c == null && c + c : c < c;
+  Expect.isFalse(c6);
+
+  // Concrete use-case.
+  Expect.equals(1, const T.length("a").value);
+  Expect.equals(0, const T.length("").value);
+  Expect.equals(0, const T.length(null).value);
+  Expect.equals(1, T.length([1]).value);
+  Expect.equals(0, T.length([]).value);
+  Expect.equals(0, T.length(null).value);
+
+  Expect.equals(1, const T.asserts("a").value);
+  Expect.equals(0, const T.asserts("").value);
+  Expect.equals(0, const T.asserts(null).value);
+  Expect.equals(1, T.asserts([1]).value);
+  Expect.equals(0, T.asserts([]).value);
+  Expect.equals(0, T.asserts(null).value);
+}
+
+class T {
+  final Object value;
+  const T(this.value);
+  const T.length(dynamic l) : value = (l == null ? 0 : l.length);
+  const T.asserts(dynamic l)
+      : assert(l == null || l.length < 2),
+        value = (l ?? "").length;
+}
+
+class C {
+  const C();
+  dynamic operator +(dynamic other) => throw "Never";
+  bool operator <(dynamic other) => throw "Never";
+}
diff --git a/tests/language/constants_2018/potential_const_type_test.dart b/tests/language/constants_2018/potential_const_type_test.dart
new file mode 100644
index 0000000..0f06507
--- /dev/null
+++ b/tests/language/constants_2018/potential_const_type_test.dart
@@ -0,0 +1,95 @@
+// 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.
+
+// Tests that types do not affect whether an expression is potentially
+// constant, they only matter if the expression is evaluated as a constant.
+
+main() {
+  const C c = C();
+  T.test01(c);
+  T.test02(c, c);
+  T.test03(c, c);
+  T.test04(c, c);
+  T.test05(c, c);
+  T.test06(c, c);
+  T.test07(c, c);
+  T.test08(c, c);
+  T.test09(c, c);
+  T.test10(c, c); //# sh3: ok
+  T.test11(c, c);
+  T.test12(c, c);
+  T.test13(c, c);
+  T.test14(c);
+  T.test15(c, c);
+  T.test16(c, c);
+  T.test17(c, c);
+  T.test18(c, c);
+  T.test19(c);
+
+  const v01 = true ? c : -c;
+  const v02 = true ? c : c + c;
+  const v03 = true ? c : c - c;
+  const v04 = true ? c : c * c;
+  const v05 = true ? c : c / c;
+  const v06 = true ? c : c ~/ c;
+  const v07 = true ? c : c % c;
+  const v08 = true ? c : c << c;
+  const v09 = true ? c : c >> c;
+  const v10 = true ? c : c >>> c; //# sh3: continued
+  const v11 = true ? c : c & c;
+  const v12 = true ? c : c | c;
+  const v13 = true ? c : c ^ c;
+  const v14 = true ? c : ~c;
+  const v15 = true ? c : c < c;
+  const v16 = true ? c : c > c;
+  const v17 = true ? c : c <= c;
+  const v18 = true ? c : c >= c;
+  const v19 = true ? c : c.length;
+}
+
+class T {
+  const T(C o);
+  const T.test01(C x) : this(-x);
+  const T.test02(C x, C y) : this(x + y);
+  const T.test03(C x, C y) : this(x - y);
+  const T.test04(C x, C y) : this(x * y);
+  const T.test05(C x, C y) : this(x / y);
+  const T.test06(C x, C y) : this(x ~/ y);
+  const T.test07(C x, C y) : this(x % y);
+  const T.test08(C x, C y) : this(x << y);
+  const T.test09(C x, C y) : this(x >> y);
+  const T.test10(C x, C y) : this(x >>> y); //# sh3: continued
+  const T.test11(C x, C y) : this(x & y);
+  const T.test12(C x, C y) : this(x | y);
+  const T.test13(C x, C y) : this(x ^ y);
+  const T.test14(C x) : this(~x);
+  const T.test15(C x, C y) : this(x < y);
+  const T.test16(C x, C y) : this(x > y);
+  const T.test17(C x, C y) : this(x <= y);
+  const T.test18(C x, C y) : this(x >= y);
+  const T.test19(C x) : this(x.length);
+}
+
+class C {
+  const C();
+  C operator -() => this;
+  C operator +(C other) => this;
+  C operator -(C other) => this;
+  C operator *(C other) => this;
+  C operator /(C other) => this;
+  C operator ~/(C other) => this;
+  C operator %(C other) => this;
+  C operator <<(C other) => this;
+  C operator >>(C other) => this;
+  C operator >>>(C other) => this; //# sh3: continued
+  C operator &(C other) => this;
+  C operator |(C other) => this;
+  C operator ^(C other) => this;
+  C operator ~() => this;
+  C operator <(C other) => this;
+  C operator >(C other) => this;
+  C operator <=(C other) => this;
+  C operator >=(C other) => this;
+  C get length => this;
+}
\ No newline at end of file
diff --git a/tests/language/constants_2018/type_cast_test.dart b/tests/language/constants_2018/type_cast_test.dart
new file mode 100644
index 0000000..679c2e2
--- /dev/null
+++ b/tests/language/constants_2018/type_cast_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+// Tests that type casts (as) are allowed.
+
+main() {
+  const t = T.explicit(Sub());
+
+  // Inline.
+  const Object o = "";
+  const len = (o as String).length;
+}
+
+class Super {
+  const Super();
+}
+
+class Sub extends Super {
+  const Sub();
+}
+
+class T {
+  final Sub value;
+  const T.explicit(Super s) : value = s as Sub;
+}
diff --git a/tests/language/constants_2018/type_check_test.dart b/tests/language/constants_2018/type_check_test.dart
new file mode 100644
index 0000000..7c7a318
--- /dev/null
+++ b/tests/language/constants_2018/type_check_test.dart
@@ -0,0 +1,41 @@
+// 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.
+
+// Tests that type checks (is) are allowed.
+
+import "package:expect/expect.dart";
+
+main() {
+  const c = C();
+  const l = [1];
+  const s = "a";
+
+  Expect.equals(1, const T.length(s, 42).value);
+  Expect.equals(42, const T.length(l, 42).value);
+  Expect.equals(1, const T.length2(s, 42).value);
+  Expect.equals(42, const T.length2(l, 42).value);
+
+  Expect.equals(3, const T.sum(1, 2).value);
+  Expect.equals(3.7, const T.sum(1.5, 2.2).value);
+  Expect.equals("abc", const T.sum("a", "bc").value);
+  Expect.equals("a", const T.sum("a", 2).value);
+}
+
+class T {
+  final Object value;
+  const T.length(dynamic l, int defaultValue)
+      : value = l is String ? l.length : defaultValue;
+  const T.length2(dynamic l, int defaultValue)
+      : value = l is! String ? defaultValue : l.length;
+  const T.sum(dynamic o1, dynamic o2)
+      : value = ((o1 is num) & (o2 is num)) | ((o1 is String) & (o2 is String))
+            ? o1 + o2
+            : o1;
+}
+
+class C {
+  const C();
+  dynamic operator +(dynamic other) => throw "Never";
+  bool operator <(dynamic other) => throw "Never";
+}
diff --git a/tests/language/constructor/bad_constructor_runtime_1_test.dart b/tests/language/constructor/bad_constructor_runtime_1_test.dart
new file mode 100644
index 0000000..cf8d562
--- /dev/null
+++ b/tests/language/constructor/bad_constructor_runtime_1_test.dart
@@ -0,0 +1,39 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// A constructor can't be static.
+class A {
+
+  A();
+}
+
+// A factory constructor can't be static.
+class B {
+
+  factory B() { return B._(); }
+
+  B._();
+}
+
+// A named constructor can have the same name as a setter.
+class E {
+  set setter(value) {}
+  E.setter();
+}
+
+// A constructor can't be static.
+class F {
+
+  F(){}
+}
+
+main() {
+  new A();
+  new B();
+  new E.setter();
+  new F();
+}
diff --git a/tests/language/constructor/bad_constructor_runtime_test.dart b/tests/language/constructor/bad_constructor_runtime_test.dart
new file mode 100644
index 0000000..71e14bd
--- /dev/null
+++ b/tests/language/constructor/bad_constructor_runtime_test.dart
@@ -0,0 +1,39 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// A constructor can't be static.
+class A {
+
+  A();
+}
+
+// A factory constructor can't be static.
+class B {
+
+  factory B() { return B._(); }
+
+  B._();
+}
+
+// A named constructor can have the same name as a setter.
+class E {
+
+  E.setter();
+}
+
+// A constructor can't be static.
+class F {
+
+  F(){}
+}
+
+main() {
+  new A();
+  new B();
+  new E.setter();
+  new F();
+}
diff --git a/tests/language/constructor/bad_constructor_test.dart b/tests/language/constructor/bad_constructor_test.dart
new file mode 100644
index 0000000..5cb42f6
--- /dev/null
+++ b/tests/language/constructor/bad_constructor_test.dart
@@ -0,0 +1,48 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// A constructor can't be static.
+class A {
+  static
+//^^^^^^
+// [analyzer] SYNTACTIC_ERROR.STATIC_CONSTRUCTOR
+// [cfe] Constructors can't be static.
+  A();
+  // ^
+  // [analyzer] SYNTACTIC_ERROR.MISSING_FUNCTION_BODY
+  // [cfe] Expected a function body or '=>'.
+}
+
+// A factory constructor can't be static.
+class B {
+  static
+//^^^^^^
+// [analyzer] SYNTACTIC_ERROR.EXTRANEOUS_MODIFIER
+// [cfe] Can't have modifier 'static' here.
+  factory B() { return B._(); }
+
+  B._();
+}
+
+// A named constructor can have the same name as a setter.
+class E {
+  set setter(value) {}
+  E.setter();
+}
+
+// A constructor can't be static.
+class F {
+  static
+//^^^^^^
+// [analyzer] SYNTACTIC_ERROR.STATIC_CONSTRUCTOR
+// [cfe] Constructors can't be static.
+  F(){}
+}
+
+main() {
+  new A();
+  new B();
+  new E.setter();
+  new F();
+}
diff --git a/tests/language/constructor/bad_named_constructor_runtime_test.dart b/tests/language/constructor/bad_named_constructor_runtime_test.dart
new file mode 100644
index 0000000..c84de90
--- /dev/null
+++ b/tests/language/constructor/bad_named_constructor_runtime_test.dart
@@ -0,0 +1,15 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class A {
+  A() {}
+
+}
+
+main() {
+  new A();
+}
diff --git a/tests/language/constructor/bad_named_constructor_test.dart b/tests/language/constructor/bad_named_constructor_test.dart
new file mode 100644
index 0000000..d8a40d9
--- /dev/null
+++ b/tests/language/constructor/bad_named_constructor_test.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.
+
+class A {
+  A() {}
+  WrongName.foo() {}
+//^^^^^^^^^
+// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTRUCTOR_NAME
+// [cfe] The name of a constructor must match the name of the enclosing class.
+}
+
+main() {
+  new A();
+}
diff --git a/tests/language/constructor/body_test.dart b/tests/language/constructor/body_test.dart
new file mode 100644
index 0000000..d64d61f
--- /dev/null
+++ b/tests/language/constructor/body_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors without function bodies.
+
+import "package:expect/expect.dart";
+
+// Test a non-const constructor works without a body.
+class First {
+  First(int this.value);
+  First.named(int this.value);
+  int value;
+}
+
+// Test a const constructor works without a body.
+class Second {
+  const Second(int this.value);
+  const Second.named(int this.value);
+  final int value;
+}
+
+class ConstructorBodyTest {
+  static testMain() {
+    Expect.equals(4, new First(4).value);
+    Expect.equals(5, new First.named(5).value);
+    Expect.equals(6, new Second(6).value);
+    Expect.equals(7, new Second.named(7).value);
+  }
+}
+
+main() {
+  ConstructorBodyTest.testMain();
+}
diff --git a/tests/language/constructor/bodyless_wrong_arg_runtime_test.dart b/tests/language/constructor/bodyless_wrong_arg_runtime_test.dart
new file mode 100644
index 0000000..6a6c07e
--- /dev/null
+++ b/tests/language/constructor/bodyless_wrong_arg_runtime_test.dart
@@ -0,0 +1,25 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Base {
+  final String name;
+  const Base(this.name);
+}
+
+class C extends Base {
+  const C(String s)
+      : super(
+        // Call super constructor with wrong argument count.
+
+        s
+
+        );
+}
+
+main() {
+  const C("str");
+}
diff --git a/tests/language/constructor/bodyless_wrong_arg_test.dart b/tests/language/constructor/bodyless_wrong_arg_test.dart
new file mode 100644
index 0000000..4e669d0
--- /dev/null
+++ b/tests/language/constructor/bodyless_wrong_arg_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+class Base {
+  final String name;
+  const Base(this.name);
+}
+
+class C extends Base {
+  const C(String s)
+      // Call super constructor with wrong argument count.
+      : super();
+      //     ^^
+      // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
+      // [cfe] Too few positional arguments: 1 required, 0 given.
+}
+
+main() {
+  const C("str");
+}
diff --git a/tests/language/constructor/call_as_function_test.dart b/tests/language/constructor/call_as_function_test.dart
new file mode 100644
index 0000000..cb1dbda
--- /dev/null
+++ b/tests/language/constructor/call_as_function_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 Point {
+  const Point(this.x, this.y);
+  final int x;
+  final int y;
+}
+
+main() {
+  Point p = Point(1, 2);
+}
diff --git a/tests/language/constructor/call_wrong_argument_count_runtime_test.dart b/tests/language/constructor/call_wrong_argument_count_runtime_test.dart
new file mode 100644
index 0000000..adb20bd
--- /dev/null
+++ b/tests/language/constructor/call_wrong_argument_count_runtime_test.dart
@@ -0,0 +1,15 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 Stockhorn {
+  Stockhorn(int a);
+}
+
+main() {
+  new Stockhorn(1);
+
+}
diff --git a/tests/language/constructor/call_wrong_argument_count_test.dart b/tests/language/constructor/call_wrong_argument_count_test.dart
new file mode 100644
index 0000000..4830bcd
--- /dev/null
+++ b/tests/language/constructor/call_wrong_argument_count_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 Stockhorn {
+  Stockhorn(int a);
+}
+
+main() {
+  new Stockhorn(1);
+  new Stockhorn();
+  //           ^^
+  // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
+  // [cfe] Too few positional arguments: 1 required, 0 given.
+}
diff --git a/tests/language/constructor/constructor10_runtime_test.dart b/tests/language/constructor/constructor10_runtime_test.dart
new file mode 100644
index 0000000..554c0e1
--- /dev/null
+++ b/tests/language/constructor/constructor10_runtime_test.dart
@@ -0,0 +1,47 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Check that the implicit super call for synthetic constructors are checked.
+
+class A {
+  final x;
+  A(this.x);
+}
+
+class B extends A {
+
+  B() : super(null);
+
+}
+
+// ==========
+
+class Y extends A {
+
+  Y() : super(null);
+
+}
+
+class Z extends Y {
+  Z() : super();
+}
+
+// ==============
+
+class G extends A {
+
+  G() : super(null);
+
+}
+
+class H extends G {}
+
+main() {
+  new B().x;
+  new Z().x;
+  new H().x;
+}
diff --git a/tests/language/constructor/constructor10_test.dart b/tests/language/constructor/constructor10_test.dart
new file mode 100644
index 0000000..06426fb
--- /dev/null
+++ b/tests/language/constructor/constructor10_test.dart
@@ -0,0 +1,53 @@
+// 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.
+
+// Check that the implicit super call for synthetic constructors are checked.
+
+class A {
+  final x;
+  A(this.x);
+}
+
+class B extends A {
+//    ^
+// [analyzer] COMPILE_TIME_ERROR.NO_DEFAULT_SUPER_CONSTRUCTOR
+// [cfe] The superclass, 'A', has no unnamed constructor that takes no arguments.
+  /*
+  B() : super(null);
+  */
+}
+
+// ==========
+
+class Y extends A {
+//    ^
+// [analyzer] COMPILE_TIME_ERROR.NO_DEFAULT_SUPER_CONSTRUCTOR
+// [cfe] The superclass, 'A', has no unnamed constructor that takes no arguments.
+  /*
+  Y() : super(null);
+  */
+}
+
+class Z extends Y {
+  Z() : super();
+}
+
+// ==============
+
+class G extends A {
+//    ^
+// [analyzer] COMPILE_TIME_ERROR.NO_DEFAULT_SUPER_CONSTRUCTOR
+// [cfe] The superclass, 'A', has no unnamed constructor that takes no arguments.
+  /*
+  G() : super(null);
+  */
+}
+
+class H extends G {}
+
+main() {
+  new B().x;
+  new Z().x;
+  new H().x;
+}
diff --git a/tests/language/constructor/constructor11_test.dart b/tests/language/constructor/constructor11_test.dart
new file mode 100644
index 0000000..73d08a3
--- /dev/null
+++ b/tests/language/constructor/constructor11_test.dart
@@ -0,0 +1,44 @@
+// 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.
+
+// Check that the implicit super call for synthetic constructors are checked.
+
+import "package:expect/expect.dart";
+
+class A {
+  final x;
+  A([this.x = 499]);
+}
+
+class B extends A {}
+
+// ==========
+
+class X {
+  final x;
+  X([this.x = 42]);
+}
+
+class Y extends X {}
+
+class Z extends Y {
+  Z() : super();
+}
+
+// ==============
+
+class F {
+  final x;
+  F([this.x = 99]);
+}
+
+class G extends F {}
+
+class H extends G {}
+
+main() {
+  Expect.equals(499, new B().x);
+  Expect.equals(42, new Z().x);
+  Expect.equals(99, new H().x);
+}
diff --git a/tests/language/constructor/constructor12_test.dart b/tests/language/constructor/constructor12_test.dart
new file mode 100644
index 0000000..477955c
--- /dev/null
+++ b/tests/language/constructor/constructor12_test.dart
@@ -0,0 +1,69 @@
+// 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:expect/expect.dart";
+
+class B {
+  final z;
+  B(this.z);
+
+  foo() => this.z;
+}
+
+class A<T> extends B {
+  var captured, captured2;
+  var typedList;
+
+  // p must be inside a box (in dart2js).
+  A(p)
+      : captured = (() => p),
+        super(p++) {
+    // Make constructor body non-inlinable.
+    try {} catch (e) {}
+
+    captured2 = () => p++;
+
+    // In the current implementation of dart2js makes the generic type an
+    // argument to the body.
+    typedList = <T>[];
+  }
+
+  foo() => captured();
+  bar() => captured2();
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+main() {
+  var a = confuse(new A<int>(1));
+  var a2 = confuse(new A(2));
+  var b = confuse(new B(3));
+  Expect.equals(2, a.foo());
+  Expect.equals(3, a2.foo());
+  Expect.equals(3, b.foo());
+  Expect.equals(1, a.z);
+  Expect.equals(2, a2.z);
+  Expect.equals(3, b.z);
+  Expect.isTrue(a is A<int>);
+  Expect.isFalse(a is A<String>);
+  Expect.isFalse(a2 is A<int>);
+  Expect.isFalse(a2 is A<String>);
+  Expect.isFalse(a2 is A<Object>);
+  Expect.isTrue(a2 is A<Object?>);
+  Expect.equals(2, a.bar());
+  Expect.equals(3, a2.bar());
+  Expect.equals(3, a.foo());
+  Expect.equals(4, a2.foo());
+  Expect.equals(0, a.typedList.length);
+  Expect.equals(0, a2.typedList.length);
+  a.typedList.add(499);
+  Expect.equals(1, a.typedList.length);
+  Expect.equals(0, a2.typedList.length);
+  Expect.isTrue(a.typedList is List<int>);
+  Expect.isFalse(a2.typedList is List<int>);
+  Expect.isFalse(a.typedList is List<String>);
+  Expect.isFalse(a2.typedList is List<String>);
+}
diff --git a/tests/language/constructor/constructor13_runtime_test.dart b/tests/language/constructor/constructor13_runtime_test.dart
new file mode 100644
index 0000000..e2ff3b6
--- /dev/null
+++ b/tests/language/constructor/constructor13_runtime_test.dart
@@ -0,0 +1,19 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Check that there's no crash when constructor called with wrong
+// number of args.
+
+class Klass {
+  Klass(v) {}
+}
+
+main() {
+
+  new Klass(1);
+
+}
diff --git a/tests/language/constructor/constructor13_test.dart b/tests/language/constructor/constructor13_test.dart
new file mode 100644
index 0000000..f6790ec
--- /dev/null
+++ b/tests/language/constructor/constructor13_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that there's no crash when constructor called with wrong
+// number of args.
+
+class Klass {
+  Klass(v) {}
+}
+
+main() {
+  new Klass();
+  //       ^^
+  // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
+  // [cfe] Too few positional arguments: 1 required, 0 given.
+  new Klass(1);
+  new Klass(1, 2);
+  //       ^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  // [cfe] Too many positional arguments: 1 allowed, but 2 found.
+}
diff --git a/tests/language/constructor/constructor2_test.dart b/tests/language/constructor/constructor2_test.dart
new file mode 100644
index 0000000..97dd7de
--- /dev/null
+++ b/tests/language/constructor/constructor2_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors and initializers.
+
+import "package:expect/expect.dart";
+
+// Expect the initializer expressions E(i) to be evaluated
+// in the order 1, 2, 3, ...
+// Each expression must be evaluated exactly once.
+
+String trace = "";
+
+int E(int i) {
+  trace += "$i-";
+  return i;
+}
+
+class A {
+  var a1;
+  A(x, y) : a1 = E(4) {
+    Expect.equals(2, x);
+    Expect.equals(3, y);
+    Expect.equals(4, a1);
+    E(6);
+  }
+}
+
+class B extends A {
+  var b1, b2;
+
+  B(x)
+      : b1 = E(1),
+        b2 = E(5),
+        super(E(2), E(3)) {
+    Expect.equals(1, b1);
+    Expect.equals(5, b2);
+    E(7);
+  }
+}
+
+main() {
+  var b = new B(0);
+  Expect.equals("1-5-2-3-4-6-7-", trace);
+}
diff --git a/tests/language/constructor/constructor3_test.dart b/tests/language/constructor/constructor3_test.dart
new file mode 100644
index 0000000..4bb7173
--- /dev/null
+++ b/tests/language/constructor/constructor3_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors and initializers.
+
+import "package:expect/expect.dart";
+
+// Expect the initializer expressions E(i) to be evaluated
+// in the order 1, 2, 3, ...
+// Each expression must be evaluated exactly once.
+
+String trace = "";
+
+int E(int i) {
+  trace += "$i-";
+  return i;
+}
+
+class A {
+  var a1;
+  A(x, y) : a1 = E(3) {
+    Expect.equals(1, x);
+    Expect.equals(2, y);
+    E(5);
+  }
+}
+
+class B extends A {
+  var b1;
+  B(x)
+      : b1 = E(4),
+        super(E(1), E(2)) {
+    // Implicit super call to A's body happens here.
+    Expect.equals(4, b1);
+    E(6);
+  }
+}
+
+main() {
+  var b = new B(0);
+  Expect.equals("4-1-2-3-5-6-", trace);
+}
diff --git a/tests/language/constructor/constructor4_test.dart b/tests/language/constructor/constructor4_test.dart
new file mode 100644
index 0000000..b4df9b0
--- /dev/null
+++ b/tests/language/constructor/constructor4_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors and initializers.
+
+import "package:expect/expect.dart";
+
+// Expect the initializer expressions E(i) to be evaluated
+// in the order 1, 2, 3, ...
+// Each expression must be evaluated exactly once.
+
+String trace = "";
+
+int E(int i) {
+  trace += "$i-";
+  return i;
+}
+
+class A {
+  var a1;
+  A() : a1 = E(2) {
+    E(3);
+  }
+}
+
+class B extends A {
+  var b1;
+  B(x) : b1 = E(1) /* Implicit super call to A's initializers happens here. */ {
+    // Implicit super call to A's body happens here.
+    E(4);
+  }
+}
+
+main() {
+  var b = new B(0);
+  Expect.equals("1-2-3-4-", trace);
+}
diff --git a/tests/language/constructor/constructor5_test.dart b/tests/language/constructor/constructor5_test.dart
new file mode 100644
index 0000000..52020cf
--- /dev/null
+++ b/tests/language/constructor/constructor5_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors and initializers.
+
+import "package:expect/expect.dart";
+
+// Super initializer and super constructor body are executed in with the same
+// bindings.
+
+String trace = "";
+
+int E(int i) {
+  trace = "$trace$i-";
+  return i;
+}
+
+class A {
+  A({arg1: 100, arg2: 200})
+      : a1 = E(arg1++),
+        a2 = E(arg2++) {
+    // b2 should be initialized between the above initializers and the following
+    // statements.
+    E(arg1); // 101
+    E(arg2); // 51
+  }
+  var a1;
+  var a2;
+}
+
+class B extends A {
+  // Initializers in order: b1, super, b2.
+  B(x, y)
+      : b1 = E(x++),
+        b2 = E(y++),
+        super(arg2: 50) {
+    // Implicit super call to A's body happens here.
+    E(x); // 11
+    E(y); // 21
+  }
+  var b1;
+  var b2;
+}
+
+class C extends B {
+  C() : super(10, 20);
+}
+
+main() {
+  var c = new C();
+  Expect.equals(100, c.a1);
+  Expect.equals(50, c.a2);
+  Expect.equals(10, c.b1);
+  Expect.equals(20, c.b2);
+
+  Expect.equals("10-20-100-50-101-51-11-21-", trace);
+}
diff --git a/tests/language/constructor/constructor6_test.dart b/tests/language/constructor/constructor6_test.dart
new file mode 100644
index 0000000..71f6c38
--- /dev/null
+++ b/tests/language/constructor/constructor6_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors and initializers.
+
+import "package:expect/expect.dart";
+
+// Super initializer and super constructor body are executed in with the same
+// bindings.
+
+String trace = "";
+
+int E(int i) {
+  trace = "$trace$i-";
+  return i;
+}
+
+class A {
+  // f closes-over arg.  arg needs to be preserved while b2 is initialized.
+  A(arg)
+      : a = E(arg += 1),
+        f = (() => E(arg += 10)) {
+    // b2 should be initialized between the above initializers and the following
+    // statements.
+    var r1 = f();
+    E(arg += 100); // If this is the same arg as closed by f, ...
+    var r2 = f(); //  .. the effect of +=100 will be seen here.
+  }
+  final a;
+  final f;
+}
+
+class B extends A {
+  // Initializers in order: b1, super, b2.
+  B(x, y)
+      : b1 = E(x++),
+        b2 = E(y++),
+        super(1000) {
+    // Implicit super call to A's body happens here.
+    E(x);
+    E(y);
+    f();
+  }
+  var b1;
+  var b2;
+}
+
+class C extends B {
+  C() : super(10, 20);
+}
+
+main() {
+  var c = new C();
+  Expect.equals("10-20-1001-1011-1111-1121-11-21-1131-", trace);
+}
diff --git a/tests/language/constructor/constructor7_test.dart b/tests/language/constructor/constructor7_test.dart
new file mode 100644
index 0000000..5ed7be4
--- /dev/null
+++ b/tests/language/constructor/constructor7_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors and initializers.
+
+import "package:expect/expect.dart";
+
+// Expect the initializer expressions E(i) to be evaluated
+// in the order 1, 2, 3, ...
+// This test has no inheritance but many fields to flush out issues with
+// ordering of fields.
+
+String trace = "";
+
+int E(int i) {
+  trace += "$i-";
+  return i;
+}
+
+class A {
+  var j; //      Names are in reverse order to detect sorting by name...
+  var i = 0; //  Initialized odd/even to detect these inits affecting order.
+  var h;
+  var g = 0;
+  var f;
+  var e = 0;
+  var d;
+  var c = 0;
+  var b;
+  var a = 0;
+
+  A()
+      : a = E(1), // Initializations in different order to decls.  Ascending...
+        b = E(2),
+        c = E(3),
+        f = E(4), // Descending to be perverse...
+        e = E(5),
+        d = E(6),
+        g = E(7), // Ascending again.
+        h = E(8),
+        i = E(9),
+        j = E(10) {
+    Expect.equals(1, a);
+    Expect.equals(2, b);
+    Expect.equals(3, c);
+
+    Expect.equals(4, f);
+    Expect.equals(5, e);
+    Expect.equals(6, d);
+
+    Expect.equals(7, g);
+    Expect.equals(8, h);
+    Expect.equals(9, i);
+    Expect.equals(10, j);
+  }
+}
+
+main() {
+  var x = new A();
+  Expect.equals('1-2-3-4-5-6-7-8-9-10-', trace);
+}
diff --git a/tests/language/constructor/constructor8_test.dart b/tests/language/constructor/constructor8_test.dart
new file mode 100644
index 0000000..2de31c4
--- /dev/null
+++ b/tests/language/constructor/constructor8_test.dart
@@ -0,0 +1,28 @@
+// 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 "package:expect/expect.dart";
+
+// Regression test for dart2js that used to crash on this program.
+
+class A {
+  var b;
+
+  // The closure in the constructor body used to confuse the SSA builder
+  // when it created the call to the constructor body.
+  A.withClosure(Map? a) {
+    var c;
+    var f = () {
+      return c = 42;
+    };
+    b = f();
+    Expect.equals(42, b);
+    Expect.equals(42, c);
+  }
+}
+
+main() {
+  new A.withClosure(null);
+  new A.withClosure({});
+}
diff --git a/tests/language/constructor/constructor9_runtime_test.dart b/tests/language/constructor/constructor9_runtime_test.dart
new file mode 100644
index 0000000..fcdbf5a
--- /dev/null
+++ b/tests/language/constructor/constructor9_runtime_test.dart
@@ -0,0 +1,19 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that all final instance fields of a class are initialized by
+// constructors.
+
+class Klass {
+  Klass(var v) : field_ = v {}
+
+  var field_;
+}
+
+main() {
+  new Klass(5);
+}
diff --git a/tests/language/constructor/constructor9_test.dart b/tests/language/constructor/constructor9_test.dart
new file mode 100644
index 0000000..4c7b35d
--- /dev/null
+++ b/tests/language/constructor/constructor9_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that all final instance fields of a class are initialized by
+// constructors.
+
+class Klass {
+  Klass(var v) : field_ = v {}
+//^^^^^
+// [analyzer] STATIC_WARNING.FINAL_NOT_INITIALIZED_CONSTRUCTOR
+  final uninitializedFinalField_;
+  //    ^
+  // [cfe] Final field 'uninitializedFinalField_' is not initialized.
+  final uninitializedFinalField_;
+  //    ^^^^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+  // [cfe] 'uninitializedFinalField_' is already declared in this scope.
+  var field_;
+}
+
+main() {
+  new Klass(5);
+}
diff --git a/tests/language/constructor/constructor_test.dart b/tests/language/constructor/constructor_test.dart
new file mode 100644
index 0000000..17c3842
--- /dev/null
+++ b/tests/language/constructor/constructor_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for constructors and initializers.
+
+import "package:expect/expect.dart";
+
+class A extends B {
+  A(x, y)
+      : a = x,
+        super(y) {}
+
+  var a;
+}
+
+class B {
+  var b;
+
+  B(x) : b = x {}
+
+  B.namedB(var x) : b = x {}
+}
+
+// Test the order of initialization: first the instance variable then
+// the super constructor.
+abstract class Alpha {
+  Alpha(v) {
+    this.foo(v);
+  }
+  foo(v) => throw 'Alpha.foo should never be called.';
+}
+
+class Beta extends Alpha {
+  Beta(v)
+      : b = 1,
+        super(v) {}
+
+  foo(v) {
+    // Check that 'b' was initialized.
+    Expect.equals(1, b);
+    b = v;
+  }
+
+  var b;
+}
+
+class ConstructorTest {
+  static testMain() {
+    var o = new A(10, 2);
+    Expect.equals(10, o.a);
+    Expect.equals(2, o.b);
+
+    var o1 = new B.namedB(10);
+    Expect.equals(10, o1.b);
+
+    Expect.equals(22, o.a + o.b + o1.b);
+
+    var beta = new Beta(3);
+    Expect.equals(3, beta.b);
+  }
+}
+
+main() {
+  ConstructorTest.testMain();
+}
diff --git a/tests/language/constructor/cyclic_constructor_test.dart b/tests/language/constructor/cyclic_constructor_test.dart
new file mode 100644
index 0000000..1b2533f
--- /dev/null
+++ b/tests/language/constructor/cyclic_constructor_test.dart
@@ -0,0 +1,23 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  A.a() : this.b();
+  //      ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
+  A.b()
+    : this.a()
+    //^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
+    //     ^
+    // [cfe] Redirecting constructors can't be cyclic.
+  ;
+  A.c() : this.b();
+}
+
+main() {
+  new A.a();
+  new A.b();
+  new A.c();
+}
diff --git a/tests/language/constructor/cyclic_runtime_test.dart b/tests/language/constructor/cyclic_runtime_test.dart
new file mode 100644
index 0000000..b0cf8aff
--- /dev/null
+++ b/tests/language/constructor/cyclic_runtime_test.dart
@@ -0,0 +1,20 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  A.a() : this.b();
+  A.b()
+
+  ;
+  A.c() : this.b();
+}
+
+main() {
+  new A.a();
+  new A.b();
+  new A.c();
+}
diff --git a/tests/language/constructor/default_class_implicit_constructor_test.dart b/tests/language/constructor/default_class_implicit_constructor_test.dart
new file mode 100644
index 0000000..30d48a5
--- /dev/null
+++ b/tests/language/constructor/default_class_implicit_constructor_test.dart
@@ -0,0 +1,20 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// An abstract class with a redirecting factory to a class with no declared
+// constructor should use the implicit default constructor.
+
+abstract class A {
+  factory A() = B;
+}
+
+class B implements A {}
+
+main() {
+  var val = new A();
+  Expect.equals(true, val is A);
+  Expect.equals(true, val is B);
+}
diff --git a/tests/language/constructor/default_factory2_runtime_test.dart b/tests/language/constructor/default_factory2_runtime_test.dart
new file mode 100644
index 0000000..2113b80
--- /dev/null
+++ b/tests/language/constructor/default_factory2_runtime_test.dart
@@ -0,0 +1,24 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Check type bounds when invoking a redirecting factory method
+
+abstract class Foo {}
+
+abstract class IA<T> {
+
+}
+
+class A<T extends Foo> implements IA<T> {
+  factory A() { return A._(); }
+
+  A._();
+}
+
+main() {
+
+}
diff --git a/tests/language/constructor/default_factory2_test.dart b/tests/language/constructor/default_factory2_test.dart
new file mode 100644
index 0000000..a8b56b8
--- /dev/null
+++ b/tests/language/constructor/default_factory2_test.dart
@@ -0,0 +1,27 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Check type bounds when invoking a redirecting factory method
+
+abstract class Foo {}
+
+abstract class IA<T> {
+  factory IA() = A<T>;
+  //             ^
+  // [cfe] The type 'T' doesn't extend 'Foo'.
+  //               ^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+}
+
+class A<T extends Foo> implements IA<T> {
+  factory A() { return A._(); }
+
+  A._();
+}
+
+main() {
+  var result = new IA<String>();
+  //               ^
+  // [cfe] Type argument 'String' doesn't conform to the bound 'Foo' of the type variable 'T' on 'A'.
+}
diff --git a/tests/language/constructor/default_factory3_test.dart b/tests/language/constructor/default_factory3_test.dart
new file mode 100644
index 0000000..58d89b9
--- /dev/null
+++ b/tests/language/constructor/default_factory3_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Check possibly still unresolved upper bounds of default factory class.
+
+abstract class A<T extends Foo> {
+  factory A() = _AImpl<T>;
+}
+
+class Moo extends Foo {}
+
+class Foo extends Bar {}
+
+class Bar {}
+
+class _AImpl<T extends Foo> implements A<T> {
+  factory _AImpl() { return _AImpl._(); }
+
+  _AImpl._();
+}
+
+main() {
+  var result = new A<Moo>();
+}
diff --git a/tests/language/constructor/default_factory_library.dart b/tests/language/constructor/default_factory_library.dart
new file mode 100644
index 0000000..a7cd293
--- /dev/null
+++ b/tests/language/constructor/default_factory_library.dart
@@ -0,0 +1,15 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Dart test program for testing default factories defined across libraries
+
+library lib;
+
+import "default_factory_library_test.dart" as test;
+
+// References a factory class in another library
+abstract class A {
+  factory A() = test.C.A;
+  int methodA();
+}
diff --git a/tests/language/constructor/default_factory_library_test.dart b/tests/language/constructor/default_factory_library_test.dart
new file mode 100644
index 0000000..d141456
--- /dev/null
+++ b/tests/language/constructor/default_factory_library_test.dart
@@ -0,0 +1,34 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Dart test program for testing factories defined across libraries
+
+library test;
+
+import "package:expect/expect.dart";
+import "default_factory_library.dart" as lib;
+
+class B implements lib.A, C {
+  int methodA() {
+    return 1;
+  }
+
+  int methodB() {
+    return 2;
+  }
+}
+
+abstract class C implements lib.A {
+  // Referenced from an abstract class in another library
+  factory C.A() {
+    return new B();
+  }
+}
+
+main() {
+  dynamic val = new lib.A();
+  Expect.equals(true, (val is B));
+  Expect.equals(1, val.methodA());
+  Expect.equals(2, val.methodB());
+}
diff --git a/tests/language/constructor/default_factory_runtime_test.dart b/tests/language/constructor/default_factory_runtime_test.dart
new file mode 100644
index 0000000..a12c7e5
--- /dev/null
+++ b/tests/language/constructor/default_factory_runtime_test.dart
@@ -0,0 +1,38 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test program for testing default factories.
+
+abstract class Vehicle {
+
+}
+
+class Bike implements Vehicle, GoogleOne {
+  Bike.redOne() {}
+}
+
+abstract class SpaceShip {
+  factory SpaceShip() = GoogleOne;
+}
+
+class GoogleOne implements SpaceShip {
+  GoogleOne.internal_() {}
+  factory GoogleOne() {
+    return new GoogleOne.internal_();
+  }
+  factory GoogleOne.Vehicle() {
+    return new Bike.redOne();
+  }
+}
+
+main() {
+  Expect.equals(true, (new Bike.redOne()) is Bike);
+  Expect.equals(true, (new SpaceShip()) is GoogleOne);
+
+}
diff --git a/tests/language/constructor/default_factory_test.dart b/tests/language/constructor/default_factory_test.dart
new file mode 100644
index 0000000..43a93e8
--- /dev/null
+++ b/tests/language/constructor/default_factory_test.dart
@@ -0,0 +1,38 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test program for testing default factories.
+
+abstract class Vehicle {
+  factory Vehicle() = GoogleOne.Vehicle;
+  //                  ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.REDIRECT_TO_INVALID_RETURN_TYPE
+  // [cfe] The constructor function type 'GoogleOne Function()' isn't a subtype of 'Vehicle Function()'.
+}
+
+class Bike implements Vehicle, GoogleOne {
+  Bike.redOne() {}
+}
+
+abstract class SpaceShip {
+  factory SpaceShip() = GoogleOne;
+}
+
+class GoogleOne implements SpaceShip {
+  GoogleOne.internal_() {}
+  factory GoogleOne() {
+    return new GoogleOne.internal_();
+  }
+  factory GoogleOne.Vehicle() {
+    return new Bike.redOne();
+  }
+}
+
+main() {
+  Expect.equals(true, (new Bike.redOne()) is Bike);
+  Expect.equals(true, (new SpaceShip()) is GoogleOne);
+  var ensureItsCalled = new Vehicle();
+}
diff --git a/tests/language/constructor/default_test.dart b/tests/language/constructor/default_test.dart
new file mode 100644
index 0000000..aae9c52
--- /dev/null
+++ b/tests/language/constructor/default_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for default constructors.
+
+import "package:expect/expect.dart";
+
+class A {
+  A() : a = 499;
+
+  var a;
+}
+
+class B extends A {
+  B() {
+    Expect.equals(499, a);
+  }
+}
+
+main() {
+  new B();
+}
diff --git a/tests/language/constructor/duplicate_final_test.dart b/tests/language/constructor/duplicate_final_test.dart
new file mode 100644
index 0000000..96c1d22
--- /dev/null
+++ b/tests/language/constructor/duplicate_final_test.dart
@@ -0,0 +1,23 @@
+// 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.
+
+// Check that duplicate initialization of a final field is a runtime error.
+
+class Class {
+  final f = 10;
+
+  Class(v) : f = v; //# 01: compile-time error
+
+  Class(this.f); //# 02: compile-time error
+
+  // If a field is initialized multiple times in the initializer
+  // list, it's a compile time error.
+  Class(this.f) : f = 0; //# 03: compile-time error
+}
+
+main() {
+  new Class(5); //# 01: continued
+  new Class(5); //# 02: continued
+  new Class(5); //# 03: continued
+}
diff --git a/tests/language/constructor/duplicate_initializers_runtime_test.dart b/tests/language/constructor/duplicate_initializers_runtime_test.dart
new file mode 100644
index 0000000..94a3466
--- /dev/null
+++ b/tests/language/constructor/duplicate_initializers_runtime_test.dart
@@ -0,0 +1,32 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that initializers are not duplicated
+
+ class Class {
+   Class(var v) : field_ = v
+   // Test against duplicate final field initialization in initializing list.
+
+   ;
+   Class.field(this.field_)
+   // Test against duplicate final field initialization between initializing
+   // formals and initializer list.
+
+   ;
+   // Test against duplicate final field initialization in initializing formals.
+   Class.two_fields(this.field_
+
+       );
+   final field_;
+ }
+
+ main() {
+   new Class(42);
+   new Class.field(42);
+   new Class.two_fields(42
+
+       );
+ }
diff --git a/tests/language/constructor/duplicate_initializers_test.dart b/tests/language/constructor/duplicate_initializers_test.dart
new file mode 100644
index 0000000..1b4125a
--- /dev/null
+++ b/tests/language/constructor/duplicate_initializers_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 that initializers are not duplicated
+
+ class Class {
+   Class(var v) : field_ = v
+   // Test against duplicate final field initialization in initializing list.
+    , field_ = 2
+    //^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS
+    //       ^
+    // [cfe] 'field_' is a final instance variable that has already been initialized.
+   ;
+   Class.field(this.field_)
+   // Test against duplicate final field initialization between initializing
+   // formals and initializer list.
+    : field_ = 2
+    //^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER
+    //       ^
+    // [cfe] 'field_' is a final instance variable that has already been initialized.
+   ;
+   // Test against duplicate final field initialization in initializing formals.
+   Class.two_fields(this.field_
+    , this.field_
+    //     ^^^^^^
+    // [cfe] 'field_' is a final instance variable that has already been initialized.
+    //     ^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.FINAL_INITIALIZED_MULTIPLE_TIMES
+    // [cfe] Duplicated parameter name 'field_'.
+       );
+   final field_;
+ }
+
+ main() {
+   new Class(42);
+   new Class.field(42);
+   new Class.two_fields(42
+     , 42
+       );
+ }
diff --git a/tests/language/constructor/duplicate_runtime_test.dart b/tests/language/constructor/duplicate_runtime_test.dart
new file mode 100644
index 0000000..c65bc41
--- /dev/null
+++ b/tests/language/constructor/duplicate_runtime_test.dart
@@ -0,0 +1,15 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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();
+
+}
+
+main() {
+  new Foo();
+}
diff --git a/tests/language/constructor/duplicate_test.dart b/tests/language/constructor/duplicate_test.dart
new file mode 100644
index 0000000..80f717e
--- /dev/null
+++ b/tests/language/constructor/duplicate_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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();
+  Foo();
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.DUPLICATE_CONSTRUCTOR
+// [cfe] 'Foo' is already declared in this scope.
+}
+
+main() {
+  new Foo();
+  //  ^
+  // [cfe] Can't use 'Foo' because it is declared more than once.
+}
diff --git a/tests/language/constructor/evaluation_redirecting_constructor_test.dart b/tests/language/constructor/evaluation_redirecting_constructor_test.dart
new file mode 100644
index 0000000..6236c0a
--- /dev/null
+++ b/tests/language/constructor/evaluation_redirecting_constructor_test.dart
@@ -0,0 +1,26 @@
+// 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 "package:expect/expect.dart";
+
+int counter = 0;
+
+class Bar {
+  Bar() {
+    counter++;
+  }
+}
+
+class A {
+  var _bar = new Bar();
+  A() : this._();
+  A._() {
+    () => 42;
+  }
+}
+
+main() {
+  new A();
+  Expect.equals(1, counter);
+}
diff --git a/tests/language/constructor/example_constructor_test.dart b/tests/language/constructor/example_constructor_test.dart
new file mode 100644
index 0000000..f015b07
--- /dev/null
+++ b/tests/language/constructor/example_constructor_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test for testing order of constructor invocation.
+
+import "package:expect/expect.dart";
+
+var trace = "";
+
+int rec(int i) {
+  trace += "$i ";
+  return i;
+}
+
+class A {
+  A(int x) : x = rec(4) {
+    Expect.equals(3, x); // Parameter x
+    Expect.equals(4, this.x);
+    rec(5);
+  }
+  final int x;
+}
+
+class B extends A {
+  B(this.a, int y, int z)
+      : z = rec(1),
+        y = rec(2),
+        super(rec(3)) {
+    rec(6);
+  }
+  int a;
+  int y;
+  int z;
+}
+
+main() {
+  var test = new B(rec(0), 0, 0);
+  Expect.equals(0, test.a);
+  Expect.equals(4, test.x);
+  Expect.equals(2, test.y);
+  Expect.equals(1, test.z);
+  Expect.equals("0 1 2 3 4 5 6 ", trace);
+}
diff --git a/tests/language/constructor/forwarding_factory_constructor_default_values_test.dart b/tests/language/constructor/forwarding_factory_constructor_default_values_test.dart
new file mode 100644
index 0000000..70738fe
--- /dev/null
+++ b/tests/language/constructor/forwarding_factory_constructor_default_values_test.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// Regression test for dart2js bug 18257: Properly infer types for forwarding
+// factory constructors with optional parameters with default values.
+
+main() {
+  A a = new A.a1();
+  a.test();
+}
+
+class A {
+  final bool condition;
+
+  A({this.condition: true});
+
+  factory A.a1({condition}) = _A1.boo;
+
+  test() {
+    if (condition != true) {
+      throw "FAILED";
+    }
+  }
+}
+
+class _A1 extends A {
+  _A1.boo({condition: true}) : super(condition: condition);
+}
diff --git a/tests/language/constructor/implicit_super_constructor_call_test.dart b/tests/language/constructor/implicit_super_constructor_call_test.dart
new file mode 100644
index 0000000..fca1a62
--- /dev/null
+++ b/tests/language/constructor/implicit_super_constructor_call_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.
+
+// This is a regression test for http://dartbug.com/22723.
+
+import "package:expect/expect.dart";
+
+class A {
+  final x;
+
+  @pragma('dart2js:noInline')
+  A({this.x: "foo"}) {
+    Expect.equals("foo", x.toString());
+  }
+}
+
+class C extends A {
+  C(foobar) {}
+}
+
+main() {
+  var c = new C(499);
+  Expect.equals("foo", c.x.toString());
+}
diff --git a/tests/language/constructor/implicit_super_constructor_test.dart b/tests/language/constructor/implicit_super_constructor_test.dart
new file mode 100644
index 0000000..2c31206
--- /dev/null
+++ b/tests/language/constructor/implicit_super_constructor_test.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 "package:expect/expect.dart";
+
+abstract class A {
+  int _x = 42;
+}
+
+abstract class B extends A {}
+
+class C extends B {
+  C() {}
+}
+
+main() {
+  // Regression test for https://github.com/dart-lang/sdk/issues/27421
+  Expect.equals(new C()._x, 42);
+}
diff --git a/tests/language/constructor/inference_super_constructor_call_test.dart b/tests/language/constructor/inference_super_constructor_call_test.dart
new file mode 100644
index 0000000..a95c185
--- /dev/null
+++ b/tests/language/constructor/inference_super_constructor_call_test.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// Regression test for dart2js's inferrer that used to not propagate
+// types given to generative constructors in super constructor calls.
+
+import "package:expect/expect.dart";
+
+class A {
+  final field;
+  A.full(this.field);
+}
+
+class B extends A {
+  // The following super call used to not be analyzed properly.
+  B.full(field) : super.full(field);
+}
+
+main() {
+  // Call [A.full] with an int to have the inferrer think [field] is
+  // always an int.
+  Expect.equals(84, new A.full(42).field + 42);
+  Expect.throwsNoSuchMethodError(() => new B.full(null).field + 42,);
+}
diff --git a/tests/language/constructor/initializer_test.dart b/tests/language/constructor/initializer_test.dart
new file mode 100644
index 0000000..4204885
--- /dev/null
+++ b/tests/language/constructor/initializer_test.dart
@@ -0,0 +1,43 @@
+// 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 "package:expect/expect.dart";
+
+class A {
+  var _x, _y;
+  A(x, [y = 10])
+      : _x = x++,
+        _y = y++ {
+    // Check that value of modified constructor parameters
+    // is remembered in the constructor body.
+    Expect.equals(x, _x + 1);
+    Expect.equals(y, _y + 1);
+  }
+}
+
+class B extends A {
+  var _a, _b;
+  // The super call in the middle of the initializer list conceptually
+  // forces two super call chains, one for initializer list and a second
+  // one for the constructor bodies.
+  B(a, b)
+      : _a = a++,
+        _b = b++,
+        super(a + b++) {
+    Expect.equals(a, _a + 1);
+    Expect.equals(b, _b + 2);
+    Expect.equals(a + (b - 2), _x - 1);
+  }
+}
+
+main() {
+  dynamic o = new B(3, 5);
+  Expect.equals(3, o._a);
+  Expect.equals(5, o._b);
+  Expect.equals(10, o._x);
+  Expect.equals(10, o._y);
+  o = new A(3);
+  Expect.equals(3, o._x);
+  Expect.equals(10, o._y);
+}
diff --git a/tests/language/constructor/missing_const_constructor_test.dart b/tests/language/constructor/missing_const_constructor_test.dart
new file mode 100644
index 0000000..123eccf
--- /dev/null
+++ b/tests/language/constructor/missing_const_constructor_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Test handling of unknown constructor in const expression.
+
+class GoodClass {
+  const GoodClass();
+}
+
+GoodClass? GOOD_CLASS
+    = const GoodClass() //# 01: ok
+    = const GoodClass.BAD_NAME() //# 02: compile-time error
+    = const GoodClass("bad arg") //# 03: compile-time error
+    ;
+
+const BadClass BAD_CLASS = const BadClass(); //# 04: compile-time error
+BadClass BAD_CLASS = const BadClass(); //# 05: compile-time error
+
+void main() {
+  try {
+    print(GOOD_CLASS);
+    print(BAD_CLASS); //# 04: continued
+    print(BAD_CLASS); //# 05: continued
+    print(const BadClass()); //# 06: compile-time error
+  } catch (e) {}
+}
diff --git a/tests/language/constructor/multiple_field_assignment_constructor_test.dart b/tests/language/constructor/multiple_field_assignment_constructor_test.dart
new file mode 100644
index 0000000..7292e80
--- /dev/null
+++ b/tests/language/constructor/multiple_field_assignment_constructor_test.dart
@@ -0,0 +1,52 @@
+// 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 "package:expect/expect.dart";
+import "../compiler_annotations.dart";
+
+var a = [null];
+
+class A {
+  var foo;
+  var bar;
+
+  @DontInline()
+  A() {
+    // Currently defeat inlining by using a closure.
+    bar = () => 42;
+    foo = 42;
+    foo = a[0];
+  }
+}
+
+class B {
+  var foo;
+  var bar;
+
+  @DontInline()
+  B() {
+    // Currently defeat inlining by using a closure.
+    bar = () => 42;
+    foo = 42;
+    foo = a[0];
+    if (false) foo = 42;
+  }
+}
+
+main() {
+  // Surround the call to [bar] by allocations of [A] and [B] to
+  // ensure their constructors get analyzed first.
+  new A();
+  new B();
+  bar();
+  new A();
+  new B();
+}
+
+@DontInline()
+bar() {
+  // Currently defeat inlining by using a closure.
+  Expect.throwsNoSuchMethodError(() => new A().foo + 42);
+  Expect.throwsNoSuchMethodError(() => new B().foo + 42);
+}
diff --git a/tests/language/constructor/name_clash_lib.dart b/tests/language/constructor/name_clash_lib.dart
new file mode 100644
index 0000000..ff52f3b
--- /dev/null
+++ b/tests/language/constructor/name_clash_lib.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.
+
+library lib;
+
+var global = 0;
+
+class A {
+  A() {
+    global += 10;
+    try {} catch (e) {} // no inline
+  }
+}
diff --git a/tests/language/constructor/name_clash_test.dart b/tests/language/constructor/name_clash_test.dart
new file mode 100644
index 0000000..e7681ef
--- /dev/null
+++ b/tests/language/constructor/name_clash_test.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.
+
+import 'package:expect/expect.dart';
+import 'name_clash_lib.dart' as lib;
+
+class A extends lib.A {
+  A() {
+    lib.global += 100;
+    try {} catch (e) {} // no inline
+  }
+}
+
+main() {
+  new A();
+  Expect.equals(110, lib.global);
+}
diff --git a/tests/language/constructor/name_test.dart b/tests/language/constructor/name_test.dart
new file mode 100644
index 0000000..43e764f
--- /dev/null
+++ b/tests/language/constructor/name_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+class Foo {
+  Bar.Foo(); //# 01: compile-time error
+  factory Bar(); //# 02: syntax error
+  factory Bar.Baz(); //# 03: syntax error
+}
+
+void main() {
+  new Foo();
+  new Foo.Foo(); //# 01: continued
+  new Foo.Baz(); //# 03: continued
+}
diff --git a/tests/language/constructor/named_arguments_test.dart b/tests/language/constructor/named_arguments_test.dart
new file mode 100644
index 0000000..854ae04
--- /dev/null
+++ b/tests/language/constructor/named_arguments_test.dart
@@ -0,0 +1,57 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for default constructors.
+
+import "package:expect/expect.dart";
+
+late String message;
+
+foo() {
+  message += 'foo';
+  return 1;
+}
+
+bar() {
+  message += 'bar';
+  return 2;
+}
+
+class X {
+  var i;
+  var j;
+  X({a: 'defa', b: 'defb'})
+      : this.i = a,
+        this.j = b;
+  X.foo() : this(b: 1, a: 2);
+  X.bar()
+      : this(
+                     1, // //# 01: compile-time error, runtime error
+            a: 2);
+  X.baz() : this(a: 1, b: 2);
+  X.qux() : this(b: 2);
+  X.hest() : this();
+  X.fisk() : this(b: bar(), a: foo());
+  X.naebdyr() : this(a: foo(), b: bar());
+}
+
+test(x, a, b) {
+  Expect.equals(x.i, a);
+  Expect.equals(x.j, b);
+}
+
+main() {
+  test(new X.foo(), 2, 1);
+  test(new X.bar(), 2, 'defb');
+  test(new X.baz(), 1, 2);
+  test(new X.qux(), 'defa', 2);
+  test(new X.hest(), 'defa', 'defb');
+
+  message = '';
+  new X.fisk();
+  Expect.equals('barfoo', message);
+
+  message = '';
+  new X.naebdyr();
+  Expect.equals('foobar', message);
+}
diff --git a/tests/language/constructor/named_constructor_test.dart b/tests/language/constructor/named_constructor_test.dart
new file mode 100644
index 0000000..915f147
--- /dev/null
+++ b/tests/language/constructor/named_constructor_test.dart
@@ -0,0 +1,104 @@
+// 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 named_constructor_test;
+
+import 'package:expect/expect.dart';
+import 'named_lib.dart' as prefix;
+
+class Class<T> {
+  final int value;
+  Class() : value = 0;
+  Class.named() : value = 1;
+}
+
+void main() {
+  Expect.equals(0, new Class().value);
+  Expect.equals(0, new Class<int>().value);
+
+  Expect.equals(1, new Class.named().value);
+  Expect.equals(1, new Class<int>.named().value);
+  // 'Class.named' is not a type:
+  new Class.named<int>().value;
+  //        ^
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //             ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+
+  // 'Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+  new Class<int>.named<int>().value;
+  //             ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+
+  new prefix.Class().value;
+  // 'prefix' is not a type:
+  new prefix<int>.Class().value;
+  //  ^^^^^^
+  // [analyzer] STATIC_WARNING.NEW_WITH_NON_TYPE
+  // [cfe] Method not found: 'prefix.Class'.
+  new prefix.Class<int>().value;
+  // 'prefix<int>.Class<int>' doesn't fit the grammar syntax T.id:
+  new prefix<int>.Class<int>().value;
+  //  ^^^^^^
+  // [analyzer] STATIC_WARNING.NEW_WITH_NON_TYPE
+  // [cfe] Method not found: 'prefix.Class'.
+  //              ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+
+  new prefix.Class.named().value;
+  // 'prefix<int>.Class.named' doesn't fit the grammar syntax T.id:
+  new prefix<int>.Class.named().value;
+  //  ^^^^^^
+  // [analyzer] STATIC_WARNING.NEW_WITH_NON_TYPE
+  // [cfe] Method not found: 'prefix.Class'.
+  //              ^^^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Expected '(' after this.
+
+
+  // 'prefix.Class<int>.named' doesn't fit the grammar syntax T.id:
+  new prefix.Class<int>.named().value;
+  // 'prefix.Class.named<int>' doesn't fit the grammar syntax T.id:
+  new prefix.Class.named<int>().value;
+  //               ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+
+  // 'prefix<int>.Class<int>' doesn't fit the grammar syntax T.id:
+  new prefix<int>.Class<int>.named().value;
+  //  ^^^^^^
+  // [analyzer] STATIC_WARNING.NEW_WITH_NON_TYPE
+  // [cfe] Method not found: 'prefix.Class'.
+  //              ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+
+
+  // 'prefix<int>.Class.named<int>' doesn't fit the grammar syntax T.id:
+  new prefix<int>.Class.named<int>().value;
+  //  ^^^^^^
+  // [analyzer] STATIC_WARNING.NEW_WITH_NON_TYPE
+  // [cfe] Method not found: 'prefix.Class'.
+  //              ^^^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Expected '(' after this.
+
+
+  // 'prefix.Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+  new prefix.Class<int>.named<int>().value;
+  //                    ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+
+  // 'prefix<int>.Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+  new prefix<int>.Class<int>.named<int>().value;
+  //  ^^^^^^
+  // [analyzer] STATIC_WARNING.NEW_WITH_NON_TYPE
+  // [cfe] Method not found: 'prefix.Class'.
+  //              ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+}
diff --git a/tests/language/constructor/named_lib.dart b/tests/language/constructor/named_lib.dart
new file mode 100644
index 0000000..210d54c
--- /dev/null
+++ b/tests/language/constructor/named_lib.dart
@@ -0,0 +1,11 @@
+// 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 named_constructor_lib;
+
+class Class<T> {
+  final int value;
+  Class() : value = 2;
+  Class.named() : value = 3;
+}
diff --git a/tests/language/constructor/named_runtime_test.dart b/tests/language/constructor/named_runtime_test.dart
new file mode 100644
index 0000000..815b05b
--- /dev/null
+++ b/tests/language/constructor/named_runtime_test.dart
@@ -0,0 +1,52 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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 named_constructor_test;
+
+import 'package:expect/expect.dart';
+import 'named_lib.dart' as prefix;
+
+class Class<T> {
+  final int value;
+  Class() : value = 0;
+  Class.named() : value = 1;
+}
+
+void main() {
+  Expect.equals(0, new Class().value);
+  Expect.equals(0, new Class<int>().value);
+
+  Expect.equals(1, new Class.named().value);
+  Expect.equals(1, new Class<int>.named().value);
+  // 'Class.named' is not a type:
+
+  // 'Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+
+
+  new prefix.Class().value;
+  // 'prefix' is not a type:
+
+  new prefix.Class<int>().value;
+  // 'prefix<int>.Class<int>' doesn't fit the grammar syntax T.id:
+
+
+  new prefix.Class.named().value;
+  // 'prefix<int>.Class.named' doesn't fit the grammar syntax T.id:
+
+  // 'prefix.Class<int>.named' doesn't fit the grammar syntax T.id:
+  new prefix.Class<int>.named().value;
+  // 'prefix.Class.named<int>' doesn't fit the grammar syntax T.id:
+
+  // 'prefix<int>.Class<int>' doesn't fit the grammar syntax T.id:
+
+  // 'prefix<int>.Class.named<int>' doesn't fit the grammar syntax T.id:
+
+  // 'prefix.Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+
+  // 'prefix<int>.Class<int>.named<int>' doesn't fit the grammar syntax T.id:
+
+}
diff --git a/tests/language/constructor/no_such_constructor_runtime_test.dart b/tests/language/constructor/no_such_constructor_runtime_test.dart
new file mode 100644
index 0000000..17ee996
--- /dev/null
+++ b/tests/language/constructor/no_such_constructor_runtime_test.dart
@@ -0,0 +1,14 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class A {
+  A();
+}
+
+main() {
+
+}
diff --git a/tests/language/constructor/no_such_constructor_test.dart b/tests/language/constructor/no_such_constructor_test.dart
new file mode 100644
index 0000000..b106273
--- /dev/null
+++ b/tests/language/constructor/no_such_constructor_test.dart
@@ -0,0 +1,14 @@
+// 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.
+
+class A {
+  A();
+}
+
+main() {
+  new A(42);
+  //   ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  // [cfe] Too many positional arguments: 0 allowed, but 1 found.
+}
diff --git a/tests/language/constructor/non_const_constructor_without_body_test.dart b/tests/language/constructor/non_const_constructor_without_body_test.dart
new file mode 100644
index 0000000..cd2005a
--- /dev/null
+++ b/tests/language/constructor/non_const_constructor_without_body_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 NonConstConstructorWithoutBodyTest {
+  int x = -1;
+
+  NonConstConstructorWithoutBodyTest();
+  NonConstConstructorWithoutBodyTest.named();
+  NonConstConstructorWithoutBodyTest.initializers() : x = 1;
+  NonConstConstructorWithoutBodyTest.parameters(int x) : x = x + 1;
+  NonConstConstructorWithoutBodyTest.fieldParameter(int this.x);
+  NonConstConstructorWithoutBodyTest.redirection() : this.initializers();
+
+  static testMain() {
+    Expect.equals(-1, new NonConstConstructorWithoutBodyTest().x);
+    Expect.equals(-1, new NonConstConstructorWithoutBodyTest.named().x);
+    Expect.equals(1, new NonConstConstructorWithoutBodyTest.initializers().x);
+    Expect.equals(2, new NonConstConstructorWithoutBodyTest.parameters(1).x);
+    Expect.equals(
+        2, new NonConstConstructorWithoutBodyTest.fieldParameter(2).x);
+    Expect.equals(1, new NonConstConstructorWithoutBodyTest.redirection().x);
+  }
+}
+
+main() {
+  NonConstConstructorWithoutBodyTest.testMain();
+}
diff --git a/tests/language/constructor/non_parameterized_factory2_test.dart b/tests/language/constructor/non_parameterized_factory2_test.dart
new file mode 100644
index 0000000..2833d06
--- /dev/null
+++ b/tests/language/constructor/non_parameterized_factory2_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Interface<T> {
+  factory Interface() = Factory<T>;
+  factory Interface.withArg(T value) = Factory<T>.withArg;
+}
+
+class Factory<T> implements Interface<T> {
+  factory Factory() {
+    return Factory._();
+  }
+
+  factory Factory.withArg(T value) {
+    return Factory._();
+  }
+
+  Factory._();
+}
+
+main() {
+  new Interface<int>();
+  new Interface<int>.withArg(4);
+}
diff --git a/tests/language/constructor/non_parameterized_factory_test.dart b/tests/language/constructor/non_parameterized_factory_test.dart
new file mode 100644
index 0000000..36cd6aa
--- /dev/null
+++ b/tests/language/constructor/non_parameterized_factory_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Interface<T> {
+  factory Interface() = Factory<T>;
+  factory Interface.withArg(T value) = Factory<T>.withArg;
+}
+
+class Factory<T> implements Interface<T> {
+  factory Factory() {
+    return Factory._();
+  }
+
+  factory Factory.withArg(T value) {
+    return Factory._();
+  }
+
+  Factory._();
+}
+
+main() {
+  new Interface();
+  new Interface.withArg(4);
+}
diff --git a/tests/language/constructor/redirect2_runtime_test.dart b/tests/language/constructor/redirect2_runtime_test.dart
new file mode 100644
index 0000000..f5216f6
--- /dev/null
+++ b/tests/language/constructor/redirect2_runtime_test.dart
@@ -0,0 +1,32 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Redirection constructors must not have a function body.
+
+class A {
+  var x;
+  A(this.x) {}
+
+  // Redirecting constructor must not have a function body.
+
+
+  // Redirecting constructor must not initialize any fields.
+
+
+  // Redirecting constructor must not have initializing formal parameters.
+
+
+  // Redirection constructors must not call super constructor.
+
+}
+
+main() {
+  new A(3);
+
+
+
+
+}
diff --git a/tests/language/constructor/redirect2_test.dart b/tests/language/constructor/redirect2_test.dart
new file mode 100644
index 0000000..0999747
--- /dev/null
+++ b/tests/language/constructor/redirect2_test.dart
@@ -0,0 +1,46 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Redirection constructors must not have a function body.
+
+class A {
+  var x;
+  A(this.x) {}
+
+  // Redirecting constructor must not have a function body.
+  A.illegalBody(x) : this(3) {}
+  //                         ^
+  // [analyzer] SYNTACTIC_ERROR.REDIRECTING_CONSTRUCTOR_WITH_BODY
+  // [cfe] Redirecting constructors can't have a body.
+
+  // Redirecting constructor must not initialize any fields.
+  A.illegalInit() : this(3), x = 5;
+  //                         ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
+  //                           ^
+  // [cfe] Can't have other initializers together with 'this'.
+
+  // Redirecting constructor must not have initializing formal parameters.
+  A.illegalFormal(this.x) : this(3);
+  //              ^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
+  //                   ^
+  // [cfe] Can't have other initializers together with 'this'.
+
+  // Redirection constructors must not call super constructor.
+  A.illegalSuper() : this(3), super(3);
+  //                          ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.SUPER_IN_REDIRECTING_CONSTRUCTOR
+  // [cfe] Can't have other initializers together with 'this'.
+  //                               ^^^
+  // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  // [cfe] Too many positional arguments: 0 allowed, but 1 found.
+}
+
+main() {
+  new A(3);
+  new A.illegalBody(10);
+  new A.illegalInit();
+  new A.illegalFormal(10);
+  new A.illegalSuper();
+}
diff --git a/tests/language/constructor/redirect_cycle_runtime_test.dart b/tests/language/constructor/redirect_cycle_runtime_test.dart
new file mode 100644
index 0000000..4a05857
--- /dev/null
+++ b/tests/language/constructor/redirect_cycle_runtime_test.dart
@@ -0,0 +1,18 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Redirection constructors must not be cyclic.
+
+class A {
+  var x;
+  A(x)
+
+      ;
+}
+
+main() {
+  new A(10);
+}
diff --git a/tests/language/constructor/redirect_cycle_test.dart b/tests/language/constructor/redirect_cycle_test.dart
new file mode 100644
index 0000000..6730e06
--- /dev/null
+++ b/tests/language/constructor/redirect_cycle_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Redirection constructors must not be cyclic.
+
+class A {
+  var x;
+  A(x)
+      : this(0)
+      //^^^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
+      // [cfe] Redirecting constructors can't be cyclic.
+      ;
+}
+
+main() {
+  new A(10);
+}
diff --git a/tests/language/constructor/redirect_indirect_cycle_runtime_test.dart b/tests/language/constructor/redirect_indirect_cycle_runtime_test.dart
new file mode 100644
index 0000000..94159a5
--- /dev/null
+++ b/tests/language/constructor/redirect_indirect_cycle_runtime_test.dart
@@ -0,0 +1,19 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 {
+  var x;
+  A(x) : this.named(x, 0);
+  A.named(x, int y)
+      // Redirecting constructors must not be cyclic.
+
+      ;
+}
+
+main() {
+  new A(10);
+}
diff --git a/tests/language/constructor/redirect_indirect_cycle_test.dart b/tests/language/constructor/redirect_indirect_cycle_test.dart
new file mode 100644
index 0000000..aa2bb69
--- /dev/null
+++ b/tests/language/constructor/redirect_indirect_cycle_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 {
+  var x;
+  A(x) : this.named(x, 0);
+  //     ^^^^^^^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
+  A.named(x, int y)
+      // Redirecting constructors must not be cyclic.
+      : this(x + y)
+      //^^^^^^^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
+      // [cfe] Redirecting constructors can't be cyclic.
+      ;
+}
+
+main() {
+  new A(10);
+}
diff --git a/tests/language/constructor/redirect_runtime_test.dart b/tests/language/constructor/redirect_runtime_test.dart
new file mode 100644
index 0000000..f6084b8
--- /dev/null
+++ b/tests/language/constructor/redirect_runtime_test.dart
@@ -0,0 +1,75 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for redirection constructors.
+
+import "package:expect/expect.dart";
+
+class A {
+  var x;
+  A(this.x) {}
+  A.named(x, int y) : this(x + y);
+  A.named2(int x, int y, z) : this.named(staticFun(x, y), z);
+
+  // The following is a bit tricky. It is a compile-time error to
+  // refer to this (implicitly or explicitly) from an initializer.
+  // When we remove the line with moreStaticFun, staticFun is really a
+  // static function and it is legal to call it. This is what will
+  // happen in the /none version of this test. However, in /01,
+  // staticFun isn't really a static function and should cause a
+  // compile-time error.
+  static
+
+      int staticFun(int v1, int v2) {
+    return v1 * v2;
+  }
+}
+
+class B extends A {
+  B(y) : super(y + 1) {}
+  B.named(y) : super.named(y, y + 1) {}
+}
+
+class C {
+  final x;
+  const C(this.x);
+  const C.named(x, int y) : this(x + y);
+}
+
+class D extends C {
+  const D(y) : super(y + 1);
+  const D.named(y) : super.named(y, y + 1);
+}
+
+class ConstructorRedirectTest {
+  static testMain() {
+    var a = new A(499);
+    Expect.equals(499, a.x);
+    a = new A.named(349, 499);
+    Expect.equals(349 + 499, a.x);
+    a = new A.named2(11, 42, 99);
+    Expect.equals(11 * 42 + 99, a.x);
+
+    var b = new B(498);
+    Expect.equals(499, b.x);
+    b = new B.named(249);
+    Expect.equals(499, b.x);
+
+    C c = const C(499);
+    Expect.equals(499, c.x);
+    c = const C.named(249, 250);
+    Expect.equals(499, c.x);
+
+    D d = const D(498);
+    Expect.equals(499, d.x);
+    d = const D.named(249);
+    Expect.equals(499, d.x);
+  }
+}
+
+main() {
+  ConstructorRedirectTest.testMain();
+}
diff --git a/tests/language/constructor/redirect_test.dart b/tests/language/constructor/redirect_test.dart
new file mode 100644
index 0000000..0f1ee3a
--- /dev/null
+++ b/tests/language/constructor/redirect_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for redirection constructors.
+
+import "package:expect/expect.dart";
+
+class A {
+  var x;
+  A(this.x) {}
+  A.named(x, int y) : this(x + y);
+  A.named2(int x, int y, z) : this.named(staticFun(x, y), z);
+  //                                     ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER
+  // [cfe] Can't access 'this' in a field initializer to read 'staticFun'.
+
+  // The following is a bit tricky. It is a compile-time error to
+  // refer to this (implicitly or explicitly) from an initializer.
+  // When we remove the line with moreStaticFun, staticFun is really a
+  // static function and it is legal to call it. This is what will
+  // happen in the /none version of this test. However, in /01,
+  // staticFun isn't really a static function and should cause a
+  // compile-time error.
+  static
+  moreStaticFun() {}
+      int staticFun(int v1, int v2) {
+    return v1 * v2;
+  }
+}
+
+class B extends A {
+  B(y) : super(y + 1) {}
+  B.named(y) : super.named(y, y + 1) {}
+}
+
+class C {
+  final x;
+  const C(this.x);
+  const C.named(x, int y) : this(x + y);
+}
+
+class D extends C {
+  const D(y) : super(y + 1);
+  const D.named(y) : super.named(y, y + 1);
+}
+
+class ConstructorRedirectTest {
+  static testMain() {
+    var a = new A(499);
+    Expect.equals(499, a.x);
+    a = new A.named(349, 499);
+    Expect.equals(349 + 499, a.x);
+    a = new A.named2(11, 42, 99);
+    Expect.equals(11 * 42 + 99, a.x);
+
+    var b = new B(498);
+    Expect.equals(499, b.x);
+    b = new B.named(249);
+    Expect.equals(499, b.x);
+
+    C c = const C(499);
+    Expect.equals(499, c.x);
+    c = const C.named(249, 250);
+    Expect.equals(499, c.x);
+
+    D d = const D(498);
+    Expect.equals(499, d.x);
+    d = const D.named(249);
+    Expect.equals(499, d.x);
+  }
+}
+
+main() {
+  ConstructorRedirectTest.testMain();
+}
diff --git a/tests/language/constructor/reference_runtime_10_test.dart b/tests/language/constructor/reference_runtime_10_test.dart
new file mode 100644
index 0000000..b96d8f9
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_10_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Foo.bar();
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_11_test.dart b/tests/language/constructor/reference_runtime_11_test.dart
new file mode 100644
index 0000000..cea554d
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_11_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Foo<int>();
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_12_test.dart b/tests/language/constructor/reference_runtime_12_test.dart
new file mode 100644
index 0000000..5b58eae
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_12_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Foo<int>.bar();
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_1_test.dart b/tests/language/constructor/reference_runtime_1_test.dart
new file mode 100644
index 0000000..450bc7f
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_1_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+  new Foo();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_2_test.dart b/tests/language/constructor/reference_runtime_2_test.dart
new file mode 100644
index 0000000..cab730f
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_2_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+  new Foo.bar();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_3_test.dart b/tests/language/constructor/reference_runtime_3_test.dart
new file mode 100644
index 0000000..20ac3d2
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_3_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+  new Foo<int>();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_4_test.dart b/tests/language/constructor/reference_runtime_4_test.dart
new file mode 100644
index 0000000..e69fe77
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_4_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+  new Foo<int>.bar();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_5_test.dart b/tests/language/constructor/reference_runtime_5_test.dart
new file mode 100644
index 0000000..4dda061
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_5_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+  const Foo();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_6_test.dart b/tests/language/constructor/reference_runtime_6_test.dart
new file mode 100644
index 0000000..75859e0
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_6_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+  const Foo.bar();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_7_test.dart b/tests/language/constructor/reference_runtime_7_test.dart
new file mode 100644
index 0000000..b18721e
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_7_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+  const Foo<int>();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_8_test.dart b/tests/language/constructor/reference_runtime_8_test.dart
new file mode 100644
index 0000000..1493e34
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_8_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  const Foo<int>.bar();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_9_test.dart b/tests/language/constructor/reference_runtime_9_test.dart
new file mode 100644
index 0000000..cad70b0
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_9_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Foo();
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_runtime_test.dart b/tests/language/constructor/reference_runtime_test.dart
new file mode 100644
index 0000000..12b5314
--- /dev/null
+++ b/tests/language/constructor/reference_runtime_test.dart
@@ -0,0 +1,44 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/constructor/reference_test.dart b/tests/language/constructor/reference_test.dart
new file mode 100644
index 0000000..52e1235
--- /dev/null
+++ b/tests/language/constructor/reference_test.dart
@@ -0,0 +1,117 @@
+// 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.
+
+class Foo<X> {
+  const Foo();
+  const Foo.bar();
+  const Foo.baz();
+}
+
+main() {
+  new Foo();
+  new Foo.bar();
+  new Foo.bar.baz();
+  //  ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
+  //          ^
+  // [cfe] Method not found: 'Foo.bar.baz'.
+  new Foo<int>();
+  new Foo<int>.bar();
+  new Foo<int>.bar.baz();
+  //           ^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Expected '(' after this.
+  //               ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] The method 'baz' isn't defined for the class 'Foo<int>'.
+  new Foo.bar<int>();
+  //      ^
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //         ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  new Foo.bar<int>.baz();
+  //      ^
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //         ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  //               ^
+  // [cfe] Method not found: 'Foo.bar.baz'.
+  new Foo.bar.baz<int>();
+  //  ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
+  //          ^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //          ^
+  // [cfe] Method not found: 'Foo.bar.baz'.
+
+  const Foo();
+  const Foo.bar();
+  const Foo.bar.baz();
+  //    ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
+  //            ^
+  // [cfe] Method not found: 'Foo.bar.baz'.
+  const Foo<int>();
+  const Foo<int>.bar();
+  const Foo<int>.bar.baz();
+  //             ^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Expected '(' after this.
+  //                 ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] The method 'baz' isn't defined for the class 'Foo<int>'.
+  const Foo.bar<int>();
+  //        ^
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //           ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  const Foo.bar<int>.baz();
+  //        ^
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //           ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  //                 ^
+  // [cfe] Method not found: 'Foo.bar.baz'.
+  const Foo.bar.baz<int>();
+  //    ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
+  //            ^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //            ^
+  // [cfe] Method not found: 'Foo.bar.baz'.
+
+  Foo();
+  Foo.bar();
+  Foo.bar.baz();
+  //  ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] Getter not found: 'bar'.
+  Foo<int>();
+  Foo<int>.bar();
+  Foo<int>.bar.baz();
+  //       ^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Expected '(' after this.
+  //           ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] The method 'baz' isn't defined for the class 'Foo<int>'.
+  Foo.bar<int>();
+  //  ^
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //     ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  Foo.bar<int>.baz();
+  //  ^
+  // [cfe] A constructor invocation can't have type arguments on the constructor name.
+  //     ^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR
+  //           ^
+  // [cfe] Method not found: 'Foo.bar.baz'.
+  Foo.bar.baz<int>();
+  //  ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] Getter not found: 'bar'.
+}
diff --git a/tests/language/constructor/return_runtime_test.dart b/tests/language/constructor/return_runtime_test.dart
new file mode 100644
index 0000000..9c23cd9
--- /dev/null
+++ b/tests/language/constructor/return_runtime_test.dart
@@ -0,0 +1,47 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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";
+
+// Dart spec 0.03, section 11.10 - generative constructors can only have return
+// statements in the form 'return;'.
+class A {
+  int x;
+  A(this.x) {
+    return;
+  }
+  A.test1(this.x) {
+
+  }
+  A.test2(this.x) {
+
+  }
+  int foo(int y) => x + y;
+}
+
+class B {
+
+}
+
+class C {
+  int value = -1;
+
+}
+
+class D {
+  int value = -1;
+
+}
+
+main() {
+  Expect.equals((new A(1)).foo(10), 11);
+  Expect.equals((new A.test1(1)).foo(10), 11);
+  Expect.equals((new A.test2(1)).foo(10), 11);
+  new B();
+  new C();
+  new D();
+}
diff --git a/tests/language/constructor/return_test.dart b/tests/language/constructor/return_test.dart
new file mode 100644
index 0000000..6a46892
--- /dev/null
+++ b/tests/language/constructor/return_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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";
+
+// Dart spec 0.03, section 11.10 - generative constructors can only have return
+// statements in the form 'return;'.
+class A {
+  int x;
+  A(this.x) {
+    return;
+  }
+  A.test1(this.x) {
+    return this;
+//  ^
+// [cfe] Constructors can't have a return type.
+//         ^^^^
+// [analyzer] COMPILE_TIME_ERROR.RETURN_IN_GENERATIVE_CONSTRUCTOR
+  }
+  A.test2(this.x) {
+    return null;
+//  ^
+// [cfe] Constructors can't have a return type.
+//         ^^^^
+// [analyzer] COMPILE_TIME_ERROR.RETURN_IN_GENERATIVE_CONSTRUCTOR
+  }
+  int foo(int y) => x + y;
+}
+
+class B {
+  B() => B._();
+  //  ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.RETURN_IN_GENERATIVE_CONSTRUCTOR
+  //     ^
+  // [cfe] Constructors can't have a return type.
+
+  B._();
+}
+
+class C {
+  int value;
+  C() : value = 1 { return null; }
+  //                ^
+  // [cfe] Constructors can't have a return type.
+  //                       ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.RETURN_IN_GENERATIVE_CONSTRUCTOR
+}
+
+class D {
+  int value = -1;
+  D(): value = 1 => D._();
+  //             ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.RETURN_IN_GENERATIVE_CONSTRUCTOR
+  //                ^
+  // [cfe] Constructors can't have a return type.
+
+  D._();
+}
+
+main() {
+  Expect.equals((new A(1)).foo(10), 11);
+  Expect.equals((new A.test1(1)).foo(10), 11);
+  Expect.equals((new A.test2(1)).foo(10), 11);
+  new B();
+  new C();
+  new D();
+}
diff --git a/tests/language/constructor/setter_test.dart b/tests/language/constructor/setter_test.dart
new file mode 100644
index 0000000..bad56d3
--- /dev/null
+++ b/tests/language/constructor/setter_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 setters are not invokable in the initializer list.
+
+class A {
+  A() : a = 499; /*@compile-error=unspecified*/
+
+  set a(val) {}
+}
+
+main() {
+  new A();
+}
diff --git a/tests/language/constructor/type_parameter_runtime_test.dart b/tests/language/constructor/type_parameter_runtime_test.dart
new file mode 100644
index 0000000..6cb2a75
--- /dev/null
+++ b/tests/language/constructor/type_parameter_runtime_test.dart
@@ -0,0 +1,14 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo {
+
+}
+
+main() {
+  new Foo();
+}
diff --git a/tests/language/constructor/type_parameter_test.dart b/tests/language/constructor/type_parameter_test.dart
new file mode 100644
index 0000000..3712c26
--- /dev/null
+++ b/tests/language/constructor/type_parameter_test.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.
+
+class Foo {
+  Foo<A>() {}
+  // ^^^
+  // [analyzer] SYNTACTIC_ERROR.TYPE_PARAMETER_ON_CONSTRUCTOR
+  // [cfe] Constructors can't have type parameters.
+}
+
+main() {
+  new Foo();
+}
diff --git a/tests/language/constructor/unresolved_default_constructor_test.dart b/tests/language/constructor/unresolved_default_constructor_test.dart
new file mode 100644
index 0000000..07fdc72
--- /dev/null
+++ b/tests/language/constructor/unresolved_default_constructor_test.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.
+
+// Test unresolved default constructor calls cause compilation errors.
+
+import 'package:expect/expect.dart';
+
+class A {
+  A.named();
+  static method() {}
+}
+
+main() {
+  A.method();
+  Expect.throws(() => new A());
+  //                      ^
+  // [analyzer] STATIC_WARNING.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
+  // [cfe] Method not found: 'A'.
+}
diff --git a/tests/language/constructor/unresolved_default_runtime_test.dart b/tests/language/constructor/unresolved_default_runtime_test.dart
new file mode 100644
index 0000000..dd83067
--- /dev/null
+++ b/tests/language/constructor/unresolved_default_runtime_test.dart
@@ -0,0 +1,20 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test unresolved default constructor calls cause compilation errors.
+
+import 'package:expect/expect.dart';
+
+class A {
+  A.named();
+  static method() {}
+}
+
+main() {
+  A.method();
+
+}
diff --git a/tests/language/constructor/unresolved_in_factory_test.dart b/tests/language/constructor/unresolved_in_factory_test.dart
new file mode 100644
index 0000000..a9aa72a
--- /dev/null
+++ b/tests/language/constructor/unresolved_in_factory_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 unresolved method call in a factory is a compile error.
+
+class A {
+  factory A() {
+    foo(); /*@compile-error=unspecified*/
+  }
+}
+
+main() {
+  new A();
+}
diff --git a/tests/language/constructor/with_mixin_test.dart b/tests/language/constructor/with_mixin_test.dart
new file mode 100644
index 0000000..5e4badc
--- /dev/null
+++ b/tests/language/constructor/with_mixin_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.
+
+// Test super constructor invocation with mixins.
+// Regression test for issue dartbug.com/22604
+
+import "package:expect/expect.dart";
+
+var a_count = 0;
+var b_count = 0;
+
+class A {
+  final int x;
+  A(int this.x) {
+    a_count++;
+  }
+}
+
+class I {}
+
+class B extends A with I {
+  int y;
+
+  B(int xx)
+      : y = 13,
+        super(xx) {
+    b_count++;
+  }
+}
+
+void main() {
+  var b = new B(17);
+  Expect.equals(1, a_count);
+  Expect.equals(1, b_count);
+}
diff --git a/tests/language/constructor/with_type_parameters_test.dart b/tests/language/constructor/with_type_parameters_test.dart
new file mode 100644
index 0000000..8df1733
--- /dev/null
+++ b/tests/language/constructor/with_type_parameters_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.
+
+class Bar<T> {
+  Bar() {} //# 01: ok
+  Bar.boo() {} //# 02: ok
+  Bar<E>() {} //# 03: compile-time error
+  Bar<E>.boo() {} //# 04: syntax error
+  Bar.boo<E>() {} //# 05: syntax error
+  Bar.boo<E>.baz() {} //# 06: syntax error
+
+  Bar(); //# 07: ok
+  Bar.boo(); //# 08: ok
+  Bar<E>(); //# 09: compile-time error
+  Bar<E>.boo(); //# 10: syntax error
+  Bar.boo<E>(); //# 11: syntax error
+  Bar.boo<E>.baz(); //# 12: syntax error
+
+  const Bar(); //# 13: ok
+  const Bar.boo(); //# 14: ok
+  const Bar<E>(); //# 15: syntax error
+  const Bar<E>.boo(); //# 16: syntax error
+  const Bar.boo<E>(); //# 17: syntax error
+  const Bar.boo<E>.baz(); //# 18: syntax error
+}
+
+main() {}
diff --git a/tests/language/control_flow_collections/await_for_downcast_test.dart b/tests/language/control_flow_collections/await_for_downcast_test.dart
new file mode 100644
index 0000000..be8aa65
--- /dev/null
+++ b/tests/language/control_flow_collections/await_for_downcast_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 downcasting elements in collection-await-for is a compile error.
+Stream<int> stream(List<int> values) => Stream.fromIterable(values);
+Stream<num> numStream(List<num> values) => Stream.fromIterable(values);
+
+void main() async {
+  await testList();
+  await testMap();
+  await testSet();
+}
+
+Future<void> testList() async {
+  // Downcast stream.
+  Object obj = stream([1, 2, 3, 4]);
+  var a = <int>[await for (var n in obj) n];
+  //                                ^^^
+  // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_TYPE
+  // [cfe] The type 'Object' used in the 'for' loop must implement 'Stream<dynamic>'.
+
+  // Downcast variable.
+  var b = <int>[
+    await for (int n in numStream([1, 2, 3, 4])) n
+    //             ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //                  ^^^^^^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_ELEMENT_TYPE
+  ];
+
+  // Downcast element.
+  var c = <int>[
+    await for (num n in numStream([1, 2, 3, 4])) n
+    //                                           ^
+    // [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+  ];
+}
+
+Future<void> testMap() async {
+  // Downcast stream.
+  Object obj = stream([1, 2, 3, 4]);
+  var a = <int, int>{await for (var n in obj) n: n};
+  //                                     ^^^
+  // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_TYPE
+  // [cfe] The type 'Object' used in the 'for' loop must implement 'Stream<dynamic>'.
+
+  // Downcast variable.
+  var b = <int, int>{
+    await for (int n in numStream([1, 2, 3, 4])) n: n
+    //             ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //                  ^^^^^^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_ELEMENT_TYPE
+  };
+
+  // Downcast element.
+  var c = <int, int>{
+    await for (num n in numStream([1, 2, 3, 4])) n: n
+    //                                           ^
+    // [analyzer] STATIC_WARNING.MAP_KEY_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //                                              ^
+    // [analyzer] STATIC_WARNING.MAP_VALUE_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+  };
+}
+
+Future<void> testSet() async {
+  // Downcast stream.
+  Object obj = stream([1, 2, 3, 4]);
+  var a = <int>{await for (var n in obj) n};
+  //                                ^^^
+  // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_TYPE
+  // [cfe] The type 'Object' used in the 'for' loop must implement 'Stream<dynamic>'.
+
+  // Downcast variable.
+  var b = <int>{
+    await for (int n in numStream([1, 2, 3, 4])) n
+    //             ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //                  ^^^^^^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_ELEMENT_TYPE
+  };
+
+  // Downcast element.
+  var c = <int>{
+    await for (num n in numStream([1, 2, 3, 4])) n
+    //                                           ^
+    // [analyzer] STATIC_WARNING.SET_ELEMENT_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+  };
+}
diff --git a/tests/language/control_flow_collections/await_for_dynamic_null_test.dart b/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
new file mode 100644
index 0000000..aad701f2
--- /dev/null
+++ b/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
@@ -0,0 +1,19 @@
+// 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 that an implicit dynamic cast of a null stream is caught.
+import 'package:async_helper/async_helper.dart';
+
+void main() {
+  asyncTest(() async {
+    // Null stream.
+    dynamic nullStream = null;
+    asyncExpectThrows<Error>(
+        () async => <int>[await for (var i in nullStream) 1]);
+    asyncExpectThrows<Error>(
+        () async => <int, int>{await for (var i in nullStream) 1: 1});
+    asyncExpectThrows<Error>(
+        () async => <int>{await for (var i in nullStream) 1});
+  });
+}
diff --git a/tests/language/control_flow_collections/await_for_inference_test.dart b/tests/language/control_flow_collections/await_for_inference_test.dart
new file mode 100644
index 0000000..e0c1df8
--- /dev/null
+++ b/tests/language/control_flow_collections/await_for_inference_test.dart
@@ -0,0 +1,110 @@
+// 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 how await for interacts with inference.
+import "package:async_helper/async_helper.dart";
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+Stream<int> stream() => Stream.fromIterable([1]);
+
+void main() {
+  asyncTest(() async {
+    await testBottomUpInference();
+    await testLoopVariableInference();
+    await testTopDownInference();
+  });
+}
+
+Future<void> testBottomUpInference() async {
+  // Lists.
+  Expect.type<List<int>>([await for (var i in stream()) 1]);
+  Expect.type<List<int>>(
+      [await for (var i in stream()) 1, await for (var i in stream()) 2]);
+  Expect.type<List<num>>(
+      [await for (var i in stream()) 1, await for (var i in stream()) 0.2]);
+  Expect.type<List<int>>([await for (var i in stream()) 1, 2]);
+  Expect.type<List<num>>([await for (var i in stream()) 1, 0.2]);
+  Expect.type<List<dynamic>>([await for (var i in stream()) ...[]]);
+  Expect.type<List<int>>([await for (var i in stream()) ...<int>[]]);
+
+  // Maps.
+  Expect.type<Map<int, int>>({await for (var i in stream()) 1: 1});
+  Expect.type<Map<int, int>>(
+      {await for (var i in stream()) 1: 1, await for (var i in stream()) 2: 2});
+  Expect.type<Map<num, num>>({
+    await for (var i in stream()) 1: 0.1,
+    await for (var i in stream()) 0.2: 2
+  });
+  Expect.type<Map<int, int>>({await for (var i in stream()) 1: 1, 2: 2});
+  Expect.type<Map<num, num>>({await for (var i in stream()) 1: 0.1, 0.2: 2});
+  Expect.type<Map<dynamic, dynamic>>({await for (var i in stream()) ...{}});
+  Expect.type<Map<int, int>>({await for (var i in stream()) ...<int, int>{}});
+
+  // Sets.
+  Expect.type<Set<int>>({await for (var i in stream()) 1});
+  Expect.type<Set<int>>(
+      {await for (var i in stream()) 1, await for (var i in stream()) 2});
+  Expect.type<Set<num>>(
+      {await for (var i in stream()) 1, await for (var i in stream()) 0.2});
+  Expect.type<Set<int>>({await for (var i in stream()) 1, 2});
+  Expect.type<Set<num>>({await for (var i in stream()) 1, 0.2});
+  Expect.type<Set<dynamic>>({await for (var i in stream()) ...[]});
+  Expect.type<Set<int>>({await for (var i in stream()) ...<int>[]});
+
+  // If a nested iterable's type is dynamic, the element type is dynamic.
+  Expect.type<List<dynamic>>(
+      [1, await for (var i in stream()) ...([] as dynamic)]);
+  Expect.type<Set<dynamic>>(
+      {1, await for (var i in stream()) ...([] as dynamic)});
+
+  // If a nested maps's type is dynamic, the key and value types are dynamic.
+  Expect.type<Map<dynamic, dynamic>>(
+      {1: 1, await for (var i in stream()) ...({} as dynamic)});
+}
+
+Future<void> testLoopVariableInference() async {
+  // Infers loop variable from stream.
+  Expect.type<List<int>>([await for (var i in stream()) i]);
+  Expect.type<List<String>>(
+      [await for (var i in stream()) i.toRadixString(10)]);
+
+  // Loop variable type is pushed into stream.
+  Expect.listEquals(<int>[1], [await for (int i in expectIntStream([1])) i]);
+}
+
+Future<void> testTopDownInference() async {
+  // Lists.
+
+  // The context element type is pushed into the body.
+  Expect.listEquals(<int>[1],
+      <int>[await for (var i in stream()) expectInt(1)]);
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.listEquals(<int>[1, 2],
+      [1, await for (var i in stream()) expectDynamic(2)]);
+
+  // Maps.
+
+  // The context element type is pushed into the body.
+  Expect.mapEquals(<int, String>{1: "s"}, <int, String>{
+    await for (var i in stream()) expectInt(1): expectString("s")
+  });
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.mapEquals(<int, String>{1: "s", 2: "t"}, {
+    1: "s",
+    await for (var i in stream()) expectDynamic(2): expectDynamic("t")
+  });
+
+  // Sets.
+
+  // The context element type is pushed into the body.
+  Expect.setEquals(<int>{1}, <int>{await for (var i in stream()) expectInt(1)});
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.setEquals(<int>{1, 2},
+      {1, await for (var i in stream()) expectDynamic(2)});
+}
diff --git a/tests/language/control_flow_collections/await_for_null_test.dart b/tests/language/control_flow_collections/await_for_null_test.dart
new file mode 100644
index 0000000..492e153
--- /dev/null
+++ b/tests/language/control_flow_collections/await_for_null_test.dart
@@ -0,0 +1,21 @@
+// 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 that a null stream expression produces a compile error.
+void main() async {
+  // Null stream.
+  Stream<int>? nullStream;
+  var a = <int>[await for (var i in nullStream) 1];
+  //                                ^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] The type 'Stream<int>?' used in the 'for' loop must implement 'Stream<dynamic>'.
+  var b = <int, int>{await for (var i in nullStream) 1: 1};
+  //                                     ^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] The type 'Stream<int>?' used in the 'for' loop must implement 'Stream<dynamic>'.
+  var c = <int>{await for (var i in nullStream) 1};
+  //                                ^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] The type 'Stream<int>?' used in the 'for' loop must implement 'Stream<dynamic>'.
+}
diff --git a/tests/language/control_flow_collections/await_for_syntax_error_test.dart b/tests/language/control_flow_collections/await_for_syntax_error_test.dart
new file mode 100644
index 0000000..d64303a
--- /dev/null
+++ b/tests/language/control_flow_collections/await_for_syntax_error_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+void main() {
+  // Use await for in non-async function.
+  var _ = [await for (var i in Stream<int>.empty()) i]; //# 01: compile-time error
+
+  () async {
+    // Use await for variable out of scope.
+    var _ = [await for (var i in Stream<int>.empty()) 1, i]; //# 02: compile-time error
+
+    // Use await for variable in own initializer.
+    var _ = [await for (var i in Stream<Object>.fromIterable([i])) 1]; //# 03: compile-time error
+  }();
+}
diff --git a/tests/language/control_flow_collections/await_for_test.dart b/tests/language/control_flow_collections/await_for_test.dart
new file mode 100644
index 0000000..ce84fe0
--- /dev/null
+++ b/tests/language/control_flow_collections/await_for_test.dart
@@ -0,0 +1,234 @@
+// 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:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+final list = [1, 2, 3, 4];
+final map = {1: 1, 2: 2, 3: 3, 4: 4};
+final set = {1, 2, 3, 4};
+
+Stream<int> stream(List<int> values) => Stream.fromIterable(values);
+Stream<num> numStream(List<num> values) => Stream.fromIterable(values);
+
+void main() {
+  asyncTest(() async {
+    await testList();
+    await testMap();
+    await testSet();
+    await testDuplicateKeys();
+    await testKeyOrder();
+    await testRuntimeErrors();
+  });
+}
+
+Future<void> testList() async {
+  // Only await for.
+  Expect.listEquals(list, <int>[await for (var i in stream(list)) i]);
+
+  // Await for at beginning.
+  Expect.listEquals(list, <int>[await for (var i in stream([1, 2])) i, 3, 4]);
+
+  // Await for in middle.
+  Expect.listEquals(list, <int>[1, await for (var i in stream([2, 3])) i, 4]);
+
+  // Await for at end.
+  Expect.listEquals(list, <int>[1, 2, await for (var i in stream([3, 4])) i]);
+
+  // Empty await for.
+  Expect.listEquals(list,
+      <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
+
+  // Multiple await fors.
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([1])) i,
+    2,
+    await for (var i in stream([3, 4])) i
+  ]);
+
+  // Spread inside await for.
+  Expect.listEquals(list,
+      <int>[await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]]);
+
+  // If inside await for.
+  Expect.listEquals(list,
+      <int>[await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i]);
+
+  // Else inside await for.
+  Expect.listEquals(list,
+      <int>[await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i]);
+
+  // For inside await for.
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+  ]);
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], [await for (var i in stream([1])) [i]].first);
+  Expect.mapEquals({1: 1}, [await for (var i in stream([1])) {i: i}].first);
+  Expect.setEquals({1}, [await for (var i in stream([1])) {i}].first);
+}
+
+Future<void> testMap() async {
+  // Only for.
+  Expect.mapEquals(map, <int, int>{await for (var i in stream(list)) i: i});
+
+  // Await for at beginning.
+  Expect.mapEquals(map,
+      <int, int>{await for (var i in stream([1, 2])) i: i, 3: 3, 4: 4});
+
+  // Await for in middle.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, await for (var i in stream([2, 3])) i: i, 4: 4});
+
+  // Await for at end.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, 2: 2, await for (var i in stream([3, 4])) i: i});
+
+  // Empty await for.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    await for (var i in stream([])) i: i,
+    2: 2,
+    3: 3,
+    4: 4
+  });
+
+  // Multiple await fors.
+  Expect.mapEquals(map, <int, int>{
+    await for (var i in stream([1])) i: i,
+    2: 2,
+    await for (var i in stream([3, 4])) i: i
+  });
+
+  // Spread inside await for.
+  Expect.mapEquals(map, <int, int>{
+    await for (var i in stream([0, 2]))
+      ...<int, int>{1 + i: 1 + i, 2 + i: 2 + i}
+  });
+
+  // If inside await for.
+  Expect.mapEquals(map, <int, int>{
+    await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i: i
+  });
+
+  // Else inside await for.
+  Expect.mapEquals(map, <int, int>{
+    await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i: -i else i: i
+  });
+
+  // For inside await for.
+  Expect.mapEquals(map, <int, int>{
+    await for (var i in stream([0, 2]))
+      for (var j = 1; j <= 2; j++) i + j: i + j
+  });
+}
+
+Future<void> testSet() async {
+  // Only await for.
+  Expect.setEquals(set, <int>{await for (var i in stream(list)) i});
+
+  // Await for at beginning.
+  Expect.setEquals(set, <int>{await for (var i in stream([1, 2])) i, 3, 4});
+
+  // Await for in middle.
+  Expect.setEquals(set, <int>{1, await for (var i in stream([2, 3])) i, 4});
+
+  // Await for at end.
+  Expect.setEquals(set, <int>{1, 2, await for (var i in stream([3, 4])) i});
+
+  // Empty await for.
+  Expect.setEquals(set,
+      <int>{1, await for (var i in stream([])) i, 2, 3, 4});
+
+  // Multiple await fors.
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([1])) i,
+    2,
+    await for (var i in stream([3, 4])) i
+  });
+
+  // Spread inside await for.
+  Expect.setEquals(set,
+      <int>{await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]});
+
+  // If inside await for.
+  Expect.setEquals(set,
+      <int>{await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i});
+
+  // Else inside await for.
+  Expect.setEquals(set,
+      <int>{await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i});
+
+  // For inside await for.
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+  });
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], {await for (var i in stream([1])) [i]}.first);
+  Expect.mapEquals({1: 1}, {await for (var i in stream([1])) {i: i}}.first);
+  Expect.setEquals({1}, {await for (var i in stream([1])) {i}}.first);
+}
+
+Future<void> testDuplicateKeys() async {
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    await for (var i in stream([1, 2, 3])) i: i,
+    await for (var i in stream([2, 3])) i: i,
+    3: 3,
+    4: 4
+  });
+  Expect.setEquals(set, <int>{
+    1,
+    await for (var i in stream([1, 2, 3])) i,
+    await for (var i in stream([2, 3])) i,
+    3,
+    4
+  });
+}
+
+Future<void> testKeyOrder() async {
+  // First equal key wins.
+  var e1a = Equality(1, "a");
+  var e1b = Equality(1, "b");
+  var e2a = Equality(2, "a");
+  var e2b = Equality(2, "b");
+  var keys = [e1b, e2a, e2b];
+  var values = [2, 3, 4];
+
+  var map = <Equality, int>{
+    e1a: 1,
+    await for (var i in stream([0, 1, 2])) keys[i]: values[i]
+  };
+  Expect.equals("1:a,2:a", map.keys.join(","));
+  Expect.equals("2,4", map.values.join(","));
+
+  var set = <Equality>{e1a, await for (var i in stream([0, 1, 2])) keys[i]};
+  Expect.equals("1:a,2:a", set.join(","));
+}
+
+Future<void> testRuntimeErrors() async {
+  // Cast variable.
+  dynamic nonStream = 3;
+  asyncExpectThrows<TypeError>(
+      () async => <int>[await for (int i in nonStream) 1]);
+  asyncExpectThrows<TypeError>(
+      () async => <int, int>{await for (int i in nonStream) 1: 1});
+  asyncExpectThrows<TypeError>(
+      () async => <int>{await for (int i in nonStream) 1});
+
+  // Wrong element type.
+  dynamic nonInt = "string";
+  asyncExpectThrows<TypeError>(
+      () async => <int>[await for (var i in stream([1])) nonInt]);
+  asyncExpectThrows<TypeError>(
+      () async => <int, int>{await for (var i in stream([1])) nonInt: 1});
+  asyncExpectThrows<TypeError>(
+      () async => <int, int>{await for (var i in stream([1])) 1: nonInt});
+  asyncExpectThrows<TypeError>(
+      () async => <int>{await for (var i in stream([1])) nonInt});
+}
diff --git a/tests/language/control_flow_collections/await_for_type_error_test.dart b/tests/language/control_flow_collections/await_for_type_error_test.dart
new file mode 100644
index 0000000..e63a52e
--- /dev/null
+++ b/tests/language/control_flow_collections/await_for_type_error_test.dart
@@ -0,0 +1,25 @@
+// 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.
+
+void main() {
+  () async {
+    // Non-Stream type.
+    int nonStream = 3;
+    var _ = <int>[await for (var i in nonStream) 1]; //# 01: compile-time error
+    var _ = <int, int>{await for (var i in nonStream) 1: 1}; //# 02: compile-time error
+    var _ = <int>{await for (var i in nonStream) 1}; //# 03: compile-time error
+
+    // Wrong element type.
+    Stream<String> s = Stream.fromIterable(["s"]);
+    var _ = <int>[await for (int i in s) 1]; //# 07: compile-time error
+    var _ = <int, int>{await for (int i in s) 1: 1}; //# 08: compile-time error
+    var _ = <int>{await for (int i in s) 1}; //# 09: compile-time error
+
+    // Wrong body element type.
+    var _ = <int>[await for (var i in s) "s"]; //# 10: compile-time error
+    var _ = <int, int>{await for (var i in s) "s": 1}; //# 11: compile-time error
+    var _ = <int, int>{await for (var i in s) 1: "s"}; //# 12: compile-time error
+    var _ = <int>{await for (var i in s) "s"}; //# 13: compile-time error
+  }();
+}
diff --git a/tests/language/control_flow_collections/for_await_test.dart b/tests/language/control_flow_collections/for_await_test.dart
new file mode 100644
index 0000000..2baeefc
--- /dev/null
+++ b/tests/language/control_flow_collections/for_await_test.dart
@@ -0,0 +1,105 @@
+// 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:async_helper/async_helper.dart";
+import 'package:expect/expect.dart';
+
+final list = [1, 2, 3];
+final map = {1: 1, 2: 2, 3: 3};
+final set = {1, 2, 3};
+
+void main() {
+  asyncTest(() async {
+    await testList();
+    await testMap();
+    await testSet();
+  });
+}
+
+Future<void> testList() async {
+  var future123 = Future.value([1, 2, 3]);
+  var future1 = Future.value(1);
+
+  // Await in iterable.
+  Expect.listEquals(list, [for (var i in await future123) i]);
+
+  // Await in for-in body.
+  Expect.listEquals(list, [for (var i in [1, 2, 3]) await Future.value(i)]);
+
+  // Await in initializer.
+  Expect.listEquals(list, [for (var i = await future1; i < 4; i++) i]);
+
+  // Await in condition.
+  Expect.listEquals(list,
+      [for (var i = 1; await Future.value(i < 4); i++) i]);
+
+  // Await in increment.
+  Expect.listEquals(list,
+      [for (var i = 1; i < 4; await Future(() => i++)) i]);
+
+  // Await in for body.
+  Expect.listEquals(list,
+      [for (var i = 1; i < 4; i++) await Future.value(i)]);
+}
+
+Future<void> testMap() async {
+  var future123 = Future.value([1, 2, 3]);
+  var future1 = Future.value(1);
+
+  // Await in iterable.
+  Expect.mapEquals(map, {for (var i in await future123) i: i});
+
+  // Await in for-in body key.
+  Expect.mapEquals(map,
+      {for (var i in [1, 2, 3]) await Future.value(i): i});
+
+  // Await in for-in body value.
+  Expect.mapEquals(map,
+      {for (var i in [1, 2, 3]) i: await Future.value(i)});
+
+  // Await in initializer.
+  Expect.mapEquals(map, {for (var i = await future1; i < 4; i++) i: i});
+
+  // Await in condition.
+  Expect.mapEquals(map,
+      {for (var i = 1; await Future.value(i < 4); i++) i: i});
+
+  // Await in increment.
+  Expect.mapEquals(map,
+      {for (var i = 1; i < 4; await Future(() => i++)) i: i});
+
+  // Await in for body key.
+  Expect.mapEquals(map,
+      {for (var i = 1; i < 4; i++) await Future.value(i): i});
+
+  // Await in for body value.
+  Expect.mapEquals(map,
+      {for (var i = 1; i < 4; i++) i: await Future.value(i)});
+}
+
+Future<void> testSet() async {
+  var future123 = Future.value([1, 2, 3]);
+  var future1 = Future.value(1);
+
+  // Await in iterable.
+  Expect.setEquals(set, {for (var i in await future123) i});
+
+  // Await in for-in body.
+  Expect.setEquals(set, {for (var i in [1, 2, 3]) await Future.value(i)});
+
+  // Await in initializer.
+  Expect.setEquals(set, {for (var i = await future1; i < 4; i++) i});
+
+  // Await in condition.
+  Expect.setEquals(set,
+      {for (var i = 1; await Future.value(i < 4); i++) i});
+
+  // Await in increment.
+  Expect.setEquals(set,
+      {for (var i = 1; i < 4; await Future(() => i++)) i});
+
+  // Await in for body.
+  Expect.setEquals(set,
+      {for (var i = 1; i < 4; i++) await Future.value(i)});
+}
diff --git a/tests/language/control_flow_collections/for_const_error_test.dart b/tests/language/control_flow_collections/for_const_error_test.dart
new file mode 100644
index 0000000..3348639
--- /dev/null
+++ b/tests/language/control_flow_collections/for_const_error_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.
+
+void main() {
+  // For cannot be used in a const collection.
+  const _ = [for (var i in []) 1]; //# 00: compile-time error
+  const _ = {for (var i in []) 1: 1}; //# 01: compile-time error
+  const _ = {for (var i in []) 1}; //# 02: compile-time error
+
+  const _ = [for (; false;) 1]; //# 03: compile-time error
+  const _ = {for (; false;) 1: 1}; //# 04: compile-time error
+  const _ = {for (; false;) 1}; //# 05: compile-time error
+
+  () async {
+    const _ = <int>[await for (var i in []) 1]; //# 06: compile-time error
+    const _ = <int, int>{await for (var i in []) 1: 1}; //# 07: compile-time error
+    const _ = <int>{await for (var i in []) 1}; //# 08: compile-time error
+  }();
+}
diff --git a/tests/language/control_flow_collections/for_downcast_test.dart b/tests/language/control_flow_collections/for_downcast_test.dart
new file mode 100644
index 0000000..e16067e
--- /dev/null
+++ b/tests/language/control_flow_collections/for_downcast_test.dart
@@ -0,0 +1,130 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 downcasting elements in collection-for is a compile error.
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testNullIterable();
+}
+
+void testList() {
+  // Downcast iterable.
+  Object obj = <int>[1, 2, 3, 4];
+  var a = <int>[for (var n in obj) n];
+  //                          ^^^
+  // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_TYPE
+  // [cfe] The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+
+  // Downcast variable.
+  var b = <int>[
+    for (int n in <num>[1, 2, 3, 4]) n
+    //       ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //            ^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_ELEMENT_TYPE
+  ];
+
+  // Downcast element.
+  var c = <int>[
+    for (num n in <num>[1, 2, 3, 4]) n
+    //                               ^
+    // [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+  ];
+
+  // Downcast condition.
+  var d = <int>[for (var i = 1; (i < 2) as Object; i++) i];
+  //                            ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+  //                                    ^
+  // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+}
+
+void testMap() {
+  // Downcast iterable.
+  Object obj = <int>[1, 2, 3, 4];
+  var a = <int, int>{for (var n in obj) n: n};
+  //                               ^^^
+  // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_TYPE
+  // [cfe] The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+
+  // Downcast variable.
+  var b = <int, int>{
+    for (int n in <num>[1, 2, 3, 4]) n: n
+    //       ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //            ^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_ELEMENT_TYPE
+  };
+
+  // Downcast element.
+  var c = <int, int>{
+    for (num n in <num>[1, 2, 3, 4]) n: n
+    //                               ^
+    // [analyzer] STATIC_WARNING.MAP_KEY_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //                                  ^
+    // [analyzer] STATIC_WARNING.MAP_VALUE_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+  };
+
+  // Downcast condition.
+  var d = <int, int>{for (var i = 1; (i < 2) as Object; i++) i: i};
+  //                                 ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+  //                                         ^
+  // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+}
+
+void testSet() {
+  // Downcast iterable.
+  Object obj = <int>[1, 2, 3, 4];
+  var a = <int>{for (var n in obj) n};
+  //                          ^^^
+  // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_TYPE
+  // [cfe] The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+
+  // Downcast variable.
+  var b = <int>{
+    for (int n in <num>[1, 2, 3, 4]) n
+    //       ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+    //            ^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.FOR_IN_OF_INVALID_ELEMENT_TYPE
+  };
+
+  // Downcast element.
+  var c = <int>{
+    for (num n in <num>[1, 2, 3, 4]) n
+    //                               ^
+    // [analyzer] STATIC_WARNING.SET_ELEMENT_TYPE_NOT_ASSIGNABLE
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
+  };
+
+  // Downcast condition.
+  var d = <int>{for (var i = 1; (i < 2) as Object; i++) i};
+  //                            ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+  //                                    ^
+  // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+}
+
+void testNullIterable() {
+  // Null iterable.
+  Iterable<int>? nullIterable = null;
+  var a = <int>[for (var i in nullIterable) 1];
+  //                          ^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+  var b = {for (var i in nullIterable) 1: 1};
+  //                     ^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+  var c = <int>{for (var i in nullIterable) 1};
+  //                          ^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+}
diff --git a/tests/language/control_flow_collections/for_dynamic_null_strong_test.dart b/tests/language/control_flow_collections/for_dynamic_null_strong_test.dart
new file mode 100644
index 0000000..a0565d8
--- /dev/null
+++ b/tests/language/control_flow_collections/for_dynamic_null_strong_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.
+
+// Requirements=nnbd-strong
+import 'package:expect/expect.dart';
+
+void main() {
+  // Null condition expression.
+  dynamic nullBool = null;
+  Expect.throwsTypeError(() => <int>[for (; nullBool;) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (; nullBool;) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (; nullBool;) 1});
+
+  // Null iterable.
+  dynamic nullIterable = null;
+  Expect.throwsTypeError(() => <int>[for (var i in nullIterable) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (var i in nullIterable) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (var i in nullIterable) 1});
+}
diff --git a/tests/language/control_flow_collections/for_dynamic_null_weak_test.dart b/tests/language/control_flow_collections/for_dynamic_null_weak_test.dart
new file mode 100644
index 0000000..0337e9c
--- /dev/null
+++ b/tests/language/control_flow_collections/for_dynamic_null_weak_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// Requirements=nnbd-weak
+import 'package:expect/expect.dart';
+
+void main() {
+  // Null condition expression.
+  dynamic nullBool = null;
+  Expect.throwsAssertionError(() => <int>[for (; nullBool;) 1]);
+  Expect.throwsAssertionError(() => <int, int>{for (; nullBool;) 1: 1});
+  Expect.throwsAssertionError(() => <int>{for (; nullBool;) 1});
+
+  // Null iterable.
+  dynamic nullIterable = null;
+  Expect.throwsAssertionError(() => <int>[for (var i in nullIterable) 1]);
+  Expect.throwsAssertionError(
+      () => <int, int>{for (var i in nullIterable) 1: 1});
+  Expect.throwsAssertionError(() => <int>{for (var i in nullIterable) 1});
+}
diff --git a/tests/language/control_flow_collections/for_inference_test.dart b/tests/language/control_flow_collections/for_inference_test.dart
new file mode 100644
index 0000000..4e022e0
--- /dev/null
+++ b/tests/language/control_flow_collections/for_inference_test.dart
@@ -0,0 +1,99 @@
+// 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 how control flow interacts with inference.
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+void main() {
+  testBottomUpInference();
+  testLoopVariableInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  // Lists.
+  Expect.type<List<int>>([for (; false;) 1]);
+  Expect.type<List<int>>([for (; false;) 1, for (; false;) 2]);
+  Expect.type<List<num>>([for (; false;) 1, for (; false;) 0.2]);
+  Expect.type<List<int>>([for (; false;) 1, 2]);
+  Expect.type<List<num>>([for (; false;) 1, 0.2]);
+  Expect.type<List<dynamic>>([for (; false;) ...[]]);
+  Expect.type<List<int>>([for (; false;) ...<int>[]]);
+
+  // Maps.
+  Expect.type<Map<int, int>>({for (; false;) 1: 1});
+  Expect.type<Map<int, int>>({for (; false;) 1: 1, for (; false;) 2: 2});
+  Expect.type<Map<num, num>>({for (; false;) 1: 0.1, for (; false;) 0.2: 2});
+  Expect.type<Map<int, int>>({for (; false;) 1: 1, 2: 2});
+  Expect.type<Map<num, num>>({for (; false;) 1: 0.1, 0.2: 2});
+  Expect.type<Map<dynamic, dynamic>>({for (; false;) ...{}});
+  Expect.type<Map<int, int>>({for (; false;) ...<int, int>{}});
+
+  // Sets.
+  Expect.type<Set<int>>({for (; false;) 1});
+  Expect.type<Set<int>>({for (; false;) 1, for (; false;) 2});
+  Expect.type<Set<num>>({for (; false;) 1, for (; false;) 0.2});
+  Expect.type<Set<int>>({for (; false;) 1, 2});
+  Expect.type<Set<num>>({for (; false;) 1, 0.2});
+  Expect.type<Set<dynamic>>({for (; false;) ...[]});
+  Expect.type<Set<int>>({for (; false;) ...<int>[]});
+
+  // If a nested iterable's type is dynamic, the element type is dynamic.
+  Expect.type<List<dynamic>>([for (; false;) ...([] as dynamic)]);
+  Expect.type<Set<dynamic>>({1, for (; false;) ...([] as dynamic)});
+
+  // If a nested maps's type is dynamic, the key and value types are dynamic.
+  Expect.type<Map<dynamic, dynamic>>({1: 1, for (; false;) ...({} as dynamic)});
+}
+
+void testLoopVariableInference() {
+  // Infers loop variable from iterable.
+  Expect.type<List<int>>([for (var i in <int>[1]) i]);
+  Expect.type<List<String>>([for (var i in <int>[1]) i.toRadixString(10)]);
+
+  // Infers loop variable from initializer.
+  Expect.type<List<int>>([for (var i = 1; i < 2; i++) i]);
+  Expect.type<List<String>>([for (var i = 1; i < 2; i++) i.toRadixString(10)]);
+
+  // Loop variable type is pushed into sequence.
+  Expect.listEquals(<int>[1], [for (int i in expectIntIterable([1])) i]);
+
+  // Loop variable type is pushed into initializer.
+  Expect.listEquals(<int>[1], [for (int i = expectInt(1); i < 2; i++) i]);
+}
+
+void testTopDownInference() {
+  // Lists.
+
+  // The context element type is pushed into the body.
+  Expect.listEquals(<int>[1], <int>[for (var i = 0; i < 1; i++) expectInt(1)]);
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.listEquals(<int>[1, 2],
+      [1, for (var i = 0; i < 1; i++) expectDynamic(2)]);
+
+  // Maps.
+
+  // The context element type is pushed into the body.
+  Expect.mapEquals(<int, String>{1: "s"}, <int, String>{
+    for (var i = 0; i < 1; i++) expectInt(1): expectString("s")
+  });
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.mapEquals(<int, String>{1: "s", 2: "t"}, {
+    1: "s",
+    for (var i = 0; i < 1; i++) expectDynamic(2): expectDynamic("t")
+  });
+
+  // Sets.
+
+  // The context element type is pushed into the body.
+  Expect.setEquals(<int>{1}, <int>{for (var i = 0; i < 1; i++) expectInt(1)});
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.setEquals(<int>{1, 2},
+      {1, for (var i = 0; i < 1; i++) expectDynamic(2)});
+}
diff --git a/tests/language/control_flow_collections/for_non_bool_condition_test.dart b/tests/language/control_flow_collections/for_non_bool_condition_test.dart
new file mode 100644
index 0000000..a808e9c
--- /dev/null
+++ b/tests/language/control_flow_collections/for_non_bool_condition_test.dart
@@ -0,0 +1,13 @@
+// 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:expect/expect.dart';
+
+void main() {
+  // Non-bool condition expression.
+  dynamic nonBool = 3;
+  Expect.throwsTypeError(() => <int>[for (; nonBool;) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (; nonBool;) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (; nonBool;) 1});
+}
diff --git a/tests/language/control_flow_collections/for_null_condition_test.dart b/tests/language/control_flow_collections/for_null_condition_test.dart
new file mode 100644
index 0000000..e88d665
--- /dev/null
+++ b/tests/language/control_flow_collections/for_null_condition_test.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.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  // Null condition expression.
+  bool? nullBool = null;
+  var a = <int>[for (; nullBool;) 1];
+  //                   ^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
+  var b = <int, int>{for (; nullBool;) 1: 1};
+  //                        ^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
+  var c = <int>{for (; nullBool;) 1};
+  //                   ^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
+}
diff --git a/tests/language/control_flow_collections/for_runtime_error_test.dart b/tests/language/control_flow_collections/for_runtime_error_test.dart
new file mode 100644
index 0000000..ea5cfe4
--- /dev/null
+++ b/tests/language/control_flow_collections/for_runtime_error_test.dart
@@ -0,0 +1,27 @@
+// 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:expect/expect.dart';
+
+void main() {
+  // Cast for variable.
+  dynamic nonInt = "string";
+  Expect.throwsTypeError(() => <int>[for (int i = nonInt; false;) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (int i = nonInt; false;) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (int i = nonInt; false;) 1});
+
+  // Cast for-in variable.
+  dynamic nonIterable = 3;
+  Expect.throwsTypeError(() => <int>[for (int i in nonIterable) 1]);
+  Expect.throwsTypeError(() => <int, int>{for (int i in nonIterable) 1: 1});
+  Expect.throwsTypeError(() => <int>{for (int i in nonIterable) 1});
+
+  // Wrong element type.
+  Expect.throwsTypeError(() => <int>[for (var i = 0; i < 1; i++) nonInt]);
+  Expect.throwsTypeError(
+      () => <int, int>{for (var i = 0; i < 1; i++) nonInt: 1});
+  Expect.throwsTypeError(
+      () => <int, int>{for (var i = 0; i < 1; i++) 1: nonInt});
+  Expect.throwsTypeError(() => <int>{for (var i = 0; i < 1; i++) nonInt});
+}
diff --git a/tests/language/control_flow_collections/for_test.dart b/tests/language/control_flow_collections/for_test.dart
new file mode 100644
index 0000000..c25a4d4
--- /dev/null
+++ b/tests/language/control_flow_collections/for_test.dart
@@ -0,0 +1,204 @@
+// 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:expect/expect.dart';
+
+import 'utils.dart';
+
+final list = [1, 2, 3, 4];
+final map = {1: 1, 2: 2, 3: 3, 4: 4};
+final set = {1, 2, 3, 4};
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testDuplicateKeys();
+  testKeyOrder();
+}
+
+void testList() {
+  // Only for.
+  Expect.listEquals(list, <int>[for (var i in list) i]);
+
+  // For at beginning.
+  Expect.listEquals(list, <int>[for (var i in <int>[1, 2]) i, 3, 4]);
+
+  // For in middle.
+  Expect.listEquals(list, <int>[1, for (var i in <int>[2, 3]) i, 4]);
+
+  // For at end.
+  Expect.listEquals(list, <int>[1, 2, for (var i in <int>[3, 4]) i]);
+
+  // Empty for.
+  Expect.listEquals(list,
+      <int>[1, for (var i in <int>[]) i, 2, 3, for (; false;) 9, 4]);
+
+  // Multiple fors.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[1]) i, 2, for (var i = 3; i <= 4; i++) i]);
+
+  // Spread inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[0, 2]) ...<int>[1 + i, 2 + i]]);
+
+  // If inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[1, 9, 2, 3, 9, 4]) if (i != 9) i]);
+
+  // Else inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i else i]);
+
+  // For inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[0, 2]) for (var j = 1; j <= 2; j++) i + j]);
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], [for (var i = 1; i < 2; i++) [i]].first);
+  Expect.mapEquals({1: 1}, [for (var i = 1; i < 2; i++) {i: i}].first);
+  Expect.setEquals({1}, [for (var i = 1; i < 2; i++) {i}].first);
+
+  // Downcast condition.
+  Expect.listEquals([1], <int>[for (var i = 1; (i < 2) as dynamic; i++) i]);
+}
+
+void testMap() {
+  // Only for.
+  Expect.mapEquals(map, <int, int>{for (var i in list) i: i});
+
+  // For at beginning.
+  Expect.mapEquals(map,
+      <int, int>{for (var i in <int>[1, 2]) i: i, 3: 3, 4: 4});
+
+  // For in middle.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, for (var i in <int>[2, 3]) i: i, 4: 4});
+
+  // For at end.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, 2: 2, for (var i in <int>[3, 4]) i: i});
+
+  // Empty for.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    for (var i in <int>[]) i: i,
+    2: 2,
+    3: 3,
+    for (; false;) 9: 9,
+    4: 4
+  });
+
+  // Multiple fors.
+  Expect.mapEquals(map, <int, int>{
+    for (var i in <int>[1]) i: i,
+    2: 2,
+    for (var i = 3; i <= 4; i++) i: i
+  });
+
+  // Spread inside for.
+  Expect.mapEquals(map, <int, int>{
+    for (var i in <int>[0, 2]) ...<int, int>{1 + i: 1 + i, 2 + i: 2 + i}
+  });
+
+  // If inside for.
+  Expect.mapEquals(map,
+      <int, int>{for (var i in <int>[1, 9, 2, 3, 9, 4]) if (i != 9) i: i});
+
+  // Else inside for.
+  Expect.mapEquals(map,
+      <int, int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i: -i else i: i});
+
+  // For inside for.
+  Expect.mapEquals(map, <int, int>{
+    for (var i in <int>[0, 2]) for (var j = 1; j <= 2; j++) i + j: i + j
+  });
+
+  // Downcast condition.
+  Expect.mapEquals({1 : 1},
+      <int, int>{for (var i = 1; (i < 2) as dynamic; i++) i: i});
+}
+
+void testSet() {
+  // Only for.
+  Expect.setEquals(set, <int>{for (var i in list) i});
+
+  // For at beginning.
+  Expect.setEquals(set, <int>{for (var i in <int>[1, 2]) i, 3, 4});
+
+  // For in middle.
+  Expect.setEquals(set, <int>{1, for (var i in <int>[2, 3]) i, 4});
+
+  // For at end.
+  Expect.setEquals(set, <int>{1, 2, for (var i in <int>[3, 4]) i});
+
+  // Empty for.
+  Expect.setEquals(set,
+      <int>{1, for (var i in <int>[]) i, 2, 3, for (; false;) 9, 4});
+
+  // Multiple fors.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[1]) i, 2, for (var i = 3; i <= 4; i++) i});
+
+  // Spread inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[0, 2]) ...<int>[1 + i, 2 + i]});
+
+  // If inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[1, 9, 2, 3, 9, 4]) if (i != 9) i});
+
+  // Else inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i else i});
+
+  // For inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[0, 2]) for (var j = 1; j <= 2; j++) i + j});
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], {for (var i = 1; i < 2; i++) [i]}.first);
+  Expect.mapEquals({1: 1}, {for (var i = 1; i < 2; i++) {i: i}}.first);
+  Expect.setEquals({1}, {for (var i = 1; i < 2; i++) {i}}.first);
+
+  // Downcast condition.
+  Expect.setEquals({1}, <int>{for (var i = 1; (i < 2) as dynamic; i++) i});
+}
+
+void testDuplicateKeys() {
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    for (var i in <int>[1, 2, 3]) i: i,
+    for (var i = 2; i <= 3; i++) i: i,
+    3: 3,
+    4: 4
+  });
+  Expect.setEquals(set, <int>{
+    1,
+    for (var i in <int>[1, 2, 3]) i,
+    for (var i = 2; i <= 3; i++) i,
+    3,
+    4
+  });
+}
+
+void testKeyOrder() {
+  // First equal key wins.
+  var e1a = Equality(1, "a");
+  var e1b = Equality(1, "b");
+  var e2a = Equality(2, "a");
+  var e2b = Equality(2, "b");
+  var keys = [e1b, e2a, e2b];
+  var values = [2, 3, 4];
+
+  var map = <Equality, int>{
+    e1a: 1,
+    for (var i = 0; i < keys.length; i++) keys[i]: values[i]
+  };
+  Expect.equals("1:a,2:a", map.keys.join(","));
+  Expect.equals("2,4", map.values.join(","));
+
+  var set = <Equality>{e1a, for (var i = 0; i < keys.length; i++) keys[i]};
+  Expect.equals("1:a,2:a", set.join(","));
+}
diff --git a/tests/language/control_flow_collections/for_variable_test.dart b/tests/language/control_flow_collections/for_variable_test.dart
new file mode 100644
index 0000000..8433907
--- /dev/null
+++ b/tests/language/control_flow_collections/for_variable_test.dart
@@ -0,0 +1,202 @@
+// 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.
+
+/// Tests for how variables and scoping work with for elements.
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+String global = "global";
+
+void main() {
+  testClosure();
+  Test().shadowing();
+  Test().reuseVariable();
+}
+
+void testClosure() {
+  var closures = [];
+  capture(callback) {
+    closures.add(callback);
+    return callback();
+  }
+
+  reset() {
+    closures.clear();
+  }
+
+  // Close over for-in loop variable in element.
+  var list = [for (var i in [0, 1]) () => i];
+  Expect.equals(0, list[0]());
+  Expect.equals(1, list[1]());
+
+  // Close over loop variable in element.
+  list = [for (var i = 0; i < 2; i++) () => i];
+  Expect.equals(0, list[0]());
+  Expect.equals(1, list[1]());
+
+  // Close over variable in condition expression.
+  var list2 = [for (var i = 0; capture(() => i++) < 2;) i];
+  Expect.equals(1, closures[0]());
+  Expect.equals(2, closures[1]());
+  Expect.listEquals([1, 2], list2);
+  reset();
+
+  // Close over variable in increment expression.
+  var list3 = [for (var i = 0; i < 2; capture(() => i++)) i];
+  Expect.equals(1, closures[0]());
+  Expect.equals(2, closures[1]());
+  Expect.listEquals([0, 1], list3);
+  reset();
+}
+
+class TestBase {
+  String inherited = "inherited";
+}
+
+class Test extends TestBase {
+  static String staticField = "static field";
+
+  String field = "field";
+
+  void shadowing() {
+    var local = "local";
+
+    // C-style for.
+    var list = [
+      for (String? global = "for"; global != null; global = null) global
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (String? staticField = "for"; staticField != null; staticField = null)
+        staticField
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (String? field = "for"; field != null; field = null) field
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (String? inherited = "for"; inherited != null; inherited = null) inherited
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (String? local = "for"; local != null; local = null) local
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (String? outer = "outer"; outer != null; outer = null)
+        for (String? outer = "for"; outer != null; outer = null)
+          outer
+    ];
+    Expect.listEquals(["for"], list);
+
+    // For-in.
+    list = [for (var global in ["for"]) global];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var staticField in ["for"]) staticField];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var field in ["for"]) field];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var inherited in ["for"]) inherited];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var local in ["for"]) local];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var outer in ["outer"]) for (var outer in ["for"]) outer];
+    Expect.listEquals(["for"], list);
+  }
+
+  void reuseVariable() {
+    var local = "local";
+
+    // C-style for.
+    var list = [
+      for (global = "for"; global == "for"; global = "after") global
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", global);
+    global = "global";
+
+    list = [
+      for (staticField = "for"; staticField == "for"; staticField = "after")
+        staticField
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", staticField);
+    staticField = "staticField";
+
+    list = [
+      for (field = "for"; field == "for"; field = "after") field
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", field);
+    field = "field";
+
+    list = [
+      for (inherited = "for"; inherited == "for"; inherited = "after") inherited
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", inherited);
+    inherited = "inherited";
+
+    list = [
+      for (local = "for"; local == "for"; local = "after") local
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", local);
+    local = "local";
+
+    list = [
+      for (var outer = "outer"; outer == "outer"; outer = "outer after") ...[
+        for (outer = "for"; outer == "for"; outer = "after") outer,
+        outer
+      ]
+    ];
+    Expect.listEquals(["for", "after"], list);
+
+    // For-in.
+    list = [for (global in ["for"]) global];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", global);
+    global = "global";
+
+    list = [for (staticField in ["for"]) staticField];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", staticField);
+    staticField = "staticField";
+
+    list = [for (field in ["for"]) field];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", field);
+    field = "field";
+
+    list = [for (inherited in ["for"]) inherited];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", inherited);
+    inherited = "inherited";
+
+    list = [for (local in ["for"]) local];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", local);
+    local = "local";
+
+    list = [
+      for (var outer in ["outer"]) ...[
+        for (outer in ["for"]) outer,
+        outer
+      ]
+    ];
+    Expect.listEquals(["for", "for"], list);
+  }
+}
diff --git a/tests/language/control_flow_collections/if_await_test.dart b/tests/language/control_flow_collections/if_await_test.dart
new file mode 100644
index 0000000..08d0c60
--- /dev/null
+++ b/tests/language/control_flow_collections/if_await_test.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 "package:async_helper/async_helper.dart";
+import 'package:expect/expect.dart';
+
+final list = [1, 2, 3];
+final map = {1: 1, 2: 2, 3: 3};
+final set = {1, 2, 3};
+
+void main() {
+  asyncTest(() async {
+    await testList();
+    await testMap();
+    await testSet();
+  });
+}
+
+Future<void> testList() async {
+  var futureTrue = Future.value(true);
+  var future2 = Future.value(2);
+  var future9 = Future.value(9);
+
+  // Await in condition.
+  Expect.listEquals(list, [1, if (await futureTrue) 2, 3]);
+
+  // Await in then branch.
+  Expect.listEquals(list, [1, if (true) await future2, 3]);
+
+  // Await in else branch.
+  Expect.listEquals(list, [1, if (false) 9 else await future2, 3]);
+
+  // Await in untaken then branch.
+  Expect.listEquals(list, [1, 2, if (false) await future9, 3]);
+
+  // Await in untaken else branch.
+  Expect.listEquals(list, [1, if (true) 2 else await future9, 3]);
+}
+
+Future<void> testMap() async {
+  var futureTrue = Future.value(true);
+  var future2 = Future.value(2);
+  var future9 = Future.value(9);
+
+  // Await in condition.
+  Expect.mapEquals(map, {1: 1, if (await futureTrue) 2: 2, 3: 3});
+
+  // Await in then branch key.
+  Expect.mapEquals(map, {1: 1, if (true) await future2: 2, 3: 3});
+
+  // Await in then branch value.
+  Expect.mapEquals(map, {1: 1, if (true) 2: await future2, 3: 3});
+
+  // Await in else branch key.
+  Expect.mapEquals(map, {1: 1, if (false) 9: 9 else await future2: 2, 3: 3});
+
+  // Await in else branch value.
+  Expect.mapEquals(map, {1: 1, if (false) 9: 9 else 2: await future2, 3: 3});
+
+  // Await in untaken then branch key.
+  Expect.mapEquals(map, {1: 1, 2: 2, if (false) await future9: 9, 3: 3});
+
+  // Await in untaken then branch value.
+  Expect.mapEquals(map, {1: 1, 2: 2, if (false) 9: await future9, 3: 3});
+
+  // Await in untaken else branch key.
+  Expect.mapEquals(map, {1: 1, if (true) 2: 2 else await future9: 9, 3: 3});
+
+  // Await in untaken else branch value.
+  Expect.mapEquals(map, {1: 1, if (true) 2: 2 else 9: await future9, 3: 3});
+}
+
+Future<void> testSet() async {
+  var futureTrue = Future.value(true);
+  var future2 = Future.value(2);
+  var future9 = Future.value(9);
+
+  // Await in condition.
+  Expect.setEquals(set, {1, if (await futureTrue) 2, 3});
+
+  // Await in then branch.
+  Expect.setEquals(set, {1, if (true) await future2, 3});
+
+  // Await in else branch.
+  Expect.setEquals(set, {1, if (false) 9 else await future2, 3});
+
+  // Await in untaken then branch.
+  Expect.setEquals(set, {1, 2, if (false) await future9, 3});
+
+  // Await in untaken else branch.
+  Expect.setEquals(set, {1, if (true) 2 else await future9, 3});
+}
diff --git a/tests/language/control_flow_collections/if_const_error_test.dart b/tests/language/control_flow_collections/if_const_error_test.dart
new file mode 100644
index 0000000..bc1d0e2
--- /dev/null
+++ b/tests/language/control_flow_collections/if_const_error_test.dart
@@ -0,0 +1,137 @@
+// 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:collection';
+
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+final nonConstBool = true;
+final nonConstInt = 3;
+
+const dynamic nonBool = 3;
+const dynamic nonInt = "s";
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testShortCircuit();
+}
+
+void testList() {
+  // Condition must be constant.
+  const _ = <int>[if (nonConstBool) 1]; //# 01: compile-time error
+
+  // Condition must be Boolean.
+  const _ = <int>[if (nonBool) 1]; //# 02: compile-time error
+
+  // Then element must be constant, whether or not branch is taken.
+  const _ = <int>[if (true) nonConstInt]; //# 03: compile-time error
+  const _ = <int>[if (false) nonConstInt]; //# 04: compile-time error
+
+  // Else element must be constant, whether or not branch is taken.
+  const _ = <int>[if (true) 1 else nonConstInt]; //# 05: compile-time error
+  const _ = <int>[if (false) 1 else nonConstInt]; //# 06: compile-time error
+
+  // Then element must have right type if branch is chosen.
+  const _ = <int>[if (true) nonInt]; //# 07: compile-time error
+
+  // Else element must have right type if branch is chosen.
+  const _ = <int>[if (false) 9 else nonInt]; //# 08: compile-time error
+}
+
+void testMap() {
+  // Condition must be constant.
+  const _ = <int, int>{if (nonConstBool) 1: 1}; //# 09: compile-time error
+
+  // Condition must be Boolean.
+  const _ = <int, int>{if (nonBool) 1: 1}; //# 10: compile-time error
+
+  // Then key element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) nonConstInt: 1}; //# 11: compile-time error
+  const _ = <int, int>{if (false) nonConstInt: 1}; //# 12: compile-time error
+
+  // Then value element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) 1: nonConstInt}; //# 13: compile-time error
+  const _ = <int, int>{if (false) 1: nonConstInt}; //# 14: compile-time error
+
+  // Else key element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) 1 else nonConstInt: 1}; //# 15: compile-time error
+  const _ = <int, int>{if (false) 1 else nonConstInt: 1}; //# 16: compile-time error
+
+  // Else value element must be constant, whether or not branch is taken.
+  const _ = <int, int>{if (true) 1 else 1: nonConstInt}; //# 17: compile-time error
+  const _ = <int, int>{if (false) 1 else 1: nonConstInt}; //# 18: compile-time error
+
+  // Then key element must have right type if branch is chosen.
+  const _ = <int, int>{if (true) nonInt: 1}; //# 19: compile-time error
+
+  // Then value element must have right type if branch is chosen.
+  const _ = <int, int>{if (true) 1: nonInt}; //# 20: compile-time error
+
+  // Else key element must have right type if branch is chosen.
+  const _ = <int, int>{if (false) 9 else nonInt: 1}; //# 21: compile-time error
+
+  // Else value element must have right type if branch is chosen.
+  const _ = <int, int>{if (false) 9 else 1: nonInt}; //# 22: compile-time error
+
+  // Key cannot override operator.==().
+  const obj = 0.1;
+  const _ = {if (true) 0.1: 1}; //# 23: compile-time error
+  const _ = {if (true) Duration(seconds: 0): 1}; //# 24: compile-time error
+  const _ = {if (true) obj: 1}; //# 25: compile-time error
+
+  // Cannot have key collision when branch is chosen.
+  const _ = <int, int>{1: 1, if (true) 1: 1}; //# 25: compile-time error
+  const _ = <int, int>{if (true) 1: 1, if (true) 1: 1}; //# 26: compile-time error
+}
+
+void testSet() {
+  // Condition must be constant.
+  const _ = <int>{if (nonConstBool) 1}; //# 27: compile-time error
+
+  // Condition must be Boolean.
+  const _ = <int>{if (nonBool) 1}; //# 28: compile-time error
+
+  // Then element must be constant, whether or not branch is taken.
+  const _ = <int>{if (true) nonConstInt}; //# 29: compile-time error
+  const _ = <int>{if (false) nonConstInt}; //# 30: compile-time error
+
+  // Else element must be constant, whether or not branch is taken.
+  const _ = <int>{if (true) 1 else nonConstInt}; //# 31: compile-time error
+  const _ = <int>{if (false) 1 else nonConstInt}; //# 32: compile-time error
+
+  // Then element must have right type if branch is chosen.
+  const _ = <int>{if (true) nonInt}; //# 33: compile-time error
+
+  // Else element must have right type if branch is chosen.
+  const _ = <int>{if (false) 9 else nonInt}; //# 34: compile-time error
+
+  // Cannot override operator.==().
+  const obj = 0.1;
+  const _ = {if (true) 0.1}; //# 35: compile-time error
+  const _ = {if (true) Duration(seconds: 0)}; //# 36: compile-time error
+  const _ = {if (true) obj}; //# 37: compile-time error
+
+  // Cannot have collision when branch is chosen.
+  const _ = <int>{1, if (true) 1}; //# 38: compile-time error
+  const _ = <int>{if (true) 1, if (true) 1}; //# 39: compile-time error
+}
+
+void testShortCircuit() {
+  // A const expression that throws causes a compile error if it occurs inside
+  // the chosen branch of an if.
+
+  // Store null in a dynamically-typed constant to avoid the type error on "+".
+  const dynamic nil = null;
+
+  // With no else.
+  const _ = [if (true) nil + 1]; //# 40: compile-time error
+
+  // With else.
+  const _ = [if (true) nil + 1 else 1]; //# 41: compile-time error
+  const _ = [if (false) 1 else nil + 1]; //# 42: compile-time error
+}
diff --git a/tests/language/control_flow_collections/if_const_test.dart b/tests/language/control_flow_collections/if_const_test.dart
new file mode 100644
index 0000000..78417bc
--- /dev/null
+++ b/tests/language/control_flow_collections/if_const_test.dart
@@ -0,0 +1,238 @@
+// 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:expect/expect.dart';
+
+import 'utils.dart';
+
+// Typed as dynamic to also test spreading a value of type dynamic.
+const dynamic list = [1, 2, 3];
+const dynamic map = {1: 1, 2: 2, 3: 3};
+const dynamic set = {1, 2, 3};
+
+const dynamic dynamicTrue = true;
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testShortCircuit();
+  testDuplicateKeys();
+  testKeyOrder();
+}
+
+void testList() {
+  // Then if true.
+  Expect.identical(list, const <int>[1, if (true) 2, 3]);
+
+  // Nothing if false and no else.
+  Expect.identical(list, const <int>[1, if (false) 9, 2, 3]);
+
+  // Else if false.
+  Expect.identical(list, const <int>[1, if (false) 9 else 2, 3]);
+
+  // Only if.
+  Expect.identical(const [1], const <int>[if (true) 1]);
+
+  // If at beginning.
+  Expect.identical(list, const <int>[if (true) 1, 2, 3]);
+
+  // If in middle.
+  Expect.identical(list, const <int>[1, if (true) 2, 3]);
+
+  // If at end.
+  Expect.identical(list, const <int>[1, 2, if (true) 3]);
+
+  // Multiple ifs.
+  Expect.identical(list,
+      const <int>[if (true) 1, if (false) 9, 2, if (true) 3]);
+
+  // Cast condition.
+  Expect.identical(const [1], const <int>[if (dynamicTrue) 1]);
+
+  // Does not flatten nested collection literal.
+  Expect.identical(const [1], const [if (true) [1]].first);
+  Expect.identical(const {1: 1}, const [if (true) {1: 1}].first);
+  Expect.identical(const {1}, const [if (true) {1}].first);
+
+  // Nested spread.
+  Expect.identical(list,
+      const <int>[if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]]);
+
+  // Nested if in then.
+  Expect.identical(const [1],
+      const <int>[if (true) if (true) 1, if (true) if (false) 9]);
+
+  // Nested if in else.
+  Expect.identical(const [1], const <int>[if (false) 9 else if (true) 1]);
+}
+
+void testMap() {
+  // Then if true.
+  Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // Nothing if false and no else.
+  Expect.identical(map, const <int, int>{1: 1, if (false) 9: 9, 2: 2, 3: 3});
+
+  // Else if false.
+  Expect.identical(map,
+      const <int, int>{1: 1, if (false) 9: 9 else 2: 2, 3: 3});
+
+  // Only if.
+  Expect.identical(const {1: 1}, const <int, int>{if (true) 1: 1});
+
+  // If at beginning.
+  Expect.identical(map, const <int, int>{if (true) 1: 1, 2: 2, 3: 3});
+
+  // If in middle.
+  Expect.identical(map, const <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // If at end.
+  Expect.identical(map, const <int, int>{1: 1, 2: 2, if (true) 3: 3});
+
+  // Multiple ifs.
+  Expect.identical(map,
+      const <int, int>{if (true) 1: 1, if (false) 9: 9, 2: 2, if (true) 3: 3});
+
+  // Cast condition.
+  Expect.identical(const {1: 1}, const <int, int>{if (dynamicTrue) 1: 1});
+
+  // Nested spread.
+  Expect.identical(map, const <int, int>{
+    if (true) ...<int, int>{1: 1, 2: 2},
+    if (false) 9: 9 else ...<int, int>{3: 3}
+  });
+
+  // Nested if in then.
+  Expect.identical(const {1: 1},
+      const <int, int>{if (true) if (true) 1: 1, if (true) if (false) 9: 9});
+
+  // Nested if in else.
+  Expect.identical(const {1: 1},
+      const <int, int>{if (false) 9: 9 else if (true) 1: 1});
+}
+
+void testSet() {
+  // Then if true.
+  Expect.identical(set, const <int>{1, if (true) 2, 3});
+
+  // Nothing if false and no else.
+  Expect.identical(set, const <int>{1, if (false) 9, 2, 3});
+
+  // Else if false.
+  Expect.identical(set, const <int>{1, if (false) 9 else 2, 3});
+
+  // Only if.
+  Expect.identical(const <int>{1}, const <int>{if (true) 1});
+
+  // If at beginning.
+  Expect.identical(set, const <int>{if (true) 1, 2, 3});
+
+  // If in middle.
+  Expect.identical(set, const <int>{1, if (true) 2, 3});
+
+  // If at end.
+  Expect.identical(set, const <int>{1, 2, if (true) 3});
+
+  // Multiple ifs.
+  Expect.identical(set,
+      const <int>{if (true) 1, if (false) 9, 2, if (true) 3});
+
+  // Cast condition.
+  Expect.identical(const <int>{1}, const <int>{if (dynamicTrue) 1});
+
+  // Does not flatten nested collection literal.
+  Expect.identical(const <int>[1], const <List<int>>{if (true) [1]}.first);
+  Expect.identical(
+      const <int, int>{1: 1}, const <Map<int, int>>{if (true) {1: 1}}.first);
+  Expect.identical(const <int>{1}, const <Set<int>>{if (true) {1}}.first);
+
+  // Nested spread.
+  Expect.identical(set,
+      const <int>{if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]});
+
+  // Nested if in then.
+  Expect.identical(const <int>{1},
+      const <int>{if (true) if (true) 1, if (true) if (false) 9});
+
+  // Nested if in else.
+  Expect.identical(const <int>{1}, const <int>{if (false) 9 else if (true) 1});
+}
+
+void testShortCircuit() {
+  // A const expression that throws does not cause a compile error if it occurs
+  // inside an unchosen branch of an if.
+
+  // Store null in a dynamically-typed constant to avoid the type error on "+".
+  const dynamic nil = null;
+
+  Expect.identical(const <int>[1],
+      const <int>[if (true) 1, if (false) nil + 1]);
+  Expect.identical(const <int>[1, 2],
+      const <int>[if (true) 1 else nil + 1, if (false) nil + 1 else 2]);
+
+  Expect.identical(const <int, int>{1: 1}, const <int, int>{
+    if (true) 1: 1,
+    if (false) nil + 1: 9,
+    if (false) 9: nil + 1
+  });
+  Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
+    if (true) 1: 1 else nil + 1: 9,
+    if (false) 9: nil + 1 else 2: 2
+  });
+
+  Expect.identical(const <int>{1},
+      const <int>{if (true) 1, if (false) nil + 1});
+  Expect.identical(const <int>{1, 2},
+      const <int>{if (true) 1 else nil + 1, if (false) nil + 1 else 2});
+
+  // A const expression whose value isn't the right type does not cause a
+  // compile error if it occurs inside an unchosen branch.
+  const dynamic nonInt = "s";
+
+  Expect.identical(const <int>[1], const <int>[if (true) 1, if (false) nonInt]);
+  Expect.identical(const <int>[1, 2],
+      const <int>[if (true) 1 else nonInt, if (false) nonInt else 2]);
+
+  Expect.identical(const <int, int>{1: 1}, const <int, int>{
+    if (true) 1: 1,
+    if (false) nonInt: 9,
+    if (false) 9: nonInt
+  });
+  Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
+    if (true) 1: 1 else nonInt: 9,
+    if (false) 9: nonInt else 2: 2
+  });
+
+  Expect.identical(const <int>{1}, const <int>{if (true) 1, if (false) nonInt});
+  Expect.identical(const <int>{1, 2},
+      const <int>{if (true) 1 else nonInt, if (false) nonInt else 2});
+}
+
+void testDuplicateKeys() {
+  // Duplicate keys from unchosen branches are not an error.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    if (false) 1: 1,
+    if (true) 2: 2 else 3: 3,
+    3: 3
+  });
+
+  Expect.setEquals(set, const <int>{1, if (false) 1, if (true) 2 else 3, 3});
+}
+
+void testKeyOrder() {
+  // Canonicalization isn't affected by which elements are conditional.
+  Expect.identical(map,
+      const <int, int>{1: 1, if (true) 2: 2, if (false) 9: 9, 3: 3});
+  Expect.identical(map,
+      const <int, int>{if (false) 9: 9 else 1: 1, 2: 2, if (true) 3: 3});
+
+  Expect.identical(set, const <int>{1, if (true) 2, if (false) 9, 3});
+  Expect.identical(set, const <int>{if (false) 9 else 1, 2, if (true) 3});
+
+  // Ordering does affect canonicalization.
+  Expect.notIdentical(map, const <int, int>{1: 1, if (true) 3: 3, 2: 2});
+  Expect.notIdentical(set, const <int>{1, if (true) 3, 2});
+}
diff --git a/tests/language/control_flow_collections/if_downcast_test.dart b/tests/language/control_flow_collections/if_downcast_test.dart
new file mode 100644
index 0000000..4150456
--- /dev/null
+++ b/tests/language/control_flow_collections/if_downcast_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.
+
+void main() {
+  var a = <int>[if (true as Object) 1];
+  //                ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+  //                     ^
+  // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+
+  var b = <int, int>{if (true as Object) 1: 1};
+  //                     ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+  //                          ^
+  // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+
+  var c = <int>{if (true as Object) 1};
+  //                ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+  //                     ^
+  // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+}
diff --git a/tests/language/control_flow_collections/if_dynamic_null_strong_test.dart b/tests/language/control_flow_collections/if_dynamic_null_strong_test.dart
new file mode 100644
index 0000000..0450c0b
--- /dev/null
+++ b/tests/language/control_flow_collections/if_dynamic_null_strong_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.
+
+// Requirements=nnbd-strong
+import 'package:expect/expect.dart';
+
+void main() {
+  dynamic nullBool;
+  Expect.throwsTypeError(() => <int>[if (nullBool) 1]);
+  Expect.throwsTypeError(() => <int, int>{if (nullBool) 1: 1});
+  Expect.throwsTypeError(() => <int>{if (nullBool) 1});
+}
diff --git a/tests/language/control_flow_collections/if_dynamic_null_weak_test.dart b/tests/language/control_flow_collections/if_dynamic_null_weak_test.dart
new file mode 100644
index 0000000..4e76cf3
--- /dev/null
+++ b/tests/language/control_flow_collections/if_dynamic_null_weak_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.
+
+// Requirements=nnbd-weak
+import 'package:expect/expect.dart';
+
+void main() {
+  dynamic nullBool;
+  Expect.throwsAssertionError(() => <int>[if (nullBool) 1]);
+  Expect.throwsAssertionError(() => <int, int>{if (nullBool) 1: 1});
+  Expect.throwsAssertionError(() => <int>{if (nullBool) 1});
+}
diff --git a/tests/language/control_flow_collections/if_inference_test.dart b/tests/language/control_flow_collections/if_inference_test.dart
new file mode 100644
index 0000000..11c7b95
--- /dev/null
+++ b/tests/language/control_flow_collections/if_inference_test.dart
@@ -0,0 +1,81 @@
+// 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 how control flow interacts with inference.
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+void main() {
+  testBottomUpInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  // Lists.
+  expectListOf<int>([if (true) 1]);
+  expectListOf<int>([if (true) 1 else 2]);
+  expectListOf<num>([if (true) 1 else 0.2]);
+  expectListOf<int>([if (true) 1, 2]);
+  expectListOf<num>([if (true) 1, 0.2]);
+  expectListOf<dynamic>([if (true) ...[]]);
+  expectListOf<int>([if (true) ...<int>[]]);
+
+  // Maps.
+  expectMapOf<int, int>({if (true) 1: 1});
+  expectMapOf<int, int>({if (true) 1: 1 else 2: 2});
+  expectMapOf<num, num>({if (true) 1: 0.1 else 0.2: 2});
+  expectMapOf<int, int>({if (true) 1: 1, 2: 2});
+  expectMapOf<num, num>({if (true) 1: 0.1, 0.2: 2});
+  expectMapOf<dynamic, dynamic>({if (true) ...{}});
+  expectMapOf<int, int>({if (true) ...<int, int>{}});
+
+  // Sets.
+  expectSetOf<int>({if (true) 1});
+  expectSetOf<int>({if (true) 1 else 2});
+  expectSetOf<num>({if (true) 1 else 0.2});
+  expectSetOf<int>({if (true) 1, 2});
+  expectSetOf<num>({if (true) 1, 0.2});
+  expectSetOf<dynamic>({if (true) ...[]});
+  expectSetOf<int>({if (true) ...<int>[]});
+
+  // If a nested iterable's type is dynamic, the element type is dynamic.
+  expectListOf<dynamic>([if (true) ...([] as dynamic)]);
+  expectSetOf<dynamic>({1, if (true) ...([] as dynamic)});
+
+  // If a nested maps's type is dynamic, the key and value types are dynamic.
+  expectMapOf<dynamic, dynamic>({1: 1, if (true) ...({} as dynamic)});
+}
+
+void testTopDownInference() {
+  // Lists.
+
+  // The context element type is pushed into the branches.
+  Expect.listEquals(<int>[1], <int>[if (true) expectInt(1)]);
+  Expect.listEquals(<int>[1], <int>[if (false) 9 else expectInt(1)]);
+
+  // Bottom up-inference from elements is not pushed back down into branches.
+  Expect.listEquals(<int>[1, 2], [1, if (true) expectDynamic(2)]);
+  Expect.listEquals(<int>[1, 2], [1, if (false) 9 else expectDynamic(2)]);
+
+  // Maps.
+
+  // The context element type is pushed into the branches.
+  Expect.mapEquals(<int, String>{1: "s"},
+      <int, String>{if (true) expectInt(1): expectString("s")});
+
+  // Bottom up-inference from elements is not pushed back down into branches.
+  Expect.mapEquals(<int, String>{1: "s", 2: "t"},
+      {1: "s", if (true) expectDynamic(2): expectDynamic("t")});
+
+  // Sets.
+
+  // The context element type is pushed into the branches.
+  Expect.setEquals(<int>{1}, <int>{if (true) expectInt(1)});
+  Expect.setEquals(<int>{1}, <int>{if (false) 9 else expectInt(1)});
+
+  // Bottom up-inference from elements is not pushed back down into branches.
+  Expect.setEquals(<int>{1, 2}, {1, if (true) expectDynamic(2)});
+  Expect.setEquals(<int>{1, 2}, {1, if (false) 9 else expectDynamic(2)});
+}
diff --git a/tests/language/control_flow_collections/if_null_condition_test.dart b/tests/language/control_flow_collections/if_null_condition_test.dart
new file mode 100644
index 0000000..4e613c2
--- /dev/null
+++ b/tests/language/control_flow_collections/if_null_condition_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+void main() {
+  bool? nullBool;
+  var a = <int>[if (nullBool) 1];
+  //                ^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
+
+  var b = <int, int>{if (nullBool) 1: 1};
+  //                     ^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
+
+  var c = <int>{if (nullBool) 1};
+  //                ^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
+}
diff --git a/tests/language/control_flow_collections/if_promotion_test.dart b/tests/language/control_flow_collections/if_promotion_test.dart
new file mode 100644
index 0000000..382db01
--- /dev/null
+++ b/tests/language/control_flow_collections/if_promotion_test.dart
@@ -0,0 +1,55 @@
+// 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 A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+void main() {
+  A a = A();
+  print(a.a);
+  print(a.b); //# 01: compile-time error
+
+  var list = [
+    a.a,
+    a.b, //# 02: compile-time error
+    a.c, //# 03: compile-time error
+
+    if (a is B) [
+      a.a,
+      a.b,
+      a.c, //# 04: compile-time error
+
+      if (a is C) [
+        a.a,
+        a.b,
+        a.c,
+      ] else [
+        a.a,
+        a.b,
+        a.c, //# 05: compile-time error
+      ],
+
+      a.a,
+      a.b,
+      a.c, //# 06: compile-time error
+    ] else [
+      a.a,
+      a.b, //# 07: compile-time error
+      a.c, //# 08: compile-time error
+    ],
+
+    a.a,
+    a.b, //# 09: compile-time error
+    a.c, //# 10: compile-time error
+  ];
+}
diff --git a/tests/language/control_flow_collections/if_runtime_error_test.dart b/tests/language/control_flow_collections/if_runtime_error_test.dart
new file mode 100644
index 0000000..1dba5b8
--- /dev/null
+++ b/tests/language/control_flow_collections/if_runtime_error_test.dart
@@ -0,0 +1,12 @@
+// 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:expect/expect.dart';
+
+void main() {
+  dynamic nonBool = 3;
+  Expect.throwsTypeError(() => <int>[if (nonBool) 1]);
+  Expect.throwsTypeError(() => <int, int>{if (nonBool) 1: 1});
+  Expect.throwsTypeError(() => <int>{if (nonBool) 1});
+}
diff --git a/tests/language/control_flow_collections/if_test.dart b/tests/language/control_flow_collections/if_test.dart
new file mode 100644
index 0000000..6113823
--- /dev/null
+++ b/tests/language/control_flow_collections/if_test.dart
@@ -0,0 +1,225 @@
+// 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:expect/expect.dart';
+
+import 'utils.dart';
+
+final list = [1, 2, 3];
+final map = {1: 1, 2: 2, 3: 3};
+final set = {1, 2, 3};
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testShortCircuit();
+  testDuplicateKeys();
+  testKeyOrder();
+}
+
+void testList() {
+  // Then if true.
+  Expect.listEquals(list, <int>[1, if (true) 2, 3]);
+
+  // Nothing if false and no else.
+  Expect.listEquals(list, <int>[1, if (false) 9, 2, 3]);
+
+  // Else if false.
+  Expect.listEquals(list, <int>[1, if (false) 9 else 2, 3]);
+
+  // Only if.
+  Expect.listEquals([1], <int>[if (true) 1]);
+
+  // If at beginning.
+  Expect.listEquals(list, <int>[if (true) 1, 2, 3]);
+
+  // If in middle.
+  Expect.listEquals(list, <int>[1, if (true) 2, 3]);
+
+  // If at end.
+  Expect.listEquals(list, <int>[1, 2, if (true) 3]);
+
+  // Multiple ifs.
+  Expect.listEquals(list,
+      <int>[if (true) 1, if (false) 9, 2, if (true) 3]);
+
+  // Cast condition.
+  Expect.listEquals(<int>[1], <int>[if (true as dynamic) 1]);
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], [if (true) [1]].first);
+  Expect.mapEquals({1: 1}, [if (true) {1: 1}].first);
+  Expect.setEquals({1}, [if (true) {1}].first);
+
+  // Nested spread.
+  Expect.listEquals(list,
+      <int>[if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]]);
+
+  // Nested if in then.
+  Expect.listEquals([1], <int>[if (true) if (true) 1, if (true) if (false) 9]);
+
+  // Nested if in else.
+  Expect.listEquals([1], <int>[if (false) 9 else if (true) 1]);
+
+  // Nested for in then.
+  Expect.listEquals(list, <int>[if (true) for (var i in list) i]);
+
+  // Nested for in else.
+  Expect.listEquals(list, <int>[if (false) 9 else for (var i in list) i]);
+}
+
+void testMap() {
+  // Then if true.
+  Expect.mapEquals(map, <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // Nothing if false and no else.
+  Expect.mapEquals(map, <int, int>{1: 1, if (false) 9: 9, 2: 2, 3: 3});
+
+  // Else if false.
+  Expect.mapEquals(map, <int, int>{1: 1, if (false) 9: 9 else 2: 2, 3: 3});
+
+  // Only if.
+  Expect.mapEquals(<int, int>{1: 1}, <int, int>{if (true) 1: 1});
+
+  // If at beginning.
+  Expect.mapEquals(map, <int, int>{if (true) 1: 1, 2: 2, 3: 3});
+
+  // If in middle.
+  Expect.mapEquals(map, <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // If at end.
+  Expect.mapEquals(map, <int, int>{1: 1, 2: 2, if (true) 3: 3});
+
+  // Multiple ifs.
+  Expect.mapEquals(map,
+      <int, int>{if (true) 1: 1, if (false) 9: 9, 2: 2, if (true) 3: 3});
+
+  // Cast condition.
+  Expect.mapEquals(<int, int>{1: 1}, <int, int>{if (true as dynamic) 1: 1});
+
+  // Nested spread.
+  Expect.mapEquals(map, <int, int>{
+    if (true) ...<int, int>{1: 1, 2: 2},
+    if (false) 9: 9 else ...<int, int>{3: 3}
+  });
+
+  // Nested if in then.
+  Expect.mapEquals({1: 1},
+      <int, int>{if (true) if (true) 1: 1, if (true) if (false) 9: 9});
+
+  // Nested if in else.
+  Expect.mapEquals({1: 1},
+      <int, int>{if (false) 9: 9 else if (true) 1: 1});
+
+  // Nested for in then.
+  Expect.mapEquals(map, <int, int>{if (true) for (var i in list) i: i});
+
+  // Nested for in else.
+  Expect.mapEquals(map, <int, int>{if (false) 9: 9 else for (var i in list) i: i});
+}
+
+void testSet() {
+  // Then if true.
+  Expect.setEquals(set, <int>{1, if (true) 2, 3});
+
+  // Nothing if false and no else.
+  Expect.setEquals(set, <int>{1, if (false) 9, 2, 3});
+
+  // Else if false.
+  Expect.setEquals(set, <int>{1, if (false) 9 else 2, 3});
+
+  // Only if.
+  Expect.setEquals({1}, <int>{if (true) 1});
+
+  // If at beginning.
+  Expect.setEquals(set, <int>{if (true) 1, 2, 3});
+
+  // If in middle.
+  Expect.setEquals(set, <int>{1, if (true) 2, 3});
+
+  // If at end.
+  Expect.setEquals(set, <int>{1, 2, if (true) 3});
+
+  // Multiple ifs.
+  Expect.setEquals(set,
+      <int>{if (true) 1, if (false) 9, 2, if (true) 3});
+
+  // Cast condition.
+  Expect.setEquals({1}, <int>{if (true as dynamic) 1});
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], {if (true) [1]}.first);
+  Expect.mapEquals({1: 1}, {if (true) {1: 1}}.first);
+  Expect.setEquals({1}, {if (true) {1}}.first);
+
+  // Nested spread.
+  Expect.setEquals(set,
+      <int>{if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]});
+
+  // Nested if in then.
+  Expect.setEquals({1}, <int>{if (true) if (true) 1, if (true) if (false) 9});
+
+  // Nested if in else.
+  Expect.setEquals({1}, <int>{if (false) 9 else if (true) 1});
+
+  // Nested for in then.
+  Expect.setEquals(set, <int>{if (true) for (var i in list) i});
+
+  // Nested for in else.
+  Expect.setEquals(set, <int>{if (false) 9 else for (var i in list) i});
+}
+
+void testShortCircuit() {
+  var transcript = <String>[];
+  T log<T>(T value) {
+    transcript.add(value.toString());
+    return value;
+  }
+
+  // With no else.
+  Expect.listEquals([1], [if (true) log(1), if (false) log(2)]);
+  Expect.equals("1", transcript.join(","));
+  transcript.clear();
+
+  // With else.
+  Expect.listEquals([1, 4],
+      [if (true) log(1) else log(2), if (false) log(3) else log(4)]);
+  Expect.equals("1,4", transcript.join(","));
+}
+
+void testDuplicateKeys() {
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    if (true) 1: 1,
+    if (false) 9: 9 else 2: 2,
+    2: 2,
+    3: 3
+  });
+  Expect.setEquals(set, <int>{1, if (true) 1, if (false) 9 else 2, 2, 3});
+}
+
+void testKeyOrder() {
+  // First equal key wins.
+  var e1a = Equality(1, "a");
+  var e1b = Equality(1, "b");
+  var e2a = Equality(2, "a");
+  var e2b = Equality(2, "b");
+
+  var map = <Equality, int>{
+    e1a: 0,
+    if (true) e1b: 0,
+    if (true) e2a: 0,
+    if (true) e2b: 0
+  };
+  Expect.equals("1:a,2:a", map.keys.join(","));
+
+  var set = <Equality>{
+    e1a,
+    if (true) e1b,
+    if (true) e2a,
+    if (true) e2b
+  };
+  Expect.equals("1:a,2:a", set.join(","));
+}
diff --git a/tests/language/control_flow_collections/map_set_ambiguity_error_test.dart b/tests/language/control_flow_collections/map_set_ambiguity_error_test.dart
new file mode 100644
index 0000000..ae4fee4
--- /dev/null
+++ b/tests/language/control_flow_collections/map_set_ambiguity_error_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.
+
+// Test cases where the syntax is ambiguous between maps and sets when control
+// flow elements contain spreads.
+import 'dart:collection';
+
+import 'utils.dart';
+
+void main() {
+  Map<int, int> map = {};
+  Set<int> set = Set();
+  dynamic dyn = map;
+  Iterable<int> iterable = [];
+  CustomSet customSet = CustomSet();
+  CustomMap customMap = CustomMap();
+
+  var _ = {if (true) ...dyn}; //# 00: compile-time error
+  var _ = {if (true) ...map else ...set}; //# 01: compile-time error
+  var _ = {if (true) ...map else ...iterable}; //# 02: compile-time error
+  var _ = {if (true) ...map else ...customSet}; //# 03: compile-time error
+  var _ = {if (true) ...set else ...customMap}; //# 04: compile-time error
+  var _ = {if (true) ...dyn else ...dyn}; //# 05: compile-time error
+  var _ = {if (true) ...iterable else ...customMap}; //# 06: compile-time error
+  var _ = {if (true) ...customSet else ...customMap}; //# 07: compile-time error
+
+  var _ = {for (; false;) ...dyn}; //# 08: compile-time error
+  var _ = {for (; false;) ...map, ...set}; //# 09: compile-time error
+  var _ = {for (; false;) ...map, ...iterable}; //# 10: compile-time error
+  var _ = {for (; false;) ...map, ...customSet}; //# 11: compile-time error
+  var _ = {for (; false;) ...set, ...customMap}; //# 12: compile-time error
+  var _ = {for (; false;) ...dyn, ...dyn}; //# 13: compile-time error
+  var _ = {for (; false;) ...iterable, ...customMap}; //# 14: compile-time error
+  var _ = {for (; false;) ...customSet, ...customMap}; //# 15: compile-time error
+}
diff --git a/tests/language/control_flow_collections/map_set_ambiguity_test.dart b/tests/language/control_flow_collections/map_set_ambiguity_test.dart
new file mode 100644
index 0000000..bf5f685
--- /dev/null
+++ b/tests/language/control_flow_collections/map_set_ambiguity_test.dart
@@ -0,0 +1,128 @@
+// 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 cases where the syntax is ambiguous between maps and sets because of
+// spreads inside control flow.
+import 'dart:collection';
+
+import 'utils.dart';
+
+void main() {
+  testBottomUpInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  Map<int, int> map = {};
+  Set<int> set = Set();
+  dynamic dynMap = map;
+  dynamic dynSet = set;
+  Iterable<int> iterable = [];
+  CustomSet customSet = CustomSet();
+  CustomMap customMap = CustomMap();
+
+  // Note: The commented out cases are the error cases. They are shown here for
+  // completeness and tested in map_set_ambiguity_error_test.dart.
+  expectMapOf<int, int>({if (true) ...map});
+  expectSetOf<int>({if (true) ...set});
+  // expect___Of<...>({if (true) ...dyn});
+  expectSetOf<int>({if (true) ...iterable});
+  expectSetOf<int>({if (true) ...customSet});
+  expectMapOf<int, String>({if (true) ...customMap});
+
+  expectMapOf<int, int>({if (true) ...map else ...map});
+  // expect___Of<...>({if (true) ...map else ...set});
+  expectMapOf<dynamic, dynamic>({if (true) ...map else ...dynMap});
+  // expect___Of<...>({if (true) ...map else ...iterable});
+  // expect___Of<...>({if (true) ...map else ...customSet});
+  expectMapOf<int, Object>({if (true) ...map else ...customMap});
+
+  expectSetOf<int>({if (true) ...set else ...set});
+  expectSetOf<dynamic>({if (true) ...set else ...dynSet});
+  expectSetOf<int>({if (true) ...set else ...iterable});
+  expectSetOf<int>({if (true) ...set else ...customSet});
+  // expect___Of<...>({if (true) ...set else ...customMap});
+
+  // expect___Of<...>({if (true) ...dyn else ...dyn});
+  expectSetOf<dynamic>({if (true) ...dynSet else ...iterable});
+  expectSetOf<dynamic>({if (true) ...dynSet else ...customSet});
+  expectMapOf<dynamic, dynamic>({if (true) ...dynMap else ...customMap});
+
+  expectSetOf<int>({if (true) ...iterable else ...iterable});
+  expectSetOf<int>({if (true) ...iterable else ...customSet});
+  // expect___Of<...>({if (true) ...iterable else ...customMap});
+
+  expectSetOf<int>({if (true) ...customSet else ...customSet});
+  // expect___Of<...>({if (true) ...customSet else ...customMap});
+
+  expectMapOf<int, String>({if (true) ...customMap else ...customMap});
+
+  // Note: The commented out cases are the error cases. They are shown here for
+  // completeness and tested in map_set_ambiguity_error_test.dart.
+  expectMapOf<int, int>({for (; false;) ...map});
+  expectSetOf<int>({for (; false;) ...set});
+  // expect___Of<...>({for (; false;) ...dyn});
+  expectSetOf<int>({for (; false;) ...iterable});
+  expectSetOf<int>({for (; false;) ...customSet});
+  expectMapOf<int, String>({for (; false;) ...customMap});
+
+  expectMapOf<int, int>({for (; false;) ...map, for (; false;) ...map});
+  // expect___Of<...>({for (; false;) ...map, for (; false;) ...set});
+  expectMapOf<dynamic, dynamic>(
+      {for (; false;) ...map, for (; false;) ...dynMap});
+  // expect___Of<...>({for (; false;) ...map, for (; false;) ...iterable});
+  // expect___Of<...>({for (; false;) ...map, for (; false;) ...customSet});
+  expectMapOf<int, Object>(
+      {for (; false;) ...map, for (; false;) ...customMap});
+
+  expectSetOf<int>({for (; false;) ...set, for (; false;) ...set});
+  expectSetOf<dynamic>({for (; false;) ...set, for (; false;) ...dynSet});
+  expectSetOf<int>({for (; false;) ...set, for (; false;) ...iterable});
+  expectSetOf<int>({for (; false;) ...set, for (; false;) ...customSet});
+  // expect___Of<...>({for (; false;) ...set, for (; false;) ...customMap});
+
+  // expect___Of<...>({for (; false;) ...dyn, for (; false;) ...dyn});
+  expectSetOf<dynamic>(
+      {for (; false;) ...dynSet, for (; false;) ...iterable});
+  expectSetOf<dynamic>(
+      {for (; false;) ...dynSet, for (; false;) ...customSet});
+  expectMapOf<dynamic, dynamic>(
+      {for (; false;) ...dynMap, for (; false;) ...customMap});
+
+  expectSetOf<int>(
+      {for (; false;) ...iterable, for (; false;) ...iterable});
+  expectSetOf<int>(
+      {for (; false;) ...iterable, for (; false;) ...customSet});
+  // expect___Of<...>(
+  //     {for (; false;) ...iterable, for (; false;) ...customMap});
+
+  expectSetOf<int>(
+      {for (; false;) ...customSet, for (; false;) ...customSet});
+  // expect___Of<...>(
+  //     {for (; false;) ...customSet, for (; false;) ...customMap});
+
+  expectMapOf<int, String>(
+      {for (; false;) ...customMap, for (; false;) ...customMap});
+}
+
+void testTopDownInference() {
+  dynamic untypedMap = <int, int>{};
+  dynamic untypedIterable = <int>[];
+
+  Map<int, int> map = {if (true) ...untypedMap};
+  Set<int> set = {if (true) ...untypedIterable};
+  Iterable<int> iterable = {if (true) ...untypedIterable};
+
+  expectMapOf<int, int>(map);
+  expectSetOf<int>(set);
+  expectSetOf<int>(iterable);
+
+  map = {for (; false;) ...untypedMap};
+  set = {for (; false;) ...untypedIterable};
+  iterable = {for (; false;) ...untypedIterable};
+
+  expectMapOf<int, int>(map);
+  expectSetOf<int>(set);
+  expectSetOf<int>(iterable);
+}
diff --git a/tests/language/control_flow_collections/syntax_error_test.dart b/tests/language/control_flow_collections/syntax_error_test.dart
new file mode 100644
index 0000000..8b9fa65
--- /dev/null
+++ b/tests/language/control_flow_collections/syntax_error_test.dart
@@ -0,0 +1,40 @@
+// 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.
+
+void main() {
+  // No then element.
+  var _ = [if (true)]; //# 00: syntax error
+
+  // No then element with else.
+  var _ = [if (true) else 0]; //# 01: syntax error
+
+  // No else element.
+  var _ = [if (true) 0 else]; //# 02: syntax error
+
+  // Spread if.
+  var _ = [...if (true) 0]; //# 03: syntax error
+
+  // Spread for.
+  var _ = [...for (; false;) 0]; //# 04: syntax error
+
+  // Use if in map entry.
+  var _ = {if (true) 1: 1: 2}; //# 05: syntax error
+  var _ = {1: if (true) 2: 2}; //# 06: syntax error
+
+  // Use for in map entry.
+  var _ = {for (; false;) 1: 1: 2}; //# 07: syntax error
+  var _ = {1: for (; false;) 2: 2}; //# 08: syntax error
+
+  // Use for variable out of scope.
+  var _ = [for (var i = 0; false;) 1, i]; //# 09: compile-time error
+
+  // Use for-in variable out of scope.
+  var _ = [for (var i in [1]; false;) 1, i]; //# 10: syntax error
+
+  // Use for variable in own initializer.
+  var _ = [for (var i = i; false;) 1]; //# 11: compile-time error
+
+  // Use for-in variable in own initializer.
+  var _ = [for (var i in [i]) 1]; //# 12: compile-time error
+}
diff --git a/tests/language/control_flow_collections/syntax_test.dart b/tests/language/control_flow_collections/syntax_test.dart
new file mode 100644
index 0000000..0ed9829
--- /dev/null
+++ b/tests/language/control_flow_collections/syntax_test.dart
@@ -0,0 +1,44 @@
+// 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.
+
+// Tests syntax edge cases.
+import 'package:expect/expect.dart';
+
+void main() {
+  // Trailing comma after then.
+  Expect.listEquals([1], [if (true) 1,]);
+  Expect.mapEquals({1: 1}, {if (true) 1: 1,});
+  Expect.setEquals({1}, {if (true) 1,});
+
+  // Trailing comma after else.
+  Expect.listEquals([1], [if (true) 1 else 2,]);
+  Expect.mapEquals({1: 1}, {if (true) 1: 1 else 2: 2,});
+  Expect.setEquals({1}, {if (true) 1 else 2,});
+
+  // Trailing comma after for.
+  Expect.listEquals([1], [1, for (; false;) 2,]);
+  Expect.mapEquals({1: 1}, {1: 1, for (; false;) 2: 2,});
+  Expect.setEquals({1}, {1, for (; false;) 2,});
+
+  // Dangling else.
+  Expect.listEquals([1], [if (true) if (false) 0 else 1]);
+  Expect.listEquals([1], [if (true) if (false) 0 else 1 else 2]);
+  Expect.listEquals([2], [if (false) if (false) 0 else 1 else 2]);
+
+  // Precedence of then.
+  Expect.listEquals([1, 2, 3], [1, if (true) true ? 2 : 0, 3]);
+  var a = 0;
+  Expect.listEquals([1, 2, 3], [1, if (true) a = 2, 3]);
+
+  // Precedence of else.
+  Expect.listEquals([1, 2, 3], [1, if (false) 0 else true ? 2 : 0, 3]);
+  a = 0;
+  Expect.listEquals([1, 2, 3], [1, if (false) 0 else a = 2, 3]);
+
+  // Precedence of for.
+  Expect.listEquals([1, 2, 3],
+      [1, for (var i = 0; i < 1; i++) true ? 2 : 0, 3]);
+  a = 0;
+  Expect.listEquals([1, 2, 3], [1, for (var i = 0; i < 1; i++) a = 2, 3]);
+}
diff --git a/tests/language/control_flow_collections/type_error_test.dart b/tests/language/control_flow_collections/type_error_test.dart
new file mode 100644
index 0000000..63f6706
--- /dev/null
+++ b/tests/language/control_flow_collections/type_error_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.
+
+void main() {
+  // Non-Boolean if condition.
+  var _ = <int>[if (1) 2]; //# 00: compile-time error
+  var _ = <int, int>{if (1) 2: 2}; //# 01: compile-time error
+  var _ = <int>{if (1) 2}; //# 02: compile-time error
+
+  // Wrong then element type.
+  var _ = <int>[if (true) "s"]; //# 04: compile-time error
+  var _ = <int, int>{if (true) "s": 1}; //# 05: compile-time error
+  var _ = <int, int>{if (true) 1: "s"}; //# 06: compile-time error
+  var _ = <int>{if (true) "s"}; //# 07: compile-time error
+
+  // Wrong else element type.
+  var _ = <int>[if (false) 1 else "s"]; //# 08: compile-time error
+  var _ = <int, int>{if (false) 1: 1 else "s": 2}; //# 09: compile-time error
+  var _ = <int, int>{if (false) 1: 1 else 2: "s"}; //# 10: compile-time error
+  var _ = <int>{if (false) 1 else "s"}; //# 11: compile-time error
+
+  // Non-Boolean for condition.
+  var _ = <int>[for (; 1;) 2]; //# 12: compile-time error
+  var _ = <int, int>{for (; 1;) 2: 2}; //# 13: compile-time error
+  var _ = <int>{for (; 1;) 2}; //# 14: compile-time error
+
+  // Wrong for-in element type.
+  List<String> s = ["s"];
+  var _ = <int>[for (int i in s) 1]; //# 15: compile-time error
+  var _ = <int, int>{for (int i in s) 1: 1}; //# 16: compile-time error
+  var _ = <int>{for (int i in s) 1}; //# 17: compile-time error
+
+  // Wrong for declaration element type.
+  var _ = <int>[for (int i = "s"; false;) 1]; //# 18: compile-time error
+  var _ = <int, int>{for (int i = "s"; false;) 1: 1}; //# 19: compile-time error
+  var _ = <int>{for (int i = "s"; false;) 1}; //# 20: compile-time error
+
+  // Wrong for body element type.
+  var _ = <int>[for (; false;) "s"]; //# 21: compile-time error
+  var _ = <int, int>{for (; false;) "s": 1}; //# 22: compile-time error
+  var _ = <int, int>{for (; false;) 1: "s"}; //# 23: compile-time error
+  var _ = <int>{for (; false;) "s"}; //# 24: compile-time error
+
+  // Non-iterable sequence type.
+  int nonIterable = 3;
+  var _ = <int>[for (int i in nonIterable) 1]; //# 25: compile-time error
+  var _ = <int, int>{for (int i in nonIterable) 1: 1}; //# 26: compile-time error
+  var _ = <int>{for (int i in nonIterable) 1}; //# 27: compile-time error
+}
diff --git a/tests/language/control_flow_collections/utils.dart b/tests/language/control_flow_collections/utils.dart
new file mode 100644
index 0000000..c8e5dc8
--- /dev/null
+++ b/tests/language/control_flow_collections/utils.dart
@@ -0,0 +1,109 @@
+// 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:collection';
+
+import 'package:expect/expect.dart';
+
+class CustomMap with MapMixin<int, String> {
+  Iterable<int> get keys => [];
+  String? operator [](Object? key) => "";
+  operator []=(int key, String value) {}
+  String remove(Object? key) => throw UnsupportedError("unsupported");
+  void clear() => throw UnsupportedError("unsupported");
+}
+
+class CustomSet extends SetBase<int> {
+  bool add(int value) => throw UnsupportedError("unsupported");
+  bool contains(Object? value) => throw UnsupportedError("unsupported");
+  Iterator<int> get iterator => <int>[].iterator;
+  int get length => 0;
+  int? lookup(Object? value) => throw UnsupportedError("unsupported");
+  bool remove(Object? value) => throw UnsupportedError("unsupported");
+  Set<int> toSet() => this;
+}
+
+class Equality {
+  final int id;
+  final String name;
+  const Equality(this.id, this.name);
+  int get hashCode => id;
+  bool operator ==(Object other) => other is Equality && id == other.id;
+  String toString() => "$id:$name";
+}
+
+T expectDynamic<T>(dynamic value) {
+  Expect.equals(dynamic, T);
+  return value;
+}
+
+T expectInt<T>(dynamic value) {
+  Expect.equals(int, T);
+  return value;
+}
+
+T expectString<T>(dynamic value) {
+  Expect.equals(String, T);
+  return value;
+}
+
+Iterable<T> expectIntIterable<T>(dynamic value) {
+  Expect.equals(int, T);
+  return value;
+}
+
+Set<T> expectIntSet<T>() {
+  Expect.equals(int, T);
+  return Set();
+}
+
+Stream<T> expectIntStream<T>(dynamic elements) {
+  Expect.equals(int, T);
+  return Stream<T>.fromIterable(elements);
+}
+
+Set<T> expectDynamicSet<T>() {
+  Expect.equals(dynamic, T);
+  return Set();
+}
+
+/// Hacky way of testing the inferred generic type arguments of [object].
+///
+/// [Expect.type()] only performs a subtype test, which means that it will
+/// return `true` when asked if a `List<int>` is a `List<num>` or
+/// `List<dynamic>`. For inference, we want to test the type more precisely.
+///
+/// There isn't a good way to do that in tests yet so, for now, we just see if
+/// the runtime type contains the given type argument string.
+// TODO(rnystrom): Do something less horribly brittle.
+void _expectTypeArguments(String typeArguments, Object object) {
+  var typeName = object.runtimeType.toString();
+
+  // If an implementation prints dynamic instantiations like a raw type,
+  // handle that.
+  if (!typeName.contains("<") &&
+      (typeArguments == "dynamic" || typeArguments == "dynamic, dynamic")) {
+    return;
+  }
+
+  if (!typeName.contains("<$typeArguments>")) {
+    Expect.fail("Object should have had generic type '<$typeArguments>', "
+        "but was '$typeName'.");
+  }
+}
+
+void expectListOf<T>(Object object) {
+  Expect.type<List>(object);
+  _expectTypeArguments(T.toString(), object);
+}
+
+void expectSetOf<T>(Object object) {
+  Expect.type<Set>(object);
+  _expectTypeArguments(T.toString(), object);
+}
+
+void expectMapOf<K, V>(Object object) {
+  Expect.type<Map>(object);
+  _expectTypeArguments("$K, $V", object);
+}
diff --git a/tests/language/covariant/covariant_test.dart b/tests/language/covariant/covariant_test.dart
new file mode 100644
index 0000000..2ccc708
--- /dev/null
+++ b/tests/language/covariant/covariant_test.dart
@@ -0,0 +1,431 @@
+// 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.
+
+// Test that `covariant` can be parsed (and ignored) by
+// dart2js and the VM.
+// This test only checks for non-strong mode behavior.
+//
+// Generally, `covariant` should be ignored, when it is used in the right
+// places.
+
+import 'package:expect/expect.dart';
+
+// Top level field may not have a covariant.
+// Would be considered a minor (acceptable) bug, if it was accepted here too.
+covariant // //# 00: syntax error
+int x0 = 0;
+
+covariant int covariant = 0; // //# 00b: syntax error
+
+int covariant = 0; // //# 00c: ok
+
+// Getters may never have `covariant`. (Neither on the top-level nor as members)
+covariant // //# 01: syntax error
+int get x1 => 499;
+
+// Top level setters may not have a covariant.
+// Would be considered a minor (acceptable) bug, if it was accepted here too.
+void set x2(
+    covariant //# 02: compile-time error
+    int val) {}
+
+// Same as above, but with `covariant` in different positions.
+// The `covariant` is just wrong there.
+
+int
+covariant // //# 03: syntax error
+    x3 = 0;
+
+int
+covariant // //# 04: syntax error
+    get x4 => 499;
+
+void set x5(
+    int
+    covariant //# 05: syntax error
+        val) {}
+
+// Same without types.
+
+// Since `covariant` is a built-in identifier, it is not allowed here.
+covariant x6; // //# 06: syntax error
+
+covariant covariant; // //# 06b: syntax error
+
+// Getters may never have `covariant`.
+covariant // //# 07: syntax error
+get x7 => 499;
+
+// Top level setters may not have a covariant.
+// Would be considered a minor (acceptable) bug, if it was accepted here too.
+void set x8(
+    covariant //# 08: compile-time error
+    val) {}
+
+// If there is no type, then `covariant` is simply the parameter name:
+void set x9(covariant) {}
+
+// Covariant won't work on return types.
+covariant // //# 10: syntax error
+int f10() => 499;
+
+// Covariant won't work as a return type.
+covariant // //# 11: syntax error
+f11() => 499;
+
+// Covariant should not work on top-level methods.
+// It's a minor (acceptable) bug to not error out here.
+int f12(
+    covariant //# 12: compile-time error
+        int x) =>
+    499;
+
+// `Covariant` must be in front of the types.
+int f13(
+        int
+    covariant //# 13: syntax error
+            x) =>
+    499;
+
+// Covariant should not work on top-level methods.
+// It's a minor (acceptable) bug to not error out here.
+int f14(
+    covariant //# 14: compile-time error
+        final x) =>
+    499;
+
+// `Covariant` must be in front of modifiers.
+int f15(
+        final
+    covariant //# 15: syntax error
+            x) =>
+    499;
+
+// Covariant should not work on top-level methods.
+// It's a minor (acceptable) bug to not error out here.
+int f16(
+    covariant //# 16: compile-time error
+        final int x) =>
+    499;
+
+// `Covariant` must be in front of modifiers.
+int f17(
+        final
+    covariant //# 17: syntax error
+            int
+            x) =>
+    499;
+
+// On its own, `covariant` is just a parameter name.
+int f18(covariant) => covariant;
+
+covariant; // //# 19: syntax error
+
+// All of the above as statics in a class.
+class A {
+  // Static fields may not have a covariant.
+  // Would be considered a minor (acceptable) bug, if it was accepted here too.
+  static
+  covariant // //# 20: syntax error
+      int x20 = 0;
+
+  static covariant int covariant = 0; // //# 20b: syntax error
+
+  static int covariant = 0; // //# 20c: ok
+
+  // Getters may never have `covariant`.
+  static
+  covariant // //# 21: syntax error
+      int get x21 => 499;
+
+  // Getters may never have `covariant`.
+  covariant // //# 21b: syntax error
+  static int get x21b => 499;
+
+  // Static setters may not have a covariant.
+  // Would be considered a minor (acceptable) bug, if it was accepted here too.
+  static void set x22(
+      covariant //# 22: compile-time error
+      int val) {}
+
+  // Same as above, but with `covariant` in different positions.
+  // The `covariant` is just wrong there.
+
+  static int
+  covariant // //# 23: syntax error
+      x23 = 0;
+
+  static int
+  covariant // //# 24: syntax error
+      get x24 => 499;
+
+  static void set x25(
+      int
+    covariant //# 25: syntax error
+          val) {}
+
+  // Since `covariant` is a built-in identifier, it is not allowed here.
+  static covariant x26; //# 26: syntax error
+  static covariant covariant; //# 26b: syntax error
+
+  // Getters may never have `covariant`.
+  static
+  covariant // //# 27: syntax error
+      get x27 => 499;
+
+  covariant // //# 27b: syntax error
+  static get x27b => 499;
+
+  // Static setters may not have a covariant.
+  // Would be considered a minor (acceptable) bug, if it was accepted here too.
+  static void set x28(
+      covariant //# 28: compile-time error
+      val) {}
+
+  // If there is no type, then `covariant` is simply the parameter name:
+  static void set x29(covariant) {}
+
+  // Covariant won't work on return types.
+  static
+  covariant // //# 30: syntax error
+      int f30() => 499;
+
+  covariant // //# 30b: syntax error
+  static int f30b() => 499;
+
+  // Covariant won't work as a return type.
+  static
+  covariant // //# 31: syntax error
+      f31() => 499;
+
+  covariant // //# 31b: syntax error
+  static f31b() => 499;
+
+  // Covariant should not work on static methods.
+  // It's a minor (acceptable) bug to not error out here.
+  static int f32(
+      covariant //# 32: compile-time error
+          int x) =>
+      499;
+
+  // `Covariant` must be in front of the types.
+  static int f33(
+          int
+      covariant //# 33: syntax error
+              x) =>
+      499;
+
+  // Covariant should not work on top-level methods.
+  // It's a minor (acceptable) bug to not error out here.
+  static int f34(
+      covariant //# 34: compile-time error
+          final x) =>
+      499;
+
+  // `Covariant` must be in front of modifiers.
+  static int f35(
+          final
+      covariant //# 35: syntax error
+              x) =>
+      499;
+
+  // Covariant should not work on top-level methods.
+  // It's a minor (acceptable) bug to not error out here.
+  static int f36(
+      covariant //# 36: compile-time error
+          final int x) =>
+      499;
+
+  // `Covariant` must be in front of modifiers.
+  static int f37(
+          final
+      covariant //# 37: syntax error
+              int
+              x) =>
+      499;
+
+  // `Covariant` on its own is just a parameter name.
+  static int f38(covariant) => covariant;
+
+  static covariant; // //# 39: syntax error
+
+}
+
+// All of the above as instance members in a class.
+class B {
+  covariant // //# 40: ok
+  int x40 = 0;
+
+  covariant int covariant = 0; // //# 40b: ok
+
+  int covariant = 0; //           //# 40c: ok
+
+  // Getters may never have `covariant`.
+  covariant // //# 41: syntax error
+  int get x41 => 499;
+
+  void set x42(
+      covariant // //# 42: ok
+      int val) {}
+
+  // `covariant` in the wrong position.
+  int
+  covariant // //# 43: syntax error
+      x43 = 0;
+
+  // `covariant` in the wrong position.
+  int
+  covariant // //# 44: syntax error
+      get x44 => 499;
+
+  void set x45(
+      int
+    covariant //# 45: syntax error
+          val) {}
+
+  // Since `covariant` is a built-in identifier, it is not allowed here.
+  covariant x46; //# 46: syntax error
+  covariant covariant; //# 46b: syntax error
+
+  // Getters may never have `covariant`.
+  covariant // //# 47: syntax error
+  get x47 => 499;
+
+  void set x48(
+      covariant // //# 48: ok
+      val) {}
+
+  // If there is no type, then `covariant` is simply the parameter name:
+  void set x49(covariant) {}
+
+  // Covariant won't work on return types.
+  covariant // //# 50: syntax error
+  int f50() => 499;
+
+  // Covariant won't work as a return type.
+  covariant // //# 51: syntax error
+  f51() => 499;
+
+  int f52(
+      covariant // //# 52: ok
+          int x) =>
+      499;
+
+  // `Covariant` must be in front of the types.
+  int f53(
+          int
+      covariant //# 53: syntax error
+              x) =>
+      499;
+
+  int f54(
+      covariant // //# 54: ok
+          final x) =>
+      499;
+
+  // `Covariant` must be in front of modifiers.
+  int f55(
+          final
+      covariant //# 55: syntax error
+              x) =>
+      499;
+
+  int f56(
+      covariant // //# 56: ok
+          final int x) =>
+      499;
+
+  // `Covariant` must be in front of modifiers.
+  int f57(
+          final
+      covariant //# 57: syntax error
+              int
+              x) =>
+      499;
+
+  // `Covariant` on its own is just a parameter name.
+  int f58(covariant) => covariant;
+
+  covariant; // //# 59: syntax error
+}
+
+void use(x) {}
+
+main() {
+  x0 = 0;
+  covariant = 0; // //# 00b: continued
+  covariant = 0; // //# 00c: continued
+  use(x1);
+  x2 = 499;
+  use(x3);
+  use(x4);
+  x5 = 42;
+  x6 = 0; //# 06: continued
+  covariant = 0; //# 06b: continued
+  use(x7);
+  x8 = 11;
+  x9 = 12;
+  use(f10());
+  use(f11());
+  use(f12(2));
+  use(f13(3));
+  use(f14(3));
+  use(f15(3));
+  use(f16(3));
+  use(f17(3));
+  Expect.equals(123, f18(123));
+  use(covariant); // //# 19: continued
+
+  A.x20 = 0;
+  A.covariant = 0; // //# 20b: continued
+  A.covariant = 0; // //# 20c: continued
+  use(A.x21);
+  use(A.x21b);
+  A.x22 = 499;
+  use(A.x23);
+  use(A.x24);
+  A.x25 = 42;
+  A.x26 = 0; //# 26: continued
+  A.covariant = 0; //# 26b: continued
+  use(A.x27);
+  use(A.x27b);
+  A.x28 = 11;
+  A.x29 = 12;
+  use(A.f30());
+  use(A.f31());
+  use(A.f31b());
+  use(A.f32(2));
+  use(A.f33(3));
+  use(A.f34(3));
+  use(A.f35(3));
+  use(A.f36(3));
+  use(A.f37(3));
+  Expect.equals(1234, A.f38(1234));
+  use(A.covariant); // //# 39: continued
+
+  var b = new B();
+  b.x40 = 0;
+  b.covariant = 0; // //# 40b: continued
+  b.covariant = 0; // //# 40c: continued
+  use(b.x41);
+  b.x42 = 499;
+  use(b.x43);
+  use(b.x44);
+  b.x45 = 42;
+  b.x46 = 0; //# 46: continued
+  b.covariant = 0; //# 46b: continued
+  use(b.x47);
+  b.x48 = 11;
+  b.x49 = 12;
+  use(b.f50());
+  use(b.f51());
+  use(b.f52(2));
+  use(b.f53(2));
+  use(b.f54(3));
+  use(b.f55(3));
+  use(b.f56(3));
+  use(b.f57(3));
+  Expect.equals(12345, b.f58(12345));
+  use(B.covariant); // //# 59: continued
+}
diff --git a/tests/language/covariant/field_test.dart b/tests/language/covariant/field_test.dart
new file mode 100644
index 0000000..11ed033
--- /dev/null
+++ b/tests/language/covariant/field_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:expect/expect.dart";
+
+class A {}
+
+abstract class B<T> {
+  // x will be marked genericCovariantInterface, since x's type is covariant in
+  // the type parameter T.
+  void set s2(T x);
+
+  // x will be marked genericCovariantInterface, since x's type is covariant in
+  // the type parameter T.
+  void set s3(T x);
+
+  void set s4(Object? x);
+
+  void set s5(Object? x) {
+    s4 = x;
+  }
+}
+
+class C extends B<A> {
+  A? s1;
+
+  // s2 will be marked genericCovariantImpl, since it might be called via
+  // e.g. B<Object>.
+  A? s2;
+
+  // s3 will be marked genericCovariantImpl, since it might be called via
+  // e.g. B<Object>.
+  covariant A? s3;
+
+  covariant A? s4;
+}
+
+main() {
+  // Dynamic method calls should always have their arguments type checked.
+  dynamic d = new C();
+  Expect.throwsTypeError(() => d.s1 = new Object()); //# 01: ok
+
+  // Interface calls should have any arguments marked "genericCovariantImpl"
+  // type checked provided that the corresponding argument on the interface
+  // target is marked "genericCovariantInterface".
+  B<Object> b = new C();
+  Expect.throwsTypeError(() => b.s2 = new Object()); //# 02: ok
+
+  // Interface calls should have any arguments marked "covariant" type checked,
+  // regardless of whether the corresponding argument on the interface target is
+  // marked "genericCovariantInterface".
+  Expect.throwsTypeError(() => b.s3 = new Object()); //# 03: ok
+  Expect.throwsTypeError(() => b.s4 = new Object()); //# 04: ok
+
+  // This calls should have any arguments marked "covariant" type checked.
+  Expect.throwsTypeError(() => b.s5 = new Object()); //# 05: ok
+}
diff --git a/tests/language/covariant/method_test.dart b/tests/language/covariant/method_test.dart
new file mode 100644
index 0000000..03ea520
--- /dev/null
+++ b/tests/language/covariant/method_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.
+
+import "package:expect/expect.dart";
+
+class A {}
+
+abstract class B<T> {
+  // x will be marked genericCovariantInterface, since x's type is covariant in
+  // the type parameter T.
+  void f2(T x);
+
+  // x will be marked genericCovariantInterface, since x's type is covariant in
+  // the type parameter T.
+  void f3(T x);
+
+  void f4(Object x);
+
+  void f5(Object x) {
+    f4(x);
+  }
+}
+
+class C extends B<A> {
+  void f1(A x) {}
+
+  // x will be marked genericCovariantImpl, since it might be called via
+  // e.g. B<Object>.
+  void f2(A x) {}
+
+  // x will be marked genericCovariantImpl, since it might be called via
+  // e.g. B<Object>.
+  void f3(covariant A x) {}
+
+  void f4(covariant A x) {}
+}
+
+main() {
+  // Dynamic method calls should always have their arguments type checked.
+  dynamic d = new C();
+  Expect.throwsTypeError(() => d.f1(new Object())); //# 01: ok
+
+  // Closure calls should have any arguments marked "genericCovariantImpl" type
+  // checked.
+  B<Object> b = new C();
+  void Function(Object) f = b.f2;
+  Expect.throwsTypeError(() => f(new Object())); //# 02: ok
+
+  // Interface calls should have any arguments marked "genericCovariantImpl"
+  // type checked provided that the corresponding argument on the interface
+  // target is marked "genericCovariantInterface".
+  Expect.throwsTypeError(() => b.f2(new Object())); //# 03: ok
+
+  // Interface calls should have any arguments marked "covariant" type checked,
+  // regardless of whether the corresponding argument on the interface target is
+  // marked "genericCovariantInterface".
+  Expect.throwsTypeError(() => b.f3(new Object())); //# 04: ok
+  Expect.throwsTypeError(() => b.f4(new Object())); //# 05: ok
+
+  // This calls should have any arguments marked "covariant" type checked.
+  Expect.throwsTypeError(() => b.f5(new Object())); //# 06: ok
+}
diff --git a/tests/language/covariant/override_test.dart b/tests/language/covariant/override_test.dart
new file mode 100644
index 0000000..503cf86
--- /dev/null
+++ b/tests/language/covariant/override_test.dart
@@ -0,0 +1,96 @@
+// 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 covariant_override_test;
+
+// This test contains cases where `covariant` is used as intended.
+
+abstract class A {
+  A(this.f1, this.f2, this.f3);
+
+  // Normal usage, "by design": superclass requests covariance.
+  void m1(covariant Object o);
+
+  // Normal usage, "ad hoc": subclass requests covariance.
+  void m2(Object o);
+
+  // Syntactic special case: omit the type in subclass.
+  void m3(Object o);
+
+  // Positional optional arguments.
+  void m4([covariant Object o = 0]);
+  void m5([Object o = 0]);
+  void m6([Object o = 0]);
+
+  // Named arguments.
+  void m7({covariant Object arg = 0});
+  void m8({Object arg = 0});
+  void m9({Object arg = 0});
+
+  // Normal usage on field, "by design": superclass requests covariance.
+  covariant Object f1;
+
+  // Normal usage on field, "ad hoc": subclass requests covariance.
+  Object f2;
+
+  // Syntactic special case.
+  Object f3;
+}
+
+abstract class B extends A {
+  B(num f1, num f2, num f3) : super(f1, f2, f3);
+
+  void m1(num n);
+  void m2(covariant num n);
+  void m3(covariant n);
+  void m4([num n]);
+  void m5([covariant num n]);
+  void m6([covariant n]);
+  void m7({num arg});
+  void m8({covariant num arg});
+  void m9({covariant arg});
+  num get f1;
+  void set f1(num n);
+  num get f2;
+  void set f2(covariant num n);
+  void set f3(covariant n);
+}
+
+class C extends B {
+  C(int f1, int f2, int f3) : super(f1, f2, f3);
+
+  void m1(int i) {}
+  void m2(int i) {}
+  void m3(int i) {}
+  void m4([int i = 0]) {}
+  void m5([int i = 0]) {}
+  void m6([int i = 0]) {}
+  void m7({int arg = 0}) {}
+  void m8({int arg = 0}) {}
+  void m9({int arg = 0}) {}
+  int get f1 => 0;
+  void set f1(covariant int i) {}
+  int get f2 => 0;
+  void set f2(covariant int i) {}
+  int get f3 => 0;
+  void set f3(int i) {}
+}
+
+main() {
+  // For Dart 1.x, `covariant` has no runtime semantics; we just ensure
+  // that the code is not unused, such that we know it will be parsed.
+  A a = new C(39, 40, 41);
+  a.m1(42);
+  a.m2(42);
+  a.m3(42);
+  a.m4(42);
+  a.m5(42);
+  a.m6(42);
+  a.m7(arg: 42);
+  a.m8(arg: 42);
+  a.m9(arg: 42);
+  a.f1 = 42;
+  a.f2 = 42;
+  a.f3 = 42;
+}
diff --git a/tests/language/covariant/return_type_test.dart b/tests/language/covariant/return_type_test.dart
new file mode 100644
index 0000000..43c6c9e
--- /dev/null
+++ b/tests/language/covariant/return_type_test.dart
@@ -0,0 +1,74 @@
+// 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:expect/expect.dart';
+
+void main() {
+  List<int> l = [1, 2, 3].where((x) => x.isEven).map((x) => x + 1);
+  //            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                             ^
+  // [cfe] A value of type 'Iterable<int>' can't be assigned to a variable of type 'List<int>'.
+
+  {
+    // Works.
+    C<Object> c = C<Object>(1);
+    Iterable<bool Function(Object)> myList = c.f();
+  }
+
+  {
+    C<Object> c = C<Object>(1);
+    List<bool Function(Object)> myList = c.f();
+    //                                   ^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //                                     ^
+    // [cfe] A value of type 'Iterable<bool Function(Object)>' can't be assigned to a variable of type 'List<bool Function(Object)>'.
+  }
+
+  {
+    C<Object> c = C<int>(1);
+    List<bool Function(Object)> myList = c.f();
+    //                                   ^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //                                     ^
+    // [cfe] A value of type 'Iterable<bool Function(Object)>' can't be assigned to a variable of type 'List<bool Function(Object)>'.
+  }
+
+  {
+    C<Object> c = C<int>(1);
+    Iterable<bool Function(Object)> myList = c.f();
+  }
+
+  {
+    // Works.
+    C<Iterable<Object>> c = D<Object>([1]);
+    Iterable<bool Function(Iterable<Object>)> myList = c.f();
+  }
+
+  {
+    C<Iterable<Object>> c = D<Object>([1]);
+    List<bool Function(Iterable<Object>)> myList = c.f();
+    //                                             ^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //                                               ^
+    // [cfe] A value of type 'Iterable<bool Function(Iterable<Object>)>' can't be assigned to a variable of type 'List<bool Function(Iterable<Object>)>'.
+  }
+
+  {
+    C<Iterable<Object>> c = D<int>([1]);
+    Iterable<bool Function(Iterable<Object>)> myList = c.f();
+  }
+}
+
+class C<T> {
+  final T t;
+  C(this.t);
+  Iterable<bool Function(T)> f() sync* {
+    yield (T x) => x == t;
+  }
+}
+
+class D<S> extends C<Iterable<S>> {
+  D(Iterable<S> s) : super(s);
+}
diff --git a/tests/language/covariant/setter_test.dart b/tests/language/covariant/setter_test.dart
new file mode 100644
index 0000000..1a19dca
--- /dev/null
+++ b/tests/language/covariant/setter_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 "package:expect/expect.dart";
+
+class A {}
+
+abstract class B<T> {
+  // x will be marked genericCovariantInterface, since x's type is covariant in
+  // the type parameter T.
+  void set s2(T x);
+
+  // x will be marked genericCovariantInterface, since x's type is covariant in
+  // the type parameter T.
+  void set s3(T x);
+
+  void set s4(Object x);
+
+  void set s5(Object x) {
+    s4 = x;
+  }
+}
+
+class C extends B<A> {
+  void set s1(A x) {}
+
+  // x will be marked genericCovariantImpl, since it might be called via
+  // e.g. B<Object>.
+  void set s2(A x) {}
+
+  // x will be marked genericCovariantImpl, since it might be called via
+  // e.g. B<Object>.
+  void set s3(covariant A x) {}
+
+  void set s4(covariant A x) {}
+}
+
+main() {
+  // Dynamic method calls should always have their arguments type checked.
+  dynamic d = new C();
+  Expect.throwsTypeError(() => d.s1 = new Object()); //# 01: ok
+
+  // Interface calls should have any arguments marked "genericCovariantImpl"
+  // type checked provided that the corresponding argument on the interface
+  // target is marked "genericCovariantInterface".
+  B<Object> b = new C();
+  Expect.throwsTypeError(() => b.s2 = new Object()); //# 02: ok
+
+  // Interface calls should have any arguments marked "covariant" type checked,
+  // regardless of whether the corresponding argument on the interface target is
+  // marked "genericCovariantInterface".
+  Expect.throwsTypeError(() => b.s3 = new Object()); //# 03: ok
+  Expect.throwsTypeError(() => b.s4 = new Object()); //# 04: ok
+
+  // This calls should have any arguments marked "covariant" type checked.
+  Expect.throwsTypeError(() => b.s5 = new Object()); //# 05: ok
+
+  testMixin(); //# 06: ok
+}
+
+abstract class D<T> {
+  void set m1(T x);
+}
+
+class E {
+  void set m1(A x) {}
+}
+
+class F = Object with E implements D<A>;
+class G = C with E implements D<A>;
+
+class H extends Object with E implements D<A> {}
+
+class I extends Object with F {}
+
+void testMixin() {
+  D<Object> f = new F();
+  f.m1 = new A();
+  Expect.throwsTypeError(() => f.m1 = new Object());
+  f = new G();
+  f.m1 = new A();
+  Expect.throwsTypeError(() => f.m1 = new Object());
+  f = new H();
+  f.m1 = new A();
+  Expect.throwsTypeError(() => f.m1 = new Object());
+  f = new I();
+  f.m1 = new A();
+  Expect.throwsTypeError(() => f.m1 = new Object());
+}
diff --git a/tests/language/covariant/subtyping_tearoff1_test.dart b/tests/language/covariant/subtyping_tearoff1_test.dart
new file mode 100644
index 0000000..404b4bb
--- /dev/null
+++ b/tests/language/covariant/subtyping_tearoff1_test.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.
+import 'package:expect/expect.dart';
+
+class Foo<T> {
+  dynamic method(T x) {}
+}
+
+typedef dynamic TakeNum(num x);
+
+main() {
+  Foo<int> intFoo = new Foo<int>();
+  Foo<num> numFoo = intFoo;
+  TakeNum f = numFoo.method;
+  Expect.throws(() => f(2.5));
+  dynamic f2 = numFoo.method;
+  Expect.throws(() => f2(2.5));
+}
diff --git a/tests/language/covariant/subtyping_tearoff2_test.dart b/tests/language/covariant/subtyping_tearoff2_test.dart
new file mode 100644
index 0000000..306d83d
--- /dev/null
+++ b/tests/language/covariant/subtyping_tearoff2_test.dart
@@ -0,0 +1,26 @@
+// 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 Implementation {
+  dynamic method(int x) {}
+}
+
+abstract class Interface<T> {
+  dynamic method(T x);
+}
+
+class Subclass extends Implementation implements Interface<int> {}
+
+typedef dynamic TakeNum(num x);
+
+main() {
+  Subclass subclass = new Subclass();
+  Interface<int> intInterface = subclass;
+  Interface<num> numInterface = intInterface;
+  TakeNum f = numInterface.method;
+  Expect.throws(() => f(2.5));
+  dynamic f2 = f;
+  Expect.throws(() => f2(2.5));
+}
diff --git a/tests/language/covariant/subtyping_tearoff3_test.dart b/tests/language/covariant/subtyping_tearoff3_test.dart
new file mode 100644
index 0000000..3e1109b
--- /dev/null
+++ b/tests/language/covariant/subtyping_tearoff3_test.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.
+import 'package:expect/expect.dart';
+
+class Implementation {
+  dynamic method(int x) {}
+}
+
+abstract class Interface1<T> {
+  dynamic method(T x);
+}
+
+abstract class Interface2<T> {
+  dynamic method(T x);
+}
+
+class Subclass extends Implementation
+    implements Interface1<int>, Interface2<int> {}
+
+typedef dynamic TakeNum(num x);
+
+main() {
+  Subclass subclass = new Subclass();
+
+  Interface1<int> intInterface1 = subclass;
+  Interface1<num> numInterface1 = intInterface1;
+  TakeNum f1 = numInterface1.method;
+  Expect.throws(() => f1(2.5));
+  dynamic f1dynamic = f1;
+  Expect.throws(() => f1dynamic(2.5));
+
+  Interface2<int> intInterface2 = subclass;
+  Interface2<num> numInterface2 = intInterface2;
+  TakeNum f2 = numInterface2.method;
+  Expect.throws(() => f2(2.5));
+  dynamic f2dynamic = f2;
+  Expect.throws(() => f2dynamic(2.5));
+}
diff --git a/tests/language/covariant/subtyping_test.dart b/tests/language/covariant/subtyping_test.dart
new file mode 100644
index 0000000..da7af10
--- /dev/null
+++ b/tests/language/covariant/subtyping_test.dart
@@ -0,0 +1,248 @@
+// 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:expect/expect.dart';
+
+class Fields<T> {
+  late T x;
+  late T _y;
+  late T _z;
+
+  m() {
+    _y = x;
+  }
+
+  n(Fields<T> c) {
+    c._z = x;
+  }
+}
+
+testField() {
+  Fields<Object> c = new Fields<int>();
+  Expect.throwsTypeError(() => c.x = 'hello');
+
+  Fields<dynamic> d = new Fields<int>();
+  Expect.throwsTypeError(() => c.x = 'hello');
+}
+
+testPrivateFields() {
+  Fields<Object> c = new Fields<int>()..x = 42;
+  c.m();
+  Expect.equals(c._y, 42);
+
+  Fields<Object> c2 = new Fields<String>()..x = 'hi';
+  c2.n(c2);
+  Expect.equals(c2._z, 'hi');
+  Expect.throwsTypeError(() => c.n(c2));
+  Expect.equals(c2._z, 'hi');
+}
+
+class NumBounds<T extends num> {
+  bool m(T t) => t.isNegative;
+}
+
+class MethodTakesNum extends NumBounds<int> {
+  bool m(num obj) => obj.isNegative; // does not need check
+}
+
+class MethodTakesInt extends NumBounds<int> {
+  bool m(int obj) => obj.isNegative; // needs a check
+}
+
+testClassBounds() {
+  NumBounds<num> d = new MethodTakesNum();
+  Expect.equals(d.m(-1.1), true);
+  d = new MethodTakesInt();
+  Expect.throwsTypeError(() => d.m(-1.1));
+}
+
+typedef void F<T>(T t);
+typedef G<T> = void Function<S extends T>(S s);
+
+class FnChecks<T> {
+  late F<T> f;
+  late G<T> g;
+  late T _t;
+  T getT() => _t;
+  F<T> setterForT() {
+    return (T t) {
+      _t = t;
+    };
+  }
+}
+
+testReturnOfFunctionType() {
+  FnChecks<int> cInt = new FnChecks<int>();
+  FnChecks<Object> cObj = cInt;
+  Expect.throwsTypeError(() => cObj.setterForT());
+  Expect.throwsTypeError(() => (cObj.setterForT() as F<Object>));
+  FnChecks<dynamic> cDyn = cInt;
+  Expect.throwsTypeError(() => cDyn.setterForT());
+  Expect.throwsTypeError(
+      () => (cDyn as dynamic).setterForT()('hi')); // dcall throws
+  cInt.setterForT()(42);
+  Expect.equals(cObj.getT(), 42);
+}
+
+testTearoffReturningFunctionType() {
+  FnChecks<int> cInt = new FnChecks<int>();
+  FnChecks<Object> cObj = cInt;
+
+  Expect.throwsTypeError(
+      () => cObj.setterForT, 'unsound tear-off throws at runtime');
+  Expect.equals(cInt.setterForT, cInt.setterForT, 'sound tear-off works');
+}
+
+testFieldOfFunctionType() {
+  FnChecks<Object> c = new FnChecks<String>()..f = (String b) {};
+  Expect.throwsTypeError(() {
+    F<Object> f = c.f;
+  });
+  Expect.throwsTypeError(() {
+    Object f = c.f;
+  });
+  Expect.throwsTypeError(() => c.f);
+  Expect.throwsTypeError(() => c.f(42));
+  Expect.throwsTypeError(() => c.f('hi'));
+  FnChecks<String> cStr = c as FnChecks<String>;
+  cStr.f('hi');
+  FnChecks<dynamic> cDyn = c;
+  Expect.throwsTypeError(() => cDyn.f);
+  Expect.throwsTypeError(() => (cDyn as dynamic).f(42)); // dcall throws
+}
+
+testFieldOfGenericFunctionType() {
+  FnChecks<Object> c = new FnChecks<num>()
+    ..g = <S extends num>(S s) => s.isNegative;
+
+  Expect.throwsTypeError(() {
+    G<Object> g = c.g;
+  });
+  Expect.throwsTypeError(() {
+    var g = c.g;
+  });
+  Expect.throwsTypeError(() => c.g<String>('hi'));
+  Expect.throwsTypeError(() => c.g<int>(42));
+  FnChecks<num> cNum = c as FnChecks<num>;
+  cNum.g(42);
+}
+
+class Base {
+  int _t = 0;
+  add(int t) {
+    _t += t;
+  }
+}
+
+abstract class I<T> {
+  add(T t);
+}
+
+class ExtendsBase extends Base implements I<int> {}
+
+class MixinBase extends Object with Base implements I<int> {}
+
+class MixinBase2 = Object with Base implements I<int>;
+
+testMixinApplication() {
+  I<Object> i = new ExtendsBase();
+  I<Object> j = new MixinBase();
+  I<Object> k = new MixinBase2();
+  Expect.throwsTypeError(() => i.add('hi'));
+  Expect.throwsTypeError(() => j.add('hi'));
+  Expect.throwsTypeError(() => k.add('hi'));
+}
+
+class GenericMethodBounds<T> {
+  Type get t => T;
+  GenericMethodBounds<E> foo<E extends T>() => new GenericMethodBounds<E>();
+  GenericMethodBounds<E> bar<E extends void Function(T)>() =>
+      new GenericMethodBounds<E>();
+}
+
+class GenericMethodBoundsDerived extends GenericMethodBounds<num> {
+  GenericMethodBounds<E> foo<E extends num>() => new GenericMethodBounds<E>();
+  GenericMethodBounds<E> bar<E extends void Function(num)>() =>
+      new GenericMethodBounds<E>();
+}
+
+GenericMethodBounds<E> Function<E extends T>() genericFunctionWithBounds<T>() {
+  inner<E extends T>() => new GenericMethodBounds<E>();
+  return inner;
+}
+
+testGenericMethodBounds() {
+  test(GenericMethodBounds<Object?> g) {
+    Expect.throwsTypeError(() => g.foo<String>());
+    Expect.throwsTypeError(() => g.foo());
+    Expect.equals(g.foo<Null>().t, Null);
+    Expect.equals(g.foo<int>().t, int);
+    Expect.isFalse(g.foo<int>() is GenericMethodBounds<double>);
+    g.bar<Function(Object?)>();
+    dynamic d = g;
+    d.bar<Function(num)>();
+    Expect.throwsTypeError(() => d.bar<Function(String)>());
+    Expect.throwsTypeError(() => d.bar<Function(Null)>());
+  }
+
+  test(new GenericMethodBounds<num>());
+  test(new GenericMethodBounds<int>());
+  test(new GenericMethodBoundsDerived());
+  test(genericFunctionWithBounds<num>()<int>());
+}
+
+class ClassF<T> {
+  late T x;
+  void call(T t) {
+    x = t;
+  }
+}
+
+testCallMethod() {
+  ClassF<int> cc = new ClassF<int>();
+  ClassF<Object> ca = cc; // An upcast, per covariance.
+  F<Object> f = ca;
+  void f2(Object x) {}
+  Expect.equals(f.runtimeType, f2.runtimeType);
+  Expect.throwsTypeError(() => f(new Object()));
+}
+
+class TearOff<T> {
+  method1(T t) => null; // needs check
+  method2(Function(T) takesT) => null;
+  method3(T Function() returnsT) => null; // needs check
+  method4(Function(Function(T)) takesTakesT) => null; // needs check
+  method5(Function(T Function()) takesReturnsT) => null;
+  method6(Function(T) Function() returnsTakesT) => null;
+  method7(T Function() Function() returnsReturnsT) => null; // needs check
+}
+
+testTearOffRuntimeType() {
+  expectRTTI(tearoff, type) => Expect.equals('${tearoff.runtimeType}', type,
+      'covariant params should reify with Object as their type');
+
+  TearOff<num> t = new TearOff<int>();
+  expectRTTI(t.method1, '(Object) => dynamic');
+
+  expectRTTI(t.method2, '((int) => dynamic) => dynamic');
+  expectRTTI(t.method3, '(Object) => dynamic');
+
+  expectRTTI(t.method4, '(Object) => dynamic');
+  expectRTTI(t.method5, '((() => int) => dynamic) => dynamic');
+  expectRTTI(t.method6, '(() => (int) => dynamic) => dynamic');
+  expectRTTI(t.method7, '(Object) => dynamic');
+}
+
+main() {
+  testField();
+  testPrivateFields();
+  testClassBounds();
+  testReturnOfFunctionType();
+  testTearoffReturningFunctionType();
+  testFieldOfFunctionType();
+  testFieldOfGenericFunctionType();
+  testMixinApplication();
+  testGenericMethodBounds();
+  testCallMethod();
+  testTearOffRuntimeType();
+}
diff --git a/tests/language/covariant/subtyping_unsafe_call1_test.dart b/tests/language/covariant/subtyping_unsafe_call1_test.dart
new file mode 100644
index 0000000..b5d4884
--- /dev/null
+++ b/tests/language/covariant/subtyping_unsafe_call1_test.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 'package:expect/expect.dart';
+
+class Foo<T> {
+  dynamic method(T x) {}
+}
+
+main() {
+  Foo<int> intFoo = new Foo<int>();
+  Foo<num> numFoo = intFoo;
+  Expect.throws(() => numFoo.method(2.5));
+}
diff --git a/tests/language/covariant/subtyping_unsafe_call2_test.dart b/tests/language/covariant/subtyping_unsafe_call2_test.dart
new file mode 100644
index 0000000..5e45c37
--- /dev/null
+++ b/tests/language/covariant/subtyping_unsafe_call2_test.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.
+import 'package:expect/expect.dart';
+
+class Implementation {
+  dynamic method(int x) {}
+}
+
+abstract class Interface<T> {
+  dynamic method(T x);
+}
+
+class Subclass extends Implementation implements Interface<int> {}
+
+main() {
+  Subclass subclass = new Subclass();
+  Interface<int> intInterface = subclass;
+  Interface<num> numInterface = intInterface;
+  Expect.throws(() => numInterface.method(2.5));
+}
diff --git a/tests/language/covariant/subtyping_unsafe_call3_test.dart b/tests/language/covariant/subtyping_unsafe_call3_test.dart
new file mode 100644
index 0000000..71143e6
--- /dev/null
+++ b/tests/language/covariant/subtyping_unsafe_call3_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:expect/expect.dart';
+
+class Implementation {
+  dynamic method(int x) {}
+}
+
+abstract class Interface1<T> {
+  dynamic method(T x);
+}
+
+abstract class Interface2<T> {
+  dynamic method(T x);
+}
+
+class Subclass extends Implementation
+    implements Interface1<int>, Interface2<int> {}
+
+main() {
+  Subclass subclass = new Subclass();
+
+  Interface1<int> intInterface1 = subclass;
+  Interface1<num> numInterface1 = intInterface1;
+  Expect.throws(() => numInterface1.method(2.5));
+
+  Interface2<int> intInterface2 = subclass;
+  Interface2<num> numInterface2 = intInterface2;
+  Expect.throws(() => numInterface2.method(2.5));
+}
diff --git a/tests/language/covariant/subtyping_with_mixin_test.dart b/tests/language/covariant/subtyping_with_mixin_test.dart
new file mode 100644
index 0000000..8bff28e
--- /dev/null
+++ b/tests/language/covariant/subtyping_with_mixin_test.dart
@@ -0,0 +1,29 @@
+// 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:expect/expect.dart';
+
+class A {}
+
+class B extends A {}
+
+class Base<S> {}
+
+class Mixin<T> {
+  void f(T arg) {}
+}
+
+abstract class Interface {
+  void f(covariant A arg);
+}
+
+class C<S> extends Base<S> with Mixin<B> implements Interface {}
+
+main() {
+  Interface i = new C<String>();
+  i.f(new B());
+  Expect.throwsTypeError(() {
+    i.f(new A());
+  });
+}
diff --git a/tests/language/covariant/tear_off_type_test.dart b/tests/language/covariant/tear_off_type_test.dart
new file mode 100644
index 0000000..160f46f
--- /dev/null
+++ b/tests/language/covariant/tear_off_type_test.dart
@@ -0,0 +1,29 @@
+// 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:expect/expect.dart";
+
+typedef U F<T, U>(T x);
+
+class C<T> {
+  T f(List<T> x) {
+    throw "uncalled";
+  }
+}
+
+F<List<num>, num> g(C<num> c) {
+  return c.f;
+}
+
+void main() {
+  var tearoff = g(new C<int>());
+  // Since C.f's x parameter is covariant, its type is changed to Object when
+  // determining the type of the tearoff.  So the type of the tearoff should be
+  // `(Object) -> int`.  (Not, for example, `(List<Object>) -> int` or
+  // `(List<Object>) -> Object`)
+  Expect.isTrue(tearoff is F<Object, int>);
+  // Because the function accepts any object, we can pass strings to it.  This
+  // will not work in Dart 1.
+  Expect.isTrue(tearoff is F<String, int>);
+}
diff --git a/tests/language/covariant/type_parameter_test.dart b/tests/language/covariant/type_parameter_test.dart
new file mode 100644
index 0000000..7bff58b
--- /dev/null
+++ b/tests/language/covariant/type_parameter_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 "package:expect/expect.dart";
+
+class A {}
+
+abstract class B<T> {
+  // U will be marked genericCovariantInterface, since U's bound is covariant in
+  // the type parameter T.
+  void f2<U extends T>();
+}
+
+class C extends B<A> {
+  void f1<U extends A>() {}
+
+  // x will be marked genericCovariantImpl, since it might be called via
+  // e.g. B<Object>.
+  void f2<U extends A>() {}
+}
+
+main() {
+  // Dynamic method calls should always have their type arguments checked.
+  dynamic d = new C();
+  Expect.throwsTypeError(() => d.f1<Object>()); //# 01: ok
+
+  // Closure calls should have any type arguments marked "genericCovariantImpl"
+  // checked.
+  B<Object> b = new C();
+  void Function<U extends Object>() f = b.f2;
+  Expect.throwsTypeError(() => f<Object>()); //# 02: ok
+
+  // Interface calls should have any type arguments marked
+  // "genericCovariantImpl" checked provided that the corresponding type
+  // argument on the interface target is marked "genericCovariantInterface".
+  Expect.throwsTypeError(() => b.f2<Object>()); //# 03: ok
+}
diff --git a/tests/language/covariant_override/runtime_check_test.dart b/tests/language/covariant_override/runtime_check_test.dart
new file mode 100644
index 0000000..eedc274
--- /dev/null
+++ b/tests/language/covariant_override/runtime_check_test.dart
@@ -0,0 +1,34 @@
+// 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 View {
+  addChild(View v) {}
+  transform(View fn(View v)) {}
+}
+
+class MyView extends View {
+  addChild(covariant MyView v) {}
+  transform(covariant MyView fn(Object v)) {}
+}
+
+main() {
+  dynamic mv = new MyView();
+  dynamic v = new View();
+
+  mv.addChild(mv);
+  Expect.throws(() => mv.addChild(v));
+
+  mv.transform((_) => new MyView());
+
+  // TODO(jmesserly): these *should* be cast failures, but DDC is currently
+  // ignoring function type failures w/ a warning at the console...
+
+  // * -> * not a subtype of Object -> MyView
+  Expect.throws(() => mv.transform((_) => mv));
+
+  // View -> View not a subtype of Object -> MyView
+  Expect.throws(() => mv.transform((View x) => x));
+}
diff --git a/tests/language/covariant_override/tear_off_type_test.dart b/tests/language/covariant_override/tear_off_type_test.dart
new file mode 100644
index 0000000..732aaf6
--- /dev/null
+++ b/tests/language/covariant_override/tear_off_type_test.dart
@@ -0,0 +1,159 @@
+// 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";
+
+// If a parameter is directly or indirectly a covariant override, its type in
+// the method tear-off should become Object?.
+
+typedef void TakeInts(int a, int b, int c, int d, int e);
+typedef void TakeObjectsAndInts(Object? a, int b, Object? c, int d, int e);
+typedef void TakeObjects(Object? a, Object? b, Object? c, Object? d, Object? e);
+
+typedef void TakeOptionalInts([int a, int b, int c, int d]);
+typedef void TakeOptionalObjectsAndInts([Object? a, int b, Object? c, int d]);
+
+typedef void TakeNamedInts({int a, int b, int c, int d});
+typedef void TakeNamedObjectsAndInts({Object? a, int b, Object? c, int d});
+
+class M1 {
+  method(covariant int a, int b) {}
+}
+
+class M2 {
+  method(int a, covariant int b) {}
+}
+
+class C extends Object with M1, M2 {}
+
+class Direct {
+  void positional(covariant int a, int b, covariant int c, int d, int e) {}
+  void optional(
+      [covariant int a = 0, int b = 0, covariant int c = 0, int d = 0]) {}
+  void named(
+      {covariant int a = 0, int b = 0, covariant int c = 0, int d = 0}) {}
+}
+
+class Inherited extends Direct {}
+
+// ---
+
+class Override1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Override2 extends Override1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Override3 extends Override2 {
+  void method(int a, int b, int c, int d, int e) {}
+}
+
+// ---
+
+abstract class Implement1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Implement2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Implement3 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Implement4 implements Implement3 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Implement5 implements Implement1, Implement2, Implement4 {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+// ---
+
+class Interface1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Interface2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Mixin1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Mixin2 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Superclass {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+class Mixed extends Superclass
+    with Mixin1, Mixin2
+    implements Interface1, Interface2 {}
+
+void main() {
+  testDirect();
+  testInherited();
+  testOverriden();
+  testImplemented();
+  testMixed();
+}
+
+void testDirect() {
+  var positional = new Direct().positional;
+  Expect.isTrue(positional is TakeInts);
+  Expect.isTrue(positional is TakeObjectsAndInts);
+
+  var optional = new Direct().optional;
+  Expect.isTrue(optional is TakeOptionalInts);
+  Expect.isTrue(optional is TakeOptionalObjectsAndInts);
+
+  var named = new Direct().named;
+  Expect.isTrue(named is TakeNamedInts);
+  Expect.isTrue(named is TakeNamedObjectsAndInts);
+}
+
+void testInherited() {
+  var positional = new Inherited().positional;
+  Expect.isTrue(positional is TakeInts);
+  Expect.isTrue(positional is TakeObjectsAndInts);
+
+  var optional = new Inherited().optional;
+  Expect.isTrue(optional is TakeOptionalInts);
+  Expect.isTrue(optional is TakeOptionalObjectsAndInts);
+
+  var named = new Inherited().named;
+  Expect.isTrue(named is TakeNamedInts);
+  Expect.isTrue(named is TakeNamedObjectsAndInts);
+}
+
+void testOverriden() {
+  var method2 = new Override2().method;
+  Expect.isTrue(method2 is TakeInts);
+  Expect.isTrue(method2 is TakeObjectsAndInts);
+
+  var method3 = new Override3().method;
+  Expect.isTrue(method3 is TakeInts);
+  Expect.isTrue(method3 is TakeObjectsAndInts);
+}
+
+void testImplemented() {
+  var method = new Implement5().method;
+  Expect.isTrue(method is TakeInts);
+  Expect.isTrue(method is TakeObjects);
+}
+
+void testMixed() {
+  // TODO(rnystrom): https://github.com/dart-lang/sdk/issues/28395
+  var method = new Mixed().method;
+  Expect.isTrue(method is TakeInts);
+  Expect.isTrue(method is TakeObjects);
+}
diff --git a/tests/language/deferred/call_empty_before_load_lib.dart b/tests/language/deferred/call_empty_before_load_lib.dart
new file mode 100644
index 0000000..32dd376
--- /dev/null
+++ b/tests/language/deferred/call_empty_before_load_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+thefun() {}
diff --git a/tests/language/deferred/call_empty_before_load_test.dart b/tests/language/deferred/call_empty_before_load_test.dart
new file mode 100644
index 0000000..9a13981
--- /dev/null
+++ b/tests/language/deferred/call_empty_before_load_test.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.
+
+// Test that calling a function, even though it itself has no effect, will
+// trigger an error if the corresponding deferred library has not been loaded.
+
+import "package:expect/expect.dart";
+import "call_empty_before_load_lib.dart" deferred as lib1;
+
+main() {
+  Expect.throws(() => lib1.thefun());
+}
diff --git a/tests/language/deferred/closurize_load_library_lib.dart b/tests/language/deferred/closurize_load_library_lib.dart
new file mode 100644
index 0000000..9878ae9
--- /dev/null
+++ b/tests/language/deferred/closurize_load_library_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+var trueVar = true;
diff --git a/tests/language/deferred/closurize_load_library_test.dart b/tests/language/deferred/closurize_load_library_test.dart
new file mode 100644
index 0000000..0f45d3a
--- /dev/null
+++ b/tests/language/deferred/closurize_load_library_test.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.
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+import "closurize_load_library_lib.dart" deferred as lib;
+
+void main() {
+  var x = lib.loadLibrary;
+  asyncStart();
+  x().then((_) {
+    Expect.isTrue(lib.trueVar);
+    asyncEnd();
+  });
+}
diff --git a/tests/language/deferred/constant_list_lib.dart b/tests/language/deferred/constant_list_lib.dart
new file mode 100644
index 0000000..93a6740
--- /dev/null
+++ b/tests/language/deferred/constant_list_lib.dart
@@ -0,0 +1,6 @@
+// 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.
+
+final finalConstList = const [1, 2];
+var nonFinalConstList = const [3, 4];
diff --git a/tests/language/deferred/constant_list_test.dart b/tests/language/deferred/constant_list_test.dart
new file mode 100644
index 0000000..01ee8d6
--- /dev/null
+++ b/tests/language/deferred/constant_list_test.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.
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+import "constant_list_lib.dart" deferred as lib;
+
+void main() {
+  asyncStart();
+  lib.loadLibrary().then((_) {
+    Expect.equals("[1, 2]", lib.finalConstList.toString());
+    Expect.equals("[3, 4]", lib.nonFinalConstList.toString());
+    asyncEnd();
+  });
+}
diff --git a/tests/language/deferred/constraints_lib.dart b/tests/language/deferred/constraints_lib.dart
new file mode 100644
index 0000000..0bf3cc9
--- /dev/null
+++ b/tests/language/deferred/constraints_lib.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.
+
+class C {
+  static int staticMethod() => 42;
+}
+
+class G<T> {}
+
+class Const {
+  const Const();
+  const Const.otherConstructor();
+  static const instance = const Const();
+}
+
+const constantInstance = const Const();
diff --git a/tests/language/deferred/constraints_lib2.dart b/tests/language/deferred/constraints_lib2.dart
new file mode 100644
index 0000000..830705f
--- /dev/null
+++ b/tests/language/deferred/constraints_lib2.dart
@@ -0,0 +1,7 @@
+// 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.
+
+foo() => 42;
+
+class C {}
diff --git a/tests/language/deferred/constraints_type_annotation_test.dart b/tests/language/deferred/constraints_type_annotation_test.dart
new file mode 100644
index 0000000..9d86ccb
--- /dev/null
+++ b/tests/language/deferred/constraints_type_annotation_test.dart
@@ -0,0 +1,51 @@
+// 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:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+import "constraints_lib.dart" deferred as lib;
+import "constraints_lib.dart" as lib2; //# type_annotation_non_deferred: ok
+
+class F {}
+
+class G2<T> {}
+
+main() {
+  lib.C a = null; //# type_annotation_null: compile-time error
+  Expect.throws(() { //# new_before_load: compile-time error
+    lib.C a = new lib.C(); //# new_before_load: continued
+  }, (e) => e is Error); //# new_before_load: continued
+
+  // In this case we do not defer C.
+  lib2.C a1 = new lib2.C(); //# type_annotation_non_deferred: continued
+  asyncStart();
+  lib.loadLibrary().then((_) {
+    lib.C a2 = new lib.C(); //# type_annotation1: dynamic type error, compile-time error
+    lib.G<F> a3 = new lib.G<F>(); //# type_annotation_generic1: dynamic type error, compile-time error
+    G2<lib.C> a4 = new G2(); //# type_annotation_generic2: compile-time error
+    G2<lib.C> a5 = new G2<lib.C>(); //# type_annotation_generic3: compile-time error
+    lib.G<lib.C> a = new lib.G<lib.C>(); //# type_annotation_generic4: dynamic type error, compile-time error
+    var a6 = new lib.C(); //# new: ok
+    var g1 = new lib.G<F>(); //# new_generic1: ok
+    // new G2<lib.C>() does not give a dynamic type error because a malformed
+    // type used as type-parameter is treated as dynamic.
+    var g2 = new G2<lib.C>(); //# new_generic2: compile-time error
+    var g3 = new lib.G<lib.C>(); //# new_generic3: compile-time error
+    var instance = lib.constantInstance;
+    Expect.throwsTypeError(() { //# is_check: compile-time error
+      bool a7 = instance is lib.Const; //# is_check: continued
+    }); //# is_check: continued
+    Expect.throwsTypeError(() { //# as_operation: compile-time error
+      instance as lib.Const; //# as_operation: continued
+    }); //# as_operation: continued
+    Expect.throwsTypeError(() { //# catch_check: compile-time error
+      try { throw instance; } on lib.Const {} //# catch_check: continued
+    }); //# catch_check: continued
+    int i = lib.C.staticMethod(); //# static_method: ok
+    asyncEnd();
+  });
+}
+
+lib.C a9 = null; //# type_annotation_top_level: compile-time error
diff --git a/tests/language/deferred/duplicate_prefix1_runtime_test.dart b/tests/language/deferred/duplicate_prefix1_runtime_test.dart
new file mode 100644
index 0000000..0feaa2e
--- /dev/null
+++ b/tests/language/deferred/duplicate_prefix1_runtime_test.dart
@@ -0,0 +1,11 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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 "prefix_constraints_lib2.dart" as lib;
+
+
+void main() {}
diff --git a/tests/language/deferred/duplicate_prefix1_test.dart b/tests/language/deferred/duplicate_prefix1_test.dart
new file mode 100644
index 0000000..7668c0f
--- /dev/null
+++ b/tests/language/deferred/duplicate_prefix1_test.dart
@@ -0,0 +1,12 @@
+// 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 "prefix_constraints_lib2.dart" as lib;
+import "prefix_constraints_lib.dart" deferred as lib;
+//                                   ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.SHARED_DEFERRED_PREFIX
+//                                               ^
+// [cfe] Can't use the name 'lib' for a deferred library, as the name is used elsewhere.
+
+void main() {}
diff --git a/tests/language/deferred/duplicate_prefix2_runtime_test.dart b/tests/language/deferred/duplicate_prefix2_runtime_test.dart
new file mode 100644
index 0000000..482f828
--- /dev/null
+++ b/tests/language/deferred/duplicate_prefix2_runtime_test.dart
@@ -0,0 +1,11 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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 "prefix_constraints_lib2.dart" as lib;
+
+void main() {}
diff --git a/tests/language/deferred/duplicate_prefix2_test.dart b/tests/language/deferred/duplicate_prefix2_test.dart
new file mode 100644
index 0000000..cee67e0
--- /dev/null
+++ b/tests/language/deferred/duplicate_prefix2_test.dart
@@ -0,0 +1,12 @@
+// 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 "prefix_constraints_lib.dart" deferred as lib;
+//                                   ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.SHARED_DEFERRED_PREFIX
+//                                               ^
+// [cfe] Can't use the name 'lib' for a deferred library, as the name is used elsewhere.
+import "prefix_constraints_lib2.dart" as lib;
+
+void main() {}
diff --git a/tests/language/deferred/duplicate_prefix3_runtime_test.dart b/tests/language/deferred/duplicate_prefix3_runtime_test.dart
new file mode 100644
index 0000000..3f409b6
--- /dev/null
+++ b/tests/language/deferred/duplicate_prefix3_runtime_test.dart
@@ -0,0 +1,11 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+
+
+
+void main() {}
diff --git a/tests/language/deferred/duplicate_prefix3_test.dart b/tests/language/deferred/duplicate_prefix3_test.dart
new file mode 100644
index 0000000..ee80c82
--- /dev/null
+++ b/tests/language/deferred/duplicate_prefix3_test.dart
@@ -0,0 +1,14 @@
+// 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 "prefix_constraints_lib.dart" deferred as lib;
+//                                   ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.SHARED_DEFERRED_PREFIX
+import "prefix_constraints_lib2.dart" deferred as lib;
+//                                    ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.SHARED_DEFERRED_PREFIX
+//                                                ^
+// [cfe] Can't use the name 'lib' for a deferred library, as the name is used elsewhere.
+
+void main() {}
diff --git a/tests/language/deferred/function_type_lib.dart b/tests/language/deferred/function_type_lib.dart
new file mode 100644
index 0000000..939122e
--- /dev/null
+++ b/tests/language/deferred/function_type_lib.dart
@@ -0,0 +1,20 @@
+// 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:expect/expect.dart';
+
+class T {
+  A foo(int x) { return A(); }
+}
+
+class A {}
+
+typedef A F(int x);
+
+use(x) => x;
+
+runTest() {
+  use(new A());
+  Expect.isTrue(new T().foo is F);
+}
diff --git a/tests/language/deferred/function_type_test.dart b/tests/language/deferred/function_type_test.dart
new file mode 100644
index 0000000..49e151b
--- /dev/null
+++ b/tests/language/deferred/function_type_test.dart
@@ -0,0 +1,11 @@
+// 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 'function_type_lib.dart' deferred as lib;
+
+main() {
+  lib.loadLibrary().then((_) {
+    lib.runTest();
+  });
+}
diff --git a/tests/language/deferred/global_lib.dart b/tests/language/deferred/global_lib.dart
new file mode 100644
index 0000000..d4f3f05
--- /dev/null
+++ b/tests/language/deferred/global_lib.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.
+
+var sideEffectCounter = 0;
+
+final finalConstGlobal = "finalConstGlobal";
+final finalNonConstGlobal = (() {
+  sideEffectCounter++;
+  return "finalNonConstGlobal";
+}());
+
+var lazyConstGlobal = "lazyConstGlobal";
+// Regression test for bug #21840.
+var const1Global = const {};
+final lazyConstGlobal2 = const1Global;
+
+var lazyNonConstGlobal = (() {
+  sideEffectCounter++;
+  return "lazyNonConstGlobal";
+}());
+
+readFinalConstGlobal() => finalConstGlobal;
+readFinalNonConstGlobal() => finalNonConstGlobal;
+readLazyConstGlobal() => lazyConstGlobal;
+readLazyNonConstGlobal() => lazyNonConstGlobal;
+writeLazyConstGlobal(x) {
+  lazyConstGlobal = x;
+}
+
+writeLazyNonConstGlobal(x) {
+  lazyNonConstGlobal = x;
+}
diff --git a/tests/language/deferred/global_test.dart b/tests/language/deferred/global_test.dart
new file mode 100644
index 0000000..6d13fc1
--- /dev/null
+++ b/tests/language/deferred/global_test.dart
@@ -0,0 +1,60 @@
+// 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:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+import "global_lib.dart" deferred as lib;
+
+Object? nonDeferredGlobal = const {};
+
+void main() {
+  nonDeferredGlobal = null;
+  asyncStart();
+  lib.loadLibrary().then((_) {
+    // Ensure non-deferred globals are not reset when loading a deferred
+    // library.
+    Expect.equals(null, nonDeferredGlobal);
+
+    Expect.equals("finalConstGlobal", lib.finalConstGlobal);
+    Expect.equals(0, lib.sideEffectCounter);
+    Expect.equals("finalNonConstGlobal", lib.finalNonConstGlobal);
+    Expect.equals(1, lib.sideEffectCounter);
+    Expect.equals("finalConstGlobal", lib.finalConstGlobal);
+    Expect.equals("finalNonConstGlobal", lib.finalNonConstGlobal);
+    Expect.equals("lazyConstGlobal", lib.lazyConstGlobal);
+    Expect.equals(1, lib.sideEffectCounter);
+    Expect.equals("lazyNonConstGlobal", lib.lazyNonConstGlobal);
+    Expect.equals(2, lib.sideEffectCounter);
+    Expect.equals("finalConstGlobal", lib.readFinalConstGlobal());
+    Expect.equals("finalNonConstGlobal", lib.readFinalNonConstGlobal());
+    Expect.equals("lazyConstGlobal", lib.readLazyConstGlobal());
+    Expect.equals("lazyNonConstGlobal", lib.readLazyNonConstGlobal());
+
+    lib.lazyConstGlobal = "lazyConstGlobal_mutated";
+    lib.lazyNonConstGlobal = "lazyNonConstGlobal_mutated";
+    Expect.equals("lazyConstGlobal_mutated", lib.lazyConstGlobal);
+    Expect.equals("lazyNonConstGlobal_mutated", lib.lazyNonConstGlobal);
+    Expect.equals("lazyConstGlobal_mutated", lib.readLazyConstGlobal());
+    Expect.equals("lazyNonConstGlobal_mutated", lib.readLazyNonConstGlobal());
+    Expect.equals(2, lib.sideEffectCounter);
+
+    lib.writeLazyConstGlobal("lazyConstGlobal_mutated2");
+    lib.writeLazyNonConstGlobal("lazyNonConstGlobal_mutated2");
+    Expect.equals("lazyConstGlobal_mutated2", lib.lazyConstGlobal);
+    Expect.equals("lazyNonConstGlobal_mutated2", lib.lazyNonConstGlobal);
+    Expect.equals("lazyConstGlobal_mutated2", lib.readLazyConstGlobal());
+    Expect.equals("lazyNonConstGlobal_mutated2", lib.readLazyNonConstGlobal());
+
+    Expect.mapEquals({}, lib.lazyConstGlobal2);
+    lib.const1Global = const {'foo': 'bar'};
+    Expect.equals(2, lib.sideEffectCounter);
+    Expect.equals(const {'foo': 'bar'}['foo'], lib.const1Global['foo']);
+    // Try loading the deferred library again, should not reset the globals.
+    lib.loadLibrary().then((_) {
+      Expect.equals(const {'foo': 'bar'}['foo'], lib.const1Global['foo']);
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/language/deferred/import_core_test.dart b/tests/language/deferred/import_core_test.dart
new file mode 100644
index 0000000..f3d6644
--- /dev/null
+++ b/tests/language/deferred/import_core_test.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.
+
+// Nothing in the language spec explicitly prohibits a deferred import of
+// 'dart:core'.  Make sure it doesn't lead to any strange behavior.
+
+import "dart:core" deferred as core;
+
+main() {
+  core.loadLibrary().then((_) => null);
+}
diff --git a/tests/language/deferred/inheritance_constraints_lib.dart b/tests/language/deferred/inheritance_constraints_lib.dart
new file mode 100644
index 0000000..38d3e68
--- /dev/null
+++ b/tests/language/deferred/inheritance_constraints_lib.dart
@@ -0,0 +1,7 @@
+// 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.
+
+class Foo {}
+
+class Foo2 {}
diff --git a/tests/language/deferred/inheritance_constraints_runtime_test.dart b/tests/language/deferred/inheritance_constraints_runtime_test.dart
new file mode 100644
index 0000000..719a170
--- /dev/null
+++ b/tests/language/deferred/inheritance_constraints_runtime_test.dart
@@ -0,0 +1,43 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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:expect/expect.dart";
+import "inheritance_constraints_lib.dart" deferred as lib;
+
+class Foo {}
+
+class Foo2 extends D {}
+
+class A extends
+
+    Foo {}
+
+class B
+    implements
+
+        Foo {}
+
+class C1 {}
+
+class C = C1
+    with
+
+        Foo;
+
+class D {
+  D();
+  factory D.factory() =
+
+      Foo2;
+}
+
+void main() {
+  new A();
+  new B();
+  new C();
+  new D.factory();
+}
diff --git a/tests/language/deferred/inheritance_constraints_test.dart b/tests/language/deferred/inheritance_constraints_test.dart
new file mode 100644
index 0000000..9dd18f2
--- /dev/null
+++ b/tests/language/deferred/inheritance_constraints_test.dart
@@ -0,0 +1,39 @@
+// 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:expect/expect.dart";
+import "inheritance_constraints_lib.dart" deferred as lib;
+
+class Foo {}
+
+class Foo2 extends D {}
+
+class A extends lib.Foo {}
+//              ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.EXTENDS_DEFERRED_CLASS
+
+class B implements lib.Foo {}
+//                 ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_DEFERRED_CLASS
+
+class C1 {}
+
+class C = C1 with lib.Foo;
+//                ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.MIXIN_DEFERRED_CLASS
+
+class D {
+  D();
+  factory D.factory() = lib.Foo2;
+//                      ^^^^^^^^
+// [analyzer] STATIC_WARNING.REDIRECT_TO_INVALID_RETURN_TYPE
+// [cfe] The constructor function type 'Foo2 Function()' isn't a subtype of 'D Function()'.
+}
+
+void main() {
+  new A();
+  new B();
+  new C();
+  new D.factory();
+}
diff --git a/tests/language/deferred/inlined_test.dart b/tests/language/deferred/inlined_test.dart
new file mode 100644
index 0000000..5aa45b0
--- /dev/null
+++ b/tests/language/deferred/inlined_test.dart
@@ -0,0 +1,36 @@
+// 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.
+// VMOptions=--optimization-counter-threshold=10
+
+// Declares foo that returns 42.
+import "constraints_lib2.dart" deferred as lib;
+
+import 'package:expect/expect.dart';
+
+bool libLoaded = false;
+
+main() {
+  Expect.equals(88, heyhey());
+
+  // Trigger optimization of 'hehey' which inlines 'barbar'.
+  for (int i = 0; i < 30000; i++) {
+    heyhey();
+  }
+
+  lib.loadLibrary().then((_) {
+    libLoaded = true;
+    Expect.equals(42, heyhey());
+  });
+}
+
+// Inline bar in optimized code.
+heyhey() => barbar();
+
+barbar() {
+  if (libLoaded) {
+    // Returns 42.
+    return lib.foo();
+  }
+  return 88;
+}
diff --git a/tests/language/deferred/load_constants.dart b/tests/language/deferred/load_constants.dart
new file mode 100644
index 0000000..a67bd03
--- /dev/null
+++ b/tests/language/deferred/load_constants.dart
@@ -0,0 +1,20 @@
+// 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.
+// Dart version of two-argument Ackermann-Peter function.
+
+library deferred_load_constants;
+
+// Constant declaration.
+const c = const C();
+
+// Class declaration (`C` is a constant expression).
+class C {
+  const C();
+  static int staticfun(int x) => x;
+}
+
+// Function type definition.
+typedef int funtype(int x);
+// Top-level function.
+int toplevel(int x) => x;
diff --git a/tests/language/deferred/load_constants_runtime_test.dart b/tests/language/deferred/load_constants_runtime_test.dart
new file mode 100644
index 0000000..97e91a2
--- /dev/null
+++ b/tests/language/deferred/load_constants_runtime_test.dart
@@ -0,0 +1,38 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+// Dart version of two-argument Ackermann-Peter function.
+
+library deferred_load_constants;
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "load_constants.dart" deferred as foo;
+import "load_constants.dart";
+
+main() {
+  asyncStart();
+  Expect.throws(() => foo.c);
+  Expect.throws(() => foo.C);
+  Expect.throws(() => foo.funtype);
+  Expect.throws(() => foo.toplevel);
+  foo.loadLibrary().whenComplete(() {
+    // Reading constant declarations through deferred prefix works.
+    Expect.identical(c, foo.c);
+    Expect.identical(C, foo.C);
+    Expect.identical(funtype, foo.funtype);
+    Expect.identical(toplevel, foo.toplevel);
+    Expect.identical(C.staticfun, foo.C.staticfun);
+    // Access through deferred prefix is not a constant expression.
+
+
+
+
+
+
+    asyncEnd();
+  });
+}
diff --git a/tests/language/deferred/load_constants_test.dart b/tests/language/deferred/load_constants_test.dart
new file mode 100644
index 0000000..a57e24c
--- /dev/null
+++ b/tests/language/deferred/load_constants_test.dart
@@ -0,0 +1,60 @@
+// 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.
+// Dart version of two-argument Ackermann-Peter function.
+
+library deferred_load_constants;
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "load_constants.dart" deferred as foo;
+import "load_constants.dart";
+
+main() {
+  asyncStart();
+  Expect.throws(() => foo.c);
+  Expect.throws(() => foo.C);
+  Expect.throws(() => foo.funtype);
+  Expect.throws(() => foo.toplevel);
+  foo.loadLibrary().whenComplete(() {
+    // Reading constant declarations through deferred prefix works.
+    Expect.identical(c, foo.c);
+    Expect.identical(C, foo.C);
+    Expect.identical(funtype, foo.funtype);
+    Expect.identical(toplevel, foo.toplevel);
+    Expect.identical(C.staticfun, foo.C.staticfun);
+    // Access through deferred prefix is not a constant expression.
+    Expect.throws(() => const [foo.c]);
+    //                  ^
+    // [cfe] Constant evaluation error:
+    //                         ^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY
+    // [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+    Expect.throws(() => const [foo.C]);
+    //                  ^
+    // [cfe] Constant evaluation error:
+    //                         ^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY
+    // [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+    Expect.throws(() => const [foo.funtype]);
+    //                  ^
+    // [cfe] Constant evaluation error:
+    //                         ^^^^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY
+    // [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+    Expect.throws(() => const [foo.toplevel]);
+    //                  ^
+    // [cfe] Constant evaluation error:
+    //                         ^^^^^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY
+    // [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+    Expect.throws(() => const [foo.C.staticfun]);
+    //                  ^
+    // [cfe] Constant evaluation error:
+    //                         ^^^^^^^^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY
+    // [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+
+    asyncEnd();
+  });
+}
diff --git a/tests/language/deferred/load_inval_code_lib.dart b/tests/language/deferred/load_inval_code_lib.dart
new file mode 100644
index 0000000..512a8b3
--- /dev/null
+++ b/tests/language/deferred/load_inval_code_lib.dart
@@ -0,0 +1,7 @@
+// 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.
+
+foo() {
+  return "foo from library";
+}
diff --git a/tests/language/deferred/load_inval_code_test.dart b/tests/language/deferred/load_inval_code_test.dart
new file mode 100644
index 0000000..596e0bc
--- /dev/null
+++ b/tests/language/deferred/load_inval_code_test.dart
@@ -0,0 +1,38 @@
+// 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.
+//
+// VMOptions=--optimization-counter-threshold=100
+
+import "load_inval_code_lib.dart" deferred as d;
+
+bool loaded = false;
+
+var x = 0;
+
+bla() {
+  if (loaded) {
+    // Loading the library should have invalidated the optimized
+    // code containing the NSME. Now expect this call to succeed.
+    d.foo();
+  } else {
+    // Do some "busy work" to trigger optimization.
+    for (var i = 0; i < 100; i++) {
+      x++;
+    }
+  }
+}
+
+warmup() {
+  for (int i = 1; i < 1000; i++) {
+    bla();
+  }
+}
+
+main() {
+  warmup();
+  d.loadLibrary().then((_) {
+    loaded = true;
+    bla();
+  });
+}
diff --git a/tests/language/deferred/load_library_wrong_args_lib.dart b/tests/language/deferred/load_library_wrong_args_lib.dart
new file mode 100644
index 0000000..0f02e43
--- /dev/null
+++ b/tests/language/deferred/load_library_wrong_args_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+foo() => 42;
diff --git a/tests/language/deferred/load_library_wrong_args_test.dart b/tests/language/deferred/load_library_wrong_args_test.dart
new file mode 100644
index 0000000..c991e2e6
--- /dev/null
+++ b/tests/language/deferred/load_library_wrong_args_test.dart
@@ -0,0 +1,10 @@
+import "load_library_wrong_args_lib.dart" deferred as lib;
+
+void main() {
+  // Loadlibrary should be called without arguments.
+  lib.loadLibrary(10);
+//^
+// [cfe] 'loadLibrary' takes no arguments.
+//               ^^^^
+// [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+}
diff --git a/tests/language/deferred/mixin_lib1.dart b/tests/language/deferred/mixin_lib1.dart
new file mode 100644
index 0000000..3b43ffe
--- /dev/null
+++ b/tests/language/deferred/mixin_lib1.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.
+
+library lib1;
+
+import "mixin_shared.dart";
+import "mixin_test.dart";
+
+class Mixin {
+  foo() => "lib1.Mixin";
+}
+
+class A extends Object with NonDeferredMixin {
+  foo() {
+    return "A with " + super.foo();
+  }
+}
+
+class B extends Object with Mixin {
+  foo() {
+    return "B with " + super.foo();
+  }
+}
+
+class C extends Object with Mixin, NonDeferredMixin1 {
+  foo() {
+    return "C with " + super.foo();
+  }
+}
+
+class D extends Object with NonDeferredMixin2, Mixin {
+  foo() {
+    return "D with " + super.foo();
+  }
+}
+
+class E extends Object with SharedMixin {
+  foo() {
+    return "E with " + super.foo();
+  }
+}
diff --git a/tests/language/deferred/mixin_lib2.dart b/tests/language/deferred/mixin_lib2.dart
new file mode 100644
index 0000000..32fafef
--- /dev/null
+++ b/tests/language/deferred/mixin_lib2.dart
@@ -0,0 +1,13 @@
+// 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 lib2;
+
+import "mixin_shared.dart";
+
+class A extends Object with SharedMixin {
+  foo() {
+    return "lib2.A with " + super.foo();
+  }
+}
diff --git a/tests/language/deferred/mixin_shared.dart b/tests/language/deferred/mixin_shared.dart
new file mode 100644
index 0000000..8b6a293
--- /dev/null
+++ b/tests/language/deferred/mixin_shared.dart
@@ -0,0 +1,9 @@
+// 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 shared;
+
+class SharedMixin {
+  foo() => "SharedMixin";
+}
diff --git a/tests/language/deferred/mixin_test.dart b/tests/language/deferred/mixin_test.dart
new file mode 100644
index 0000000..33594b7
--- /dev/null
+++ b/tests/language/deferred/mixin_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 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+import "mixin_lib1.dart" deferred as lib1;
+import "mixin_lib2.dart" deferred as lib2;
+
+class NonDeferredMixin {
+  foo() => "NonDeferredMixin";
+}
+
+class NonDeferredMixin1 {
+  foo() => "NonDeferredMixin1";
+}
+
+class NonDeferredMixin2 {
+  foo() => "NonDeferredMixin2";
+}
+
+main() {
+  Expect.equals("NonDeferredMixin", new NonDeferredMixin().foo());
+  Expect.equals("NonDeferredMixin1", new NonDeferredMixin1().foo());
+  Expect.equals("NonDeferredMixin2", new NonDeferredMixin2().foo());
+  asyncStart();
+  lib1.loadLibrary().then((_) {
+    Expect.equals("lib1.Mixin", new lib1.Mixin().foo());
+    Expect.equals("A with NonDeferredMixin", new lib1.A().foo());
+    Expect.equals("B with lib1.Mixin", new lib1.B().foo());
+    Expect.equals("C with NonDeferredMixin1", new lib1.C().foo());
+    Expect.equals("D with lib1.Mixin", new lib1.D().foo());
+    Expect.equals("E with SharedMixin", new lib1.E().foo());
+    lib2.loadLibrary().then((_) {
+      Expect.equals("lib2.A with SharedMixin", new lib2.A().foo());
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/language/deferred/no_prefix_runtime_test.dart b/tests/language/deferred/no_prefix_runtime_test.dart
new file mode 100644
index 0000000..1cbab75
--- /dev/null
+++ b/tests/language/deferred/no_prefix_runtime_test.dart
@@ -0,0 +1,13 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Loading a deferred library without prefix is not allowed.
+import "constraints_lib2.dart"
+
+    ;
+
+void main() {}
diff --git a/tests/language/deferred/no_prefix_test.dart b/tests/language/deferred/no_prefix_test.dart
new file mode 100644
index 0000000..ff778e5
--- /dev/null
+++ b/tests/language/deferred/no_prefix_test.dart
@@ -0,0 +1,13 @@
+// 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.
+
+// Loading a deferred library without prefix is not allowed.
+import "constraints_lib2.dart"
+  deferred
+//^^^^^^^^
+// [analyzer] SYNTACTIC_ERROR.MISSING_PREFIX_IN_DEFERRED_IMPORT
+// [cfe] Deferred imports should have a prefix.
+    ;
+
+void main() {}
diff --git a/tests/language/deferred/no_such_method_lib.dart b/tests/language/deferred/no_such_method_lib.dart
new file mode 100644
index 0000000..ccb0091
--- /dev/null
+++ b/tests/language/deferred/no_such_method_lib.dart
@@ -0,0 +1,8 @@
+// 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.
+
+@proxy
+class C {
+  noSuchMethod(Invocation invocation) => 42;
+}
diff --git a/tests/language/deferred/no_such_method_test.dart b/tests/language/deferred/no_such_method_test.dart
new file mode 100644
index 0000000..0673319
--- /dev/null
+++ b/tests/language/deferred/no_such_method_test.dart
@@ -0,0 +1,16 @@
+// 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:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+import "no_such_method_lib.dart" deferred as lib;
+
+void main() {
+  asyncStart();
+  lib.loadLibrary().then((_) {
+    Expect.equals(42, (new lib.C() as dynamic).nonExisting());
+    asyncEnd();
+  });
+}
diff --git a/tests/language/deferred/not_loaded_check_lib.dart b/tests/language/deferred/not_loaded_check_lib.dart
new file mode 100644
index 0000000..704b4c1
--- /dev/null
+++ b/tests/language/deferred/not_loaded_check_lib.dart
@@ -0,0 +1,22 @@
+// 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.
+
+foo(int arg) {}
+
+class C {
+  C(int arg) {}
+  static foo(int arg) {}
+}
+
+var a;
+
+int get getter => 42;
+
+void set setter(int arg) {
+  a = 10;
+}
+
+var list = <int>[];
+
+var closure = (int arg) => 3;
diff --git a/tests/language/deferred/not_loaded_check_test.dart b/tests/language/deferred/not_loaded_check_test.dart
new file mode 100644
index 0000000..44c0fd4
--- /dev/null
+++ b/tests/language/deferred/not_loaded_check_test.dart
@@ -0,0 +1,78 @@
+// 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:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+import "not_loaded_check_lib.dart" deferred as lib;
+
+// Test that we give appropriate errors when accessing an element that is not
+// yet loaded.
+
+var c;
+
+expectSideEffect(test) {
+  c = 0;
+  test();
+  Expect.isTrue(c == 1);
+}
+
+expectNoSideEffect(test) {
+  c = 0;
+  test();
+  Expect.isTrue(c == 0);
+}
+
+expectThrowsNotLoaded(test) {
+  Expect.throws(test, (e) => e is Error);
+}
+
+int sideEffect() {
+  c = 1;
+  return 10;
+}
+
+void main() {
+  expectSideEffect(() {
+    expectThrowsNotLoaded(() {
+      lib.foo(sideEffect());
+    });
+  });
+  expectNoSideEffect(() {
+    expectThrowsNotLoaded(() {
+      lib.C.foo(sideEffect());
+    });
+  });
+  expectSideEffect(() {
+    expectThrowsNotLoaded(() {
+      new lib.C(sideEffect());
+    });
+  });
+  expectThrowsNotLoaded(() {
+    lib.a;
+  });
+  expectSideEffect(() {
+    expectThrowsNotLoaded(() {
+      lib.a = sideEffect();
+    });
+  });
+  expectThrowsNotLoaded(() {
+    lib.getter;
+  });
+  expectSideEffect(() {
+    expectThrowsNotLoaded(() {
+      lib.setter = sideEffect();
+    });
+  });
+  expectNoSideEffect(() {
+    expectThrowsNotLoaded(() {
+      lib.list[sideEffect()] = sideEffect();
+    });
+  });
+  expectSideEffect(() {
+    expectThrowsNotLoaded(() {
+      lib.closure(sideEffect());
+    });
+  });
+}
diff --git a/tests/language/deferred/only_constant_lib.dart b/tests/language/deferred/only_constant_lib.dart
new file mode 100644
index 0000000..1c84126
--- /dev/null
+++ b/tests/language/deferred/only_constant_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+const constant = const ["a", "b", "c"];
diff --git a/tests/language/deferred/only_constant_test.dart b/tests/language/deferred/only_constant_test.dart
new file mode 100644
index 0000000..37d2a2a
--- /dev/null
+++ b/tests/language/deferred/only_constant_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+// Testing import of only constants from a deferred library.
+
+import 'package:expect/expect.dart';
+
+import "only_constant_lib.dart" deferred as lib;
+
+void main() {
+  lib.loadLibrary().then((_) {
+    Expect.equals(lib.constant, const ["a", "b", "c"]);
+  });
+}
diff --git a/tests/language/deferred/optimized_test.dart b/tests/language/deferred/optimized_test.dart
new file mode 100644
index 0000000..7fd0a99
--- /dev/null
+++ b/tests/language/deferred/optimized_test.dart
@@ -0,0 +1,34 @@
+// 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.
+// VMOptions=--optimization-counter-threshold=10 --compiler-passes=-Inlining
+
+// Declares foo that returns 42.
+import "constraints_lib2.dart" deferred as lib;
+
+import 'package:expect/expect.dart';
+
+bool libLoaded = false;
+
+main() {
+  Expect.equals(88, heyhey());
+
+  for (int i = 0; i < 30; i++) {
+    heyhey();
+  }
+
+  lib.loadLibrary().then((_) {
+    libLoaded = true;
+    Expect.equals(42, heyhey());
+  });
+}
+
+heyhey() => barbar();
+
+barbar() {
+  if (libLoaded) {
+    // Returns 42.
+    return lib.foo();
+  }
+  return 88;
+}
diff --git a/tests/language/deferred/prefix_constraints_lib.dart b/tests/language/deferred/prefix_constraints_lib.dart
new file mode 100644
index 0000000..c79d4e5
--- /dev/null
+++ b/tests/language/deferred/prefix_constraints_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+foo() => 24;
diff --git a/tests/language/deferred/prefix_constraints_lib2.dart b/tests/language/deferred/prefix_constraints_lib2.dart
new file mode 100644
index 0000000..c79d4e5
--- /dev/null
+++ b/tests/language/deferred/prefix_constraints_lib2.dart
@@ -0,0 +1,5 @@
+// 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.
+
+foo() => 24;
diff --git a/tests/language/deferred/redirecting_factory_lib1.dart b/tests/language/deferred/redirecting_factory_lib1.dart
new file mode 100644
index 0000000..1e1a7a1
--- /dev/null
+++ b/tests/language/deferred/redirecting_factory_lib1.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 lib1;
+
+import "redirecting_factory_lib2.dart" deferred as lib2;
+import "redirecting_factory_test.dart" as main;
+
+loadLib2() {
+  return lib2.loadLibrary();
+}
+
+class C extends main.C {
+  String get foo => "lib1";
+  C();
+  factory C.a() = lib2.C;
+}
diff --git a/tests/language/deferred/redirecting_factory_lib2.dart b/tests/language/deferred/redirecting_factory_lib2.dart
new file mode 100644
index 0000000..a72be64
--- /dev/null
+++ b/tests/language/deferred/redirecting_factory_lib2.dart
@@ -0,0 +1,11 @@
+// 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 lib2;
+
+import "redirecting_factory_lib1.dart" as lib1;
+
+class C extends lib1.C {
+  String get foo => "lib2";
+}
diff --git a/tests/language/deferred/redirecting_factory_test.dart b/tests/language/deferred/redirecting_factory_test.dart
new file mode 100644
index 0000000..1ee76d3
--- /dev/null
+++ b/tests/language/deferred/redirecting_factory_test.dart
@@ -0,0 +1,50 @@
+// 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 main;
+
+import "redirecting_factory_lib1.dart" deferred as lib1;
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+class C {
+  String get foo => "main";
+  C();
+  factory C.a() = lib1.C;
+  factory C.b() = lib1.C.a;
+}
+
+test1() async {
+  Expect.throws(() {
+    new C.a();
+  });
+  Expect.throws(() {
+    new C.b();
+  });
+}
+
+test2() async {
+  await lib1.loadLibrary();
+  Expect.equals("lib1", new C.a().foo);
+  Expect.throws(() {
+    new C.b();
+  });
+}
+
+test3() async {
+  await lib1.loadLibrary();
+  await lib1.loadLib2();
+  Expect.equals("lib1", new C.a().foo);
+  Expect.equals("lib2", new C.b().foo);
+}
+
+test() async {
+  await test1();
+  await test2();
+  await test3();
+}
+
+void main() {
+  asyncStart();
+  test().then((_) => asyncEnd());
+}
diff --git a/tests/language/deferred/regression_22995_lib.dart b/tests/language/deferred/regression_22995_lib.dart
new file mode 100644
index 0000000..b6e3aef
--- /dev/null
+++ b/tests/language/deferred/regression_22995_lib.dart
@@ -0,0 +1,11 @@
+// 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 'regression_22995_test.dart';
+
+foofoo() {
+  new A();
+  new B();
+  new C();
+}
diff --git a/tests/language/deferred/regression_22995_test.dart b/tests/language/deferred/regression_22995_test.dart
new file mode 100644
index 0000000..fdd36c1
--- /dev/null
+++ b/tests/language/deferred/regression_22995_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.
+
+// Test that closurizing a function implies a dependency on its type.
+
+import "package:expect/expect.dart";
+
+import 'regression_22995_lib.dart' deferred as lib;
+
+class A {}
+
+class B {}
+
+class C {}
+
+typedef Ti(int x);
+typedef TB(B x);
+typedef TTi(Ti x);
+typedef Tg<T>(T x);
+
+class T {
+  fA(A a) => null;
+  fTB(TB a) => null;
+  fTgC(Tg<C> a) => null;
+}
+
+main() {
+  Expect.isFalse(new T().fA is Ti);
+  Expect.isFalse(new T().fTB is TTi);
+  Expect.isFalse(new T().fTgC is TTi);
+  lib.loadLibrary().then((_) {
+    lib.foofoo();
+  });
+}
diff --git a/tests/language/deferred/regression_28678_lib.dart b/tests/language/deferred/regression_28678_lib.dart
new file mode 100644
index 0000000..d985e0a
--- /dev/null
+++ b/tests/language/deferred/regression_28678_lib.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.
+
+var v;
+
+class Clazz {}
diff --git a/tests/language/deferred/regression_28678_test.dart b/tests/language/deferred/regression_28678_test.dart
new file mode 100644
index 0000000..16a95f9
--- /dev/null
+++ b/tests/language/deferred/regression_28678_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+// Test that await after deferred loading works as expected.
+
+import 'dart:async';
+import "package:expect/expect.dart";
+import 'regression_28678_lib.dart' deferred as lib;
+
+class A {
+  m() => "here";
+}
+
+f(a, b) => new Future.microtask(() {});
+
+class R {
+  Future test_deferred() async {
+    var a = new A();
+    await lib.loadLibrary();
+    await f(lib.Clazz, lib.v);
+    Expect.equals("here", a.m());
+  }
+}
+
+main() async {
+  await new R().test_deferred();
+}
diff --git a/tests/language/deferred/shadow_load_library_lib.dart b/tests/language/deferred/shadow_load_library_lib.dart
new file mode 100644
index 0000000..e7811aa
--- /dev/null
+++ b/tests/language/deferred/shadow_load_library_lib.dart
@@ -0,0 +1,7 @@
+// 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.
+
+loadLibrary() => 42;
+
+var trueVar = true;
diff --git a/tests/language/deferred/shadow_load_library_test.dart b/tests/language/deferred/shadow_load_library_test.dart
new file mode 100644
index 0000000..2c096c9
--- /dev/null
+++ b/tests/language/deferred/shadow_load_library_test.dart
@@ -0,0 +1,23 @@
+// 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:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+// This library contains a member loadLibrary.
+// Check that we shadow this member.
+import "shadow_load_library_lib.dart" deferred as lib;
+
+void main() {
+  var x = lib.loadLibrary();
+  Expect.isTrue(x is Future);
+  asyncStart();
+  x.then((_) {
+    Expect.isTrue(lib.trueVar);
+    // Check that shadowing still is in place after loading the library.
+    Expect.isTrue(lib.loadLibrary() is Future);
+    asyncEnd();
+  });
+}
diff --git a/tests/language/deferred/shared_and_unshared_classes_lib1.dart b/tests/language/deferred/shared_and_unshared_classes_lib1.dart
new file mode 100644
index 0000000..28d2ef3
--- /dev/null
+++ b/tests/language/deferred/shared_and_unshared_classes_lib1.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 lib1;
+
+import "shared_and_unshared_classes_lib_shared.dart";
+
+foo() {
+  print(new C1());
+  print(new CShared());
+}
diff --git a/tests/language/deferred/shared_and_unshared_classes_lib2.dart b/tests/language/deferred/shared_and_unshared_classes_lib2.dart
new file mode 100644
index 0000000..86fc901
--- /dev/null
+++ b/tests/language/deferred/shared_and_unshared_classes_lib2.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 lib2;
+
+import "shared_and_unshared_classes_lib_shared.dart";
+
+foo() {
+  print(new C2());
+  print(new CShared());
+}
diff --git a/tests/language/deferred/shared_and_unshared_classes_lib_shared.dart b/tests/language/deferred/shared_and_unshared_classes_lib_shared.dart
new file mode 100644
index 0000000..a2c5665
--- /dev/null
+++ b/tests/language/deferred/shared_and_unshared_classes_lib_shared.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.
+
+library shared;
+
+class CShared {
+  toString() => "shared";
+}
+
+class C1 {
+  toString() => "C1";
+}
+
+class C2 {
+  toString() => "C2";
+}
diff --git a/tests/language/deferred/shared_and_unshared_classes_test.dart b/tests/language/deferred/shared_and_unshared_classes_test.dart
new file mode 100644
index 0000000..a815c74
--- /dev/null
+++ b/tests/language/deferred/shared_and_unshared_classes_test.dart
@@ -0,0 +1,22 @@
+// 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:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "shared_and_unshared_classes_lib1.dart" deferred as lib1;
+import "shared_and_unshared_classes_lib2.dart" deferred as lib2;
+import "dart:async";
+
+void main() {
+  asyncTest(() {
+    return Future.wait([
+      lib1.loadLibrary().then((_) {
+        lib1.foo();
+      }),
+      lib2.loadLibrary().then((_) {
+        lib2.foo();
+      })
+    ]);
+  });
+}
diff --git a/tests/language/deferred/static_seperate_lib1.dart b/tests/language/deferred/static_seperate_lib1.dart
new file mode 100644
index 0000000..07e9cf5
--- /dev/null
+++ b/tests/language/deferred/static_seperate_lib1.dart
@@ -0,0 +1,54 @@
+// 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 lib1;
+
+class ConstClass {
+  final x;
+  const ConstClass(this.x);
+}
+
+var x = const ConstClass(const ConstClass(1));
+
+class C {
+  static foo() {
+    () {}(); // Hack to avoid inlining.
+    return 1;
+  }
+
+  bar() {
+    () {}(); // Hack to avoid inlining.
+    return 1;
+  }
+}
+
+class C1 {
+  static var foo = const {};
+  var bar = const {};
+}
+
+class C2 {
+  static var foo = new Map<int, int>.from({1: 2});
+  var bar = new Map<int, int>.from({1: 2});
+}
+
+class C3 {
+  static final foo = const ConstClass(const ConstClass(1));
+  final bar = const ConstClass(const ConstClass(1));
+}
+
+class C4 {
+  static final foo = new Map<ConstClass, ConstClass>.from({x: x});
+  final bar = new Map<ConstClass, ConstClass>.from({x: x});
+}
+
+class C5 {
+  static const foo = const [
+    const {1: 3}
+  ];
+  bar() {
+    () {}(); // Hack to avoid inlining.
+    return 1;
+  }
+}
diff --git a/tests/language/deferred/static_seperate_lib2.dart b/tests/language/deferred/static_seperate_lib2.dart
new file mode 100644
index 0000000..683b9a4
--- /dev/null
+++ b/tests/language/deferred/static_seperate_lib2.dart
@@ -0,0 +1,23 @@
+// 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 lib2;
+
+import "package:expect/expect.dart";
+import "static_seperate_lib1.dart";
+
+foo() {
+  Expect.equals(1, C.foo());
+  Expect.mapEquals({}, C1.foo);
+
+  Expect.mapEquals({1: 2}, C2.foo);
+  C2.foo = {1: 2};
+  Expect.mapEquals({1: 2}, C2.foo);
+
+  Expect.equals(x, C3.foo);
+  Expect.mapEquals({x: x}, C4.foo);
+  Expect.listEquals([
+    const {1: 3}
+  ], C5.foo);
+}
diff --git a/tests/language/deferred/static_seperate_test.dart b/tests/language/deferred/static_seperate_test.dart
new file mode 100644
index 0000000..c920eb8
--- /dev/null
+++ b/tests/language/deferred/static_seperate_test.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// The class lib1.C is referenced via lib1
+// The static function lib1.C.foo is referenced via lib2
+// Dart2js will put them in seperate hunks.
+// Similarly for C2, ..., C5.
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "static_seperate_lib1.dart" deferred as lib1;
+import "static_seperate_lib2.dart" deferred as lib2;
+
+void main() {
+  asyncStart();
+  Expect.throws(() => new lib1.C());
+  lib1.loadLibrary().then((_) {
+    lib2.loadLibrary().then((_) {
+      print("HERE");
+      Expect.equals(1, new lib1.C().bar());
+      var x = new lib1.C2();
+      Expect.mapEquals({1: 2}, x.bar);
+      x.bar = {2: 3};
+      Expect.mapEquals({2: 3}, x.bar);
+
+      Expect.equals(lib1.x, new lib1.C3().bar);
+      Expect.mapEquals({lib1.x: lib1.x}, new lib1.C4().bar);
+      Expect.equals(1, new lib1.C5().bar());
+
+      lib2.foo();
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/language/deferred/super_dependency_lib.dart b/tests/language/deferred/super_dependency_lib.dart
new file mode 100644
index 0000000..8638a4f
--- /dev/null
+++ b/tests/language/deferred/super_dependency_lib.dart
@@ -0,0 +1,11 @@
+// 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.
+
+class A {}
+
+class C extends A {
+  foo() {
+    super.foo = 3;
+  }
+}
diff --git a/tests/language/deferred/super_dependency_runtime_test.dart b/tests/language/deferred/super_dependency_runtime_test.dart
new file mode 100644
index 0000000..c09a7f8
--- /dev/null
+++ b/tests/language/deferred/super_dependency_runtime_test.dart
@@ -0,0 +1,18 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Regression test.
+// lib.C.foo has code that references `super.foo=` that does not exist. This
+// used to cause a crash.
+
+import "package:expect/expect.dart";
+
+
+main() async {
+
+
+}
diff --git a/tests/language/deferred/super_dependency_test.dart b/tests/language/deferred/super_dependency_test.dart
new file mode 100644
index 0000000..f49380c
--- /dev/null
+++ b/tests/language/deferred/super_dependency_test.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.
+
+// Regression test.
+// lib.C.foo has code that references `super.foo=` that does not exist. This
+// used to cause a crash.
+
+import "package:expect/expect.dart";
+//        ^^^
+// [analyzer] STATIC_TYPE_WARNING.UNDEFINED_SUPER_SETTER
+// [cfe] Superclass has no setter named 'foo'.
+import "super_dependency_lib.dart" deferred as lib;
+
+main() async {
+  await lib.loadLibrary();
+  Expect.throwsNoSuchMethodError(() => new lib.C().foo());
+}
diff --git a/tests/language/deferred/type_dependency_lib1.dart b/tests/language/deferred/type_dependency_lib1.dart
new file mode 100644
index 0000000..491ecc6
--- /dev/null
+++ b/tests/language/deferred/type_dependency_lib1.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2015, the Dart Team. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+library lib1;
+
+import "type_dependency_lib3.dart";
+
+bool fooIs(x) {
+  return x is A;
+}
+
+bool fooAs(x) {
+  try {
+    return (x as A).p;
+  } on TypeError {
+    return false;
+  }
+}
+
+bool fooAnnotation(x) {
+  try {
+    A y = x;
+    return y is! String;
+  } on TypeError {
+    return false;
+  }
+}
diff --git a/tests/language/deferred/type_dependency_lib2.dart b/tests/language/deferred/type_dependency_lib2.dart
new file mode 100644
index 0000000..d20f4c0
--- /dev/null
+++ b/tests/language/deferred/type_dependency_lib2.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2015, the Dart Team. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+library lib2;
+
+import "type_dependency_lib3.dart";
+
+getInstance() {
+  return new A();
+}
diff --git a/tests/language/deferred/type_dependency_lib3.dart b/tests/language/deferred/type_dependency_lib3.dart
new file mode 100644
index 0000000..ae8c258
--- /dev/null
+++ b/tests/language/deferred/type_dependency_lib3.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 lib3;
+
+class A {
+  var p = true;
+}
diff --git a/tests/language/deferred/type_dependency_test.dart b/tests/language/deferred/type_dependency_test.dart
new file mode 100644
index 0000000..7d31d5f
--- /dev/null
+++ b/tests/language/deferred/type_dependency_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2015, the Dart Team. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+/// Checks that lib1.fooX's dependencies on [A] via is-checks, as-expressions
+/// and type-annotations(in checked-mode) is correctly tracked.
+
+import "type_dependency_lib1.dart" deferred as lib1;
+import "type_dependency_lib2.dart" deferred as lib2;
+import "package:expect/expect.dart";
+
+main() async {
+  await lib1.loadLibrary();
+  // Split the cases into a multi-test to test each feature separately.
+  Expect.isFalse(
+      lib1.fooIs //# is: ok
+      lib1.fooAs //# as: ok
+      lib1.fooAnnotation //# type_annotation: ok
+      ("string")
+      is! String //# none: ok
+      );
+  await lib2.loadLibrary();
+  Expect.isTrue(
+      lib1.fooIs //# is: ok
+      lib1.fooAs //# as: ok
+      lib1.fooAnnotation //# type_annotation: ok
+      (lib2.getInstance())
+      is! String //# none: ok
+      );
+}
diff --git a/tests/language/double/comparison_test.dart b/tests/language/double/comparison_test.dart
new file mode 100644
index 0000000..cf00962
--- /dev/null
+++ b/tests/language/double/comparison_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 VM optimizing compiler negate condition for doubles (bug 5376516).
+
+loop() {
+  for (double d = 0.0; d < 1100.0; d++) {}
+  for (double d = 0.0; d <= 1100.0; d++) {}
+  for (double d = 1000.0; d > 0.0; d--) {}
+  for (double d = 1000.0; d >= 0.0; d--) {}
+}
+
+main() {
+  loop();
+  loop();
+}
diff --git a/tests/language/double/identical_test.dart b/tests/language/double/identical_test.dart
new file mode 100644
index 0000000..16b99fe
--- /dev/null
+++ b/tests/language/double/identical_test.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 "package:expect/expect.dart";
+
+main() {
+  Expect.isTrue(identical(42.0, 42.0));
+  Expect.isTrue(identical(-0.0, -0.0));
+  Expect.isTrue(identical(0.0, 0.0));
+  Expect.isTrue(identical(1.234E9, 1.234E9));
+  Expect.isFalse(identical(0.0, -0.0));
+  Expect.isTrue(identical(double.nan, double.nan));
+}
diff --git a/tests/language/double/int_addition_test.dart b/tests/language/double/int_addition_test.dart
new file mode 100644
index 0000000..809fec5
--- /dev/null
+++ b/tests/language/double/int_addition_test.dart
@@ -0,0 +1,20 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+import "package:expect/expect.dart";
+
+// Test that optimized code does not silently convert integers to doubles.
+
+main() {
+  // Optimize add-op
+  for (int i = 0; i < 20; i++) {
+    addOp(1.1, 2.1);
+  }
+
+  Expect.isTrue(addOp(1.1, 2.1) is double);
+  Expect.isTrue(addOp(1, 2) is int);
+}
+
+addOp(a, b) => a + b;
diff --git a/tests/language/double/int_to_string_test.dart b/tests/language/double/int_to_string_test.dart
new file mode 100644
index 0000000..04c7ef7
--- /dev/null
+++ b/tests/language/double/int_to_string_test.dart
@@ -0,0 +1,20 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals("0.0", (0.0).toString());
+  Expect.equals("9.0", (9.0).toString());
+  Expect.equals("90.0", (90.0).toString());
+  Expect.equals(
+      "111111111111111110000.0", (111111111111111111111.0).toString());
+  Expect.equals("-9.0", (-9.0).toString());
+  Expect.equals("-90.0", (-90.0).toString());
+  Expect.equals(
+      "-111111111111111110000.0", (-111111111111111111111.0).toString());
+  Expect.equals("1000.0", (1000.0).toString());
+  Expect.equals("1000000000000000100.0", (1000000000000000128.0).toString());
+}
diff --git a/tests/language/double/invalid_runtime_test.dart b/tests/language/double/invalid_runtime_test.dart
new file mode 100644
index 0000000..a47bfc7
--- /dev/null
+++ b/tests/language/double/invalid_runtime_test.dart
@@ -0,0 +1,13 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test an invalid double format
+
+main() {
+
+  ;
+}
diff --git a/tests/language/double/invalid_test.dart b/tests/language/double/invalid_test.dart
new file mode 100644
index 0000000..dcfe3f4
--- /dev/null
+++ b/tests/language/double/invalid_test.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.
+
+// Test an invalid double format
+
+main() {
+  3457e
+//^
+// [cfe] Numbers in exponential notation should always contain an exponent (an integer number with an optional sign).
+//    ^
+// [analyzer] SYNTACTIC_ERROR.MISSING_DIGIT
+  ;
+}
diff --git a/tests/language/double/modulo_test.dart b/tests/language/double/modulo_test.dart
new file mode 100644
index 0000000..d17bcc5
--- /dev/null
+++ b/tests/language/double/modulo_test.dart
@@ -0,0 +1,19 @@
+// 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.
+// Dart test optimization of modulo operator on Double.
+// VMOptions=--optimization-counter-threshold=10
+
+import "package:expect/expect.dart";
+
+main() {
+  double k = -0.33333;
+  double firstResPos = doMod(k, 1.0);
+  double firstResNeg = doMod(k, -1.0);
+  for (int i = 0; i < 20; i++) {
+    Expect.equals(firstResPos, doMod(k, 1.0));
+    Expect.equals(firstResNeg, doMod(k, -1.0));
+  }
+}
+
+doMod(a, b) => a % b;
diff --git a/tests/language/double/nan_comparison_test.dart b/tests/language/double/nan_comparison_test.dart
new file mode 100644
index 0000000..64eb038
--- /dev/null
+++ b/tests/language/double/nan_comparison_test.dart
@@ -0,0 +1,32 @@
+// 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.
+// Tests double comparisons with NaN in different contexts.
+// VMOptions=--optimization-counter-threshold=10
+
+import "package:expect/expect.dart";
+
+test_expr(a, b) => a != b;
+
+test_conditional(a, b) => a != b ? true : false;
+
+test_branch(a, b) {
+  if (a != b) {
+    return true;
+  }
+  return false;
+}
+
+main() {
+  Expect.equals(true, test_expr(0.5, double.nan));
+  for (var i = 0; i < 20; i++) test_expr(0.5, double.nan);
+  Expect.equals(true, test_expr(0.5, double.nan));
+
+  Expect.equals(true, test_conditional(0.5, double.nan));
+  for (var i = 0; i < 20; i++) test_conditional(0.5, double.nan);
+  Expect.equals(true, test_conditional(0.5, double.nan));
+
+  Expect.equals(true, test_branch(0.5, double.nan));
+  for (var i = 0; i < 20; i++) test_branch(0.5, double.nan);
+  Expect.equals(true, test_branch(0.5, double.nan));
+}
diff --git a/tests/language/double/to_string_as_exponential2_runtime_test.dart b/tests/language/double/to_string_as_exponential2_runtime_test.dart
new file mode 100644
index 0000000..1c0a498
--- /dev/null
+++ b/tests/language/double/to_string_as_exponential2_runtime_test.dart
@@ -0,0 +1,18 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  var v = 1.0;
+  Expect.throwsRangeError(() => v.toStringAsExponential(-1));
+  Expect.throwsRangeError(() => v.toStringAsExponential(21));
+
+
+
+}
diff --git a/tests/language/double/to_string_as_exponential2_test.dart b/tests/language/double/to_string_as_exponential2_test.dart
new file mode 100644
index 0000000..fbe03c4
--- /dev/null
+++ b/tests/language/double/to_string_as_exponential2_test.dart
@@ -0,0 +1,24 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  var v = 1.0;
+  Expect.throwsRangeError(() => v.toStringAsExponential(-1));
+  Expect.throwsRangeError(() => v.toStringAsExponential(21));
+  v.toStringAsExponential(1.5);
+  //                      ^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  // [cfe] The argument type 'double' can't be assigned to the parameter type 'int?'.
+  v.toStringAsExponential("string");
+  //                      ^^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  // [cfe] The argument type 'String' can't be assigned to the parameter type 'int?'.
+  v.toStringAsExponential("3");
+  //                      ^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  // [cfe] The argument type 'String' can't be assigned to the parameter type 'int?'.
+}
diff --git a/tests/language/double/to_string_as_exponential3_test.dart b/tests/language/double/to_string_as_exponential3_test.dart
new file mode 100644
index 0000000..7300013
--- /dev/null
+++ b/tests/language/double/to_string_as_exponential3_test.dart
@@ -0,0 +1,12 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals("1.00000000000000000000e+0", (1.0).toStringAsExponential(20));
+  Expect.equals("1.00000000000000005551e-1", (0.1).toStringAsExponential(20));
+  Expect.equals(1.00000000000000005551e-1, 0.1);
+}
diff --git a/tests/language/double/to_string_as_exponential_test.dart b/tests/language/double/to_string_as_exponential_test.dart
new file mode 100644
index 0000000..e201913
--- /dev/null
+++ b/tests/language/double/to_string_as_exponential_test.dart
@@ -0,0 +1,100 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals("1e+0", (1.0).toStringAsExponential());
+  Expect.equals("1.1e+1", (11.0).toStringAsExponential());
+  Expect.equals("1.12e+2", (112.0).toStringAsExponential());
+  Expect.equals("1e+0", (1.0).toStringAsExponential(null));
+  Expect.equals("1.1e+1", (11.0).toStringAsExponential(null));
+  Expect.equals("1.12e+2", (112.0).toStringAsExponential(null));
+  Expect.equals("1e+0", (1.0).toStringAsExponential(0));
+  Expect.equals("1e+1", (11.0).toStringAsExponential(0));
+  Expect.equals("1e+2", (112.0).toStringAsExponential(0));
+  Expect.equals("1.0e+0", (1.0).toStringAsExponential(1));
+  Expect.equals("1.1e+1", (11.0).toStringAsExponential(1));
+  Expect.equals("1.1e+2", (112.0).toStringAsExponential(1));
+  Expect.equals("1.00e+0", (1.0).toStringAsExponential(2));
+  Expect.equals("1.10e+1", (11.0).toStringAsExponential(2));
+  Expect.equals("1.12e+2", (112.0).toStringAsExponential(2));
+  Expect.equals("1.000e+0", (1.0).toStringAsExponential(3));
+  Expect.equals("1.100e+1", (11.0).toStringAsExponential(3));
+  Expect.equals("1.120e+2", (112.0).toStringAsExponential(3));
+  Expect.equals("1e-1", (0.1).toStringAsExponential());
+  Expect.equals("1.1e-1", (0.11).toStringAsExponential());
+  Expect.equals("1.12e-1", (0.112).toStringAsExponential());
+  Expect.equals("1e-1", (0.1).toStringAsExponential(null));
+  Expect.equals("1.1e-1", (0.11).toStringAsExponential(null));
+  Expect.equals("1.12e-1", (0.112).toStringAsExponential(null));
+  Expect.equals("1e-1", (0.1).toStringAsExponential(0));
+  Expect.equals("1e-1", (0.11).toStringAsExponential(0));
+  Expect.equals("1e-1", (0.112).toStringAsExponential(0));
+  Expect.equals("1.0e-1", (0.1).toStringAsExponential(1));
+  Expect.equals("1.1e-1", (0.11).toStringAsExponential(1));
+  Expect.equals("1.1e-1", (0.112).toStringAsExponential(1));
+  Expect.equals("1.00e-1", (0.1).toStringAsExponential(2));
+  Expect.equals("1.10e-1", (0.11).toStringAsExponential(2));
+  Expect.equals("1.12e-1", (0.112).toStringAsExponential(2));
+  Expect.equals("1.000e-1", (0.1).toStringAsExponential(3));
+  Expect.equals("1.100e-1", (0.11).toStringAsExponential(3));
+  Expect.equals("1.120e-1", (0.112).toStringAsExponential(3));
+
+  Expect.equals("-0e+0", (-0.0).toStringAsExponential());
+  Expect.equals("-1e+0", (-1.0).toStringAsExponential());
+  Expect.equals("-1.1e+1", (-11.0).toStringAsExponential());
+  Expect.equals("-1.12e+2", (-112.0).toStringAsExponential());
+  Expect.equals("-0e+0", (-0.0).toStringAsExponential(null));
+  Expect.equals("-1e+0", (-1.0).toStringAsExponential(null));
+  Expect.equals("-1.1e+1", (-11.0).toStringAsExponential(null));
+  Expect.equals("-1.12e+2", (-112.0).toStringAsExponential(null));
+  Expect.equals("-1e+0", (-1.0).toStringAsExponential(0));
+  Expect.equals("-1e+1", (-11.0).toStringAsExponential(0));
+  Expect.equals("-1e+2", (-112.0).toStringAsExponential(0));
+  Expect.equals("-1.0e+0", (-1.0).toStringAsExponential(1));
+  Expect.equals("-1.1e+1", (-11.0).toStringAsExponential(1));
+  Expect.equals("-1.1e+2", (-112.0).toStringAsExponential(1));
+  Expect.equals("-1.00e+0", (-1.0).toStringAsExponential(2));
+  Expect.equals("-1.10e+1", (-11.0).toStringAsExponential(2));
+  Expect.equals("-1.12e+2", (-112.0).toStringAsExponential(2));
+  Expect.equals("-1.000e+0", (-1.0).toStringAsExponential(3));
+  Expect.equals("-1.100e+1", (-11.0).toStringAsExponential(3));
+  Expect.equals("-1.120e+2", (-112.0).toStringAsExponential(3));
+  Expect.equals("-1e-1", (-0.1).toStringAsExponential());
+  Expect.equals("-1.1e-1", (-0.11).toStringAsExponential());
+  Expect.equals("-1.12e-1", (-0.112).toStringAsExponential());
+  Expect.equals("-1e-1", (-0.1).toStringAsExponential(null));
+  Expect.equals("-1.1e-1", (-0.11).toStringAsExponential(null));
+  Expect.equals("-1.12e-1", (-0.112).toStringAsExponential(null));
+  Expect.equals("-1e-1", (-0.1).toStringAsExponential(0));
+  Expect.equals("-1e-1", (-0.11).toStringAsExponential(0));
+  Expect.equals("-1e-1", (-0.112).toStringAsExponential(0));
+  Expect.equals("-1.0e-1", (-0.1).toStringAsExponential(1));
+  Expect.equals("-1.1e-1", (-0.11).toStringAsExponential(1));
+  Expect.equals("-1.1e-1", (-0.112).toStringAsExponential(1));
+  Expect.equals("-1.00e-1", (-0.1).toStringAsExponential(2));
+  Expect.equals("-1.10e-1", (-0.11).toStringAsExponential(2));
+  Expect.equals("-1.12e-1", (-0.112).toStringAsExponential(2));
+  Expect.equals("-1.000e-1", (-0.1).toStringAsExponential(3));
+  Expect.equals("-1.100e-1", (-0.11).toStringAsExponential(3));
+  Expect.equals("-1.120e-1", (-0.112).toStringAsExponential(3));
+
+  Expect.equals("NaN", (double.nan).toStringAsExponential(2));
+  Expect.equals("Infinity", (double.infinity).toStringAsExponential(2));
+  Expect.equals("-Infinity", (-double.infinity).toStringAsExponential(2));
+  Expect.equals("1e+0", (1.0).toStringAsExponential(0));
+  Expect.equals("0e+0", (0.0).toStringAsExponential());
+  Expect.equals("0e+0", (0.0).toStringAsExponential(null));
+  Expect.equals("0.00e+0", (0.0).toStringAsExponential(2));
+  Expect.equals("1e+1", (11.2356).toStringAsExponential(0));
+  Expect.equals("1.1236e+1", (11.2356).toStringAsExponential(4));
+  Expect.equals("1.1236e-4", (0.000112356).toStringAsExponential(4));
+  Expect.equals("-1.1236e-4", (-0.000112356).toStringAsExponential(4));
+  Expect.equals("1.12356e-4", (0.000112356).toStringAsExponential());
+  Expect.equals("-1.12356e-4", (-0.000112356).toStringAsExponential());
+  Expect.equals("1.12356e-4", (0.000112356).toStringAsExponential(null));
+  Expect.equals("-1.12356e-4", (-0.000112356).toStringAsExponential(null));
+}
diff --git a/tests/language/double/to_string_as_fixed2_runtime_test.dart b/tests/language/double/to_string_as_fixed2_runtime_test.dart
new file mode 100644
index 0000000..821394f
--- /dev/null
+++ b/tests/language/double/to_string_as_fixed2_runtime_test.dart
@@ -0,0 +1,18 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  var v = 0.0;
+  Expect.throwsRangeError(() => v.toStringAsFixed(-1));
+  Expect.throwsRangeError(() => v.toStringAsFixed(21));
+
+
+
+}
diff --git a/tests/language/double/to_string_as_fixed_test.dart b/tests/language/double/to_string_as_fixed_test.dart
new file mode 100644
index 0000000..6e0aed2
--- /dev/null
+++ b/tests/language/double/to_string_as_fixed_test.dart
@@ -0,0 +1,104 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+class ToStringAsFixedTest {
+  static void testMain() {
+    Expect.equals("2.000", 2.0.toStringAsFixed(3));
+    Expect.equals("2.100", 2.1.toStringAsFixed(3));
+    Expect.equals("2.120", 2.12.toStringAsFixed(3));
+    Expect.equals("2.123", 2.123.toStringAsFixed(3));
+    Expect.equals("2.124", 2.1239.toStringAsFixed(3));
+    Expect.equals("NaN", (0.0 / 0.0).toStringAsFixed(3));
+    Expect.equals("Infinity", (1.0 / 0.0).toStringAsFixed(3));
+    Expect.equals("-Infinity", (-1.0 / 0.0).toStringAsFixed(3));
+    Expect.equals(
+        "1.1111111111111111e+21", 1111111111111111111111.0.toStringAsFixed(8));
+    Expect.equals("0.1", 0.1.toStringAsFixed(1));
+    Expect.equals("0.10", 0.1.toStringAsFixed(2));
+    Expect.equals("0.100", 0.1.toStringAsFixed(3));
+    Expect.equals("0.01", 0.01.toStringAsFixed(2));
+    Expect.equals("0.010", 0.01.toStringAsFixed(3));
+    Expect.equals("0.0100", 0.01.toStringAsFixed(4));
+    Expect.equals("0.00", 0.001.toStringAsFixed(2));
+    Expect.equals("0.001", 0.001.toStringAsFixed(3));
+    Expect.equals("0.0010", 0.001.toStringAsFixed(4));
+    Expect.equals("1.0000", 1.0.toStringAsFixed(4));
+    Expect.equals("1.0", 1.0.toStringAsFixed(1));
+    Expect.equals("1", 1.0.toStringAsFixed(0));
+    Expect.equals("12", 12.0.toStringAsFixed(0));
+    Expect.equals("1", 1.1.toStringAsFixed(0));
+    Expect.equals("12", 12.1.toStringAsFixed(0));
+    Expect.equals("1", 1.12.toStringAsFixed(0));
+    Expect.equals("12", 12.12.toStringAsFixed(0));
+    Expect.equals("0.0000006", 0.0000006.toStringAsFixed(7));
+    Expect.equals("0.00000006", 0.00000006.toStringAsFixed(8));
+    Expect.equals("0.000000060", 0.00000006.toStringAsFixed(9));
+    Expect.equals("0.0000000600", 0.00000006.toStringAsFixed(10));
+    Expect.equals("0", 0.0.toStringAsFixed(0));
+    Expect.equals("0.0", 0.0.toStringAsFixed(1));
+    Expect.equals("0.00", 0.0.toStringAsFixed(2));
+
+    Expect.equals("-0.1", (-0.1).toStringAsFixed(1));
+    Expect.equals("-0.10", (-0.1).toStringAsFixed(2));
+    Expect.equals("-0.100", (-0.1).toStringAsFixed(3));
+    Expect.equals("-0.01", (-0.01).toStringAsFixed(2));
+    Expect.equals("-0.010", (-0.01).toStringAsFixed(3));
+    Expect.equals("-0.0100", (-0.01).toStringAsFixed(4));
+    Expect.equals("-0.00", (-0.001).toStringAsFixed(2));
+    Expect.equals("-0.001", (-0.001).toStringAsFixed(3));
+    Expect.equals("-0.0010", (-0.001).toStringAsFixed(4));
+    Expect.equals("-1.0000", (-1.0).toStringAsFixed(4));
+    Expect.equals("-1.0", (-1.0).toStringAsFixed(1));
+    Expect.equals("-1", (-1.0).toStringAsFixed(0));
+    Expect.equals("-1", (-1.1).toStringAsFixed(0));
+    Expect.equals("-12", (-12.1).toStringAsFixed(0));
+    Expect.equals("-1", (-1.12).toStringAsFixed(0));
+    Expect.equals("-12", (-12.12).toStringAsFixed(0));
+    Expect.equals("-0.0000006", (-0.0000006).toStringAsFixed(7));
+    Expect.equals("-0.00000006", (-0.00000006).toStringAsFixed(8));
+    Expect.equals("-0.000000060", (-0.00000006).toStringAsFixed(9));
+    Expect.equals("-0.0000000600", (-0.00000006).toStringAsFixed(10));
+    Expect.equals("-0", (-0.0).toStringAsFixed(0));
+    Expect.equals("-0.0", (-0.0).toStringAsFixed(1));
+    Expect.equals("-0.00", (-0.0).toStringAsFixed(2));
+
+    Expect.equals("1000", 1000.0.toStringAsFixed(0));
+    Expect.equals("0", 0.00001.toStringAsFixed(0));
+    Expect.equals("0.00001", 0.00001.toStringAsFixed(5));
+    Expect.equals(
+        "0.00000000000000000010", 0.0000000000000000001.toStringAsFixed(20));
+    Expect.equals("0.00001000000000000", 0.00001.toStringAsFixed(17));
+    Expect.equals("1.00000000000000000", 1.0.toStringAsFixed(17));
+    Expect.equals(
+        "1000000000000000128", 1000000000000000128.0.toStringAsFixed(0));
+    Expect.equals(
+        "100000000000000128.0", 100000000000000128.0.toStringAsFixed(1));
+    Expect.equals(
+        "10000000000000128.00", 10000000000000128.0.toStringAsFixed(2));
+    Expect.equals("10000000000000128.00000000000000000000",
+        10000000000000128.0.toStringAsFixed(20));
+    Expect.equals("0", 0.0.toStringAsFixed(0));
+    Expect.equals("-42.000", (-42.0).toStringAsFixed(3));
+    Expect.equals(
+        "-1000000000000000128", (-1000000000000000128.0).toStringAsFixed(0));
+    Expect.equals("-0.00000000000000000010",
+        (-0.0000000000000000001).toStringAsFixed(20));
+    Expect.equals(
+        "0.12312312312312299889", 0.123123123123123.toStringAsFixed(20));
+    // Test that we round up even when the last digit generated is even.
+    // dtoa does not do this in its original form.
+    Expect.equals("1", 0.5.toStringAsFixed(0));
+    Expect.equals("-1", (-0.5).toStringAsFixed(0));
+    Expect.equals("1.3", 1.25.toStringAsFixed(1));
+    Expect.equals("234.2040", 234.20405.toStringAsFixed(4));
+    Expect.equals("234.2041", 234.2040506.toStringAsFixed(4));
+  }
+}
+
+main() {
+  ToStringAsFixedTest.testMain();
+}
diff --git a/tests/language/double/to_string_as_precision2_runtime_test.dart b/tests/language/double/to_string_as_precision2_runtime_test.dart
new file mode 100644
index 0000000..8831dca
--- /dev/null
+++ b/tests/language/double/to_string_as_precision2_runtime_test.dart
@@ -0,0 +1,18 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  var v = 0.0;
+  Expect.throwsRangeError(() => v.toStringAsPrecision(0));
+  Expect.throwsRangeError(() => v.toStringAsPrecision(22));
+
+
+
+}
diff --git a/tests/language/double/to_string_as_precision3_test.dart b/tests/language/double/to_string_as_precision3_test.dart
new file mode 100644
index 0000000..19f390ca
--- /dev/null
+++ b/tests/language/double/to_string_as_precision3_test.dart
@@ -0,0 +1,18 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals(
+      "0.000555000000000000046248", (0.000555).toStringAsPrecision(21));
+  Expect.equals(0.000555000000000000046248, 0.000555);
+  Expect.equals(
+      "5.54999999999999980179e-7", (0.000000555).toStringAsPrecision(21));
+  Expect.equals(5.54999999999999980179e-7, 0.000000555);
+  Expect.equals(
+      "-5.54999999999999980179e-7", (-0.000000555).toStringAsPrecision(21));
+  Expect.equals(-5.54999999999999980179e-7, -0.000000555);
+}
diff --git a/tests/language/double/to_string_as_precision_test.dart b/tests/language/double/to_string_as_precision_test.dart
new file mode 100644
index 0000000..6c048fe
--- /dev/null
+++ b/tests/language/double/to_string_as_precision_test.dart
@@ -0,0 +1,42 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals("NaN", (double.nan).toStringAsPrecision(1));
+  Expect.equals("Infinity", (double.infinity).toStringAsPrecision(2));
+  Expect.equals("-Infinity", (-double.infinity).toStringAsPrecision(2));
+  Expect.equals("0.000555000000000000", (0.000555).toStringAsPrecision(15));
+  Expect.equals("5.55000000000000e-7", (0.000000555).toStringAsPrecision(15));
+  Expect.equals("-5.55000000000000e-7", (-0.000000555).toStringAsPrecision(15));
+  Expect.equals("1e+8", (123456789.0).toStringAsPrecision(1));
+  Expect.equals("123456789", (123456789.0).toStringAsPrecision(9));
+  Expect.equals("1.2345679e+8", (123456789.0).toStringAsPrecision(8));
+  Expect.equals("1.234568e+8", (123456789.0).toStringAsPrecision(7));
+  Expect.equals("-1.234568e+8", (-123456789.0).toStringAsPrecision(7));
+  Expect.equals("-1.2e-9", (-.0000000012345).toStringAsPrecision(2));
+  Expect.equals("-1.2e-8", (-.000000012345).toStringAsPrecision(2));
+  Expect.equals("-1.2e-7", (-.00000012345).toStringAsPrecision(2));
+  Expect.equals("-0.0000012", (-.0000012345).toStringAsPrecision(2));
+  Expect.equals("-0.000012", (-.000012345).toStringAsPrecision(2));
+  Expect.equals("-0.00012", (-.00012345).toStringAsPrecision(2));
+  Expect.equals("-0.0012", (-.0012345).toStringAsPrecision(2));
+  Expect.equals("-0.012", (-.012345).toStringAsPrecision(2));
+  Expect.equals("-0.12", (-.12345).toStringAsPrecision(2));
+  Expect.equals("-1.2", (-1.2345).toStringAsPrecision(2));
+  Expect.equals("-12", (-12.345).toStringAsPrecision(2));
+  Expect.equals("-1.2e+2", (-123.45).toStringAsPrecision(2));
+  Expect.equals("-1.2e+3", (-1234.5).toStringAsPrecision(2));
+  Expect.equals("-1.2e+4", (-12345.0).toStringAsPrecision(2));
+  Expect.equals("-1.235e+4", (-12345.67).toStringAsPrecision(4));
+  Expect.equals("-1.234e+4", (-12344.67).toStringAsPrecision(4));
+  Expect.equals("-0.0", (-0.0).toStringAsPrecision(2));
+  Expect.equals("-0", (-0.0).toStringAsPrecision(1));
+  // Test that we round up even when the last digit generated is even.
+  // dtoa does not do this in its original form.
+  Expect.equals("1.3", 1.25.toStringAsPrecision(2));
+  Expect.equals("1.4", 1.35.toStringAsPrecision(2));
+}
diff --git a/tests/language/double/to_string_test.dart b/tests/language/double/to_string_test.dart
new file mode 100644
index 0000000..fcdafb9
--- /dev/null
+++ b/tests/language/double/to_string_test.dart
@@ -0,0 +1,56 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test basic integer operations.
+
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals("NaN", (double.nan).toString());
+  Expect.equals("Infinity", (1 / 0).toString());
+  Expect.equals("-Infinity", (-1 / 0).toString());
+  Expect.equals("90.12", (90.12).toString());
+  Expect.equals("0.1", (0.1).toString());
+  Expect.equals("0.01", (0.01).toString());
+  Expect.equals("0.0123", (0.0123).toString());
+  Expect.equals(
+      "1.1111111111111111e+21", (1111111111111111111111.0).toString());
+  Expect.equals(
+      "1.1111111111111111e+22", (11111111111111111111111.0).toString());
+  Expect.equals("0.00001", (0.00001).toString());
+  Expect.equals("0.000001", (0.000001).toString());
+  Expect.equals("1e-7", (0.0000001).toString());
+  Expect.equals("1.2e-7", (0.00000012).toString());
+  Expect.equals("1.23e-7", (0.000000123).toString());
+  Expect.equals("1e-8", (0.00000001).toString());
+  Expect.equals("1.2e-8", (0.000000012).toString());
+  Expect.equals("1.23e-8", (0.0000000123).toString());
+
+  Expect.equals("-0.0", (-0.0).toString());
+  Expect.equals("-90.12", (-90.12).toString());
+  Expect.equals("-0.1", (-0.1).toString());
+  Expect.equals("-0.01", (-0.01).toString());
+  Expect.equals("-0.0123", (-0.0123).toString());
+  Expect.equals(
+      "-1.1111111111111111e+21", (-1111111111111111111111.0).toString());
+  Expect.equals(
+      "-1.1111111111111111e+22", (-11111111111111111111111.0).toString());
+  Expect.equals("-0.00001", (-0.00001).toString());
+  Expect.equals("-0.000001", (-0.000001).toString());
+  Expect.equals("-1e-7", (-0.0000001).toString());
+  Expect.equals("-1.2e-7", (-0.00000012).toString());
+  Expect.equals("-1.23e-7", (-0.000000123).toString());
+  Expect.equals("-1e-8", (-0.00000001).toString());
+  Expect.equals("-1.2e-8", (-0.000000012).toString());
+  Expect.equals("-1.23e-8", (-0.0000000123).toString());
+
+  Expect.equals("0.00001", (0.00001).toString());
+  Expect.equals("1e+21", (1000000000000000012800.0).toString());
+  Expect.equals("-1e+21", (-1000000000000000012800.0).toString());
+  Expect.equals("1e-7", (0.0000001).toString());
+  Expect.equals("-1e-7", (-0.0000001).toString());
+  Expect.equals(
+      "1.0000000000000001e+21", (1000000000000000128000.0).toString());
+  Expect.equals("0.000001", (0.000001).toString());
+  Expect.equals("1e-7", (0.0000001).toString());
+}
diff --git a/tests/language/double_literals/double_literal_coercion_error_test.dart b/tests/language/double_literals/double_literal_coercion_error_test.dart
new file mode 100644
index 0000000..6b574fc
--- /dev/null
+++ b/tests/language/double_literals/double_literal_coercion_error_test.dart
@@ -0,0 +1,299 @@
+// 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.
+
+// Introduces a context with double as type.
+void notDouble([double value = 0.0]) {
+  if (value != 0.0) throw "unreachable";
+}
+
+main() {
+  notDouble(
+    // Large decimal numbers which are not representable as doubles.
+    9007199254740993, //     2^53+2^0      //# 001: compile-time error
+    18014398509481983, //    2^54-2^0      //# 002: compile-time error
+    18014398509481985, //    2^54+2^0      //# 003: compile-time error
+    18014398509481986, //    2^54+2^1      //# 004: compile-time error
+    4611686018427387903, //  2^62-2^0      //# 005: compile-time error
+    4611686018427387902, //  2^62-2^1      //# 006: compile-time error
+    4611686018427387900, //  2^62-2^2      //# 007: compile-time error
+    4611686018427387896, //  2^62-2^3      //# 008: compile-time error
+    4611686018427387888, //  2^62-2^4      //# 009: compile-time error
+    4611686018427387872, //  2^62-2^5      //# 010: compile-time error
+    4611686018427387840, //  2^62-2^6      //# 011: compile-time error
+    4611686018427387776, //  2^62-2^7      //# 012: compile-time error
+    4611686018427387648, //  2^62-2^8      //# 013: compile-time error
+    4611686018427387905, //  2^62+2^0      //# 014: compile-time error
+    4611686018427387906, //  2^62+2^1      //# 015: compile-time error
+    4611686018427387908, //  2^62+2^2      //# 016: compile-time error
+    4611686018427387912, //  2^62+2^3      //# 017: compile-time error
+    4611686018427387920, //  2^62+2^4      //# 018: compile-time error
+    4611686018427387936, //  2^62+2^5      //# 019: compile-time error
+    4611686018427387968, //  2^62+2^6      //# 020: compile-time error
+    4611686018427388032, //  2^62+2^7      //# 021: compile-time error
+    4611686018427388160, //  2^62+2^8      //# 022: compile-time error
+    4611686018427388416, //  2^62+2^9      //# 023: compile-time error
+    9223372036854775807, //  2^63-2^0      //# 024: compile-time error
+    9223372036854775806, //  2^63-2^1      //# 025: compile-time error
+    9223372036854775804, //  2^63-2^2      //# 026: compile-time error
+    9223372036854775800, //  2^63-2^3      //# 027: compile-time error
+    9223372036854775792, //  2^63-2^4      //# 028: compile-time error
+    9223372036854775776, //  2^63-2^5      //# 029: compile-time error
+    9223372036854775744, //  2^63-2^6      //# 030: compile-time error
+    9223372036854775680, //  2^63-2^7      //# 031: compile-time error
+    9223372036854775552, //  2^63-2^8      //# 032: compile-time error
+    9223372036854775296, //  2^63-2^9      //# 033: compile-time error
+    9223372036854775809, //  2^63+2^0      //# 034: compile-time error
+    9223372036854775810, //  2^63+2^1      //# 035: compile-time error
+    9223372036854775812, //  2^63+2^2      //# 036: compile-time error
+    9223372036854775816, //  2^63+2^3      //# 037: compile-time error
+    9223372036854775824, //  2^63+2^4      //# 038: compile-time error
+    9223372036854775840, //  2^63+2^5      //# 039: compile-time error
+    9223372036854775872, //  2^63+2^6      //# 040: compile-time error
+    9223372036854775936, //  2^63+2^7      //# 041: compile-time error
+    9223372036854776064, //  2^63+2^8      //# 042: compile-time error
+    9223372036854776320, //  2^63+2^9      //# 043: compile-time error
+    9223372036854776832, //  2^63+2^10     //# 044: compile-time error
+    18446744073709551615, // 2^64-2^0      //# 045: compile-time error
+    18446744073709551614, // 2^64-2^1      //# 046: compile-time error
+    18446744073709551612, // 2^64-2^2      //# 047: compile-time error
+    18446744073709551608, // 2^64-2^3      //# 048: compile-time error
+    18446744073709551600, // 2^64-2^4      //# 049: compile-time error
+    18446744073709551584, // 2^64-2^5      //# 050: compile-time error
+    18446744073709551552, // 2^64-2^6      //# 051: compile-time error
+    18446744073709551488, // 2^64-2^7      //# 052: compile-time error
+    18446744073709551360, // 2^64-2^8      //# 053: compile-time error
+    18446744073709551104, // 2^64-2^9      //# 054: compile-time error
+    18446744073709550592, // 2^64-2^10     //# 055: compile-time error
+    18446744073709551617, // 2^64+2^0      //# 056: compile-time error
+    18446744073709551618, // 2^64+2^1      //# 057: compile-time error
+    18446744073709551620, // 2^64+2^2      //# 058: compile-time error
+    18446744073709551624, // 2^64+2^3      //# 059: compile-time error
+    18446744073709551632, // 2^64+2^4      //# 060: compile-time error
+    18446744073709551648, // 2^64+2^5      //# 061: compile-time error
+    18446744073709551680, // 2^64+2^6      //# 062: compile-time error
+    18446744073709551744, // 2^64+2^7      //# 063: compile-time error
+    18446744073709551872, // 2^64+2^8      //# 064: compile-time error
+    18446744073709552128, // 2^64+2^9      //# 065: compile-time error
+    18446744073709552640, // 2^64+2^10     //# 066: compile-time error
+    18446744073709553664, // 2^64+2^11     //# 067: compile-time error
+    179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858367, // maxValue - 1 //# 068 : compile-time error
+    179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369, // maxValue + 1 //# 069 : compile-time error
+    359538626972463141629054847463408713596141135051689993197834953606314521560057077521179117265533756343080917907028764928468642653778928365536935093407075033972099821153102564152490980180778657888151737016910267884609166473806445896331617118664246696549595652408289446337476354361838599762500808052368249716734, // maxValue * 2 //# 070P : compile-time error
+
+    // Negative numbers too.
+    -9007199254740993, //     -(2^53+2^0)  //# 071: compile-time error
+    -18014398509481983, //    -(2^54-2^0)  //# 072: compile-time error
+    -18014398509481985, //    -(2^54+2^0)  //# 073: compile-time error
+    -18014398509481986, //    -(2^54+2^1)  //# 074: compile-time error
+    -4611686018427387903, //  -(2^62-2^0)  //# 075: compile-time error
+    -4611686018427387902, //  -(2^62-2^1)  //# 076: compile-time error
+    -4611686018427387900, //  -(2^62-2^2)  //# 077: compile-time error
+    -4611686018427387896, //  -(2^62-2^3)  //# 078: compile-time error
+    -4611686018427387888, //  -(2^62-2^4)  //# 079: compile-time error
+    -4611686018427387872, //  -(2^62-2^5)  //# 080: compile-time error
+    -4611686018427387840, //  -(2^62-2^6)  //# 081: compile-time error
+    -4611686018427387776, //  -(2^62-2^7)  //# 082: compile-time error
+    -4611686018427387648, //  -(2^62-2^8)  //# 083: compile-time error
+    -4611686018427387905, //  -(2^62+2^0)  //# 084: compile-time error
+    -4611686018427387906, //  -(2^62+2^1)  //# 085: compile-time error
+    -4611686018427387908, //  -(2^62+2^2)  //# 086: compile-time error
+    -4611686018427387912, //  -(2^62+2^3)  //# 087: compile-time error
+    -4611686018427387920, //  -(2^62+2^4)  //# 088: compile-time error
+    -4611686018427387936, //  -(2^62+2^5)  //# 089: compile-time error
+    -4611686018427387968, //  -(2^62+2^6)  //# 090: compile-time error
+    -4611686018427388032, //  -(2^62+2^7)  //# 091: compile-time error
+    -4611686018427388160, //  -(2^62+2^8)  //# 092: compile-time error
+    -4611686018427388416, //  -(2^62+2^9)  //# 093: compile-time error
+    -9223372036854775807, //  -(2^63-2^0)  //# 094: compile-time error
+    -9223372036854775806, //  -(2^63-2^1)  //# 095: compile-time error
+    -9223372036854775804, //  -(2^63-2^2)  //# 096: compile-time error
+    -9223372036854775800, //  -(2^63-2^3)  //# 097: compile-time error
+    -9223372036854775792, //  -(2^63-2^4)  //# 098: compile-time error
+    -9223372036854775776, //  -(2^63-2^5)  //# 099: compile-time error
+    -9223372036854775744, //  -(2^63-2^6)  //# 100: compile-time error
+    -9223372036854775680, //  -(2^63-2^7)  //# 101: compile-time error
+    -9223372036854775552, //  -(2^63-2^8)  //# 102: compile-time error
+    -9223372036854775296, //  -(2^63-2^9)  //# 103: compile-time error
+    -9223372036854775809, //  -(2^63+2^0)  //# 104: compile-time error
+    -9223372036854775810, //  -(2^63+2^1)  //# 105: compile-time error
+    -9223372036854775812, //  -(2^63+2^2)  //# 106: compile-time error
+    -9223372036854775816, //  -(2^63+2^3)  //# 107: compile-time error
+    -9223372036854775824, //  -(2^63+2^4)  //# 108: compile-time error
+    -9223372036854775840, //  -(2^63+2^5)  //# 109: compile-time error
+    -9223372036854775872, //  -(2^63+2^6)  //# 110: compile-time error
+    -9223372036854775936, //  -(2^63+2^7)  //# 111: compile-time error
+    -9223372036854776064, //  -(2^63+2^8)  //# 112: compile-time error
+    -9223372036854776320, //  -(2^63+2^9)  //# 113: compile-time error
+    -9223372036854776832, //  -(2^63+2^10) //# 114: compile-time error
+    -18446744073709551615, // -(2^64-2^0)  //# 115: compile-time error
+    -18446744073709551614, // -(2^64-2^1)  //# 116: compile-time error
+    -18446744073709551612, // -(2^64-2^2)  //# 117: compile-time error
+    -18446744073709551608, // -(2^64-2^3)  //# 118: compile-time error
+    -18446744073709551600, // -(2^64-2^4)  //# 119: compile-time error
+    -18446744073709551584, // -(2^64-2^5)  //# 120: compile-time error
+    -18446744073709551552, // -(2^64-2^6)  //# 121: compile-time error
+    -18446744073709551488, // -(2^64-2^7)  //# 122: compile-time error
+    -18446744073709551360, // -(2^64-2^8)  //# 123: compile-time error
+    -18446744073709551104, // -(2^64-2^9)  //# 124: compile-time error
+    -18446744073709550592, // -(2^64-2^10) //# 125: compile-time error
+    -18446744073709551617, // -(2^64+2^0)  //# 126: compile-time error
+    -18446744073709551618, // -(2^64+2^1)  //# 127: compile-time error
+    -18446744073709551620, // -(2^64+2^2)  //# 128: compile-time error
+    -18446744073709551624, // -(2^64+2^3)  //# 129: compile-time error
+    -18446744073709551632, // -(2^64+2^4)  //# 130: compile-time error
+    -18446744073709551648, // -(2^64+2^5)  //# 131: compile-time error
+    -18446744073709551680, // -(2^64+2^6)  //# 132: compile-time error
+    -18446744073709551744, // -(2^64+2^7)  //# 133: compile-time error
+    -18446744073709551872, // -(2^64+2^8)  //# 134: compile-time error
+    -18446744073709552128, // -(2^64+2^9)  //# 135: compile-time error
+    -18446744073709552640, // -(2^64+2^10) //# 136: compile-time error
+    -18446744073709553664, // -(2^64+2^11) //# 137: compile-time error
+    -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858367, // -(maxValue - 1) //# 138 : compile-time error
+    -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369, // -(maxValue + 1) //# 139 : compile-time error
+    -359538626972463141629054847463408713596141135051689993197834953606314521560057077521179117265533756343080917907028764928468642653778928365536935093407075033972099821153102564152490980180778657888151737016910267884609166473806445896331617118664246696549595652408289446337476354361838599762500808052368249716734, // -(maxValue * 2) //# 140B : compile-time error
+
+    // Same numbers as hexadecimal literals.
+    0x20000000000001, //    2^53+2^0      //# 141: compile-time error
+    0x3fffffffffffff, //    2^54-2^0      //# 142: compile-time error
+    0x40000000000001, //    2^54+2^0      //# 143: compile-time error
+    0x40000000000002, //    2^54+2^1      //# 144: compile-time error
+    0x3fffffffffffffff, //  2^62-2^0      //# 145: compile-time error
+    0x3ffffffffffffffe, //  2^62-2^1      //# 146: compile-time error
+    0x3ffffffffffffffc, //  2^62-2^2      //# 147: compile-time error
+    0x3ffffffffffffff8, //  2^62-2^3      //# 148: compile-time error
+    0x3ffffffffffffff0, //  2^62-2^4      //# 149: compile-time error
+    0x3fffffffffffffe0, //  2^62-2^5      //# 150: compile-time error
+    0x3fffffffffffffc0, //  2^62-2^6      //# 151: compile-time error
+    0x3fffffffffffff80, //  2^62-2^7      //# 152: compile-time error
+    0x3fffffffffffff00, //  2^62-2^8      //# 153: compile-time error
+    0x4000000000000001, //  2^62+2^0      //# 154: compile-time error
+    0x4000000000000002, //  2^62+2^1      //# 155: compile-time error
+    0x4000000000000004, //  2^62+2^2      //# 156: compile-time error
+    0x4000000000000008, //  2^62+2^3      //# 157: compile-time error
+    0x4000000000000010, //  2^62+2^4      //# 158: compile-time error
+    0x4000000000000020, //  2^62+2^5      //# 159: compile-time error
+    0x4000000000000040, //  2^62+2^6      //# 160: compile-time error
+    0x4000000000000080, //  2^62+2^7      //# 161: compile-time error
+    0x4000000000000100, //  2^62+2^8      //# 162: compile-time error
+    0x4000000000000200, //  2^62+2^9      //# 163: compile-time error
+    0x7fffffffffffffff, //  2^63-2^0      //# 164: compile-time error
+    0x7ffffffffffffffe, //  2^63-2^1      //# 165: compile-time error
+    0x7ffffffffffffffc, //  2^63-2^2      //# 166: compile-time error
+    0x7ffffffffffffff8, //  2^63-2^3      //# 167: compile-time error
+    0x7ffffffffffffff0, //  2^63-2^4      //# 168: compile-time error
+    0x7fffffffffffffe0, //  2^63-2^5      //# 169: compile-time error
+    0x7fffffffffffffc0, //  2^63-2^6      //# 170: compile-time error
+    0x7fffffffffffff80, //  2^63-2^7      //# 171: compile-time error
+    0x7fffffffffffff00, //  2^63-2^8      //# 172: compile-time error
+    0x7ffffffffffffe00, //  2^63-2^9      //# 173: compile-time error
+    0x8000000000000001, //  2^63+2^0      //# 174: compile-time error
+    0x8000000000000002, //  2^63+2^1      //# 175: compile-time error
+    0x8000000000000004, //  2^63+2^2      //# 176: compile-time error
+    0x8000000000000008, //  2^63+2^3      //# 177: compile-time error
+    0x8000000000000010, //  2^63+2^4      //# 178: compile-time error
+    0x8000000000000020, //  2^63+2^5      //# 179: compile-time error
+    0x8000000000000040, //  2^63+2^6      //# 180: compile-time error
+    0x8000000000000080, //  2^63+2^7      //# 181: compile-time error
+    0x8000000000000100, //  2^63+2^8      //# 182: compile-time error
+    0x8000000000000200, //  2^63+2^9      //# 183: compile-time error
+    0x8000000000000400, //  2^63+2^10     //# 184: compile-time error
+    0xffffffffffffffff, //  2^64-2^0      //# 185: compile-time error
+    0xfffffffffffffffe, //  2^64-2^1      //# 186: compile-time error
+    0xfffffffffffffffc, //  2^64-2^2      //# 187: compile-time error
+    0xfffffffffffffff8, //  2^64-2^3      //# 188: compile-time error
+    0xfffffffffffffff0, //  2^64-2^4      //# 189: compile-time error
+    0xffffffffffffffe0, //  2^64-2^5      //# 190: compile-time error
+    0xffffffffffffffc0, //  2^64-2^6      //# 191: compile-time error
+    0xffffffffffffff80, //  2^64-2^7      //# 192: compile-time error
+    0xffffffffffffff00, //  2^64-2^8      //# 193: compile-time error
+    0xfffffffffffffe00, //  2^64-2^9      //# 194: compile-time error
+    0xfffffffffffffc00, //  2^64-2^10     //# 195: compile-time error
+    0x10000000000000001, // 2^64+2^0      //# 196: compile-time error
+    0x10000000000000002, // 2^64+2^1      //# 197: compile-time error
+    0x10000000000000004, // 2^64+2^2      //# 198: compile-time error
+    0x10000000000000008, // 2^64+2^3      //# 199: compile-time error
+    0x10000000000000010, // 2^64+2^4      //# 200: compile-time error
+    0x10000000000000020, // 2^64+2^5      //# 201: compile-time error
+    0x10000000000000040, // 2^64+2^6      //# 202: compile-time error
+    0x10000000000000080, // 2^64+2^7      //# 203: compile-time error
+    0x10000000000000100, // 2^64+2^8      //# 204: compile-time error
+    0x10000000000000200, // 2^64+2^9      //# 205: compile-time error
+    0x10000000000000400, // 2^64+2^10     //# 206: compile-time error
+    0x10000000000000800, // 2^64+2^11     //# 207: compile-time error
+    0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, // maxValue - 1 //# 208 : compile-time error
+    0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, // maxValue + 1 //# 209 : compile-time error
+    0x1fffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, // maxValue * 2 //# 210V : compile-time error
+
+    -0x20000000000001, //    -(2^53+2^0)      //# 211: compile-time error
+    -0x3fffffffffffff, //    -(2^54-2^0)      //# 212: compile-time error
+    -0x40000000000001, //    -(2^54+2^0)      //# 213: compile-time error
+    -0x40000000000002, //    -(2^54+2^1)      //# 214: compile-time error
+    -0x3fffffffffffffff, //  -(2^62-2^0)      //# 215: compile-time error
+    -0x3ffffffffffffffe, //  -(2^62-2^1)      //# 216: compile-time error
+    -0x3ffffffffffffffc, //  -(2^62-2^2)      //# 217: compile-time error
+    -0x3ffffffffffffff8, //  -(2^62-2^3)      //# 218: compile-time error
+    -0x3ffffffffffffff0, //  -(2^62-2^4)      //# 219: compile-time error
+    -0x3fffffffffffffe0, //  -(2^62-2^5)      //# 220: compile-time error
+    -0x3fffffffffffffc0, //  -(2^62-2^6)      //# 221: compile-time error
+    -0x3fffffffffffff80, //  -(2^62-2^7)      //# 222: compile-time error
+    -0x3fffffffffffff00, //  -(2^62-2^8)      //# 223: compile-time error
+    -0x4000000000000001, //  -(2^62+2^0)      //# 224: compile-time error
+    -0x4000000000000002, //  -(2^62+2^1)      //# 225: compile-time error
+    -0x4000000000000004, //  -(2^62+2^2)      //# 226: compile-time error
+    -0x4000000000000008, //  -(2^62+2^3)      //# 227: compile-time error
+    -0x4000000000000010, //  -(2^62+2^4)      //# 228: compile-time error
+    -0x4000000000000020, //  -(2^62+2^5)      //# 229: compile-time error
+    -0x4000000000000040, //  -(2^62+2^6)      //# 230: compile-time error
+    -0x4000000000000080, //  -(2^62+2^7)      //# 231: compile-time error
+    -0x4000000000000100, //  -(2^62+2^8)      //# 232: compile-time error
+    -0x4000000000000200, //  -(2^62+2^9)      //# 233: compile-time error
+    -0x7fffffffffffffff, //  -(2^63-2^0)      //# 234: compile-time error
+    -0x7ffffffffffffffe, //  -(2^63-2^1)      //# 235: compile-time error
+    -0x7ffffffffffffffc, //  -(2^63-2^2)      //# 236: compile-time error
+    -0x7ffffffffffffff8, //  -(2^63-2^3)      //# 237: compile-time error
+    -0x7ffffffffffffff0, //  -(2^63-2^4)      //# 238: compile-time error
+    -0x7fffffffffffffe0, //  -(2^63-2^5)      //# 239: compile-time error
+    -0x7fffffffffffffc0, //  -(2^63-2^6)      //# 240: compile-time error
+    -0x7fffffffffffff80, //  -(2^63-2^7)      //# 241: compile-time error
+    -0x7fffffffffffff00, //  -(2^63-2^8)      //# 242: compile-time error
+    -0x7ffffffffffffe00, //  -(2^63-2^9)      //# 243: compile-time error
+    -0x8000000000000001, //  -(2^63+2^0)      //# 244: compile-time error
+    -0x8000000000000002, //  -(2^63+2^1)      //# 245: compile-time error
+    -0x8000000000000004, //  -(2^63+2^2)      //# 246: compile-time error
+    -0x8000000000000008, //  -(2^63+2^3)      //# 247: compile-time error
+    -0x8000000000000010, //  -(2^63+2^4)      //# 248: compile-time error
+    -0x8000000000000020, //  -(2^63+2^5)      //# 249: compile-time error
+    -0x8000000000000040, //  -(2^63+2^6)      //# 250: compile-time error
+    -0x8000000000000080, //  -(2^63+2^7)      //# 251: compile-time error
+    -0x8000000000000100, //  -(2^63+2^8)      //# 252: compile-time error
+    -0x8000000000000200, //  -(2^63+2^9)      //# 253: compile-time error
+    -0x8000000000000400, //  -(2^63+2^10)     //# 254: compile-time error
+    -0xffffffffffffffff, //  -(2^64-2^0)      //# 255: compile-time error
+    -0xfffffffffffffffe, //  -(2^64-2^1)      //# 256: compile-time error
+    -0xfffffffffffffffc, //  -(2^64-2^2)      //# 257: compile-time error
+    -0xfffffffffffffff8, //  -(2^64-2^3)      //# 258: compile-time error
+    -0xfffffffffffffff0, //  -(2^64-2^4)      //# 259: compile-time error
+    -0xffffffffffffffe0, //  -(2^64-2^5)      //# 260: compile-time error
+    -0xffffffffffffffc0, //  -(2^64-2^6)      //# 261: compile-time error
+    -0xffffffffffffff80, //  -(2^64-2^7)      //# 262: compile-time error
+    -0xffffffffffffff00, //  -(2^64-2^8)      //# 263: compile-time error
+    -0xfffffffffffffe00, //  -(2^64-2^9)      //# 264: compile-time error
+    -0xfffffffffffffc00, //  -(2^64-2^10)     //# 265: compile-time error
+    -0x10000000000000001, // -(2^64+2^0)      //# 266: compile-time error
+    -0x10000000000000002, // -(2^64+2^1)      //# 267: compile-time error
+    -0x10000000000000004, // -(2^64+2^2)      //# 268: compile-time error
+    -0x10000000000000008, // -(2^64+2^3)      //# 269: compile-time error
+    -0x10000000000000010, // -(2^64+2^4)      //# 270: compile-time error
+    -0x10000000000000020, // -(2^64+2^5)      //# 271: compile-time error
+    -0x10000000000000040, // -(2^64+2^6)      //# 272: compile-time error
+    -0x10000000000000080, // -(2^64+2^7)      //# 273: compile-time error
+    -0x10000000000000100, // -(2^64+2^8)      //# 274: compile-time error
+    -0x10000000000000200, // -(2^64+2^9)      //# 275: compile-time error
+    -0x10000000000000400, // -(2^64+2^10)     //# 276: compile-time error
+    -0x10000000000000800, // -(2^64+2^11)     //# 277: compile-time error
+    -0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, // -(maxValue - 1) //# 278 : compile-time error
+    -0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, // -(maxValue + 1) //# 279 : compile-time error
+    -0x1fffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, // -(maxValue * 2) //# 280 : compile-time error
+  );
+}
diff --git a/tests/language/double_literals/double_literal_coercion_test.dart b/tests/language/double_literals/double_literal_coercion_test.dart
new file mode 100644
index 0000000..b18b22f
--- /dev/null
+++ b/tests/language/double_literals/double_literal_coercion_test.dart
@@ -0,0 +1,149 @@
+// 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:expect/expect.dart";
+
+// Pass expected value and then decimal literal value in a double context.
+void expectDouble(double expectedValue, double actualValue) {
+  Expect.identical(expectedValue, actualValue);
+}
+
+// Some exact powers of two as double values.
+double p2_8 = 256.0;
+double p2_30 = 1073741824.0;
+double p2_31 = 2147483648.0;
+double p2_32 = 4294967296.0;
+double p2_52 = 4503599627370496.0;
+double p2_53 = 9007199254740992.0;
+double p2_54 = 18014398509481984.0;
+double p2_62 = 4611686018427387904.0;
+double p2_63 = 9223372036854775808.0;
+double p2_64 = 18446744073709551616.0;
+double maxValue = 1.7976931348623157e+308;
+
+main() {
+  expectDouble(0.0, 0);
+  expectDouble(1.0, 1);
+  expectDouble(0.0, 00);
+  expectDouble(1.0, 01);
+  expectDouble(p2_8 - 1, 255);
+  expectDouble(p2_8, 256);
+  expectDouble(p2_8 + 1, 257);
+  expectDouble(p2_30 - 1, 1073741823);
+  expectDouble(p2_30, 1073741824);
+  expectDouble(p2_30 + 1, 1073741825);
+  expectDouble(p2_31 - 1, 2147483647);
+  expectDouble(p2_31, 2147483648);
+  expectDouble(p2_31 + 1, 2147483649);
+  expectDouble(p2_32 - 1, 4294967295);
+  expectDouble(p2_32, 4294967296);
+  expectDouble(p2_32 + 1, 4294967297);
+  expectDouble(p2_52 - 1, 4503599627370495);
+  expectDouble(p2_52, 4503599627370496);
+  expectDouble(p2_52 + 1, 4503599627370497);
+  expectDouble(p2_53 - 1, 9007199254740991);
+  expectDouble(p2_53, 9007199254740992);
+  expectDouble(p2_53 + 2, 9007199254740994);
+  expectDouble(p2_54 - 2, 18014398509481982);
+  expectDouble(p2_54, 18014398509481984);
+  expectDouble(p2_54 + 4, 18014398509481988);
+  expectDouble(p2_62, 4611686018427387904);
+  expectDouble(p2_63, 9223372036854775808);
+  expectDouble(p2_64, 18446744073709551616);
+  expectDouble(maxValue,
+      179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368);
+
+  expectDouble(-0.0, -0);
+  expectDouble(-1.0, -1);
+  expectDouble(-0.0, -00);
+  expectDouble(-1.0, -01);
+  expectDouble(-(p2_8 - 1), -255);
+  expectDouble(-(p2_8), -256);
+  expectDouble(-(p2_8 + 1), -257);
+  expectDouble(-(p2_30 - 1), -1073741823);
+  expectDouble(-(p2_30), -1073741824);
+  expectDouble(-(p2_30 + 1), -1073741825);
+  expectDouble(-(p2_31 - 1), -2147483647);
+  expectDouble(-(p2_31), -2147483648);
+  expectDouble(-(p2_31 + 1), -2147483649);
+  expectDouble(-(p2_32 - 1), -4294967295);
+  expectDouble(-(p2_32), -4294967296);
+  expectDouble(-(p2_32 + 1), -4294967297);
+  expectDouble(-(p2_52 - 1), -4503599627370495);
+  expectDouble(-(p2_52), -4503599627370496);
+  expectDouble(-(p2_52 + 1), -4503599627370497);
+  expectDouble(-(p2_53 - 1), -9007199254740991);
+  expectDouble(-(p2_53), -9007199254740992);
+  expectDouble(-(p2_53 + 2), -9007199254740994);
+  expectDouble(-(p2_54 - 2), -18014398509481982);
+  expectDouble(-(p2_54), -18014398509481984);
+  expectDouble(-(p2_54 + 4), -18014398509481988);
+  expectDouble(-(p2_62), -4611686018427387904);
+  expectDouble(-(p2_63), -9223372036854775808);
+  expectDouble(-(p2_64), -18446744073709551616);
+  expectDouble(-maxValue,
+      -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368);
+
+  expectDouble(0.0, 0x0);
+  expectDouble(1.0, 0x1);
+  expectDouble(0.0, 0x00);
+  expectDouble(1.0, 0x01);
+  expectDouble(p2_8 - 1, 0xff);
+  expectDouble(p2_8, 0x100);
+  expectDouble(p2_8 + 1, 0x101);
+  expectDouble(p2_30 - 1, 0x3fffffff);
+  expectDouble(p2_30, 0x40000000);
+  expectDouble(p2_30 + 1, 0x40000001);
+  expectDouble(p2_31 - 1, 0x7fffffff);
+  expectDouble(p2_31, 0x80000000);
+  expectDouble(p2_31 + 1, 0x80000001);
+  expectDouble(p2_32 - 1, 0xffffffff);
+  expectDouble(p2_32, 0x100000000);
+  expectDouble(p2_32 + 1, 0x100000001);
+  expectDouble(p2_52 - 1, 0xfffffffffffff);
+  expectDouble(p2_52, 0x10000000000000);
+  expectDouble(p2_52 + 1, 0x10000000000001);
+  expectDouble(p2_53 - 1, 0x1fffffffffffff);
+  expectDouble(p2_53, 0x20000000000000);
+  expectDouble(p2_53 + 2, 0x20000000000002);
+  expectDouble(p2_54 - 2, 0x3ffffffffffffe);
+  expectDouble(p2_54, 0x40000000000000);
+  expectDouble(p2_54 + 4, 0x40000000000004);
+  expectDouble(p2_62, 0x4000000000000000);
+  expectDouble(p2_63, 0x8000000000000000);
+  expectDouble(p2_64, 0x10000000000000000);
+  expectDouble(maxValue,
+      0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
+
+  expectDouble(-0.0, -0x0);
+  expectDouble(-1.0, -0x1);
+  expectDouble(-0.0, -0x00);
+  expectDouble(-1.0, -0x01);
+  expectDouble(-(p2_8 - 1), -0xff);
+  expectDouble(-(p2_8), -0x100);
+  expectDouble(-(p2_8 + 1), -0x101);
+  expectDouble(-(p2_30 - 1), -0x3fffffff);
+  expectDouble(-(p2_30), -0x40000000);
+  expectDouble(-(p2_30 + 1), -0x40000001);
+  expectDouble(-(p2_31 - 1), -0x7fffffff);
+  expectDouble(-(p2_31), -0x80000000);
+  expectDouble(-(p2_31 + 1), -0x80000001);
+  expectDouble(-(p2_32 - 1), -0xffffffff);
+  expectDouble(-(p2_32), -0x100000000);
+  expectDouble(-(p2_32 + 1), -0x100000001);
+  expectDouble(-(p2_52 - 1), -0xfffffffffffff);
+  expectDouble(-(p2_52), -0x10000000000000);
+  expectDouble(-(p2_52 + 1), -0x10000000000001);
+  expectDouble(-(p2_53 - 1), -0x1fffffffffffff);
+  expectDouble(-(p2_53), -0x20000000000000);
+  expectDouble(-(p2_53 + 2), -0x20000000000002);
+  expectDouble(-(p2_54 - 2), -0x3ffffffffffffe);
+  expectDouble(-(p2_54), -0x40000000000000);
+  expectDouble(-(p2_54 + 4), -0x40000000000004);
+  expectDouble(-(p2_62), -0x4000000000000000);
+  expectDouble(-(p2_63), -0x8000000000000000);
+  expectDouble(-(p2_64), -0x10000000000000000);
+  expectDouble(-maxValue,
+      -0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
+}
diff --git a/tests/language/double_literals/implicit_double_context_test.dart b/tests/language/double_literals/implicit_double_context_test.dart
new file mode 100644
index 0000000..117b5cd
--- /dev/null
+++ b/tests/language/double_literals/implicit_double_context_test.dart
@@ -0,0 +1,683 @@
+// 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" show FutureOr;
+
+import "package:expect/expect.dart";
+
+// Check that integer literals in a double context are allowed
+// for various double context.
+
+main() {
+  // Variable initializer context.
+  double v1 = 0;
+  Expect.identical(0.0, v1);
+  double v2 = 1;
+  Expect.identical(1.0, v2);
+  double v3 = -0;
+  Expect.identical(-0.0, v3);
+  double v4 = -1;
+  Expect.identical(-1.0, v4);
+  double v5 = 9223372036854775808; // 2^63, not valid signed 64-bit integer.
+  Expect.identical(9223372036854775808.0, v5);
+  double v6 = 18446744073709551616; // 2^64.
+  Expect.identical(18446744073709551616.0, v6);
+  double v7 = 0x02; // Hex literal.
+  Expect.identical(2.0, v7);
+  double v8 = -0x02; // Hex literal.
+  Expect.identical(-2.0, v8);
+
+  // Const variable initializer context.
+  const double c1 = 0;
+  Expect.identical(0.0, c1);
+  const double c2 = 1;
+  Expect.identical(1.0, c2);
+  const double c3 = -0;
+  Expect.identical(-0.0, c3);
+  const double c4 = -1;
+  Expect.identical(-1.0, c4);
+  const double c5 = 9223372036854775808;
+  Expect.identical(9223372036854775808.0, c5);
+  const double c6 = 18446744073709551616;
+  Expect.identical(18446744073709551616.0, c6);
+  const double c7 = 0x02; // Hex literal.
+  Expect.identical(2.0, c7);
+  const double c8 = -0x02; // Hex literal.
+  Expect.identical(-2.0, c8);
+
+  // Assignment context, variable.
+  double value;
+  value = 0;
+  Expect.identical(0.0, value);
+  value = 1;
+  Expect.identical(1.0, value);
+  value = -0;
+  Expect.identical(-0.0, value);
+  value = -1;
+  Expect.identical(-1.0, value);
+  value = 9223372036854775808;
+  Expect.identical(9223372036854775808.0, value);
+  value = 18446744073709551616;
+  Expect.identical(18446744073709551616.0, value);
+  value = 0x02;
+  Expect.identical(2.0, value);
+  value = -0x02;
+  Expect.identical(-2.0, value);
+
+  // Assignment context, setter.
+  setter = 0;
+  Expect.identical(0.0, lastSetValue);
+  setter = 1;
+  Expect.identical(1.0, lastSetValue);
+  setter = -0;
+  Expect.identical(-0.0, lastSetValue);
+  setter = -1;
+  Expect.identical(-1.0, lastSetValue);
+  setter = 9223372036854775808;
+  Expect.identical(9223372036854775808.0, lastSetValue);
+  setter = 18446744073709551616;
+  Expect.identical(18446744073709551616.0, lastSetValue);
+  setter = 0x02;
+  Expect.identical(2.0, lastSetValue);
+  setter = -0x02;
+  Expect.identical(-2.0, lastSetValue);
+
+  // Argument context.
+  test(0.0, 0);
+  test(1.0, 1);
+  test(-0.0, -0);
+  test(-1.0, -1);
+  test(9223372036854775808.0, 9223372036854775808);
+  test(18446744073709551616.0, 18446744073709551616);
+  test(2.0, 0x02);
+  test(-2.0, -0x02);
+
+  // Argument context, operator setter.
+  List<double> box = [0.5];
+  box[0] = 0;
+  Expect.identical(0.0, box[0]);
+  box[0] = 1;
+  Expect.identical(1.0, box[0]);
+  box[0] = -0;
+  Expect.identical(-0.0, box[0]);
+  box[0] = -1;
+  Expect.identical(-1.0, box[0]);
+  box[0] = 9223372036854775808;
+  Expect.identical(9223372036854775808.0, box[0]);
+  box[0] = 18446744073709551616;
+  Expect.identical(18446744073709551616.0, box[0]);
+  box[0] = 0x02;
+  Expect.identical(2.0, box[0]);
+  box[0] = -0x02;
+  Expect.identical(-2.0, box[0]);
+
+  // Argument context, custom operators.
+  var oper = Oper();
+  Expect.identical(0.0, oper + 0);
+  Expect.identical(1.0, oper + 1);
+  Expect.identical(-0.0, oper + -0);
+  Expect.identical(-1.0, oper + -1);
+  Expect.identical(9223372036854775808.0, oper + 9223372036854775808);
+  Expect.identical(18446744073709551616.0, oper + 18446744073709551616);
+  Expect.identical(2.0, oper + 0x02);
+  Expect.identical(-2.0, oper + -0x02);
+
+  Expect.identical(0.0, oper >> 0);
+  Expect.identical(1.0, oper >> 1);
+  Expect.identical(-0.0, oper >> -0);
+  Expect.identical(-1.0, oper >> -1);
+  Expect.identical(9223372036854775808.0, oper >> 9223372036854775808);
+  Expect.identical(18446744073709551616.0, oper >> 18446744073709551616);
+  Expect.identical(2.0, oper >> 0x02);
+  Expect.identical(-2.0, oper >> -0x02);
+
+  Expect.identical(0.0, oper[0]);
+  Expect.identical(1.0, oper[1]);
+  Expect.identical(-0.0, oper[-0]);
+  Expect.identical(-1.0, oper[-1]);
+  Expect.identical(9223372036854775808.0, oper[9223372036854775808]);
+  Expect.identical(18446744073709551616.0, oper[18446744073709551616]);
+  Expect.identical(2.0, oper[0x02]);
+  Expect.identical(-2.0, oper[-0x02]);
+
+  // Explicit return context.
+  double fun1() => 0;
+  Expect.identical(0.0, fun1());
+  double fun2() => 1;
+  Expect.identical(1.0, fun2());
+  double fun3() => -0;
+  Expect.identical(-0.0, fun3());
+  double fun4() => -1;
+  Expect.identical(-1.0, fun4());
+  double fun5() => 9223372036854775808;
+  Expect.identical(9223372036854775808.0, fun5());
+  double fun6() => 18446744073709551616;
+  Expect.identical(18446744073709551616.0, fun6());
+  double fun7() => 0x02;
+  Expect.identical(2.0, fun7());
+  double fun8() => -0x02;
+  Expect.identical(-2.0, fun8());
+
+  // Inferred return context.
+  testFun(0.0, () => 0);
+  testFun(1.0, () => 1);
+  testFun(-0.0, () => -0);
+  testFun(-1.0, () => -1);
+  testFun(9223372036854775808.0, () => 9223372036854775808);
+  testFun(18446744073709551616.0, () => 18446744073709551616);
+  testFun(2.0, () => 0x02);
+  testFun(-2.0, () => -0x02);
+
+  // Function default value context.
+  Object deffun1([double v = 0]) => v;
+  Expect.identical(0.0, deffun1());
+  Object deffun2([double v = 1]) => v;
+  Expect.identical(1.0, deffun2());
+  Object deffun3([double v = -0]) => v;
+  Expect.identical(-0.0, deffun3());
+  Object deffun4([double v = -1]) => v;
+  Expect.identical(-1.0, deffun4());
+  Object deffun5([double v = 9223372036854775808]) => v;
+  Expect.identical(9223372036854775808.0, deffun5());
+  Object deffun6([double v = 18446744073709551616]) => v;
+  Expect.identical(18446744073709551616.0, deffun6());
+  Object deffun7([double v = 0x02]) => v;
+  Expect.identical(2.0, deffun7());
+  Object deffun8([double v = -0x02]) => v;
+  Expect.identical(-2.0, deffun8());
+
+  // Explicit collection literal context.
+  box = <double>[0];
+  Expect.identical(0.0, box[0]);
+  box = <double>[1];
+  Expect.identical(1.0, box[0]);
+  box = <double>[-0];
+  Expect.identical(-0.0, box[0]);
+  box = <double>[-1];
+  Expect.identical(-1.0, box[0]);
+  box = <double>[9223372036854775808];
+  Expect.identical(9223372036854775808.0, box[0]);
+  box = <double>[18446744073709551616];
+  Expect.identical(18446744073709551616.0, box[0]);
+  box = <double>[0x02];
+  Expect.identical(2.0, box[0]);
+  box = <double>[-0x02];
+  Expect.identical(-2.0, box[0]);
+
+  // Implicit collection literal context.
+  box = [0];
+  Expect.identical(0.0, box[0]);
+  box = [1];
+  Expect.identical(1.0, box[0]);
+  box = [-0];
+  Expect.identical(-0.0, box[0]);
+  box = [-1];
+  Expect.identical(-1.0, box[0]);
+  box = [9223372036854775808];
+  Expect.identical(9223372036854775808.0, box[0]);
+  box = [18446744073709551616];
+  Expect.identical(18446744073709551616.0, box[0]);
+  box = [0x02];
+  Expect.identical(2.0, box[0]);
+  box = [-0x02];
+  Expect.identical(-2.0, box[0]);
+
+  Map<double?, double?> map;
+  // Explicit map key context.
+  map = <double, Null>{0: null};
+  Expect.identical(0.0, map.keys.first);
+  map = <double, Null>{1: null};
+  Expect.identical(1.0, map.keys.first);
+  map = <double, Null>{-0: null};
+  Expect.identical(-0.0, map.keys.first);
+  map = <double, Null>{-1: null};
+  Expect.identical(-1.0, map.keys.first);
+  map = <double, Null>{9223372036854775808: null};
+  Expect.identical(9223372036854775808.0, map.keys.first);
+  map = <double, Null>{18446744073709551616: null};
+  Expect.identical(18446744073709551616.0, map.keys.first);
+  map = <double, Null>{0x02: null};
+  Expect.identical(2.0, map.keys.first);
+  map = <double, Null>{-0x02: null};
+  Expect.identical(-2.0, map.keys.first);
+
+  // Implicit map key context.
+  map = {0: null};
+  Expect.identical(0.0, map.keys.first);
+  map = {1: null};
+  Expect.identical(1.0, map.keys.first);
+  map = {-0: null};
+  Expect.identical(-0.0, map.keys.first);
+  map = {-1: null};
+  Expect.identical(-1.0, map.keys.first);
+  map = {9223372036854775808: null};
+  Expect.identical(9223372036854775808.0, map.keys.first);
+  map = {18446744073709551616: null};
+  Expect.identical(18446744073709551616.0, map.keys.first);
+  map = {0x02: null};
+  Expect.identical(2.0, map.keys.first);
+  map = {-0x02: null};
+  Expect.identical(-2.0, map.keys.first);
+
+  // Explicit map value context.
+  map = <Null, double>{null: 0};
+  Expect.identical(0.0, map.values.first);
+  map = <Null, double>{null: 1};
+  Expect.identical(1.0, map.values.first);
+  map = <Null, double>{null: -0};
+  Expect.identical(-0.0, map.values.first);
+  map = <Null, double>{null: -1};
+  Expect.identical(-1.0, map.values.first);
+  map = <Null, double>{null: 9223372036854775808};
+  Expect.identical(9223372036854775808.0, map.values.first);
+  map = <Null, double>{null: 18446744073709551616};
+  Expect.identical(18446744073709551616.0, map.values.first);
+  map = <Null, double>{null: 0x02};
+  Expect.identical(2.0, map.values.first);
+  map = <Null, double>{null: -0x02};
+  Expect.identical(-2.0, map.values.first);
+
+  // Implicit map value context.
+  map = {null: 0};
+  Expect.identical(0.0, map.values.first);
+  map = {null: 1};
+  Expect.identical(1.0, map.values.first);
+  map = {null: -0};
+  Expect.identical(-0.0, map.values.first);
+  map = {null: -1};
+  Expect.identical(-1.0, map.values.first);
+  map = {null: 9223372036854775808};
+  Expect.identical(9223372036854775808.0, map.values.first);
+  map = {null: 18446744073709551616};
+  Expect.identical(18446744073709551616.0, map.values.first);
+  map = {null: 0x02};
+  Expect.identical(2.0, map.values.first);
+  map = {null: -0x02};
+  Expect.identical(-2.0, map.values.first);
+
+  // Top-level contexts
+  Expect.identical(0.0, ts1);
+  Expect.identical(1.0, ts2);
+  Expect.identical(-0.0, ts3);
+  Expect.identical(-1.0, ts4);
+  Expect.identical(9223372036854775808.0, ts5);
+  Expect.identical(18446744073709551616.0, ts6);
+  Expect.identical(2.0, ts7);
+  Expect.identical(-2.0, ts8);
+
+  Expect.identical(0.0, tc1);
+  Expect.identical(1.0, tc2);
+  Expect.identical(-0.0, tc3);
+  Expect.identical(-1.0, tc4);
+  Expect.identical(9223372036854775808.0, tc5);
+  Expect.identical(18446744073709551616.0, tc6);
+  Expect.identical(2.0, tc7);
+  Expect.identical(-2.0, tc8);
+
+  Expect.identical(0.0, tg1);
+  Expect.identical(1.0, tg2);
+  Expect.identical(-0.0, tg3);
+  Expect.identical(-1.0, tg4);
+  Expect.identical(9223372036854775808.0, tg5);
+  Expect.identical(18446744073709551616.0, tg6);
+  Expect.identical(2.0, tg7);
+  Expect.identical(-2.0, tg8);
+
+  // Class contexts
+  var c = new C.ci1();
+  Expect.identical(0.0, c.v1);
+  Expect.identical(1.0, c.v2);
+  Expect.identical(-0.0, c.v3);
+  Expect.identical(-1.0, c.v4);
+  Expect.identical(9223372036854775808.0, c.v5);
+  Expect.identical(18446744073709551616.0, c.v6);
+  Expect.identical(2.0, c.v7);
+  Expect.identical(-2.0, c.v8);
+
+  Expect.identical(0.0, C.s1);
+  Expect.identical(1.0, C.s2);
+  Expect.identical(-0.0, C.s3);
+  Expect.identical(-1.0, C.s4);
+  Expect.identical(9223372036854775808.0, C.s5);
+  Expect.identical(18446744073709551616.0, C.s6);
+  Expect.identical(2.0, C.s7);
+  Expect.identical(-2.0, C.s8);
+
+  Expect.identical(0.0, C.c1);
+  Expect.identical(1.0, C.c2);
+  Expect.identical(-0.0, C.c3);
+  Expect.identical(-1.0, C.c4);
+  Expect.identical(9223372036854775808.0, C.c5);
+  Expect.identical(18446744073709551616.0, C.c6);
+  Expect.identical(2.0, C.c7);
+  Expect.identical(-2.0, C.c8);
+
+  Expect.identical(0.0, new C.cc1().d);
+  Expect.identical(1.0, new C.cc2().d);
+  Expect.identical(-0.0, new C.cc3().d);
+  Expect.identical(-1.0, new C.cc4().d);
+  Expect.identical(9223372036854775808.0, new C.cc5().d);
+  Expect.identical(18446744073709551616.0, new C.cc6().d);
+  Expect.identical(2.0, new C.cc7().d);
+  Expect.identical(-2.0, new C.cc8().d);
+
+  Expect.identical(0.0, const C.cc1().d);
+  Expect.identical(1.0, const C.cc2().d);
+  Expect.identical(-0.0, const C.cc3().d);
+  Expect.identical(-1.0, const C.cc4().d);
+  Expect.identical(9223372036854775808.0, const C.cc5().d);
+  Expect.identical(18446744073709551616.0, const C.cc6().d);
+  Expect.identical(2.0, const C.cc7().d);
+  Expect.identical(-2.0, const C.cc8().d);
+
+  Expect.identical(0.0, new C.ci1().d);
+  Expect.identical(1.0, new C.ci2().d);
+  Expect.identical(-0.0, new C.ci3().d);
+  Expect.identical(-1.0, new C.ci4().d);
+  Expect.identical(9223372036854775808.0, new C.ci5().d);
+  Expect.identical(18446744073709551616.0, new C.ci6().d);
+  Expect.identical(2.0, new C.ci7().d);
+  Expect.identical(-2.0, new C.ci8().d);
+
+  Expect.identical(0.0, const C.ci1().d);
+  Expect.identical(1.0, const C.ci2().d);
+  Expect.identical(-0.0, const C.ci3().d);
+  Expect.identical(-1.0, const C.ci4().d);
+  Expect.identical(9223372036854775808.0, const C.ci5().d);
+  Expect.identical(18446744073709551616.0, const C.ci6().d);
+  Expect.identical(2.0, const C.ci7().d);
+  Expect.identical(-2.0, const C.ci8().d);
+
+  // Nested context, `?:`.
+  v1 = false ? 42.0 : 0;
+  Expect.identical(0.0, v1);
+  v2 = false ? 42.0 : 1;
+  Expect.identical(1.0, v2);
+  v3 = false ? 42.0 : -0;
+  Expect.identical(-0.0, v3);
+  v4 = false ? 42.0 : -1;
+  Expect.identical(-1.0, v4);
+  v5 = false ? 42.0 : 9223372036854775808;
+  Expect.identical(9223372036854775808.0, v5);
+  v6 = false ? 42.0 : 18446744073709551616;
+  Expect.identical(18446744073709551616.0, v6);
+  v7 = false ? 42.0 : 0x02; // Hex literal.
+  Expect.identical(2.0, v7);
+  v8 = false ? 42.0 : -0x02; // Hex literal.
+  Expect.identical(-2.0, v8);
+
+  // Nested context, `??`.
+  double? nl = double.tryParse("not a double"); // Returns null typed as double.
+  v1 = nl ?? 0;
+  Expect.identical(0.0, v1);
+  v2 = nl ?? 1;
+  Expect.identical(1.0, v2);
+  v3 = nl ?? -0;
+  Expect.identical(-0.0, v3);
+  v4 = nl ?? -1;
+  Expect.identical(-1.0, v4);
+  v5 = nl ?? 9223372036854775808;
+  Expect.identical(9223372036854775808.0, v5);
+  v6 = nl ?? 18446744073709551616;
+  Expect.identical(18446744073709551616.0, v6);
+  v7 = nl ?? 0x02; // Hex literal.
+  Expect.identical(2.0, v7);
+  v8 = nl ?? -0x02; // Hex literal.
+  Expect.identical(-2.0, v8);
+
+  // Nested context, `..`.
+  v1 = 0..toString();
+  Expect.identical(0.0, v1);
+  v2 = 1..toString();
+  Expect.identical(1.0, v2);
+  v3 = -0
+    ..toString();
+  Expect.identical(-0.0, v3);
+  v4 = -1
+    ..toString();
+  Expect.identical(-1.0, v4);
+  v5 = 9223372036854775808..toString();
+  Expect.identical(9223372036854775808.0, v5);
+  v6 = 18446744073709551616..toString();
+  Expect.identical(18446744073709551616.0, v6);
+  v7 = 0x02..toString(); // Hex literal.
+  Expect.identical(2.0, v7);
+  v8 = -0x02
+    ..toString(); // Hex literal.
+  Expect.identical(-2.0, v8);
+
+  // Nexted context, double assignment.
+  Object object;
+  object = value = 0;
+  Expect.identical(0.0, value);
+  object = value = 1;
+  Expect.identical(1.0, value);
+  object = value = -0;
+  Expect.identical(-0.0, value);
+  object = value = -1;
+  Expect.identical(-1.0, value);
+  object = value = 9223372036854775808;
+  Expect.identical(9223372036854775808.0, value);
+  object = value = 18446744073709551616;
+  Expect.identical(18446744073709551616.0, value);
+  object = value = 0x02;
+  Expect.identical(2.0, value);
+  object = value = -0x02;
+  Expect.identical(-2.0, value);
+
+  // Nested context, value of assignment.
+  Expect.identical(0.0, value = 0);
+  Expect.identical(1.0, value = 1);
+  Expect.identical(-0.0, value = -0);
+  Expect.identical(-1.0, value = -1);
+  Expect.identical(9223372036854775808.0, value = 9223372036854775808);
+  Expect.identical(18446744073709551616.0, value = 18446744073709551616);
+  Expect.identical(2.0, value = 0x02);
+  Expect.identical(-2.0, value = -0x02);
+
+  // JavaScript platforms represent integers as doubles, so negating them will
+  // result in negative zero, unfortunately.
+  int zero = 0;
+  bool platformHasNegativeZeroInts = (-zero).isNegative;
+
+  // Not promoted without a double context.
+  num x = -0;
+  Expect.identical(0, x);
+  Expect.equals(x.isNegative, platformHasNegativeZeroInts);
+
+  var list = [3.14, 2.17, -0];
+  Expect.notType<List<double>>(list);
+  Expect.identical(0, list[2]);
+  Expect.equals(list[2].isNegative, platformHasNegativeZeroInts);
+
+  // FutureOr<double> also forces double.
+  // "Type that int is not assignable to, but double is."
+  FutureOr<double> fo1 = 0;
+  Expect.identical(0.0, fo1);
+  FutureOr<double> fo2 = 1;
+  Expect.identical(1.0, fo2);
+  FutureOr<double> fo3 = -0;
+  Expect.identical(-0.0, fo3);
+  FutureOr<double> fo4 = -1;
+  Expect.identical(-1.0, fo4);
+  FutureOr<double> fo5 = 9223372036854775808;
+  Expect.identical(9223372036854775808.0, fo5);
+  FutureOr<double> fo6 = 18446744073709551616;
+  Expect.identical(18446744073709551616.0, fo6);
+  FutureOr<double> fo7 = 0x02; // Hex literal.
+  Expect.identical(2.0, fo7);
+  FutureOr<double> fo8 = -0x02; // Hex literal.
+  Expect.identical(-2.0, fo8);
+
+  // Some other FutureOr cases, without being exhaustive.
+  {
+    Object func([FutureOr<double> x = 9223372036854775808]) => x;
+    Expect.identical(9223372036854775808.0, func(9223372036854775808));
+    Expect.identical(9223372036854775808.0, func());
+    FutureOr<double> func2() => 9223372036854775808;
+    Expect.identical(9223372036854775808.0, func2());
+    testGeneric<FutureOr<double>>(9223372036854775808.0, 9223372036854775808);
+    List<FutureOr<double>> l = [9223372036854775808];
+    testGeneric<FutureOr<double>>(9223372036854775808.0, l[0]);
+    l.add(9223372036854775808);
+    testGeneric<FutureOr<double>>(9223372036854775808.0, l[1]);
+    l.add(0.0);
+    l[2] = 9223372036854775808;
+    testGeneric<FutureOr<double>>(9223372036854775808.0, l[2]);
+  }
+
+  // Type variables statically bound to double also force doubles:
+  testGeneric<double>(0.0, 0);
+  testGeneric<double>(1.0, 1);
+  testGeneric<double>(-0.0, -0);
+  testGeneric<double>(-1.0, -1);
+  testGeneric<double>(9223372036854775808.0, 9223372036854775808);
+  testGeneric<double>(18446744073709551616.0, 18446744073709551616);
+  testGeneric<double>(2.0, 0x02);
+  testGeneric<double>(-2.0, -0x02);
+
+  // Uses static type, not run-time type.
+  Super sub = Sub();
+  Expect.identical(0.0, sub.method(0));
+  Expect.identical(1.0, sub.method(1));
+  Expect.identical(-0.0, sub.method(-0));
+  Expect.identical(-1.0, sub.method(-1));
+  Expect.identical(9223372036854775808.0, sub.method(9223372036854775808));
+  Expect.identical(18446744073709551616.0, sub.method(18446744073709551616));
+  Expect.identical(2.0, sub.method(0x02));
+  Expect.identical(-2.0, sub.method(-0x02));
+
+  {
+    // Check that the correct value is used as receiver for the cascade.
+    var collector = StringBuffer();
+    double tricky = -42
+      ..toString().codeUnits.forEach(collector.writeCharCode);
+    Expect.equals("${-42.0}", collector.toString());
+  }
+
+  bool isDigit(int charCode) => (charCode ^ 0x30) <= 9;
+  // Throws because double context does not affect "4", so the toString does
+  // not contain any non-digit (like ".", which it would if 4 was a double).
+  // The context type of "4.toString..." is not double, and the `-`
+  // is not having a literal as operand.
+  Expect.throws(() {
+    double tricky =
+        -4.toString().codeUnits.firstWhere((c) => !isDigit(c)).toDouble();
+  });
+}
+
+void test(double expect, double value) {
+  Expect.identical(expect, value);
+}
+
+void testFun(double expect, double f()) {
+  Expect.identical(expect, f());
+}
+
+void testGeneric<T>(double expect, T value) {
+  Expect.identical(expect, value);
+}
+
+class Oper {
+  Object operator +(double value) => value;
+  Object operator >>(double value) => value;
+  Object operator [](double value) => value;
+}
+
+class C {
+  // Instance variable initializer
+  final double v1 = 0;
+  final double v2 = 1;
+  final double v3 = -0;
+  final double v4 = -1;
+  final double v5 = 9223372036854775808;
+  final double v6 = 18446744073709551616;
+  final double v7 = 0x02; // Hex literal.
+  final double v8 = -0x02; // Hex literal.
+
+  // Static class variable initializer
+  static double s1 = 0;
+  static double s2 = 1;
+  static double s3 = -0;
+  static double s4 = -1;
+  static double s5 = 9223372036854775808;
+  static double s6 = 18446744073709551616;
+  static double s7 = 0x02; // Hex literal.
+  static double s8 = -0x02; // Hex literal.
+
+  // Const class variable initializer context.
+  static const double c1 = 0;
+  static const double c2 = 1;
+  static const double c3 = -0;
+  static const double c4 = -1;
+  static const double c5 = 9223372036854775808;
+  static const double c6 = 18446744073709551616;
+  static const double c7 = 0x02; // Hex literal.
+  static const double c8 = -0x02; // Hex literal.
+
+  final double d;
+
+  // Default value context for a double initializing formal.
+  const C.cc1([this.d = 0]);
+  const C.cc2([this.d = 1]);
+  const C.cc3([this.d = -0]);
+  const C.cc4([this.d = -1]);
+  const C.cc5([this.d = 9223372036854775808]);
+  const C.cc6([this.d = 18446744073709551616]);
+  const C.cc7([this.d = 0x02]);
+  const C.cc8([this.d = -0x02]);
+
+  // Initializer list expressions context.
+  const C.ci1() : this.d = 0;
+  const C.ci2() : this.d = 1;
+  const C.ci3() : this.d = -0;
+  const C.ci4() : this.d = -1;
+  const C.ci5() : this.d = 9223372036854775808;
+  const C.ci6() : this.d = 18446744073709551616;
+  const C.ci7() : this.d = 0x02;
+  const C.ci8() : this.d = -0x02;
+}
+
+// Top-level lazy variable initializer
+double ts1 = 0;
+double ts2 = 1;
+double ts3 = -0;
+double ts4 = -1;
+double ts5 = 9223372036854775808;
+double ts6 = 18446744073709551616;
+double ts7 = 0x02; // Hex literal.
+double ts8 = -0x02; // Hex literal.
+
+// Top-level const variable initializer.
+const double tc1 = 0;
+const double tc2 = 1;
+const double tc3 = -0;
+const double tc4 = -1;
+const double tc5 = 9223372036854775808; // 2^63, invalid signed 64-bit integer.
+const double tc6 = 18446744073709551616;
+const double tc7 = 0x02; // Hex literal.
+const double tc8 = -0x02; // Hex literal.
+
+// Top-level getter return context.
+double get tg1 => 0;
+double get tg2 => 1;
+double get tg3 => -0;
+double get tg4 => -1;
+double get tg5 => 9223372036854775808;
+double get tg6 => 18446744073709551616;
+double get tg7 => 0x02; // Hex literal.
+double get tg8 => -0x02; // Hex literal.
+
+Object? lastSetValue = null;
+void set setter(double v) {
+  lastSetValue = v;
+}
+
+abstract class Super {
+  Object method(double v);
+}
+
+class Sub implements Super {
+  Object method(Object o) => o;
+}
diff --git a/tests/language/dynamic/call_test.dart b/tests/language/dynamic/call_test.dart
new file mode 100644
index 0000000..65335cd
--- /dev/null
+++ b/tests/language/dynamic/call_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing dynamic calls.
+
+import "package:expect/expect.dart";
+
+class Helper {
+  Helper() {}
+  int foo(int i) {
+    return i;
+  }
+}
+
+class DynamicCallTest {
+  static void testMain() {
+    Helper obj = new Helper();
+    Expect.equals(1, obj.foo(1));
+  }
+}
+
+main() {
+  DynamicCallTest.testMain();
+}
diff --git a/tests/language/dynamic/dynamic2_runtime_test.dart b/tests/language/dynamic/dynamic2_runtime_test.dart
new file mode 100644
index 0000000..d7159b8
--- /dev/null
+++ b/tests/language/dynamic/dynamic2_runtime_test.dart
@@ -0,0 +1,17 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+//
+// Test the prohibited use of 'dynamic' in extending and implementing classes.
+
+class A
+
+
+{}
+
+main() {
+  new A();
+}
diff --git a/tests/language/dynamic/dynamic2_test.dart b/tests/language/dynamic/dynamic2_test.dart
new file mode 100644
index 0000000..6871f9f
--- /dev/null
+++ b/tests/language/dynamic/dynamic2_test.dart
@@ -0,0 +1,20 @@
+// 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.
+//
+// Test the prohibited use of 'dynamic' in extending and implementing classes.
+
+class A
+//    ^
+// [cfe] The type 'dynamic' can't be used as supertype.
+  extends dynamic
+  //      ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.EXTENDS_NON_CLASS
+  implements dynamic
+  //         ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_NON_CLASS
+{}
+
+main() {
+  new A();
+}
diff --git a/tests/language/dynamic/dynamic_test.dart b/tests/language/dynamic/dynamic_test.dart
new file mode 100644
index 0000000..e89b44e
--- /dev/null
+++ b/tests/language/dynamic/dynamic_test.dart
@@ -0,0 +1,67 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program testing the use of 'dynamic' in generic types.
+
+import "package:expect/expect.dart";
+
+abstract class Iface<K, V> {}
+
+class M1<K, V> implements Iface<K, V> {}
+
+class M2<K> implements Iface<K, dynamic> {}
+
+class M3 implements Iface<String, dynamic> {}
+
+typedef dynamic F1<T>(dynamic x, T y);
+
+class HasFieldDynamic {
+  HasFieldDynamic() : dynamic = "dynamic" {}
+  var dynamic; // Field named dynamic is allowed.
+}
+
+class HasMethodDynamic {
+  dynamic() => "dynamic"; // Method named dynamic is allowed.
+}
+
+main() {
+  // dynamic is a top-type, equivalent to Object at runtime.
+  Expect.isTrue(dynamic is Type);
+  Expect.equals(dynamic, dynamic);
+
+  // dynamic is not a subtype of num or String.
+  M1<dynamic, dynamic> m1 = new M1<dynamic, dynamic>();
+  Expect.isFalse(m1 is Iface<dynamic, num>);
+  Expect.isFalse(m1 is Iface<String, dynamic>);
+  Expect.isFalse(m1 is Iface<String, num>);
+  Expect.isFalse(m1 is Iface<num, String>);
+
+  M2<dynamic> m2 = new M2<dynamic>(); // is Iface<dynamic, dynamic>.
+  Expect.isFalse(m2 is Iface<dynamic, num>);
+  Expect.isFalse(m2 is Iface<String, dynamic>);
+  Expect.isFalse(m2 is Iface<String, num>);
+  Expect.isFalse(m2 is Iface<num, String>);
+
+  M3 m3 = new M3(); // is IFace<String, dynamic>.
+  Expect.isFalse(m3 is Iface<dynamic, num>);
+  Expect.isTrue(m3 is Iface<String, dynamic>);
+  Expect.isFalse(m3 is Iface<String, num>);
+  Expect.isTrue(m3 is! Iface<num, String>);
+
+  F1<int> f1 = (dynamic s, int i) => s[i]; // is dynamic Function(dynamic, int).
+  Expect.isTrue(f1 is F1<int>);
+
+  // "dynamic" is not a reserved word or built-in identifier.
+
+  HasFieldDynamic has_field = new HasFieldDynamic();
+  Expect.equals("dynamic", has_field.dynamic);
+
+  HasMethodDynamic has_method = new HasMethodDynamic();
+  Expect.equals("dynamic", has_method.dynamic());
+
+  {
+    int dynamic = 0; // Local variable named dynamic is allowed.
+    Expect.equals(0, dynamic);
+  }
+}
diff --git a/tests/language/dynamic/field_runtime_test.dart b/tests/language/dynamic/field_runtime_test.dart
new file mode 100644
index 0000000..aebfbf6
--- /dev/null
+++ b/tests/language/dynamic/field_runtime_test.dart
@@ -0,0 +1,34 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+//
+// Test that ensures that fields can be accessed dynamically.
+
+import "package:expect/expect.dart";
+
+class A extends C {
+  var a;
+  var b;
+}
+
+class C {
+  foo() {
+
+
+  }
+  bar() {
+
+
+  }
+}
+
+main() {
+  var a = new A();
+  a.a = 1;
+  a.b = a;
+
+
+}
diff --git a/tests/language/dynamic/field_test.dart b/tests/language/dynamic/field_test.dart
new file mode 100644
index 0000000..ebe094e
--- /dev/null
+++ b/tests/language/dynamic/field_test.dart
@@ -0,0 +1,43 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+//
+// Test that ensures that fields can be accessed dynamically.
+
+import "package:expect/expect.dart";
+
+class A extends C {
+  var a;
+  var b;
+}
+
+class C {
+  foo() {
+    print(a);
+    //    ^
+    // [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+    // [cfe] The getter 'a' isn't defined for the class 'C'.
+    return a;
+    //     ^
+    // [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+    // [cfe] The getter 'a' isn't defined for the class 'C'.
+  }
+  bar() {
+    print(b.a);
+    //    ^
+    // [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+    // [cfe] The getter 'b' isn't defined for the class 'C'.
+    return b.a;
+    //     ^
+    // [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+    // [cfe] The getter 'b' isn't defined for the class 'C'.
+  }
+}
+
+main() {
+  var a = new A();
+  a.a = 1;
+  a.b = a;
+  Expect.equals(1, a.foo());
+  Expect.equals(1, a.bar());
+}
diff --git a/tests/language/dynamic/hash_code_test.dart b/tests/language/dynamic/hash_code_test.dart
new file mode 100644
index 0000000..b705dd8
--- /dev/null
+++ b/tests/language/dynamic/hash_code_test.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.
+
+import "package:expect/expect.dart";
+
+void main() {
+  dynamic x = 3;
+  Expect.equals(3, x.hashCode);
+}
diff --git a/tests/language/dynamic/invoke_test.dart b/tests/language/dynamic/invoke_test.dart
new file mode 100644
index 0000000..d01beca
--- /dev/null
+++ b/tests/language/dynamic/invoke_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing dynamic calls.
+
+import "package:expect/expect.dart";
+
+// Make this something that DDC considers side effecting.
+dynamic get d => "hello";
+
+regress29504() {
+  // These forms were being incorrectly generated as dynamic invokes, which is
+  // not supposed to be done for the Object members that are always present on
+  // all Dart types, including `null`.
+  //
+  // See https://github.com/dart-lang/sdk/issues/29504
+  //
+  // What we're testing here is that none of these generate dynamic invokes,
+  // because that will throw a NoSuchMethod error if it happens.
+  Expect.equals(d.runtimeType, String);
+  Expect.equals(d?.runtimeType, String);
+  Expect.equals(d..runtimeType, "hello");
+
+  Expect.equals(d.hashCode, "hello".hashCode);
+  Expect.equals(d?.hashCode, "hello".hashCode);
+  Expect.equals(d..hashCode, "hello");
+
+  Expect.equals(d.toString(), "hello");
+  Expect.equals(d?.toString(), "hello");
+  Expect.equals(d..toString(), "hello");
+}
+
+main() {
+  regress29504();
+}
diff --git a/tests/language/dynamic/prefix_core_test.dart b/tests/language/dynamic/prefix_core_test.dart
new file mode 100644
index 0000000..65da032
--- /dev/null
+++ b/tests/language/dynamic/prefix_core_test.dart
@@ -0,0 +1,18 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test explicit import of dart:core in the source code..
+
+library DynamicPrefixCoreTest.dart;
+
+import "package:expect/expect.dart";
+import "dart:core" as mycore;
+
+void main() {
+  // The built-in type declaration `dynamic`, which is declared in the
+  // library `dart:core`, denotes the `dynamic` type. So, in this library
+  // it must be reference with the prefix.
+  dynamic; //# 01: compile-time error
+
+  Expect.isTrue(mycore.dynamic is mycore.Type); //# 02: ok
+}
diff --git a/tests/language/dynamic/set_test.dart b/tests/language/dynamic/set_test.dart
new file mode 100644
index 0000000..35f2b97
--- /dev/null
+++ b/tests/language/dynamic/set_test.dart
@@ -0,0 +1,34 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+//
+// Test that ensures that fields can be accessed dynamically.
+
+import "package:expect/expect.dart";
+
+class C {
+  final x = "hello";
+  get y => ", ";
+  m() => "world!";
+}
+
+// Regression test for https://github.com/dart-lang/sdk/issues/27258
+main() {
+  dynamic c = new C();
+  Expect.equals(c.x + c.y + c.m(), "hello, world!");
+
+  Expect.throws(() {
+    c.x = 1;
+  });
+  Expect.throws(() {
+    c.x = '1';
+  });
+  Expect.throws(() {
+    c.y = '2';
+  });
+  Expect.throws(() {
+    c.m = '3';
+  });
+
+  Expect.equals(c.x + c.y + c.m(), "hello, world!");
+}
diff --git a/tests/language/dynamic/type_literal_test.dart b/tests/language/dynamic/type_literal_test.dart
new file mode 100644
index 0000000..335e9ae
--- /dev/null
+++ b/tests/language/dynamic/type_literal_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Test generation of 'dynamic' type literals.
+
+import "package:expect/expect.dart";
+
+void main() {
+  Expect.isTrue(dynamic is Type);
+  Expect.isFalse(dynamic == Type);
+}
diff --git a/tests/language/enum/duplicate_lib.dart b/tests/language/enum/duplicate_lib.dart
new file mode 100644
index 0000000..b9c84f5
--- /dev/null
+++ b/tests/language/enum/duplicate_lib.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.
+
+library enum_duplicate_lib;
+
+enum Enum1 {
+  A,
+  B,
+}
+
+class Enum2 {
+  static Iterable get values => ['Enum2.A', 'Enum2.B'];
+}
diff --git a/tests/language/enum/duplicate_test.dart b/tests/language/enum/duplicate_test.dart
new file mode 100644
index 0000000..7904652
--- /dev/null
+++ b/tests/language/enum/duplicate_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.
+
+// Test for duplicate enums.
+
+library enum_duplicate_test;
+
+import 'package:expect/expect.dart';
+
+import 'duplicate_lib.dart' as lib; //# 01: ok
+import 'duplicate_lib.dart' as lib; //# 02: ok
+
+enum Enum1 {
+  A,
+  B,
+}
+
+enum Enum2 {
+  A,
+  B,
+}
+
+main() {
+  Expect.equals('Enum1.A,Enum1.B', Enum1.values.join(','));
+  Expect.equals('Enum1.A,Enum1.B', lib.Enum1.values.join(',')); //# 01: continued
+  Expect.equals('Enum2.A,Enum2.B', Enum2.values.join(','));
+  Expect.equals('Enum2.A,Enum2.B', lib.Enum2.values.join(',')); //# 02: continued
+}
diff --git a/tests/language/enum/enum_test.dart b/tests/language/enum/enum_test.dart
new file mode 100644
index 0000000..87d6d65
--- /dev/null
+++ b/tests/language/enum/enum_test.dart
@@ -0,0 +1,153 @@
+// 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:expect/expect.dart';
+
+enum Enum1 { _ }
+enum Enum2 { A }
+enum Enum3 { B, C }
+enum Enum4 {
+  D,
+  E,
+}
+enum Enum5 { F, G, H }
+enum _Enum6 { I, _J }
+
+enum _IsNot { IsNot }
+
+// Regression test for https://github.com/dart-lang/sdk/issues/33348
+enum JSFunctionPrototype {
+  length,
+  prototype,
+  __proto__,
+  arguments,
+  caller,
+  calee,
+  name,
+  constructor,
+  apply,
+  bind,
+  call
+}
+
+void expectIs<T>(T t, bool Function(Object?) test) {
+  Object? obj = t;
+  Expect.isTrue(test(obj), '$obj is $T');
+  Expect.isFalse(obj is _IsNot, '$obj is _IsNot');
+  // test cast
+  t = obj as T;
+  Expect.throwsTypeError(() => obj as _IsNot, '$obj as _IsNot');
+}
+
+main() {
+  expectIs(Enum1._, (e) => e is Enum1);
+  expectIs(Enum2.A, (e) => e is Enum2);
+  expectIs(Enum3.B, (e) => e is Enum3);
+  expectIs(Enum4.E, (e) => e is Enum4);
+  expectIs(Enum5.G, (e) => e is Enum5);
+
+  Expect.equals('Enum1._', Enum1._.toString());
+  Expect.equals(0, Enum1._.index);
+  Expect.listEquals([Enum1._], Enum1.values);
+  Enum1.values.forEach(test1);
+
+  Expect.equals('Enum2.A', Enum2.A.toString());
+  Expect.equals(0, Enum2.A.index);
+  Expect.listEquals([Enum2.A], Enum2.values);
+  Expect.identical(const <Enum2>[Enum2.A], Enum2.values);
+  Enum2.values.forEach(test2);
+
+  Expect.equals('Enum3.B', Enum3.B.toString());
+  Expect.equals('Enum3.C', Enum3.C.toString());
+  Expect.equals(0, Enum3.B.index);
+  Expect.equals(1, Enum3.C.index);
+  Expect.listEquals([Enum3.B, Enum3.C], Enum3.values);
+  Enum3.values.forEach(test3);
+
+  Expect.equals('Enum4.D', Enum4.D.toString());
+  Expect.equals('Enum4.E', Enum4.E.toString());
+  Expect.equals(0, Enum4.D.index);
+  Expect.equals(1, Enum4.E.index);
+  Expect.listEquals([Enum4.D, Enum4.E], Enum4.values);
+  Enum4.values.forEach(test4);
+
+  Expect.equals('Enum5.F', Enum5.F.toString());
+  Expect.equals('Enum5.G', Enum5.G.toString());
+  Expect.equals('Enum5.H', Enum5.H.toString());
+  Expect.equals(0, Enum5.F.index);
+  Expect.equals(1, Enum5.G.index);
+  Expect.equals(2, Enum5.H.index);
+  Expect.listEquals([Enum5.F, Enum5.G, Enum5.H], Enum5.values);
+  Enum5.values.forEach(test5);
+
+  Expect.equals('_Enum6.I', _Enum6.I.toString());
+  Expect.equals('_Enum6._J', _Enum6._J.toString());
+
+  for (var value in JSFunctionPrototype.values) {
+    expectIs(value, (e) => e is JSFunctionPrototype);
+  }
+  Expect.equals(JSFunctionPrototype.length, JSFunctionPrototype.values[0]);
+}
+
+test1(Enum1 e) {
+  int index;
+  switch (e) {
+    case Enum1._:
+      index = 0;
+      break;
+  }
+  Expect.equals(e.index, index);
+}
+
+test2(Enum2 e) {
+  int index;
+  switch (e) {
+    case Enum2.A:
+      index = 0;
+      break;
+  }
+  Expect.equals(e.index, index);
+}
+
+test3(Enum3 e) {
+  int index;
+  switch (e) {
+    case Enum3.C:
+      index = 1;
+      break;
+    case Enum3.B:
+      index = 0;
+      break;
+  }
+  Expect.equals(e.index, index);
+}
+
+test4(Enum4 e) {
+  int index;
+  switch (e) {
+    case Enum4.D:
+      index = 0;
+      break;
+    case Enum4.E:
+      index = 1;
+      break;
+  }
+  Expect.equals(e.index, index);
+}
+
+test5(Enum5 e) {
+  int index;
+  switch (e) {
+    case Enum5.H:
+      index = 2;
+      break;
+    case Enum5.F:
+      index = 0;
+      break;
+    case Enum5.G:
+      index = 1;
+      break;
+  }
+  Expect.equals(e.index, index);
+}
diff --git a/tests/language/enum/index_test.dart b/tests/language/enum/index_test.dart
new file mode 100644
index 0000000..ce6994b
--- /dev/null
+++ b/tests/language/enum/index_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+// Test index access for enums.
+
+library enum_index_test;
+
+import 'package:expect/expect.dart';
+
+enum Enum {
+  A,
+  B,
+}
+
+class Class {
+  var index;
+}
+
+main() {
+  test(null, new Class());
+  test(0, Enum.A);
+  test(1, Enum.B);
+}
+
+test(expected, object) {
+  Expect.equals(expected, object.index);
+}
diff --git a/tests/language/enum/initialization_near_stack_overflow_test.dart b/tests/language/enum/initialization_near_stack_overflow_test.dart
new file mode 100644
index 0000000..598b382
--- /dev/null
+++ b/tests/language/enum/initialization_near_stack_overflow_test.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// https://github.com/flutter/flutter/issues/25041
+
+// This test may produce a compile time exception from stack overflow during
+// enum initialization or succeed in enum initialization depending on exactly
+// how much stack is left and used by the compiler. It should never crash nor
+// produce a runtime exception.
+
+enum Fruit {
+  apple,
+  banana,
+}
+
+getFruit() => Fruit.apple;
+
+recurse() {
+  try {
+    recurse();
+  } catch (e, st) {
+    print("$e ${getFruit()}");
+  }
+}
+
+main() {
+  try {
+    recurse();
+  } on StackOverflowError catch (e) {
+    // Swallow.
+  }
+}
diff --git a/tests/language/enum/is_keyword_runtime_test.dart b/tests/language/enum/is_keyword_runtime_test.dart
new file mode 100644
index 0000000..2e9a471
--- /dev/null
+++ b/tests/language/enum/is_keyword_runtime_test.dart
@@ -0,0 +1,13 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test that `enum` is considered a keyword and therefore invalid as the name of
+// declarations.
+
+main() {
+
+}
diff --git a/tests/language/enum/is_keyword_test.dart b/tests/language/enum/is_keyword_test.dart
new file mode 100644
index 0000000..5e7d0b5
--- /dev/null
+++ b/tests/language/enum/is_keyword_test.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.
+
+// Test that `enum` is considered a keyword and therefore invalid as the name of
+// declarations.
+
+main() {
+  var enum;
+  //  ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+  // [cfe] Expected an identifier, but got 'enum'.
+}
diff --git a/tests/language/enum/private_lib.dart b/tests/language/enum/private_lib.dart
new file mode 100644
index 0000000..c8fb00f
--- /dev/null
+++ b/tests/language/enum/private_lib.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 enum_private_lib;
+
+enum Enum2 {
+  _A,
+  _B,
+}
diff --git a/tests/language/enum/private_runtime_1_test.dart b/tests/language/enum/private_runtime_1_test.dart
new file mode 100644
index 0000000..34af126
--- /dev/null
+++ b/tests/language/enum/private_runtime_1_test.dart
@@ -0,0 +1,25 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test privacy issue for enums.
+
+library enum_private_test;
+
+import 'package:expect/expect.dart';
+
+import 'private_lib.dart';
+
+enum Enum1 {
+  _A,
+  _B,
+}
+
+main() {
+  Expect.equals('Enum1._A,Enum1._B', Enum1.values.join(','));
+  Expect.equals('Enum2._A,Enum2._B', Enum2.values.join(','));
+
+}
diff --git a/tests/language/enum/private_runtime_test.dart b/tests/language/enum/private_runtime_test.dart
new file mode 100644
index 0000000..adc8d7a
--- /dev/null
+++ b/tests/language/enum/private_runtime_test.dart
@@ -0,0 +1,25 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test privacy issue for enums.
+
+library enum_private_test;
+
+import 'package:expect/expect.dart';
+
+import 'private_lib.dart';
+
+enum Enum1 {
+  _A,
+  _B,
+}
+
+main() {
+  Expect.equals('Enum1._A,Enum1._B', Enum1.values.join(','));
+
+
+}
diff --git a/tests/language/enum/private_test.dart b/tests/language/enum/private_test.dart
new file mode 100644
index 0000000..bd99d84
--- /dev/null
+++ b/tests/language/enum/private_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.
+
+// Test privacy issue for enums.
+
+library enum_private_test;
+
+import 'package:expect/expect.dart';
+
+import 'private_lib.dart';
+
+enum Enum1 {
+  _A,
+  _B,
+}
+
+main() {
+  Expect.equals('Enum1._A,Enum1._B', Enum1.values.join(','));
+  Expect.equals('Enum2._A,Enum2._B', Enum2.values.join(','));
+  Expect.throwsNoSuchMethodError(() => Enum2._A);
+  //                                         ^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_ENUM_CONSTANT
+  // [cfe] Getter not found: '_A'.
+}
diff --git a/tests/language/enum/syntax_test.dart b/tests/language/enum/syntax_test.dart
new file mode 100644
index 0000000..250e1ae
--- /dev/null
+++ b/tests/language/enum/syntax_test.dart
@@ -0,0 +1,71 @@
+// 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.
+
+// Basic syntax test for enumeration types
+
+enum Color { red, orange, yellow, green }
+
+// Additional comma at end of list is ok.
+enum Veggies {
+  carrot,
+  bean,
+  broccolo,
+}
+
+// Need at least one enumeration identifier.
+enum Nada {} // //# 01: syntax error
+
+// Duplicate entries are a compile-time error
+enum ComeAgain { ahau, knust, zipfel, knust, gupf } // //# 02: compile-time error
+
+// Enum entries must not collide with implicitly defined members.
+enum ComeAgain { ahau, knust, zipfel, index } //# 03: compile-time error
+
+enum ComeAgain { ahau, knust, zipfel, values } //# 04: compile-time error
+
+enum ComeAgain { ahau, knust, zipfel, toString } //# 05: compile-time error
+
+// Enum entry must not collide with enum type name.
+enum ComeAgain { ahau, knust, zipfel, ComeAgain } //# 06: compile-time error
+
+// Missing comma.
+enum Numbers { one, two, three four, five } // //# 07: syntax error
+
+// Missing enum type name.
+enum { eins, zwei, drei } // //# 08: syntax error
+
+// Duplicate name in library scope.
+topLevelFunction() => null;
+enum topLevelFunction { bla, blah } // //# 09: compile-time error
+
+class C {}
+enum C { bla, blah } // //# 10: compile-time error
+
+var zzTop;
+enum zzTop { Billy, Dusty, Frank } // //# 11: compile-time error
+
+// Enum type cannot be super type or interface type.
+class Rainbow extends Color {} // //# 20: compile-time error
+class Rainbow implements Color {} // //# 21: compile-time error
+class Rainbow extends List with Color {} // //# 22: compile-time error
+
+main() {
+  Nada x; //# 01: continued
+  var x = ComeAgain.zipfel; // //# 02: continued
+  var x = ComeAgain.zipfel; // //# 03: continued
+  var x = ComeAgain.zipfel; // //# 04: continued
+  var x = ComeAgain.zipfel; // //# 05: continued
+  var x = ComeAgain.zipfel; // //# 06: continued
+  var x = Numbers.four; // //# 07: continued
+  var x = topLevelFunction.bla; // //# 09: continued
+  var x = C.bla; // //# 10: continued
+  var x = zzTop.Frank; // //# 11: continued
+
+  var x = new Rainbow(); // //# 20: continued
+  var x = new Rainbow(); // //# 21: continued
+  var x = new Rainbow(); // //# 22: continued
+
+  // It is a compile-time error to explicitly instantiate an enum instance.
+  var x = new Color(); // //# 30: compile-time error
+}
diff --git a/tests/language/enum/value_name_test.dart b/tests/language/enum/value_name_test.dart
new file mode 100644
index 0000000..f4a0d8a
--- /dev/null
+++ b/tests/language/enum/value_name_test.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.
+
+import 'package:expect/expect.dart';
+
+enum ErrorContext { general, name, description, targets }
+
+void main() {
+  Expect.equals(ErrorContext.name, ErrorContext.name);
+}
diff --git a/tests/language/exception/catch_liveness_test.dart b/tests/language/exception/catch_liveness_test.dart
new file mode 100644
index 0000000..df9a3dd
--- /dev/null
+++ b/tests/language/exception/catch_liveness_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:expect/expect.dart";
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+foo() => 1;
+
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+throwException() => throw 'x';
+
+main() {
+  var x = 10;
+  var e2 = null;
+  try {
+    var t = foo();
+    throwException();
+    print(t);
+    x = 3;
+  } catch (e) {
+    Expect.equals(10, x);
+    e2 = e;
+  }
+  Expect.equals(10, x);
+  Expect.equals('x', e2);
+}
diff --git a/tests/language/exception/code_after_try_is_executed_test.dart b/tests/language/exception/code_after_try_is_executed_test.dart
new file mode 100644
index 0000000..57ffd84
--- /dev/null
+++ b/tests/language/exception/code_after_try_is_executed_test.dart
@@ -0,0 +1,19 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test that the runtime still runs the code after a try/catch. The
+// test cannot use Expect.throws, because Expect.throws uses the same
+// pattern.
+
+import "package:expect/expect.dart";
+
+main() {
+  var exception;
+  try {
+    throw 'foo';
+  } on String catch (ex) {
+    exception = ex;
+  }
+  Expect.isTrue(exception is String);
+  throw 'foo'; //# 01: runtime error
+}
diff --git a/tests/language/exception/exception_test.dart b/tests/language/exception/exception_test.dart
new file mode 100644
index 0000000..86c2206
--- /dev/null
+++ b/tests/language/exception/exception_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 ExceptionTest {
+  static testMain() {
+    int i = 0;
+    try {
+      throw "Hello";
+    } on String catch (s) {
+      print(s);
+      i += 10;
+    }
+
+    try {
+      throw "bye";
+    } on String catch (s) {
+      print(s);
+      i += 10;
+    }
+    Expect.equals(20, i);
+
+    bool correctCatch = false;
+    try {
+      // This throws NullThrownError
+      throw (null as dynamic);
+    } on String catch (s) {
+      correctCatch = false;
+    } on NullThrownError catch (e) {
+      correctCatch = true;
+    } catch (x) {
+      correctCatch = false;
+    }
+    Expect.isTrue(correctCatch);
+  }
+}
+
+main() {
+  ExceptionTest.testMain();
+}
diff --git a/tests/language/exception/finally10_test.dart b/tests/language/exception/finally10_test.dart
new file mode 100644
index 0000000..dfe47b5
--- /dev/null
+++ b/tests/language/exception/finally10_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+// Regression test for dart2js that used to not treat the finally
+// block as a successor of a catch block that throws.
+
+import "package:expect/expect.dart";
+
+class A {
+  var field;
+  start() {}
+  stop() {
+    field = 42;
+  }
+}
+
+class B {
+  var totalCompileTime = new A();
+  var runCompiler = new Object();
+
+  run() {
+    totalCompileTime.start();
+    try {
+      throw 'foo';
+    } catch (exception) {
+      // Use [runCompiler] twice to ensure it will have a local
+      // variable.
+      runCompiler.toString();
+      runCompiler.toString();
+      rethrow;
+    } finally {
+      totalCompileTime.stop();
+    }
+  }
+}
+
+main() {
+  var b = new B();
+  try {
+    b.run();
+    throw 'Expected exception';
+  } catch (exception) {
+    // Expected exception.
+  }
+
+  Expect.equals(42, b.totalCompileTime.field);
+}
diff --git a/tests/language/exception/finally11_test.dart b/tests/language/exception/finally11_test.dart
new file mode 100644
index 0000000..dbe7288
--- /dev/null
+++ b/tests/language/exception/finally11_test.dart
@@ -0,0 +1,50 @@
+// 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.
+
+// Regression test for dart2js that used to not treat the finally
+// block as a successor of a nested try block.
+
+import "package:expect/expect.dart";
+
+class A {
+  var field;
+  start() {}
+  stop() {
+    field = 42;
+  }
+}
+
+class B {
+  var totalCompileTime = new A();
+  var runCompiler = new Object();
+
+  run() {
+    totalCompileTime.start();
+    try {
+      throw 'foo';
+    } catch (exception) {
+      try {
+        // Use [runCompiler] twice to ensure it will have a local
+        // variable.
+        runCompiler.toString();
+        runCompiler.toString();
+      } catch (exception) {}
+      rethrow;
+    } finally {
+      totalCompileTime.stop();
+    }
+  }
+}
+
+main() {
+  var b = new B();
+  try {
+    b.run();
+    throw 'Expected exception';
+  } catch (exception) {
+    // Expected exception.
+  }
+
+  Expect.equals(42, b.totalCompileTime.field);
+}
diff --git a/tests/language/exception/finally12_test.dart b/tests/language/exception/finally12_test.dart
new file mode 100644
index 0000000..e4f56a0
--- /dev/null
+++ b/tests/language/exception/finally12_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+// Regression test for dart2js that used to not treat the finally
+// block as a successor of a nested try block.
+
+import "package:expect/expect.dart";
+
+var a;
+
+foo() {
+  var b = a == 8; // This should not be GVN'ed.
+  while (!b) {
+    try {
+      try {} finally {
+        a = 8;
+        break;
+      }
+    } finally {
+      return a == 8;
+    }
+  }
+}
+
+main() {
+  Expect.isTrue(foo());
+}
diff --git a/tests/language/exception/finally1_test.dart b/tests/language/exception/finally1_test.dart
new file mode 100644
index 0000000..0e8510a
--- /dev/null
+++ b/tests/language/exception/finally1_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing execution of finally blocks on
+// control flow breaks because of 'return', 'continue' etc.
+
+import "package:expect/expect.dart";
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1() {
+    try {
+      int j;
+      j = func();
+      i = 1;
+      return i; // Value of i on return is 1.
+    } finally {
+      i = i + 800; // Should get executed on return.
+    }
+    return i + 200; // Should not get executed.
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class ExecuteFinally1Test {
+  static testMain() {
+    Helper obj = new Helper();
+    Expect.equals(1, obj.f1());
+    Expect.equals(801, obj.i);
+  }
+}
+
+main() {
+  ExecuteFinally1Test.testMain();
+}
diff --git a/tests/language/exception/finally2_test.dart b/tests/language/exception/finally2_test.dart
new file mode 100644
index 0000000..fd64f69
--- /dev/null
+++ b/tests/language/exception/finally2_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing execution of finally blocks on
+// control flow breaks because of 'return', 'continue' etc.
+
+import "package:expect/expect.dart";
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1() {
+    try {
+      int j;
+      j = func();
+      try {
+        i = 1;
+        return i; // Value of i is 1 on return.
+      } finally {
+        i = i + 400; // Should get executed when we return.
+      }
+      i = 2; // Should not get executed.
+      return i;
+    } finally {
+      i = i + 800; // Should get executed when we return.
+    }
+    return i + 200; // Should not get executed.
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class ExecuteFinally2Test {
+  static testMain() {
+    Helper obj = new Helper();
+    Expect.equals(1, obj.f1());
+    Expect.equals(1201, obj.i);
+  }
+}
+
+main() {
+  ExecuteFinally2Test.testMain();
+}
diff --git a/tests/language/exception/finally3_test.dart b/tests/language/exception/finally3_test.dart
new file mode 100644
index 0000000..c36ba0f
--- /dev/null
+++ b/tests/language/exception/finally3_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing execution of finally blocks on
+// control flow breaks because of 'return', 'continue' etc.
+
+import "package:expect/expect.dart";
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1() {
+    try {
+      try {
+        int j;
+        j = func();
+        L1:
+        while (i <= 0) {
+          if (i == 0) {
+            try {
+              i = 1;
+              func();
+              try {
+                int j;
+                j = func();
+                while (j < 50) {
+                  j += func();
+                  if (j > 30) {
+                    continue L1; // Break out of nested try blocks.
+                  }
+                }
+                i = 200000; // Should not get executed.
+              } finally {
+                i = i + 200; // Should get executed when we break out.
+              }
+            } finally {
+              i = i + 400; // Should get executed when we break out.
+            }
+          }
+        }
+      } finally {
+        i = i + 800; // Should get executed as normal control flow.
+      }
+      return i; // Value of i should be 1401.
+    } finally {
+      i = i + 1600; // Should get executed as part of return above.
+    }
+    i = i + 2000000; // Should not get executed.
+    return 1;
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class ExecuteFinally3Test {
+  static testMain() {
+    Helper obj = new Helper();
+    Expect.equals(1401, obj.f1());
+    Expect.equals(3001, obj.i);
+  }
+}
+
+main() {
+  ExecuteFinally3Test.testMain();
+}
diff --git a/tests/language/exception/finally4_test.dart b/tests/language/exception/finally4_test.dart
new file mode 100644
index 0000000..fcc308c
--- /dev/null
+++ b/tests/language/exception/finally4_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing execution of finally blocks on
+// control flow breaks because of 'return', 'continue' etc.
+
+import "package:expect/expect.dart";
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1() {
+    try {
+      int j;
+      j = func();
+      i = 1;
+    } finally {
+      i = i + 10;
+    }
+    return i + 200; // Should return here with i = 211.
+    try {
+      int j;
+      j = func();
+    } finally {
+      i = i + 10; // Should not get executed as part of return above.
+    }
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class ExecuteFinally4Test {
+  static testMain() {
+    Helper obj = new Helper();
+    Expect.equals(211, obj.f1());
+    Expect.equals(11, obj.i);
+  }
+}
+
+main() {
+  ExecuteFinally4Test.testMain();
+}
diff --git a/tests/language/exception/finally5_test.dart b/tests/language/exception/finally5_test.dart
new file mode 100644
index 0000000..09cbdc15
--- /dev/null
+++ b/tests/language/exception/finally5_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing execution of finally blocks on
+// control flow breaks because of 'return', 'continue' etc.
+
+import "package:expect/expect.dart";
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1(int param) {
+    if (param == 0) {
+      try {
+        int j;
+        j = func();
+        try {
+          i = 1;
+          return i; // Value of i is 1 on return.
+        } finally {
+          i = i + 400; // Should get executed when we return.
+        }
+        i = 2; // Should not get executed.
+        return i;
+      } finally {
+        i = i + 800; // Should get executed when we return.
+      }
+      return i + 200; // Should not get executed.
+    }
+    try {
+      int j;
+      j = func();
+      try {
+        i = 4;
+        return i; // Value of i is 1 on return.
+      } finally {
+        i = i + 100; // Should get executed when we return.
+      }
+      i = 2; // Should not get executed.
+      return i;
+    } finally {
+      i = i + 200; // Should get executed when we return.
+    }
+    return i + 200; // Should not get executed.
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class ExecuteFinally5Test {
+  static testMain() {
+    Helper obj = new Helper();
+    Expect.equals(1, obj.f1(0));
+    Expect.equals(1201, obj.i);
+    Expect.equals(4, obj.f1(1));
+    Expect.equals(304, obj.i);
+  }
+}
+
+main() {
+  ExecuteFinally5Test.testMain();
+}
diff --git a/tests/language/exception/finally6_test.dart b/tests/language/exception/finally6_test.dart
new file mode 100644
index 0000000..e9c5ea5
--- /dev/null
+++ b/tests/language/exception/finally6_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing execution of finally blocks on
+// control flow breaks because of 'return', 'continue' etc.
+
+import "package:expect/expect.dart";
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1() {
+    try {
+      try {
+        int j;
+        j = func();
+        L1:
+        while (i <= 0) {
+          if (i == 0) {
+            try {
+              i = 1;
+              func();
+              try {
+                int j;
+                j = func();
+                L1:
+                while (j < 50) {
+                  j += func();
+                  if (j > 30) {
+                    break L1; // Break out of nested try blocks.
+                  }
+                }
+                i += 200000; // Should get executed.
+              } finally {
+                i = i + 200; // Should get executed as normal control flow.
+              }
+            } finally {
+              i = i + 400; // Should get executed as normal control flow.
+            }
+          }
+        }
+      } finally {
+        i = i + 800; // Should get executed as normal control flow.
+      }
+      return i; // Value of i should be 201401.
+    } finally {
+      i = i + 1600; // Should get executed as part of return above.
+    }
+    i = i + 2000000; // Should not get executed.
+    return 1;
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class ExecuteFinally6Test {
+  static testMain() {
+    Helper obj = new Helper();
+    Expect.equals(201401, obj.f1());
+    Expect.equals(203001, obj.i);
+  }
+}
+
+main() {
+  ExecuteFinally6Test.testMain();
+}
diff --git a/tests/language/exception/finally7_test.dart b/tests/language/exception/finally7_test.dart
new file mode 100644
index 0000000..afa6a67
--- /dev/null
+++ b/tests/language/exception/finally7_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing execution of finally blocks after an exception
+// is thrown from inside a local function capturing a variable.
+
+import "package:expect/expect.dart";
+
+class MyException {
+  const MyException(String message) : message_ = message;
+  final String message_;
+}
+
+class Helper {
+  static int f1(int k) {
+    var b;
+    try {
+      var a = new List<dynamic>.filled(10, null);
+      int i = 0;
+      while (i < 10) {
+        int j = i;
+        a[i] = () {
+          if (j == 5) {
+            throw new MyException("Test for exception being thrown");
+          }
+          k += 10;
+          return j;
+        };
+        if (i == 0) {
+          b = a[i];
+        }
+        i++;
+      }
+      for (int i = 0; i < 10; i++) {
+        a[i]();
+      }
+    } on MyException catch (exception) {
+      k += 100;
+      print(exception.message_);
+      b();
+    } finally {
+      k += 1000;
+      b();
+    }
+    return k;
+  }
+}
+
+class ExecuteFinally7Test {
+  static testMain() {
+    Expect.equals(1171, Helper.f1(1));
+  }
+}
+
+main() {
+  ExecuteFinally7Test.testMain();
+}
diff --git a/tests/language/exception/finally8_test.dart b/tests/language/exception/finally8_test.dart
new file mode 100644
index 0000000..c697eee
--- /dev/null
+++ b/tests/language/exception/finally8_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 ensures that the finally block executes correctly when
+// there are throw, break and return statements in the finally block.
+
+import "package:expect/expect.dart";
+
+class Hello {
+  static var sum;
+
+  static foo() {
+    sum = 0;
+    try {
+      sum += 1;
+      return 'hi';
+    } finally {
+      sum += 1;
+      throw 'ball';
+      sum += 1;
+    }
+  }
+
+  static foo1() {
+    bool loop = true;
+    sum = 0;
+    L:
+    while (loop) {
+      try {
+        sum += 1;
+        return 'hi';
+      } finally {
+        sum += 1;
+        break L;
+        sum += 1;
+      }
+    }
+  }
+
+  static foo2() {
+    bool loop = true;
+    sum = 0;
+    try {
+      sum += 1;
+      return 'hi';
+    } finally {
+      sum += 1;
+      return 10;
+      sum += 1;
+    }
+  }
+
+  static foo3() {
+    sum = 0;
+    try {
+      sum += 1;
+      return 'hi';
+    } finally {
+      sum += 1;
+      return 10;
+      sum += 1;
+    }
+  }
+
+  static void main() {
+    foo1();
+    Expect.equals(2, sum);
+    foo2();
+    Expect.equals(2, sum);
+    foo3();
+    Expect.equals(2, sum);
+    try {
+      foo();
+    } catch (e) {}
+    Expect.equals(2, sum);
+  }
+}
+
+main() {
+  Hello.main();
+}
diff --git a/tests/language/exception/finally9_test.dart b/tests/language/exception/finally9_test.dart
new file mode 100644
index 0000000..5513466
--- /dev/null
+++ b/tests/language/exception/finally9_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 ensures that the finally block executes correctly when
+// there are throw, break and return statements in the finally block.
+
+import "package:expect/expect.dart";
+
+class Hello {
+  static var sum;
+
+  static foo() {
+    sum = 0;
+    try {
+      sum += 1;
+      return 'hi';
+    } catch (e) {
+      sum += 1;
+      throw 'ball';
+      sum += 1;
+    } finally {
+      sum += 1;
+      throw 'ball';
+      sum += 1;
+    }
+  }
+
+  static foo1() {
+    bool loop = true;
+    sum = 0;
+    L:
+    while (loop) {
+      try {
+        sum += 1;
+        return 'hi';
+      } catch (ex) {
+        sum += 1;
+      } finally {
+        try {
+          L1:
+          while (loop) {
+            sum += 1;
+            break L;
+            sum += 1;
+          }
+        } catch (ex) {
+          sum += 1;
+        } finally {
+          sum += 1;
+        }
+      }
+    }
+  }
+
+  static void main() {
+    foo1();
+    Expect.equals(3, sum);
+    try {
+      foo();
+    } catch (e) {
+      // Ignore.
+    }
+    Expect.equals(2, sum);
+  }
+}
+
+main() {
+  Hello.main();
+}
diff --git a/tests/language/exception/finally_test.dart b/tests/language/exception/finally_test.dart
new file mode 100644
index 0000000..9277416
--- /dev/null
+++ b/tests/language/exception/finally_test.dart
@@ -0,0 +1,30 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test for a bug in dart2js where the update of a field in a try
+// block would not be seen by the finally block. See dartbug.com/5517.
+
+class A {
+  int i;
+  A() : i = 42;
+
+  foo() {
+    bool executedFinally = false;
+    if (i == 42) {
+      try {
+        i = 12;
+      } finally {
+        Expect.equals(12, i);
+        executedFinally = true;
+      }
+    }
+    Expect.isTrue(executedFinally);
+  }
+}
+
+main() {
+  new A().foo();
+}
diff --git a/tests/language/exception/identity_test.dart b/tests/language/exception/identity_test.dart
new file mode 100644
index 0000000..2b16607
--- /dev/null
+++ b/tests/language/exception/identity_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 an object when thrown stays the same.
+
+class A {
+  A();
+}
+
+check(exception) {
+  try {
+    throw exception;
+  } catch (e) {
+    Expect.equals(exception, e);
+  }
+}
+
+main() {
+  check("str");
+  check(new A());
+  check(1);
+  check(1.2);
+}
diff --git a/tests/language/exception/in_increment_test.dart b/tests/language/exception/in_increment_test.dart
new file mode 100644
index 0000000..5e34a60
--- /dev/null
+++ b/tests/language/exception/in_increment_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test throws exception in the middle of the increment operation, the setter
+// part of the instance field increment never completes.
+// VMOptions=--optimization-counter-threshold=10
+
+main() {
+  var a = new A();
+  a.field = new A();
+  for (int i = 0; i < 20; i++) {
+    try {
+      a.foo(i);
+    } catch (e) {
+      // Ignore.
+    }
+  }
+}
+
+class A {
+  var field;
+  foo(i) {
+    field++; // throw exception
+  }
+}
diff --git a/tests/language/exception/on_catch_malformed_type_test.dart b/tests/language/exception/on_catch_malformed_type_test.dart
new file mode 100644
index 0000000..8b49027
--- /dev/null
+++ b/tests/language/exception/on_catch_malformed_type_test.dart
@@ -0,0 +1,38 @@
+// 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.
+
+// Check that malformed types in on-catch are handled correctly, that is,
+// throws a type error in both production and checked mode.
+
+import 'package:expect/expect.dart';
+
+catchUnresolvedBefore() {
+  try {
+    throw "foo";
+    Expect.fail("This code shouldn't be executed");
+  } on String catch (oks) {
+    // This is tested before the catch block below.
+  } on Unavailable catch (ex) { /*@compile-error=unspecified*/
+    Expect.fail("This code shouldn't be executed");
+  }
+}
+
+catchUnresolvedAfter() {
+  Expect.throwsTypeError(() {
+    try {
+      throw "foo";
+      Expect.fail("This code shouldn't be executed");
+    } on Unavailable catch (ex) { /*@compile-error=unspecified*/
+      // This is tested before the catch block below.
+      // In both production and checked mode the test causes a type error.
+    } on String catch (oks) {
+      Expect.fail("This code shouldn't be executed");
+    }
+  });
+}
+
+main() {
+  catchUnresolvedBefore();
+  catchUnresolvedAfter();
+}
diff --git a/tests/language/exception/rethrow_test.dart b/tests/language/exception/rethrow_test.dart
new file mode 100644
index 0000000..0b0d3bc
--- /dev/null
+++ b/tests/language/exception/rethrow_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+class MyException {
+  const MyException();
+}
+
+class OtherException {
+  const OtherException();
+}
+
+class RethrowTest {
+  late MyException currentException;
+
+  void throwException() {
+    currentException = new MyException();
+    throw currentException;
+  }
+
+  void testRethrowPastUncaught() {
+    try {
+      try {
+        try {
+          throwException();
+          Expect.fail("Should have thrown an exception");
+        } catch (e) {
+          Expect.equals(true, identical(e, currentException));
+          rethrow;
+          Expect.fail("Should have thrown an exception");
+        }
+      } on OtherException catch (e) {
+        Expect.fail("Should not have caught OtherException");
+      }
+    } catch (e) {
+      Expect.equals(true, identical(e, currentException));
+    }
+  }
+
+  void testRethrow() {
+    try {
+      try {
+        throwException();
+        Expect.fail("Should have thrown an exception");
+      } catch (e) {
+        Expect.equals(true, identical(e, currentException));
+        rethrow;
+        Expect.fail("Should have thrown an exception");
+      }
+    } catch (e) {
+      Expect.equals(true, identical(e, currentException));
+    }
+  }
+}
+
+main() {
+  RethrowTest t = new RethrowTest();
+  t.testRethrow();
+  t.testRethrowPastUncaught();
+}
diff --git a/tests/language/exception/throw1_test.dart b/tests/language/exception/throw1_test.dart
new file mode 100644
index 0000000..1ae121e
--- /dev/null
+++ b/tests/language/exception/throw1_test.dart
@@ -0,0 +1,82 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+abstract class TestException {
+  String getMessage();
+}
+
+class MyException implements TestException {
+  const MyException([String message = ""]) : message_ = message;
+  String getMessage() {
+    return message_;
+  }
+
+  final String message_;
+}
+
+class MyException2 implements TestException {
+  const MyException2([String message = ""]) : message_ = message;
+  String getMessage() {
+    return message_;
+  }
+
+  final String message_;
+}
+
+class MyException3 implements TestException {
+  const MyException3([String message = ""]) : message_ = message;
+  String getMessage() {
+    return message_;
+  }
+
+  final String message_;
+}
+
+class Helper {
+  static int f1(int i) {
+    try {
+      int j;
+      j = func();
+      if (j > 0) {
+        throw new MyException2("Test for exception being thrown");
+      }
+    } on MyException3 catch (exception) {
+      i = 100;
+      print(exception.getMessage());
+    } on TestException catch (exception) {
+      i = 50;
+      print(exception.getMessage());
+    } on MyException2 catch (exception) {
+      i = 150;
+      print(exception.getMessage());
+    } on MyException catch (exception) {
+      i = 200;
+      print(exception.getMessage());
+    } finally {
+      i = i + 800;
+    }
+    return i;
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+}
+
+class Throw1Test {
+  static testMain() {
+    Expect.equals(850, Helper.f1(1));
+  }
+}
+
+main() {
+  Throw1Test.testMain();
+}
diff --git a/tests/language/exception/throw2_test.dart b/tests/language/exception/throw2_test.dart
new file mode 100644
index 0000000..eaade24
--- /dev/null
+++ b/tests/language/exception/throw2_test.dart
@@ -0,0 +1,95 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+abstract class TestException {
+  String getMessage();
+}
+
+class MyException implements TestException {
+  const MyException([String message = ""]) : message_ = message;
+  String getMessage() {
+    return message_;
+  }
+
+  final String message_;
+}
+
+class MyException2 implements TestException {
+  const MyException2([String message = ""]) : message_ = message;
+  String getMessage() {
+    return message_;
+  }
+
+  final String message_;
+}
+
+class MyException3 implements TestException {
+  const MyException3([String message = ""]) : message_ = message;
+  String getMessage() {
+    return message_;
+  }
+
+  final String message_;
+}
+
+class Helper {
+  static int f1(int i) {
+    try {
+      int j;
+      j = func();
+    } on MyException3 catch (exception) {
+      i = 100;
+      print(exception.getMessage());
+    } on MyException2 catch (exception) {
+      try {
+        i = func2();
+        i = 200;
+      } on TestException catch (exception) {
+        i = 50;
+      }
+      print(exception.getMessage());
+    } on MyException catch (exception) {
+      i = func2();
+      print(exception.getMessage());
+    } finally {
+      i = i + 800;
+    }
+    return i;
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    if (i > 0) {
+      throw new MyException2("Test for exception being thrown");
+    }
+    return i;
+  }
+
+  static int func2() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    if (i > 0) {
+      throw new MyException2("Test for exception being thrown");
+    }
+    return i;
+  }
+}
+
+class Throw2Test {
+  static testMain() {
+    Expect.equals(850, Helper.f1(1));
+  }
+}
+
+main() {
+  Throw2Test.testMain();
+}
diff --git a/tests/language/exception/throw3_test.dart b/tests/language/exception/throw3_test.dart
new file mode 100644
index 0000000..1d72345
--- /dev/null
+++ b/tests/language/exception/throw3_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+class MyException {
+  const MyException([String message = ""]) : message_ = message;
+  final String message_;
+}
+
+class Helper {
+  static int f1(int i) {
+    try {
+      int j;
+      i = 100;
+      i = func();
+      i = 200;
+    } on MyException catch (exception) {
+      i = 50;
+      print(exception.message_);
+    } finally {
+      i = i + 800;
+    }
+    return i;
+  }
+
+  static int func() {
+    try {
+      int i = 0;
+      while (i < 10) {
+        i++;
+      }
+      if (i > 0) {
+        throw new MyException("Test for exception being thrown");
+      }
+    } on MyException catch (ex) {
+      print(ex.message_);
+      rethrow; // Rethrow the exception.
+    }
+    return 10;
+  }
+}
+
+class Throw3Test {
+  static testMain() {
+    Expect.equals(850, Helper.f1(1));
+  }
+}
+
+main() {
+  Throw3Test.testMain();
+}
diff --git a/tests/language/exception/throw4_test.dart b/tests/language/exception/throw4_test.dart
new file mode 100644
index 0000000..6dd2f74
--- /dev/null
+++ b/tests/language/exception/throw4_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+class MyException1 {
+  const MyException1([String message = "1"]) : message_ = message;
+  final String message_;
+}
+
+class MyException2 {
+  const MyException2([String message = "2"]) : message_ = message;
+  final String message_;
+}
+
+class MyException3 {
+  const MyException3([String message = "3"]) : message_ = message;
+  final String message_;
+}
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1() {
+    int j = 0;
+    try {
+      j = func();
+    } on MyException3 catch (exception) {
+      i = i + 300;
+      print(exception.message_);
+    } on MyException2 catch (exception) {
+      i = i + 200;
+      print(exception.message_);
+    } on MyException1 catch (exception) {
+      i = i + 100;
+      print(exception.message_);
+    } finally {
+      i = i + 1000;
+    }
+    return i;
+  }
+
+  // No catch in the same function for the type of exception being thrown
+  // in the try block here. We expect the handler if checks to fall thru,
+  // the finally block to run and an implicit rethrow to happen.
+  int func() {
+    i = 0;
+    try {
+      while (i < 10) {
+        i++;
+      }
+      if (i > 0) {
+        throw new MyException1("Test for MyException1 being thrown");
+      }
+    } on MyException3 catch (exception) {
+      i = 300;
+      print(exception.message_);
+    } on MyException2 catch (exception) {
+      i = 200;
+      print(exception.message_);
+    } finally {
+      i = 800;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class Throw4Test {
+  static testMain() {
+    Expect.equals(1900, new Helper().f1());
+  }
+}
+
+main() {
+  Throw4Test.testMain();
+}
diff --git a/tests/language/exception/throw5_test.dart b/tests/language/exception/throw5_test.dart
new file mode 100644
index 0000000..349ade7
--- /dev/null
+++ b/tests/language/exception/throw5_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+class MyException1 {
+  const MyException1([String message = "1"]) : message_ = message;
+  final String message_;
+}
+
+class MyException2 {
+  const MyException2([String message = "2"]) : message_ = message;
+  final String message_;
+}
+
+class MyException3 {
+  const MyException3([String message = "3"]) : message_ = message;
+  final String message_;
+}
+
+class Helper {
+  static int f1(int i) {
+    try {
+      int j;
+      j = func();
+    } on MyException3 catch (exception) {
+      i = 300;
+      print(exception.message_);
+    } on MyException2 catch (exception) {
+      i = 200;
+      print(exception.message_);
+    } on MyException1 catch (exception) {
+      i = 100;
+      print(exception.message_);
+    } finally {
+      i = i + 800;
+    }
+    return i;
+  }
+
+  // No catch in the same function for the type of exception being thrown
+  // in the try block here. We expect the handler if checks to fall thru and
+  // implicit rethrow to happen.
+  static int func() {
+    int i = 0;
+    try {
+      while (i < 10) {
+        i++;
+      }
+      if (i > 0) {
+        throw new MyException1("Test for MyException1 being thrown");
+      }
+    } on MyException3 catch (exception) {
+      i = 300;
+      print(exception.message_);
+    } on MyException2 catch (exception) {
+      i = 200;
+      print(exception.message_);
+    }
+    return i;
+  }
+}
+
+class Throw5Test {
+  static testMain() {
+    Expect.equals(900, Helper.f1(1));
+  }
+}
+
+main() {
+  Throw5Test.testMain();
+}
diff --git a/tests/language/exception/throw6_test.dart b/tests/language/exception/throw6_test.dart
new file mode 100644
index 0000000..1433467
--- /dev/null
+++ b/tests/language/exception/throw6_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+class MyException1 {
+  const MyException1([String message = "1"]) : message_ = message;
+  final String message_;
+}
+
+class Helper {
+  Helper() : i = 0 {}
+
+  int f1() {
+    int j = 0;
+    try {
+      j = func();
+    } catch (exception) {
+      i = i + 100;
+      print(exception.message_);
+    } finally {
+      i = i + 1000;
+    }
+    return i;
+  }
+
+  // No catch in the same function for the type of exception being thrown
+  // in the try block here. We expect the handler if checks to fall thru,
+  // the finally block to run and an implicit rethrow to happen.
+  int func() {
+    i = 0;
+    try {
+      while (i < 10) {
+        i++;
+      }
+      if (i > 0) {
+        throw new MyException1("Test for MyException1 being thrown");
+      }
+    } finally {
+      i = 800;
+    }
+    return i;
+  }
+
+  int i;
+}
+
+class Throw6Test {
+  static testMain() {
+    Expect.equals(1900, new Helper().f1());
+  }
+}
+
+main() {
+  Throw6Test.testMain();
+}
diff --git a/tests/language/exception/throw8_test.dart b/tests/language/exception/throw8_test.dart
new file mode 100644
index 0000000..de84012
--- /dev/null
+++ b/tests/language/exception/throw8_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+var finallyExecutionCount = 0;
+bar() {
+  try {
+    try {
+      return 499;
+    } catch (e, st) {
+      rethrow;
+    }
+  } finally {
+    finallyExecutionCount++;
+    throw "quit finally with throw";
+  }
+}
+
+main() {
+  bool hasThrown = false;
+  try {
+    bar();
+  } catch (x) {
+    hasThrown = true;
+    Expect.equals(1, finallyExecutionCount);
+  }
+  Expect.isTrue(hasThrown);
+}
diff --git a/tests/language/exception/throw_expr_test.dart b/tests/language/exception/throw_expr_test.dart
new file mode 100644
index 0000000..c1f5044
--- /dev/null
+++ b/tests/language/exception/throw_expr_test.dart
@@ -0,0 +1,111 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test program for testing throw expressions.
+
+void test1() {
+  var x = 6;
+  try {
+    throw x = 10;
+    x = 0;
+  } catch (e) {
+    Expect.equals(10, e);
+    Expect.equals(10, x);
+    x = 15;
+  }
+  Expect.equals(15, x);
+  x = 100;
+  try {
+    throw x++;
+    x = 0;
+  } catch (e) {
+    Expect.equals(100, e);
+    Expect.equals(101, x);
+    x = 150;
+  }
+  Expect.equals(150, x);
+}
+
+void test2() {
+  var x = 6;
+  try {
+    throw x + 4;
+  } catch (e) {
+    Expect.equals(10, e);
+    Expect.equals(6, x);
+    x = 15;
+  }
+  Expect.equals(15, x);
+}
+
+foo(x, y) => throw "foo" "$x";
+
+bar(x, y) => throw "foo" "${throw x}";
+
+class Q {
+  var qqq;
+  f(x) {
+    qqq = x;
+  }
+
+  Q get nono => throw "nono";
+}
+
+void test3() {
+  try {
+    throw throw throw "up";
+  } catch (e) {
+    Expect.equals("up", e);
+  }
+
+  dynamic x = 10;
+  try {
+    foo(x = 12, throw 7);
+  } catch (e) {
+    Expect.equals(7, e);
+    Expect.equals(12, x);
+  }
+
+  x = 10;
+  try {
+    foo(x++, 10);
+  } catch (e) {
+    Expect.equals("foo10", e);
+    Expect.equals(11, x);
+  }
+
+  x = 100;
+  try {
+    bar(++x, 10);
+  } catch (e) {
+    Expect.equals(101, e);
+    Expect.equals(101, x);
+  }
+
+  x = null;
+  try {
+    x = new Q();
+    x
+      ..f(11)
+      ..qqq = throw 77
+      ..f(22);
+  } catch (e) {
+    Expect.equals(77, e);
+    Expect.equals(11, x.qqq);
+  }
+}
+
+void test4() {
+  var q = new Q();
+  Expect.throws(() => q.nono, (e) => e == "nono");
+}
+
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+}
diff --git a/tests/language/exception/throw_test.dart b/tests/language/exception/throw_test.dart
new file mode 100644
index 0000000..0c864cc
--- /dev/null
+++ b/tests/language/exception/throw_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing throw statement
+
+import "package:expect/expect.dart";
+
+class MyException {
+  const MyException(String this.message_);
+  final String message_;
+}
+
+class Helper {
+  static int f1(int i) {
+    try {
+      int j;
+      j = func();
+      if (j > 0) {
+        throw new MyException("Test for exception being thrown");
+      }
+    } on MyException catch (exception) {
+      i = 100;
+      print(exception.message_);
+    } finally {
+      i = i + 800;
+    }
+    return i;
+  }
+
+  static int func() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+}
+
+class ThrowTest {
+  static testMain() {
+    Expect.equals(900, Helper.f1(1));
+  }
+}
+
+main() {
+  ThrowTest.testMain();
+}
diff --git a/tests/language/exception/try_catch2_test.dart b/tests/language/exception/try_catch2_test.dart
new file mode 100644
index 0000000..8da606c
--- /dev/null
+++ b/tests/language/exception/try_catch2_test.dart
@@ -0,0 +1,71 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing try/catch statement without any exceptions
+// being thrown. (Nested try/catch blocks).
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+abstract class TestException {
+  String getMessage();
+}
+
+class MyException implements TestException {
+  const MyException([String message = ""]) : message_ = message;
+  String getMessage() {
+    return message_;
+  }
+
+  final String message_;
+}
+
+class StackTrace {
+  StackTrace() {}
+}
+
+class Helper {
+  static int f1(int i) {
+    try {
+      int j;
+      j = f2();
+      i = i + 1;
+      try {
+        j = f2() + f3() + j;
+        i = i + 1;
+      } on TestException catch (e, trace) {
+        j = 50;
+      }
+      j = f3() + j;
+    } on MyException catch (exception) {
+      i = 100;
+    } on TestException catch (e, trace) {
+      i = 200;
+    }
+    return i;
+  }
+
+  static int f2() {
+    return 2;
+  }
+
+  static int f3() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+}
+
+class TryCatch2Test {
+  static testMain() {
+    Expect.equals(3, Helper.f1(1));
+  }
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    TryCatch2Test.testMain();
+  }
+}
diff --git a/tests/language/exception/try_catch3_test.dart b/tests/language/exception/try_catch3_test.dart
new file mode 100644
index 0000000..6cff3f8
--- /dev/null
+++ b/tests/language/exception/try_catch3_test.dart
@@ -0,0 +1,126 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing try/catch statement without any exceptions
+// being thrown.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+abstract class TestException {
+  String getMessage();
+}
+
+class MyException implements TestException {
+  const MyException([String message = ""]) : this._message = message;
+  String getMessage() {
+    return _message;
+  }
+
+  final String _message;
+}
+
+class MyParameterizedException<U, V> implements TestException {
+  const MyParameterizedException([String message = ""])
+      : this._message = message;
+  String getMessage() {
+    return _message;
+  }
+
+  final String _message;
+}
+
+class StackTrace {
+  StackTrace() {}
+  printStackTrace(TestException ex) {
+    print(ex);
+  }
+}
+
+class Helper {
+  static int test1(int i) {
+    try {
+      int j;
+      j = f2();
+      j = f3();
+      try {
+        int k = f2();
+        f3();
+      } on MyException catch (ex) {
+        int i = 10;
+        print(i);
+      } on TestException catch (ex) {
+        int k = 10;
+        print(k);
+      }
+      try {
+        j = j + 24;
+      } catch (e) {
+        i = 300;
+        print(e.getMessage());
+      }
+      try {
+        j += 20;
+      } catch (e) {
+        i = 400;
+        print(e.getMessage());
+      }
+      try {
+        j += 40;
+      } catch (e) {
+        i = 600;
+        print(e.getMessage());
+      }
+      try {
+        j += 60;
+      } catch (e, trace) {
+        i = 700;
+        print(trace.toString());
+        print(e.getMessage());
+      }
+      try {
+        j += 80;
+      } on MyException catch (e) {
+        i = 500;
+        print(e.getMessage());
+      }
+    } on MyParameterizedException<String, TestException> catch (e, trace) {
+      i = 800;
+      print(trace.toString());
+      rethrow;
+    } on MyException catch (exception) {
+      i = 100;
+      print(exception.getMessage());
+    } on TestException catch (e, trace) {
+      i = 200;
+      print(trace.toString());
+    } finally {
+      i = 900;
+    }
+    return i;
+  }
+
+  static int f2() {
+    return 2;
+  }
+
+  static int f3() {
+    int i = 0;
+    while (i < 10) {
+      i++;
+    }
+    return i;
+  }
+}
+
+class TryCatchTest {
+  static testMain() {
+    Expect.equals(900, Helper.test1(1));
+  }
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    TryCatchTest.testMain();
+  }
+}
diff --git a/tests/language/exception/try_catch4_test.dart b/tests/language/exception/try_catch4_test.dart
new file mode 100644
index 0000000..a6cbe03
--- /dev/null
+++ b/tests/language/exception/try_catch4_test.dart
@@ -0,0 +1,206 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Check that our SSA graph does have the try body a predecessor of a
+// try/finally.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+var a;
+
+foo1() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      a = 8;
+      return false;
+    } finally {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+doThrow() {
+  throw 2;
+}
+
+foo2() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      a = 8;
+      doThrow();
+      return false;
+    } catch (e) {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+foo3() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      doThrow();
+    } catch (e) {
+      a = 8;
+      entered = true;
+      return false;
+    } finally {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+foo4() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      a = 8;
+      break;
+    } finally {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+foo5() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      a = 8;
+      doThrow();
+      break;
+    } catch (e) {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+foo6() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      doThrow();
+    } catch (e) {
+      a = 8;
+      entered = true;
+      break;
+    } finally {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+foo7() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      a = 8;
+      continue;
+    } finally {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+foo8() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      a = 8;
+      doThrow();
+      continue;
+    } catch (e) {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+foo9() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      doThrow();
+    } catch (e) {
+      a = 8;
+      entered = true;
+      continue;
+    } finally {
+      b = 8 == a;
+      entered = true;
+      continue;
+    }
+  }
+}
+
+main_test() {
+  a = 0;
+  Expect.isTrue(foo1());
+  a = 0;
+  Expect.isTrue(foo2());
+  a = 0;
+  Expect.isTrue(foo3());
+  a = 0;
+  Expect.isTrue(foo4());
+  a = 0;
+  Expect.isTrue(foo5());
+  a = 0;
+  Expect.isTrue(foo6());
+  a = 0;
+  Expect.isTrue(foo7());
+  a = 0;
+  Expect.isTrue(foo8());
+  a = 0;
+  Expect.isTrue(foo9());
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    main_test();
+  }
+}
diff --git a/tests/language/exception/try_catch5_test.dart b/tests/language/exception/try_catch5_test.dart
new file mode 100644
index 0000000..6920b06
--- /dev/null
+++ b/tests/language/exception/try_catch5_test.dart
@@ -0,0 +1,38 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Check that our SSA graph does have the try body a predecessor of a
+// try/finally.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+var a;
+
+foo1() {
+  var b = false;
+  var entered = false;
+  while (true) {
+    if (entered) return b;
+    b = 8 == a; // This expression should not be GVN'ed.
+    try {
+      try {
+        a = 8;
+        return false;
+      } finally {
+        b = 8 == a;
+        entered = true;
+        continue;
+      }
+    } finally {
+      continue;
+    }
+  }
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    a = 0;
+    Expect.isTrue(foo1());
+  }
+}
diff --git a/tests/language/exception/try_catch_on_syntax_test.dart b/tests/language/exception/try_catch_on_syntax_test.dart
new file mode 100644
index 0000000..c19a94f
--- /dev/null
+++ b/tests/language/exception/try_catch_on_syntax_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 MyException {}
+
+class MyException1 extends MyException {}
+
+class MyException2 extends MyException {}
+
+void test1() {
+  var foo = 0;
+  try {
+    throw new MyException1();
+  }
+  on on MyException2 catch (e) { } //# 02: syntax error
+  catch MyException2 catch (e) { } //# 03: syntax error
+  catch catch catch (e) { } //# 04: syntax error
+  on (e) { } //# 05: syntax error
+  catch MyException2 catch (e) { } //# 06: syntax error
+  on MyException2 catch (e) {
+    foo = 1;
+  } on MyException1 catch (e) {
+    foo = 2;
+  } on MyException catch (e) {
+    foo = 3;
+  }
+  on UndefinedClass //# 07: compile-time error
+  catch (e) {
+    foo = 4;
+  }
+  Expect.equals(2, foo);
+}
+
+testFinal() {
+  try {
+    throw "catch this!";
+  } catch (e, s) {
+    // Test that the error and stack trace variables are final.
+      e = null; // //# 10: compile-time error
+      s = null; // //# 11: compile-time error
+  }
+}
+
+main() {
+  test1();
+  testFinal();
+}
diff --git a/tests/language/exception/try_catch_optimized1_test.dart b/tests/language/exception/try_catch_optimized1_test.dart
new file mode 100644
index 0000000..c3b522a
--- /dev/null
+++ b/tests/language/exception/try_catch_optimized1_test.dart
@@ -0,0 +1,290 @@
+// 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.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+maythrow(x) {
+  if (x == null) throw 42;
+  return 99;
+}
+
+f1(x) {
+  var result = 123;
+  try {
+    result = maythrow(x);
+    if (result > 100) throw 42;
+  } catch (e) {
+    Expect.equals(result, 123);
+    Expect.equals(42, e);
+    result = 0;
+  }
+  return result;
+}
+
+class A {
+  maythrow(x) {
+    if (x == null) throw 42;
+    return 99;
+  }
+}
+
+f2(x) {
+  dynamic result = 123;
+  var a = new A();
+  try {
+    result++;
+    result = a.maythrow(x);
+  } catch (e) {
+    Expect.equals(124, result);
+    result = x;
+  }
+  return result;
+}
+
+f3(x, y) {
+  var result = 123;
+  var a = new A();
+  try {
+    result++;
+    result = a.maythrow(x);
+  } catch (e) {
+    result = y + 1; // Deopt on overflow
+  }
+  return result;
+}
+
+f4(x) {
+  try {
+    maythrow(x);
+  } catch (e) {
+    check_f4(e, "abc");
+  }
+}
+
+check_f4(e, s) {
+  if (e != 42) throw "ERROR";
+  if (s != "abc") throw "ERROR";
+}
+
+f5(x) {
+  try {
+    maythrow(x);
+  } catch (e) {
+    check_f5(e, "abc");
+  }
+
+  try {
+    maythrow(x);
+  } catch (e) {
+    check_f5(e, "abc");
+  }
+}
+
+check_f5(e, s) {
+  if (e != 42) throw "ERROR";
+  if (s != "abc") throw "ERROR";
+}
+
+f6(x, y) {
+  var a = x;
+  var b = y;
+  var c = 123;
+  check_f6(42, null, 1, 123, null, 1);
+  try {
+    maythrow(x);
+  } catch (e) {
+    check_f6(e, a, b, c, x, y);
+  }
+}
+
+check_f6(e, a, b, c, x, y) {
+  if (e != 42) throw "ERROR";
+  if (a != null) throw "ERROR";
+  if (b != 1) throw "ERROR";
+  if (c != 123) throw "ERROR";
+  if (x != null) throw "ERROR";
+  if (y != 1) throw "ERROR";
+}
+
+bool f7(String str) {
+  double d = double.parse(str);
+  var t = d;
+  try {
+    var a = d.toInt();
+    return false;
+  } on UnsupportedError catch (e) {
+    Expect.equals(true, identical(t, d));
+    return true;
+  }
+}
+
+f8(x, [a = 3, b = 4]) {
+  var c = 123;
+  var y = a;
+  try {
+    maythrow(x);
+  } catch (e, s) {
+    check_f8(e, s, a, b, c, x, y);
+  }
+}
+
+check_f8(e, s, a, b, c, x, y) {
+  if (e != 42) throw "ERROR";
+  if (s is! StackTrace) throw "ERROR";
+  if (a != 3) {
+    print(a);
+    throw "ERROR";
+  }
+  if (b != 4) throw "ERROR";
+  if (c != 123) throw "ERROR";
+  if (x != null) throw "ERROR";
+  if (y != a) throw "ERROR";
+}
+
+f9(x, [a = 3, b = 4]) {
+  var c = 123;
+  var y = a;
+  try {
+    if (x < a) maythrow(null);
+    maythrow(x);
+  } catch (e, s) {
+    check_f9(e, s, a, b, c, x, y);
+  }
+}
+
+check_f9(e, s, a, b, c, x, y) {
+  if (e != 42) throw "ERROR";
+  if (s is! StackTrace) throw "ERROR";
+  if (a != 3) {
+    print(a);
+    throw "ERROR";
+  }
+  if (b != 4) throw "ERROR";
+  if (c != 123) throw "ERROR";
+  if (x != null) throw "ERROR";
+  if (y != a) throw "ERROR";
+}
+
+f10(x, y) {
+  var result = 123;
+  try {
+    result = maythrow(x);
+  } catch (e) {
+    Expect.equals(123, result);
+    Expect.equals(0.5, y / 2.0);
+    result = 0;
+  }
+  return result;
+}
+
+f11(x) {
+  var result = 123;
+  var tmp = x;
+  try {
+    result = maythrow(x);
+    if (result > 100) throw 42;
+  } catch (e, s) {
+    Expect.equals(123, result);
+    Expect.equals(true, identical(tmp, x));
+    Expect.equals(true, s is StackTrace);
+    result = 0;
+  }
+  return result;
+}
+
+f12([x = null]) {
+  try {
+    maythrow(x);
+  } catch (e) {
+    check_f12(e, x);
+  }
+}
+
+check_f12(e, x) {
+  if (e != 42) throw "ERROR";
+  if (x != null) throw "ERROR";
+}
+
+f13(x) {
+  var result = 123;
+  try {
+    try {
+      result = maythrow(x);
+      if (result > 100) throw 42;
+    } catch (e) {
+      Expect.equals(123, result);
+      result = 0;
+    }
+    maythrow(x);
+  } catch (e) {
+    result++;
+  }
+  return result;
+}
+
+main() {
+  for (var i = 0; i < 20; i++) f1("abc");
+  Expect.equals(99, f1("abc"));
+  Expect.equals(0, f1(null));
+
+  for (var i = 0; i < 20; i++) f2("abc");
+  Expect.equals(99, f2("abc"));
+  Expect.equals(null, f2(null));
+
+  f3("123", 0);
+  for (var i = 0; i < 20; i++) f3(null, 0);
+  Expect.equals(99, f3("123", 0));
+  Expect.equals(0x40000000, f3(null, 0x3fffffff));
+
+  f4(null);
+  for (var i = 0; i < 20; i++) f4(123);
+  f4(null);
+
+  f5(null);
+  for (var i = 0; i < 20; i++) f5(123);
+  f5(null);
+
+  f6(null, 1);
+  for (var i = 0; i < 20; i++) f6(123, 1);
+  f6(null, 1);
+
+  f7("1.2");
+  f7("Infinity");
+  f7("-Infinity");
+  for (var i = 0; i < 20; i++) f7("1.2");
+  Expect.equals(false, f7("1.2"));
+  Expect.equals(true, f7("Infinity"));
+  Expect.equals(true, f7("-Infinity"));
+  Expect.equals(false, f7("123456789012345")); // Deopt.
+  for (var i = 0; i < 20; i++) f7("123456789012345");
+  Expect.equals(true, f7("Infinity"));
+  Expect.equals(true, f7("-Infinity"));
+
+  for (var i = 0; i < 20; i++) f8(null);
+  f8(null);
+
+  f9(5);
+  f9(5.0);
+  for (var i = 0; i < 20; i++) f9(3);
+  f9(3);
+
+  var y = 1.0;
+  Expect.equals(0, f10(null, y));
+  for (var i = 0; i < 20; i++) f10("abc", y);
+  Expect.equals(99, f10("abc", y));
+  Expect.equals(0, f10(null, y));
+
+  for (var i = 0; i < 20; i++) f11("abc");
+  Expect.equals(99, f11("abc"));
+  Expect.equals(0, f11(null));
+
+  for (var i = 0; i < 20; i++) f12(null);
+  f12(null);
+
+  f13(null);
+  for (var i = 0; i < 20; i++) f13("abc");
+  Expect.equals(99, f13("abc"));
+  Expect.equals(1, f13(null));
+}
diff --git a/tests/language/exception/try_catch_optimized2_test.dart b/tests/language/exception/try_catch_optimized2_test.dart
new file mode 100644
index 0000000..159a6e5
--- /dev/null
+++ b/tests/language/exception/try_catch_optimized2_test.dart
@@ -0,0 +1,30 @@
+// 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.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+// Test allocation sinking with optimized try-catch.
+
+bar() {
+  // Should not be inlined.
+  try {} finally {}
+}
+
+foo(List<int> a) {
+  var r = 0;
+  for (var i in a) {
+    r += i;
+  }
+  try {
+    bar();
+  } finally {}
+  return r;
+}
+
+main() {
+  var a = [1, 2, 3];
+  for (var i = 0; i < 20; i++) foo(a);
+  Expect.equals(6, foo(a));
+}
diff --git a/tests/language/exception/try_catch_optimized3_test.dart b/tests/language/exception/try_catch_optimized3_test.dart
new file mode 100644
index 0000000..a2b03fc
--- /dev/null
+++ b/tests/language/exception/try_catch_optimized3_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.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+// Test unboxed double operations inside try-catch.
+foo(bool b) {
+  if (b) throw 123;
+}
+
+test_double(double x, bool b) {
+  try {
+    x += 1.0;
+    foo(b);
+  } catch (e) {
+    var result = x - 1.0;
+    Expect.equals(1.0, result);
+    return result;
+  }
+}
+
+main() {
+  for (var i = 0; i < 100; i++) test_double(1.0, false);
+  test_double(1.0, false);
+  Expect.equals(1.0, test_double(1.0, true));
+}
diff --git a/tests/language/exception/try_catch_optimized4_test.dart b/tests/language/exception/try_catch_optimized4_test.dart
new file mode 100644
index 0000000..dc98f31
--- /dev/null
+++ b/tests/language/exception/try_catch_optimized4_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.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import "package:expect/expect.dart";
+
+// Test correct dead phi elimination with try catch.
+
+List<Object> a = [1, 2, 3, 4, 5];
+
+class MyError {}
+
+class M {
+  maythrow(i) {
+    try {
+      if (i <= 5) throw new MyError();
+    } catch (e) {
+      throw e;
+    }
+  }
+}
+
+loop_test() {
+  bool failed = false;
+  M m = new M();
+  for (Object i in a) {
+    try {
+      String res = m.maythrow(i);
+      failed = true;
+    } on MyError catch (e) {}
+    if (!identical(failed, false)) {
+      Expect.fail("");
+    }
+  }
+}
+
+main() {
+  for (var i = 0; i < 20; i++) loop_test();
+}
diff --git a/tests/language/exception/try_catch_optimized5_test.dart b/tests/language/exception/try_catch_optimized5_test.dart
new file mode 100644
index 0000000..a3b7b99
--- /dev/null
+++ b/tests/language/exception/try_catch_optimized5_test.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.
+// Dart test program for testing try/catch statement without any exceptions
+// being thrown.
+// VMOptions=--optimization-counter-threshold=100 --no-background-compilation
+
+// Test optional parameters updated inside try-catch
+
+import "package:expect/expect.dart";
+
+@pragma('vm:never-inline')
+m1(int b) {
+  if (b == 1) throw 123;
+}
+
+@pragma('vm:never-inline')
+m2(int b) {
+  if (b == 2) throw 456;
+}
+
+@pragma('vm:never-inline')
+test1(int b, [int state = 0]) {
+  try {
+    state++;
+    m1(b);
+    state++;
+    m2(b);
+    state++;
+  } catch (e, s) {
+    if (b == 1 && state != 1) throw "fail1";
+    if (b == 2 && state != 2) throw "fail2";
+    if (b == 3 && state != 3) throw "fail3";
+    if (s is! StackTrace) throw "fail4";
+    return e;
+  }
+  return "no throw";
+}
+
+@pragma('vm:never-inline')
+test2(int b, [int state = -1]) {
+  state = 0;
+  try {
+    state++;
+    m1(b);
+    state++;
+    m2(b);
+    state++;
+  } catch (e, s) {
+    if (b == 1 && state != 1) throw "fail1";
+    if (b == 2 && state != 2) throw "fail2";
+    if (b == 3 && state != 3) throw "fail3";
+    if (s is! StackTrace) throw "fail4";
+    return e;
+  }
+  return "no throw";
+}
+
+main() {
+  for (var i = 0; i < 300; i++) {
+    Expect.equals("no throw", test1(0));
+  }
+  Expect.equals("no throw", test1(0));
+  Expect.equals(123, test1(1));
+  Expect.equals(456, test1(2));
+
+  for (var i = 0; i < 300; i++) {
+    Expect.equals("no throw", test2(0));
+  }
+  Expect.equals("no throw", test2(0));
+  Expect.equals(123, test2(1));
+  Expect.equals(456, test2(2));
+}
diff --git a/tests/language/exception/try_catch_osr_test.dart b/tests/language/exception/try_catch_osr_test.dart
new file mode 100644
index 0000000..345f764
--- /dev/null
+++ b/tests/language/exception/try_catch_osr_test.dart
@@ -0,0 +1,103 @@
+// 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.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+// Test OSR in different places of a try-catch.
+
+import "package:expect/expect.dart";
+
+maythrow(x) {
+  try {
+    if (x == null) throw 42;
+    return 99;
+  } finally {}
+}
+
+f1() {
+  var s = 0, t = "abc";
+  for (var i = 0; i < 21; ++i) {
+    s += i;
+  }
+  try {
+    maythrow(null);
+  } catch (e) {
+    Expect.equals("abc", t);
+    Expect.equals(42, e);
+    s++;
+  }
+  return s;
+}
+
+f2([int x = 1]) {
+  var s = 0;
+  var t = "abc";
+  try {
+    try {
+      for (var i = 0; i < 20; ++i) {
+        if (i == 18) maythrow(null);
+        s += x;
+      }
+    } catch (e) {
+      Expect.equals(1, x);
+      Expect.equals("abc", t);
+      Expect.equals(42, e);
+      s++;
+    }
+  } catch (e) {}
+  return s;
+}
+
+f3() {
+  var s = 0, t = "abc";
+  try {
+    maythrow(null);
+  } catch (e) {
+    Expect.equals("abc", t);
+    for (var i = 0; i < 21; ++i) {
+      s += i;
+    }
+    Expect.equals("abc", t);
+    Expect.equals(42, e);
+    return s;
+  }
+}
+
+f4() {
+  var s = 0, t = "abc";
+  try {
+    for (var i = 0; i < 21; ++i) {
+      if (i == 18) maythrow(null);
+      s += i;
+    }
+  } catch (e) {
+    Expect.equals("abc", t);
+    Expect.equals(42, e);
+    s++;
+  }
+  return s;
+}
+
+f5() {
+  var s, t = "abc";
+  try {
+    maythrow(null);
+  } catch (e) {
+    Expect.equals("abc", t);
+    Expect.equals(42, e);
+    s = 0;
+  }
+  for (var i = 0; i < 21; ++i) {
+    s += i;
+  }
+  Expect.equals("abc", t);
+  return s;
+}
+
+main() {
+  Expect.equals(211, f1());
+  Expect.equals(19, f2());
+  Expect.equals(210, f3());
+  Expect.equals(9 * 17 + 1, f4());
+  Expect.equals(210, f5());
+}
diff --git a/tests/language/exception/try_catch_regress_27483_test.dart b/tests/language/exception/try_catch_regress_27483_test.dart
new file mode 100644
index 0000000..dde7246
--- /dev/null
+++ b/tests/language/exception/try_catch_regress_27483_test.dart
@@ -0,0 +1,47 @@
+// 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.
+// Dart test program for testing try/catch statement without any exceptions
+// being thrown.
+// VMOptions=--optimization-counter-threshold=100 --no-background-compilation
+
+// Test local variables updated inside try-catch.
+
+import "package:expect/expect.dart";
+
+@pragma('vm:never-inline')
+m1(int b) {
+  if (b == 1) throw 123;
+}
+
+@pragma('vm:never-inline')
+m2(int b) {
+  if (b == 2) throw 456;
+}
+
+@pragma('vm:never-inline')
+test(b) {
+  var state = 0;
+  try {
+    state++;
+    m1(b);
+    state++;
+    m2(b);
+    state++;
+  } catch (e, s) {
+    if (b == 1 && state != 1) throw "fail1";
+    if (b == 2 && state != 2) throw "fail2";
+    if (b == 3 && state != 3) throw "fail3";
+    return e;
+  }
+  return "no throw";
+}
+
+main() {
+  for (var i = 0; i < 300; i++) {
+    Expect.equals("no throw", test(0));
+  }
+  Expect.equals("no throw", test(0));
+  Expect.equals(123, test(1));
+  Expect.equals(456, test(2));
+}
diff --git a/tests/language/exception/try_catch_runtime_test.dart b/tests/language/exception/try_catch_runtime_test.dart
new file mode 100644
index 0000000..872f9d7
--- /dev/null
+++ b/tests/language/exception/try_catch_runtime_test.dart
@@ -0,0 +1,199 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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=10
+
+import "package:expect/expect.dart";
+
+class MyException {}
+
+class MyException1 extends MyException {}
+
+class MyException2 extends MyException {}
+
+class TryCatchTest {
+  static void test1() {
+    var foo = 0;
+    try {
+      throw new MyException1();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException1 catch (e) {
+      foo = 2;
+    } on MyException catch (e) {
+      foo = 3;
+    }
+    Expect.equals(2, foo);
+  }
+
+  static void test2() {
+    var foo = 0;
+    try {
+      throw new MyException1();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException catch (e) {
+      foo = 2;
+    } on MyException1 catch (e) {
+      foo = 3;
+    }
+    Expect.equals(2, foo);
+  }
+
+  static void test3() {
+    var foo = 0;
+    try {
+      throw new MyException();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException1 catch (e) {
+      foo = 2;
+    } on MyException catch (e) {
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test4() {
+    var foo = 0;
+    try {
+      try {
+        throw new MyException();
+      } on MyException2 catch (e) {
+        foo = 1;
+      } on MyException1 catch (e) {
+        foo = 2;
+      }
+    } on MyException catch (e) {
+      Expect.equals(0, foo);
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test5() {
+    var foo = 0;
+    try {
+      throw new MyException1();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } catch (e) {
+      foo = 2;
+    }
+    Expect.equals(2, foo);
+  }
+
+  static void test6() {
+    var foo = 0;
+    try {
+      throw new MyException();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException1 catch (e) {
+      foo = 2;
+    } catch (e) {
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test7() {
+    var foo = 0;
+    try {
+      try {
+        throw new MyException();
+      } on MyException2 catch (e) {
+        foo = 1;
+      } on MyException1 catch (e) {
+        foo = 2;
+      }
+    } catch (e) {
+      Expect.equals(0, foo);
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test8() {
+    var e = 3;
+    var caught = false;
+    try {
+      throw new MyException();
+    } catch (exc) {
+      caught = true;
+    }
+    Expect.equals(true, caught);
+    Expect.equals(3, e);
+  }
+
+  static void test9() {
+    dynamic e = 6;
+    try {
+      throw "up";
+    } on String {
+      e = "s";
+    } on int {
+      e = "i";
+    }
+    Expect.equals("s", e);
+  }
+
+  static void test10() {
+    try {
+      throw "up";
+    } on String catch (e) {
+      var e = 1; // ok, shadows exception variable.
+      Expect.equals(1, e);
+    }
+  }
+
+  static void test11() {
+    var e0 = 11;
+    try {
+      throw "up";
+    } on int catch (e0) {
+      Expect.fail("unreachable");
+    } on String catch (e1) {
+      // e0 from the other catch clause is not in scope.
+      Expect.equals(11, e0);
+    }
+  }
+
+  static void test12() {
+    const x = const [];
+    try {
+      throw "up";
+    } catch (e) {
+      Expect.equals("up", e);
+    } on String catch (e) {
+      // Compile-time constants in unreachable catch blocks are still
+      // compiled.
+
+      Expect.fail("unreachable");
+    }
+  }
+
+  static void testMain() {
+    test1();
+    test2();
+    test3();
+    test4();
+    test5();
+    test6();
+    test7();
+    test8();
+    test9();
+    test10();
+    test11();
+    test12();
+  }
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    TryCatchTest.testMain();
+  }
+}
diff --git a/tests/language/exception/try_catch_syntax_test.dart b/tests/language/exception/try_catch_syntax_test.dart
new file mode 100644
index 0000000..5a192d1
--- /dev/null
+++ b/tests/language/exception/try_catch_syntax_test.dart
@@ -0,0 +1,47 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  testMissingCatch();
+  testMissingTry();
+  testDuplicateCatchVariable();
+  testIllegalFinally();
+  testIllegalCatch();
+  testIllegalRethrow();
+}
+
+testMissingCatch() {
+  try { } // //# 01: syntax error
+}
+
+testMissingTry() {
+  on Exception catch (e) { } //                  //# 02: syntax error
+  on Exception catch (e, trace) { } //           //# 03: syntax error
+  finally { } //                                 //# 04: syntax error
+}
+
+testDuplicateCatchVariable() {
+  try { } on Exception catch (e, e) { } //# 05: compile-time error
+}
+
+testIllegalFinally() {
+  try { } finally (e) { } //# 06: syntax error
+}
+
+testIllegalCatch() {
+  try { } catch () { } //             //# 07: syntax error
+  try { } on MammaMia catch (e) { } //# 08: compile-time error
+  try { } catch (var e) { } //        //# 09: syntax error
+  try { } catch (final e) { } //      //# 10: syntax error
+  try { } catch (int e) { } //        //# 11: syntax error
+  try { } catch (final int e) { } //  //# 12: syntax error
+  try { } catch ([e, s]) { } //       //# 13: syntax error
+  try { } catch (e, [s]) { } //       //# 14: syntax error
+  try { } catch (e, [s0, s1]) { } //  //# 15: syntax error
+}
+
+testIllegalRethrow() {
+  try { rethrow; } catch (e) { } //            //# 16: compile-time error
+  try { } catch (e) { } finally { rethrow; } //# 17: compile-time error
+}
diff --git a/tests/language/exception/try_catch_test.dart b/tests/language/exception/try_catch_test.dart
new file mode 100644
index 0000000..2b8fee2
--- /dev/null
+++ b/tests/language/exception/try_catch_test.dart
@@ -0,0 +1,200 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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=10
+
+import "package:expect/expect.dart";
+
+class MyException {}
+
+class MyException1 extends MyException {}
+
+class MyException2 extends MyException {}
+
+class TryCatchTest {
+  static void test1() {
+    var foo = 0;
+    try {
+      throw new MyException1();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException1 catch (e) {
+      foo = 2;
+    } on MyException catch (e) {
+      foo = 3;
+    }
+    Expect.equals(2, foo);
+  }
+
+  static void test2() {
+    var foo = 0;
+    try {
+      throw new MyException1();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException catch (e) {
+      foo = 2;
+    } on MyException1 catch (e) {
+      foo = 3;
+    }
+    Expect.equals(2, foo);
+  }
+
+  static void test3() {
+    var foo = 0;
+    try {
+      throw new MyException();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException1 catch (e) {
+      foo = 2;
+    } on MyException catch (e) {
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test4() {
+    var foo = 0;
+    try {
+      try {
+        throw new MyException();
+      } on MyException2 catch (e) {
+        foo = 1;
+      } on MyException1 catch (e) {
+        foo = 2;
+      }
+    } on MyException catch (e) {
+      Expect.equals(0, foo);
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test5() {
+    var foo = 0;
+    try {
+      throw new MyException1();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } catch (e) {
+      foo = 2;
+    }
+    Expect.equals(2, foo);
+  }
+
+  static void test6() {
+    var foo = 0;
+    try {
+      throw new MyException();
+    } on MyException2 catch (e) {
+      foo = 1;
+    } on MyException1 catch (e) {
+      foo = 2;
+    } catch (e) {
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test7() {
+    var foo = 0;
+    try {
+      try {
+        throw new MyException();
+      } on MyException2 catch (e) {
+        foo = 1;
+      } on MyException1 catch (e) {
+        foo = 2;
+      }
+    } catch (e) {
+      Expect.equals(0, foo);
+      foo = 3;
+    }
+    Expect.equals(3, foo);
+  }
+
+  static void test8() {
+    var e = 3;
+    var caught = false;
+    try {
+      throw new MyException();
+    } catch (exc) {
+      caught = true;
+    }
+    Expect.equals(true, caught);
+    Expect.equals(3, e);
+  }
+
+  static void test9() {
+    dynamic e = 6;
+    try {
+      throw "up";
+    } on String {
+      e = "s";
+    } on int {
+      e = "i";
+    }
+    Expect.equals("s", e);
+  }
+
+  static void test10() {
+    try {
+      throw "up";
+    } on String catch (e) {
+      var e = 1; // ok, shadows exception variable.
+      Expect.equals(1, e);
+    }
+  }
+
+  static void test11() {
+    var e0 = 11;
+    try {
+      throw "up";
+    } on int catch (e0) {
+      Expect.fail("unreachable");
+    } on String catch (e1) {
+      // e0 from the other catch clause is not in scope.
+      Expect.equals(11, e0);
+    }
+  }
+
+  static void test12() {
+    const x = const [];
+    try {
+      throw "up";
+    } catch (e) {
+      Expect.equals("up", e);
+    } on String catch (e) {
+      // Compile-time constants in unreachable catch blocks are still
+      // compiled.
+      const y = x[0];
+      //        ^^^^
+      // [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+      //         ^
+      // [cfe] Constant evaluation error:
+      Expect.fail("unreachable");
+    }
+  }
+
+  static void testMain() {
+    test1();
+    test2();
+    test3();
+    test4();
+    test5();
+    test6();
+    test7();
+    test8();
+    test9();
+    test10();
+    test11();
+    test12();
+  }
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    TryCatchTest.testMain();
+  }
+}
diff --git a/tests/language/exception/try_finally_regress_25333_test.dart b/tests/language/exception/try_finally_regress_25333_test.dart
new file mode 100644
index 0000000..6318f7c
--- /dev/null
+++ b/tests/language/exception/try_finally_regress_25333_test.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.
+
+// Test correct handling of try-catch inside try-finally.
+
+import "package:expect/expect.dart";
+
+void main() {
+  print("== test1 ==");
+  bool caught = false;
+  try {
+    test1();
+    print("Unexpected 1"); // should never go here
+    Expect.isTrue(false);
+  } catch (e) {
+    caught = true;
+    print("main catch 1: $e");
+    Expect.equals(e, "Ball");
+  }
+  Expect.isTrue(caught);
+  print("== test2 ==");
+  caught = false;
+  try {
+    test2();
+    print("Unexpected 2"); // should never go here
+    Expect.isTrue(false);
+  } catch (e) {
+    caught = true;
+    print("main catch 2: $e");
+    Expect.equals(e, "Ball");
+  }
+  Expect.isTrue(caught);
+}
+
+void test1() {
+  try {
+    throw "Ball";
+  } finally {
+    try {
+      throw "Frisbee";
+    } catch (e) {
+      print("test 1 catch: $e");
+      Expect.equals(e, "Frisbee");
+    }
+  }
+}
+
+void test2() {
+  try {
+    throwError(); // call a method that throws an error
+  } finally {
+    try {
+      throw "Frisbee";
+    } catch (e) {
+      print("test 2 catch: $e");
+      Expect.equals(e, "Frisbee");
+    }
+  }
+}
+
+void throwError() {
+  throw "Ball";
+}
diff --git a/tests/language/exception/try_finally_regress_25654_test.dart b/tests/language/exception/try_finally_regress_25654_test.dart
new file mode 100644
index 0000000..32a236f
--- /dev/null
+++ b/tests/language/exception/try_finally_regress_25654_test.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.
+
+// Test break out of try-finally.
+
+import "package:expect/expect.dart";
+
+var count = 0;
+
+test() {
+  L:
+  while (true) {
+    try {
+      break L;
+    } finally {
+      count++;
+    }
+  }
+  throw "ex";
+}
+
+main() {
+  bool caught = false;
+  try {
+    test();
+  } catch (e) {
+    caught = true;
+    Expect.equals(e, "ex");
+  }
+  Expect.isTrue(caught);
+  Expect.equals(1, count);
+}
diff --git a/tests/language/export/ambiguous_main_a.dart b/tests/language/export/ambiguous_main_a.dart
new file mode 100644
index 0000000..4a7b820
--- /dev/null
+++ b/tests/language/export/ambiguous_main_a.dart
@@ -0,0 +1,9 @@
+// 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 export_ambiguous_main_a;
+
+main() {
+  print('export_ambiguous_main_a');
+}
diff --git a/tests/language/export/ambiguous_main_b.dart b/tests/language/export/ambiguous_main_b.dart
new file mode 100644
index 0000000..734a620
--- /dev/null
+++ b/tests/language/export/ambiguous_main_b.dart
@@ -0,0 +1,9 @@
+// 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 export_ambiguous_main_b;
+
+main() {
+  print('export_ambiguous_main_b');
+}
diff --git a/tests/language/export/ambiguous_main_test.dart b/tests/language/export/ambiguous_main_test.dart
new file mode 100644
index 0000000..b2a8a24
--- /dev/null
+++ b/tests/language/export/ambiguous_main_test.dart
@@ -0,0 +1,6 @@
+// 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.
+
+export 'ambiguous_main_a.dart';
+export 'ambiguous_main_b.dart'; /*@compile-error=unspecified*/
diff --git a/tests/language/export/cyclic_helper1.dart b/tests/language/export/cyclic_helper1.dart
new file mode 100644
index 0000000..7e42191
--- /dev/null
+++ b/tests/language/export/cyclic_helper1.dart
@@ -0,0 +1,15 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library export_cyclic_helper1;
+
+import 'cyclic_helper2.dart';
+export 'cyclic_helper2.dart';
+
+class B {
+  A? a;
+  B? b;
+  C? c;
+  D? d;
+}
diff --git a/tests/language/export/cyclic_helper2.dart b/tests/language/export/cyclic_helper2.dart
new file mode 100644
index 0000000..d18256c
--- /dev/null
+++ b/tests/language/export/cyclic_helper2.dart
@@ -0,0 +1,17 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library export_cyclic_helper2;
+
+import 'cyclic_test.dart';
+import 'cyclic_helper3.dart';
+export 'cyclic_test.dart';
+export 'cyclic_helper3.dart';
+
+class C {
+  A? a;
+  B? b;
+  C? c;
+  D? d;
+}
diff --git a/tests/language/export/cyclic_helper3.dart b/tests/language/export/cyclic_helper3.dart
new file mode 100644
index 0000000..17b9ff9
--- /dev/null
+++ b/tests/language/export/cyclic_helper3.dart
@@ -0,0 +1,7 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library export_cyclic_helper3;
+
+class D {}
diff --git a/tests/language/export/cyclic_test.dart b/tests/language/export/cyclic_test.dart
new file mode 100644
index 0000000..d854a39
--- /dev/null
+++ b/tests/language/export/cyclic_test.dart
@@ -0,0 +1,26 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test cyclic export and re-export.
+
+/**
+ * export_cyclic_test re-exports export_cyclic_helper1 which declares B
+ * export_cyclic_helper1 re-exports export_cyclic_helper2 which declares C
+ * export_cyclic_helper2 re-exports export_cyclic_test which declares A
+ * export_cyclic_helper2 re-exports export_cyclic_helper3 which declares D
+ */
+
+library export_cyclic_test;
+
+import 'cyclic_helper1.dart';
+export 'cyclic_helper1.dart';
+
+class A {}
+
+void main() {
+  print(new A());
+  print(new B());
+  print(new C());
+  print(new D());
+}
diff --git a/tests/language/export/double_same_main_test.dart b/tests/language/export/double_same_main_test.dart
new file mode 100644
index 0000000..8923855
--- /dev/null
+++ b/tests/language/export/double_same_main_test.dart
@@ -0,0 +1,6 @@
+// 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.
+
+export 'top_level_entry_test.dart';
+export 'main_test.dart' show main;
diff --git a/tests/language/export/duplicate_collision_test.dart b/tests/language/export/duplicate_collision_test.dart
new file mode 100644
index 0000000..5948d9b
--- /dev/null
+++ b/tests/language/export/duplicate_collision_test.dart
@@ -0,0 +1,7 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'duplicate_import_libd.dart'; //# 01: compile-time error
+
+void main() {}
diff --git a/tests/language/export/duplicate_export_test.dart b/tests/language/export/duplicate_export_test.dart
new file mode 100644
index 0000000..75f8a82
--- /dev/null
+++ b/tests/language/export/duplicate_export_test.dart
@@ -0,0 +1,13 @@
+// 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.
+
+// Test that it is not a compile-time error to reexport the same elements
+// through different paths.
+
+library duplicate_export_test;
+
+export 'duplicate_import_liba.dart';
+export 'duplicate_liba.dart'; // reexports 'duplicate_import_liba.dart'.
+
+void main() {}
diff --git a/tests/language/export/duplicate_import_liba.dart b/tests/language/export/duplicate_import_liba.dart
new file mode 100644
index 0000000..b8af1a7
--- /dev/null
+++ b/tests/language/export/duplicate_import_liba.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library liba;
+
+var field;
+
+void method() {}
+
+class Class {}
+
+void methodOrClass() {}
diff --git a/tests/language/export/duplicate_import_libb.dart b/tests/language/export/duplicate_import_libb.dart
new file mode 100644
index 0000000..456147f
--- /dev/null
+++ b/tests/language/export/duplicate_import_libb.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library libb;
+
+var field;
+
+void method() {}
+
+class Class {}
+
+class methodOrClass {}
diff --git a/tests/language/export/duplicate_import_libc.dart b/tests/language/export/duplicate_import_libc.dart
new file mode 100644
index 0000000..d1f1b41
--- /dev/null
+++ b/tests/language/export/duplicate_import_libc.dart
@@ -0,0 +1,11 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library libc;
+
+var field;
+
+void method() {}
+
+class Class {}
diff --git a/tests/language/export/duplicate_import_libd.dart b/tests/language/export/duplicate_import_libd.dart
new file mode 100644
index 0000000..14f1ff4
--- /dev/null
+++ b/tests/language/export/duplicate_import_libd.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library libd;
+
+import 'duplicate_import_liba.dart';
+import 'duplicate_import_libb.dart';
+import 'duplicate_import_libc.dart';
+
+export '../duplicate_import_liba.dart';
+export 'duplicate_import_libb.dart';
+export 'duplicate_import_libc.dart';
diff --git a/tests/language/export/duplicate_liba.dart b/tests/language/export/duplicate_liba.dart
new file mode 100644
index 0000000..7b68d42
--- /dev/null
+++ b/tests/language/export/duplicate_liba.dart
@@ -0,0 +1,7 @@
+// 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 export_liba;
+
+export 'duplicate_import_liba.dart';
diff --git a/tests/language/export/export_test.dart b/tests/language/export/export_test.dart
new file mode 100644
index 0000000..e1faa61
--- /dev/null
+++ b/tests/language/export/export_test.dart
@@ -0,0 +1,17 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test export and re-export.
+
+library export_test;
+
+import 'helper1.dart';
+import 'helper3.dart' as lib;
+
+void main() {
+  print(new Exported());
+  print(new ReExported());
+  print(new lib.Exported());
+  print(new lib.ReExported());
+}
diff --git a/tests/language/export/helper1.dart b/tests/language/export/helper1.dart
new file mode 100644
index 0000000..5b670f4
--- /dev/null
+++ b/tests/language/export/helper1.dart
@@ -0,0 +1,10 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library export_helper1;
+
+import 'helper2.dart';
+export 'helper2.dart';
+
+class Exported extends ReExported {}
diff --git a/tests/language/export/helper2.dart b/tests/language/export/helper2.dart
new file mode 100644
index 0000000..50dcc3d
--- /dev/null
+++ b/tests/language/export/helper2.dart
@@ -0,0 +1,7 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library export_helper2;
+
+class ReExported {}
diff --git a/tests/language/export/helper3.dart b/tests/language/export/helper3.dart
new file mode 100644
index 0000000..3b3bed9
--- /dev/null
+++ b/tests/language/export/helper3.dart
@@ -0,0 +1,10 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library export_helper3;
+
+import 'helper4.dart';
+export 'helper4.dart';
+
+class Exported extends ReExported {}
diff --git a/tests/language/export/helper4.dart b/tests/language/export/helper4.dart
new file mode 100644
index 0000000..3ca68ec
--- /dev/null
+++ b/tests/language/export/helper4.dart
@@ -0,0 +1,7 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library export_helper4;
+
+class ReExported {}
diff --git a/tests/language/export/local_a.dart b/tests/language/export/local_a.dart
new file mode 100644
index 0000000..dd6d039
--- /dev/null
+++ b/tests/language/export/local_a.dart
@@ -0,0 +1,11 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library local_export_a;
+
+export 'local_a_export.dart';
+
+class A {
+  method() => 42;
+}
diff --git a/tests/language/export/local_a_export.dart b/tests/language/export/local_a_export.dart
new file mode 100644
index 0000000..1919d38
--- /dev/null
+++ b/tests/language/export/local_a_export.dart
@@ -0,0 +1,7 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library local_export_a_export;
+
+int A = 0;
diff --git a/tests/language/export/local_export_test.dart b/tests/language/export/local_export_test.dart
new file mode 100644
index 0000000..2ed4659
--- /dev/null
+++ b/tests/language/export/local_export_test.dart
@@ -0,0 +1,12 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library localExportTest;
+
+import "package:expect/expect.dart";
+import 'local_a.dart';
+
+void main() {
+  Expect.equals(42, new A().method());
+}
diff --git a/tests/language/export/main_override_test.dart b/tests/language/export/main_override_test.dart
new file mode 100644
index 0000000..6578288
--- /dev/null
+++ b/tests/language/export/main_override_test.dart
@@ -0,0 +1,9 @@
+// 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.
+
+export 'top_level_entry_test.dart';
+
+main() {
+  print('export_main_override');
+}
diff --git a/tests/language/export/main_test.dart b/tests/language/export/main_test.dart
new file mode 100644
index 0000000..1e920a7
--- /dev/null
+++ b/tests/language/export/main_test.dart
@@ -0,0 +1,5 @@
+// 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.
+
+export 'top_level_entry_test.dart';
diff --git a/tests/language/export/not_shadowed_by_prefix_helper.dart b/tests/language/export/not_shadowed_by_prefix_helper.dart
new file mode 100644
index 0000000..d6d44fd
--- /dev/null
+++ b/tests/language/export/not_shadowed_by_prefix_helper.dart
@@ -0,0 +1,6 @@
+// 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.
+
+export "not_shadowed_by_prefix_helper2.dart";
+import "dart:core" as f;
diff --git a/tests/language/export/not_shadowed_by_prefix_helper2.dart b/tests/language/export/not_shadowed_by_prefix_helper2.dart
new file mode 100644
index 0000000..ae2dca5
--- /dev/null
+++ b/tests/language/export/not_shadowed_by_prefix_helper2.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.
+
+void f() {
+  f_called = true;
+}
+
+bool f_called = false;
diff --git a/tests/language/export/not_shadowed_by_prefix_test.dart b/tests/language/export/not_shadowed_by_prefix_test.dart
new file mode 100644
index 0000000..6cebd57
--- /dev/null
+++ b/tests/language/export/not_shadowed_by_prefix_test.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.
+
+// Verify that import prefixes within an imported library don't shadow
+// names re-exported by that library.
+
+import "package:expect/expect.dart";
+import "not_shadowed_by_prefix_helper.dart";
+
+main() {
+  f();
+  Expect.isTrue(f_called);
+}
diff --git a/tests/language/export/order_helper1.dart b/tests/language/export/order_helper1.dart
new file mode 100644
index 0000000..68dd448
--- /dev/null
+++ b/tests/language/export/order_helper1.dart
@@ -0,0 +1,6 @@
+// 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.
+
+export 'order_test.dart';
+export 'order_helper2.dart' show z;
diff --git a/tests/language/export/order_helper2.dart b/tests/language/export/order_helper2.dart
new file mode 100644
index 0000000..7effbfb
--- /dev/null
+++ b/tests/language/export/order_helper2.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.
+
+import 'order_helper1.dart';
+
+class Info {
+  int x = y;
+}
+
+int get z => 38;
diff --git a/tests/language/export/order_test.dart b/tests/language/export/order_test.dart
new file mode 100644
index 0000000..94cb915
--- /dev/null
+++ b/tests/language/export/order_test.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.
+
+import 'package:expect/expect.dart';
+import 'order_helper1.dart' as bar;
+import 'order_helper2.dart';
+
+final y = 38;
+final info = new Info();
+
+void main() {
+  Expect.equals(38, info.x);
+  Expect.equals(38, bar.y);
+  Expect.equals(38, bar.z);
+}
diff --git a/tests/language/export/private_runtime_test.dart b/tests/language/export/private_runtime_test.dart
new file mode 100644
index 0000000..e78b2b1
--- /dev/null
+++ b/tests/language/export/private_runtime_test.dart
@@ -0,0 +1,13 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+// Check that private dart:_ libraries cannot be imported.
+
+
+
+main() {
+  print("Done.");
+}
diff --git a/tests/language/export/private_test.dart b/tests/language/export/private_test.dart
new file mode 100644
index 0000000..d152f32
--- /dev/null
+++ b/tests/language/export/private_test.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.
+// Check that private dart:_ libraries cannot be imported.
+
+export "dart:_internal";
+// [error line 6, column 1, length 24]
+// [analyzer] COMPILE_TIME_ERROR.EXPORT_INTERNAL_LIBRARY
+// [cfe] Can't access platform private library.
+
+main() {
+  print("Done.");
+}
diff --git a/tests/language/export/reexport_core_helper.dart b/tests/language/export/reexport_core_helper.dart
new file mode 100644
index 0000000..86c81bf5
--- /dev/null
+++ b/tests/language/export/reexport_core_helper.dart
@@ -0,0 +1,7 @@
+// 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 reexport_core_helper;
+
+export 'dart:core';
diff --git a/tests/language/export/reexport_core_test.dart b/tests/language/export/reexport_core_test.dart
new file mode 100644
index 0000000..e4a17dd
--- /dev/null
+++ b/tests/language/export/reexport_core_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests that exports are handled for libraries loaded prior to the entry point
+// library.
+//
+// This test uses the fact that dart2js loads dart:core before the
+// reexport_core_helper and reexport_core_test libraries and the exports of
+// dart:core is therefore computed before the exports of reexport_core_helper.
+
+library reexport_core_test;
+
+import "package:expect/expect.dart";
+import 'reexport_core_helper.dart' as core;
+
+void main() {
+  var o = new Object();
+  Expect.isTrue(o is core.Object);
+}
diff --git a/tests/language/export/top_level_entry.dart b/tests/language/export/top_level_entry.dart
new file mode 100644
index 0000000..4399b58
--- /dev/null
+++ b/tests/language/export/top_level_entry.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 top_level_entry_test.dart;
+
+main() {}
diff --git a/tests/language/export/top_level_entry_test.dart b/tests/language/export/top_level_entry_test.dart
new file mode 100644
index 0000000..5f8c178
--- /dev/null
+++ b/tests/language/export/top_level_entry_test.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 top_level_entry_test.dart;
+
+part 'top_level_entry.dart';
diff --git a/tests/language/factory/and_instance_variable_runtime_test.dart b/tests/language/factory/and_instance_variable_runtime_test.dart
new file mode 100644
index 0000000..f250fb8
--- /dev/null
+++ b/tests/language/factory/and_instance_variable_runtime_test.dart
@@ -0,0 +1,41 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.md file.
+
+abstract class A {
+  var bar;
+  factory A.bar() = B.bar;
+
+  get foo => bar;
+
+}
+
+class B implements A {
+  var bar;
+  factory B.bar() => new C.bar();
+
+  get foo => bar;
+
+
+  B() {}
+}
+
+class C extends B {
+  C.bar() {
+    bar = "foo";
+  }
+
+
+}
+
+main() {
+  assert(new A.bar().foo == "foo");
+  assert(new B.bar().foo == "foo");
+  assert(new C.bar().foo == "foo");
+  assert(new A.bar().bar == "foo");
+  assert(new B.bar().bar == "foo");
+  assert(new C.bar().bar == "foo");
+}
diff --git a/tests/language/factory/and_instance_variable_test.dart b/tests/language/factory/and_instance_variable_test.dart
new file mode 100644
index 0000000..b35c290
--- /dev/null
+++ b/tests/language/factory/and_instance_variable_test.dart
@@ -0,0 +1,47 @@
+// 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.md file.
+
+abstract class A {
+  var bar;
+  factory A.bar() = B.bar;
+
+  get foo => bar;
+  static get baz => bar;
+  //                ^^^
+  // [analyzer] COMPILE_TIME_ERROR.INSTANCE_MEMBER_ACCESS_FROM_STATIC
+  // [cfe] Getter not found: 'bar'.
+}
+
+class B implements A {
+  var bar;
+  factory B.bar() => new C.bar();
+
+  get foo => bar;
+  static get baz => bar;
+  //                ^^^
+  // [analyzer] COMPILE_TIME_ERROR.INSTANCE_MEMBER_ACCESS_FROM_STATIC
+  // [cfe] Getter not found: 'bar'.
+
+  B() {}
+}
+
+class C extends B {
+  C.bar() {
+    bar = "foo";
+  }
+
+  static get baz => bar;
+  //                ^^^
+  // [analyzer] COMPILE_TIME_ERROR.INSTANCE_MEMBER_ACCESS_FROM_STATIC
+  // [cfe] Getter not found: 'bar'.
+}
+
+main() {
+  assert(new A.bar().foo == "foo");
+  assert(new B.bar().foo == "foo");
+  assert(new C.bar().foo == "foo");
+  assert(new A.bar().bar == "foo");
+  assert(new B.bar().bar == "foo");
+  assert(new C.bar().bar == "foo");
+}
diff --git a/tests/language/factory/arrow_test.dart b/tests/language/factory/arrow_test.dart
new file mode 100644
index 0000000..d2cf528
--- /dev/null
+++ b/tests/language/factory/arrow_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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.foo() {}
+  factory A() => new A.foo();
+}
+
+main() {
+  Expect.isTrue(new A() is A);
+}
diff --git a/tests/language/factory/factory1_test.dart b/tests/language/factory/factory1_test.dart
new file mode 100644
index 0000000..d29187b
--- /dev/null
+++ b/tests/language/factory/factory1_test.dart
@@ -0,0 +1,27 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing factory generic result types.
+
+class A<T> {
+  A() {}
+  factory A.factory() {
+    return new A<String>(); // //# 00: compile-time error
+    return A<T>();
+  }
+}
+
+class B<T> extends A<T> {
+  B() {}
+  factory B.factory() {
+    return new B<String>(); // //# 01: compile-time error
+    return B<T>();
+  }
+}
+
+main() {
+  new A<String>.factory();
+  new A<int>.factory(); // //# 00: dynamic type error
+  new B<String>.factory();
+  new B<int>.factory(); // //# 01: dynamic type error
+}
diff --git a/tests/language/factory/factory2_test.dart b/tests/language/factory/factory2_test.dart
new file mode 100644
index 0000000..f8a2e3a
--- /dev/null
+++ b/tests/language/factory/factory2_test.dart
@@ -0,0 +1,67 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test compile time error for factories with parameterized types.
+
+import "dart:collection";
+
+abstract class A<T> {
+  factory A.create() = AFactory<T>.create; // //# 01: compile-time error
+}
+
+class AFactory {
+  //   Compile time error: should be AFactory<T> to match abstract class above
+  factory A.create() { // //# 01: compile-time error
+    return null;// //# 01: continued
+  } // //# 01: continued
+}
+
+abstract class Link<T> extends IterableBase<T> {
+  // does not match constructor for LinkFactory
+  factory Link(T head, [Link<T> tail]) = LinkFactory<T>; //# 03: compile-time error
+  Link<T> prepend(T element);
+}
+
+abstract class EmptyLink<T> extends Link<T> {
+  const factory EmptyLink() = LinkTail<T>;
+}
+
+class LinkFactory<T> {
+  factory LinkFactory(head, [Link tail]) {}
+}
+
+// Does not implement all of Iterable
+class AbstractLink<T> implements Link<T> { /*@compile-error=unspecified*/
+  const AbstractLink();
+  Link<T> prepend(T element) {
+    return new Link<T>(element, this);
+  }
+}
+
+// Does not implement all of Iterable
+class LinkTail<T> extends AbstractLink<T> implements EmptyLink<T> { /*@compile-error=unspecified*/
+  const LinkTail();
+}
+
+// Does not implement all of Iterable
+class LinkEntry<T> extends AbstractLink<T> { /*@compile-error=unspecified*/
+  LinkEntry(T head, Link<T> realTail);
+}
+
+class Fisk {
+  // instantiation of abstract class
+  Link<String> nodes = const EmptyLink(); /*@compile-error=unspecified*/
+}
+
+main() {
+  // Equivalent to new Link<dynamic>.create().
+  var a = new A.create(); // //# none: compile-time error
+  var a = new A.create(); // //# 01: continued
+
+  new Fisk();
+  // instantiation of abstract class
+  new EmptyLink<String>().prepend('hest'); //# compile-time error
+  // instantiation of abstract class
+  const EmptyLink<String>().prepend('fisk'); //# compile-time error
+}
diff --git a/tests/language/factory/factory3_test.dart b/tests/language/factory/factory3_test.dart
new file mode 100644
index 0000000..fe15ad9
--- /dev/null
+++ b/tests/language/factory/factory3_test.dart
@@ -0,0 +1,62 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:collection";
+
+// Test compile time error for factories with parameterized types.
+
+abstract class A<T> {
+  A();
+  A.create();
+}
+
+abstract class B<T> extends A<T>{}
+
+// Compile time error: should be AFactory<T> to match abstract class above
+class AFactory extends B<int> {
+  factory A.create() { // //# 01: compile-time error
+    return null; // //# 01: continued
+  } // //# 01: continued
+}
+
+abstract class Link<T> extends IterableBase<T> {
+  factory Link(T head, [Link<T> tail]) = LinkEntry<T>;
+  Link<T> prepend(T element);
+}
+
+abstract class EmptyLink<T> extends Link<T> {
+  const factory EmptyLink() = LinkTail<T>;
+}
+
+class AbstractLink<T> implements Link<T> { /*@compile-error=unspecified*/
+  const AbstractLink();
+  Link<T> prepend(T element) {
+    print("$element");
+    if (0 is T) {
+      throw "0 is not a T";
+    }
+    return new Link<T>(element, this);
+  }
+}
+
+class LinkTail<T> extends AbstractLink<T> implements EmptyLink<T> { /*@compile-error=unspecified*/
+  const LinkTail();
+}
+
+class LinkEntry<T> extends AbstractLink<T> { /*@compile-error=unspecified*/
+  LinkEntry(T head, [Link<T> Tail]);
+}
+
+class Fisk {
+  Link<Fisk> nodes = const EmptyLink<Fisk>();
+  final int id;
+  Fisk(this.id);
+  toString() => id.toString();
+}
+
+main() {
+  var a = new AFactory.create(); // //# 01: continued
+  var a = new AFactory.create(); // //# none: compile-time error
+  new Fisk(0).nodes.prepend(new Fisk(1)).prepend(new Fisk(2));
+}
diff --git a/tests/language/factory/factory4_runtime_test.dart b/tests/language/factory/factory4_runtime_test.dart
new file mode 100644
index 0000000..931127b
--- /dev/null
+++ b/tests/language/factory/factory4_runtime_test.dart
@@ -0,0 +1,24 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Link<T> {
+
+}
+
+class A<T> {}
+
+class LinkFactory<T> extends A<T> {
+  factory LinkFactory.create() {
+    return LinkFactory._();
+  }
+
+  LinkFactory._();
+}
+
+main() {
+
+}
diff --git a/tests/language/factory/factory4_test.dart b/tests/language/factory/factory4_test.dart
new file mode 100644
index 0000000..8aeb051
--- /dev/null
+++ b/tests/language/factory/factory4_test.dart
@@ -0,0 +1,24 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Link<T> {
+  factory Link.create() = LinkFactory.create;
+  //                      ^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.REDIRECT_TO_INVALID_RETURN_TYPE
+  // [cfe] The constructor function type 'LinkFactory<dynamic> Function()' isn't a subtype of 'Link<T> Function()'.
+}
+
+class A<T> {}
+
+class LinkFactory<T> extends A<T> {
+  factory LinkFactory.create() {
+    return LinkFactory._();
+  }
+
+  LinkFactory._();
+}
+
+main() {
+  new Link<int>.create();
+}
diff --git a/tests/language/factory/factory5_runtime_test.dart b/tests/language/factory/factory5_runtime_test.dart
new file mode 100644
index 0000000..f5205c3
--- /dev/null
+++ b/tests/language/factory/factory5_runtime_test.dart
@@ -0,0 +1,22 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Link<T> {
+
+}
+
+class LinkFactory<T> {
+  factory LinkFactory.create() {
+    return LinkFactory._();
+  }
+
+  LinkFactory._();
+}
+
+main() {
+
+}
diff --git a/tests/language/factory/factory5_test.dart b/tests/language/factory/factory5_test.dart
new file mode 100644
index 0000000..b06af33
--- /dev/null
+++ b/tests/language/factory/factory5_test.dart
@@ -0,0 +1,28 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Link<T> {
+  factory Link.create() = LinkFactory<T>.create;
+  //                      ^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.REDIRECT_TO_INVALID_RETURN_TYPE
+  // [cfe] The constructor function type 'LinkFactory<T> Function()' isn't a subtype of 'Link<T> Function()'.
+}
+
+class LinkFactory<T> {
+  factory LinkFactory.create() {
+    return LinkFactory._();
+  }
+  factory LinkFactory.Foo() = Foo<T>;
+  //                          ^^^
+  // [analyzer] COMPILE_TIME_ERROR.REDIRECT_TO_NON_CLASS
+  // [cfe] Couldn't find constructor 'Foo'.
+  //                          ^
+  // [cfe] Redirection constructor target not found: 'Foo'
+
+  LinkFactory._();
+}
+
+main() {
+  new Link<int>.create();
+}
diff --git a/tests/language/factory/factory6_runtime_test.dart b/tests/language/factory/factory6_runtime_test.dart
new file mode 100644
index 0000000..8452028
--- /dev/null
+++ b/tests/language/factory/factory6_runtime_test.dart
@@ -0,0 +1,20 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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';
+
+abstract class Link<T> {
+
+}
+
+class LinkFactory<T> {
+
+}
+
+main() {
+
+}
diff --git a/tests/language/factory/factory6_test.dart b/tests/language/factory/factory6_test.dart
new file mode 100644
index 0000000..7e36cb9
--- /dev/null
+++ b/tests/language/factory/factory6_test.dart
@@ -0,0 +1,25 @@
+// 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';
+
+abstract class Link<T> {
+  factory Link.Foo() = LinkFactory<T>.Foo;
+  //                   ^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.REDIRECT_TO_INVALID_RETURN_TYPE
+  // [cfe] The constructor function type 'LinkFactory<T> Function()' isn't a subtype of 'Link<T> Function()'.
+}
+
+class LinkFactory<T> {
+  factory LinkFactory.Foo() = Foo<T>;
+  //                          ^^^
+  // [analyzer] COMPILE_TIME_ERROR.REDIRECT_TO_NON_CLASS
+  // [cfe] Couldn't find constructor 'Foo'.
+  //                          ^
+  // [cfe] Redirection constructor target not found: 'Foo'
+}
+
+main() {
+  Expect.throws(() => new Link<int>.Foo());
+}
diff --git a/tests/language/factory/factory_test.dart b/tests/language/factory/factory_test.dart
new file mode 100644
index 0000000..14a5983
--- /dev/null
+++ b/tests/language/factory/factory_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing factories.
+
+import "package:expect/expect.dart";
+
+class A {
+  factory A(n) {
+    return new A.internal(n);
+  }
+  A.internal(n) : n_ = n {}
+  var n_;
+}
+
+class B {
+  factory B.my() {
+    return new B(3);
+  }
+  B(n) : n_ = n {}
+  var n_;
+}
+
+class FactoryTest {
+  static testMain() {
+    new B.my();
+    var b = new B.my();
+    Expect.equals(3, b.n_);
+    var a = new A(5);
+    Expect.equals(5, a.n_);
+  }
+}
+
+// Test compile time error for factories with parameterized types.
+
+abstract class Link<T> {
+  factory Link.create() = LinkFactory<T>.create;
+  //                      ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS
+  // [cfe] Expected 0 type arguments.
+  //                      ^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.REDIRECT_TO_INVALID_RETURN_TYPE
+}
+
+class LinkFactory {
+  //   Compile time error: should be LinkFactory<T> to match abstract class above
+  factory Link.create() {
+  //      ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_FACTORY_NAME_NOT_A_CLASS
+  // [cfe] The name of a constructor must match the name of the enclosing class.
+    return LinkFactory._();
+  }
+
+  LinkFactory._();
+}
+
+
+main() {
+  FactoryTest.testMain();
+  var a = new Link<int>.create();
+  //          ^
+  // [cfe] Expected 0 type arguments.
+}
diff --git a/tests/language/factory/implementation_test.dart b/tests/language/factory/implementation_test.dart
new file mode 100644
index 0000000..7492df8
--- /dev/null
+++ b/tests/language/factory/implementation_test.dart
@@ -0,0 +1,37 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class A {
+  factory A(int x, int y) = B;
+}
+
+class B implements A {
+  final int x;
+  final int y;
+
+  B(this.x, this.y);
+
+  // This factory should never be invoked.
+  factory B.A(int a, int b) {
+    return new B(0, 0);
+  }
+
+  factory B.X(int a, int b) {
+    return new B(a * 10, b * 10);
+  }
+}
+
+main() {
+  var a = new B(1, 2);
+  // Check that constructor B is invoked and not factory B.A.
+  Expect.equals(1, a.x);
+  Expect.equals(2, a.y);
+
+  var x = new B.X(11, 22);
+  // Check that factory is invoked.
+  Expect.equals(110, x.x);
+  Expect.equals(220, x.y);
+}
diff --git a/tests/language/factory/redirection2_runtime_test.dart b/tests/language/factory/redirection2_runtime_test.dart
new file mode 100644
index 0000000..2592b7e
--- /dev/null
+++ b/tests/language/factory/redirection2_runtime_test.dart
@@ -0,0 +1,28 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that it is a compile-time error to have a redirection in a
+// non-factory constructor.
+
+class Foo {
+  Foo()
+
+  ;
+}
+
+class Bar extends Foo {
+  factory Bar() => Bar._();
+
+  Bar._();
+}
+
+main() {
+  Expect.isTrue(new Foo() is Foo);
+  Expect.isFalse(new Foo() is Bar);
+}
diff --git a/tests/language/factory/redirection2_test.dart b/tests/language/factory/redirection2_test.dart
new file mode 100644
index 0000000..275d766
--- /dev/null
+++ b/tests/language/factory/redirection2_test.dart
@@ -0,0 +1,32 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that it is a compile-time error to have a redirection in a
+// non-factory constructor.
+
+class Foo {
+  Foo()
+  = Bar
+//^
+// [analyzer] SYNTACTIC_ERROR.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR
+// [cfe] Expected a function body or '=>'.
+//^
+// [cfe] Only factory constructor can specify '=' redirection.
+//  ^
+// [cfe] Constructors can't have a return type.
+  ;
+}
+
+class Bar extends Foo {
+  factory Bar() => Bar._();
+
+  Bar._();
+}
+
+main() {
+  Expect.isTrue(new Foo() is Foo);
+  Expect.isFalse(new Foo() is Bar);
+}
diff --git a/tests/language/factory/redirection3_cyclic_runtime_test.dart b/tests/language/factory/redirection3_cyclic_runtime_test.dart
new file mode 100644
index 0000000..ecbccc2
--- /dev/null
+++ b/tests/language/factory/redirection3_cyclic_runtime_test.dart
@@ -0,0 +1,28 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+// Test that a cycle in redirecting factories leads to a compile-time error.
+
+class A {
+  factory A.foo() = B;
+}
+
+class B implements A {
+  factory B() = C.bar;
+}
+
+class C implements B {
+  factory C.bar() = C.foo;
+  factory C.foo() = C
+
+  ;
+  C();
+}
+
+main() {
+  new A.foo();
+}
diff --git a/tests/language/factory/redirection3_cyclic_test.dart b/tests/language/factory/redirection3_cyclic_test.dart
new file mode 100644
index 0000000..ed352be
--- /dev/null
+++ b/tests/language/factory/redirection3_cyclic_test.dart
@@ -0,0 +1,37 @@
+// 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.
+
+// Test that a cycle in redirecting factories leads to a compile-time error.
+
+class A {
+  factory A.foo() = B;
+  //      ^
+  // [cfe] Cyclic definition of factory 'A.foo'.
+}
+
+class B implements A {
+  factory B() = C.bar;
+}
+
+class C implements B {
+  factory C.bar() = C.foo;
+  //                ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+  factory C.foo() = C.bar();
+  //                ^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+  //                  ^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Expected ';' after this.
+  //                     ^
+  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+  // [cfe] Expected an identifier, but got '('.
+  //                     ^^^
+  // [analyzer] STATIC_WARNING.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER
+  C();
+}
+
+main() {
+  new A.foo();
+}
diff --git a/tests/language/factory/redirection_test.dart b/tests/language/factory/redirection_test.dart
new file mode 100644
index 0000000..bddc5368
--- /dev/null
+++ b/tests/language/factory/redirection_test.dart
@@ -0,0 +1,77 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  A() : x = null;
+
+  const A.constant(this.x);
+
+  factory A.factory() {
+    return new B<Set>();
+  }
+
+  factory A.test01() = T; // //# 01: compile-time error
+
+  factory A.test02() = dynamic; // //# 02: compile-time error
+
+  factory A.test03() = Undefined; // //# 03: compile-time error
+
+  factory A.test04() = C.test04; // //# 04: compile-time error
+
+  final T x;
+}
+
+class B<T> extends A<T> {
+  B();
+
+  factory B.A() = A<T>;
+
+  const factory B.A_constant(T x) = A<T>.constant;
+
+  factory B.A_factory() = A<T>.factory;
+
+  factory B.test04() = A.test04; // //# 04: continued
+
+  factory B.test05(int incompatible) = A<T>.factory; // //# 05: compile-time error
+
+  factory B.test05(int incompatible) = A<T>.factory; // //# 06: compile-time error
+}
+
+class C<K, V> extends B<V> {
+  C();
+
+  factory C.A() = A<V>; // //# none: compile-time error
+
+  factory C.A_factory() = A<V>.factory;  // //# none: compile-time error
+
+  const factory C.B_constant(V x) = B<V>.A_constant;
+
+  factory C.test04() = B.test04; // //# 04: continued
+
+  factory C.test06(int incompatible) = B<K>.test05; // //# 06: continued
+
+  const factory C.test07(V x) = B<V>.A; // //# 07: compile-time error
+}
+
+main() {
+  new A<List>.test01(); // //# 01: continued
+  new A<List>.test02(); // //# 02: continued
+  new A<List>.test03(); // //# 03: continued
+  new C.test04(); // //# 04: continued
+  new B.test05(0); // //# 05: continued
+  new C<int, int>.test06(0); // //# 06: continued
+  new C<int, int>.test07(0); // //# 07: continued
+  Expect.isTrue(new A<List>() is A<List>);
+  Expect.isTrue(new A<bool>.constant(true).x);
+  Expect.isTrue(new A<Set>.factory() is B<Set>);
+  Expect.isTrue(new B<List>.A() is A<List>); // //# 08: compile-time error
+  Expect.isFalse(new B<List>.A() is A<Set>); // //# 09: compile-time error
+  Expect.isTrue(new B<bool>.A_constant(true).x); // //# 10: compile-time error
+  Expect.isTrue(new B<List>.A_factory() is B<Set>); // //# 11: compile-time error
+  Expect.isTrue(new C<String, num>.A() is A<num>); // //# 12: compile-time error
+  Expect.isTrue(new C<String, num>.A_factory() is B<Set>); // //# 13: compile-time error
+  Expect.isTrue(new C<String, bool>.B_constant(true).x); // //# 14: compile-time error
+}
diff --git a/tests/language/factory/return_type_checked_runtime_test.dart b/tests/language/factory/return_type_checked_runtime_test.dart
new file mode 100644
index 0000000..3bef4c2
--- /dev/null
+++ b/tests/language/factory/return_type_checked_runtime_test.dart
@@ -0,0 +1,16 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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 "package:expect/expect.dart";
+
+class A {
+
+}
+
+main() {
+
+}
diff --git a/tests/language/factory/return_type_checked_test.dart b/tests/language/factory/return_type_checked_test.dart
new file mode 100644
index 0000000..bff29b4
--- /dev/null
+++ b/tests/language/factory/return_type_checked_test.dart
@@ -0,0 +1,16 @@
+// 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 "package:expect/expect.dart";
+
+class A {
+  factory A() => 42;
+  //             ^^
+  // [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE_FROM_CLOSURE
+  // [cfe] A value of type 'int' can't be assigned to a variable of type 'A'.
+}
+
+main() {
+  Expect.throws(() => new A());
+}
diff --git a/tests/language/factory/runtime_test.dart b/tests/language/factory/runtime_test.dart
new file mode 100644
index 0000000..bac5c66
--- /dev/null
+++ b/tests/language/factory/runtime_test.dart
@@ -0,0 +1,54 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing factories.
+
+import "package:expect/expect.dart";
+
+class A {
+  factory A(n) {
+    return new A.internal(n);
+  }
+  A.internal(n) : n_ = n {}
+  var n_;
+}
+
+class B {
+  factory B.my() {
+    return new B(3);
+  }
+  B(n) : n_ = n {}
+  var n_;
+}
+
+class FactoryTest {
+  static testMain() {
+    new B.my();
+    var b = new B.my();
+    Expect.equals(3, b.n_);
+    var a = new A(5);
+    Expect.equals(5, a.n_);
+  }
+}
+
+// Test compile time error for factories with parameterized types.
+
+
+
+
+
+
+  //   Compile time error: should be LinkFactory<T> to match abstract class above
+
+
+
+
+
+
+main() {
+  FactoryTest.testMain();
+
+}
diff --git a/tests/language/factory/type_parameter2_test.dart b/tests/language/factory/type_parameter2_test.dart
new file mode 100644
index 0000000..6536be8
--- /dev/null
+++ b/tests/language/factory/type_parameter2_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+// Test that type variables are correctly set in instances created by factories.
+
+import 'package:expect/expect.dart';
+
+var p;
+bool done = false;
+
+class D {}
+
+abstract class I<T> {
+  factory I.name() {
+    return new C<T>.name();
+  }
+}
+
+class C<T> implements I<T> {
+  C.name() {
+    Expect.isTrue(p is T);
+    done = true;
+  }
+}
+
+main() {
+  p = new D();
+  new I<D>.name();
+  Expect.equals(true, done);
+}
diff --git a/tests/language/factory/type_parameter_test.dart b/tests/language/factory/type_parameter_test.dart
new file mode 100644
index 0000000..c9e7a0b
--- /dev/null
+++ b/tests/language/factory/type_parameter_test.dart
@@ -0,0 +1,44 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  factory A.factory() {
+    return new B<T>();
+  }
+
+  A();
+
+  build() {
+    return new A<T>();
+  }
+}
+
+class B<T> extends A<T> {
+  B();
+
+  build() {
+    return new B<T>();
+  }
+}
+
+main() {
+  Expect.isTrue(new A<List>() is A<List>);
+  Expect.isTrue(new A<List>.factory() is B<List>);
+
+  // Check that we don't always return true for is checks with
+  // generics.
+  Expect.isFalse(new A<List>() is A<Set>);
+  Expect.isFalse(new A<List>.factory() is B<Set>);
+
+  Expect.isTrue(new A<List>().build() is A<List>);
+  Expect.isFalse(new A<List>().build() is A<Set>);
+
+  Expect.isTrue(new A<List>.factory().build() is B<List>);
+  Expect.isFalse(new A<List>.factory().build() is B<Set>);
+
+  Expect.isTrue(new B<List>().build() is B<List>);
+  Expect.isFalse(new B<List>().build() is B<Set>);
+}
diff --git a/tests/language/factory/with_type_parameters_test.dart b/tests/language/factory/with_type_parameters_test.dart
new file mode 100644
index 0000000..e0c1583
--- /dev/null
+++ b/tests/language/factory/with_type_parameters_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+class Foo<T> {
+  Foo._();
+
+  factory Foo
+             <X> //# 01: syntax error
+             <X extends T> //# 02: syntax error
+             () => new Bar<T>();
+
+  factory Foo
+             <X> //# 03: syntax error
+             <X extends T> //# 04: syntax error
+             .far
+                 <X> //# 05: syntax error
+                 <X extends T> //# 06: syntax error
+                 <X>.fip //# 07: syntax error
+                 <X extends T>.fip //# 08: syntax error
+                 () => new Bar<T>();
+}
+
+class Bar<T> extends Foo<T> {
+  Bar(): super._() {}
+}
+
+main() {
+  new Foo<String>();
+  new Foo<String>.far();
+}
diff --git a/tests/language/field/decl_missing_var_type_runtime_test.dart b/tests/language/field/decl_missing_var_type_runtime_test.dart
new file mode 100644
index 0000000..3d31ad0
--- /dev/null
+++ b/tests/language/field/decl_missing_var_type_runtime_test.dart
@@ -0,0 +1,19 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Exercises issue 2997, missing var or type on field declarations should
+// generate a compile-time error.
+
+class A {
+
+
+}
+
+main() {
+
+}
diff --git a/tests/language/field/decl_missing_var_type_test.dart b/tests/language/field/decl_missing_var_type_test.dart
new file mode 100644
index 0000000..6435dfb
--- /dev/null
+++ b/tests/language/field/decl_missing_var_type_test.dart
@@ -0,0 +1,19 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Exercises issue 2997, missing var or type on field declarations should
+// generate a compile-time error.
+
+class A {
+  _this;
+//^^^^^
+// [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+// [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+  A(x) : this._this = x;
+}
+
+main() {
+  new A(0);
+}
diff --git a/tests/language/field/field1_test.dart b/tests/language/field/field1_test.dart
new file mode 100644
index 0000000..1591ad1
--- /dev/null
+++ b/tests/language/field/field1_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test to catch error reporting bugs in class fields declarations.
+// Should be an error because we have setter/getter functions and fields
+// in the class.
+
+class C {
+  var a;
+
+  get a {/*@compile-error=unspecified*/
+    return 1;
+  }
+
+  set a(int val) {/*@compile-error=unspecified*/
+    var x = val;
+  }
+
+  get b {
+    return 2;
+  }
+
+  set b(int val) {
+    var x = val;
+  }
+}
+
+class Field1Test {
+  static testMain() {
+    var c = new C();
+  }
+}
+
+main() {
+  Field1Test.testMain();
+}
diff --git a/tests/language/field/field2_test.dart b/tests/language/field/field2_test.dart
new file mode 100644
index 0000000..a822357
--- /dev/null
+++ b/tests/language/field/field2_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test to catch error reporting bugs in class fields declarations.
+// Should be an error because we have setter/getter functions and fields
+// in the class.
+
+class C {
+  get a {
+    return 1;
+  }
+
+  set a(int val) {
+    var x = val;
+  }
+
+  get b {
+    return 2;
+  }
+
+  set b(int val) {
+    var x = val;
+  }
+
+  var a;/*@compile-error=unspecified*/
+}
+
+class Field2Test {
+  static testMain() {
+    var c = new C();
+  }
+}
+
+main() {
+  Field2Test.testMain();
+}
diff --git a/tests/language/field/field3_test.dart b/tests/language/field/field3_test.dart
new file mode 100644
index 0000000..901dd06
--- /dev/null
+++ b/tests/language/field/field3_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test to catch error reporting bugs in class fields declarations.
+
+import "package:expect/expect.dart";
+
+class C {
+  // illegal: var cannot follow final
+  final var a = 0;// //# 00: syntax error
+  // illegal: final field declaration, must be initialized
+  final b; // //# 01: compile-time error
+  final c; // //# 02: compile-time error
+  final d; // //# 03: ok
+  final e; // //# 04: ok
+  final f = 0; // //# 05: ok
+
+  C() {} //# 02: continued
+  C(this.d) {} //# 03: continued
+  C(x) : e = x {} //# 04: continued
+}
+
+main() {
+  var val = new C(); //# 00: continued
+  var val = new C(); //# 01: continued
+  var val = new C(); //# 02: continued
+  var val = new C(0); //# 03: continued
+  var val = new C(0); //# 04: continued
+  var val = new C(); //# 05: continued
+}
diff --git a/tests/language/field/field4_test.dart b/tests/language/field/field4_test.dart
new file mode 100644
index 0000000..8c8ef6d
--- /dev/null
+++ b/tests/language/field/field4_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test to catch error reporting bugs in class fields declarations.
+// Should be an error because we have a field overriding a function name.
+
+class A {
+  int a() {
+    return 1;
+  }
+
+  var a;/*@compile-error=unspecified*/
+}
+
+class Field4Test {
+  static testMain() {
+    var a = new A();
+  }
+}
+
+main() {
+  Field4Test.testMain();
+}
diff --git a/tests/language/field/field5_test.dart b/tests/language/field/field5_test.dart
new file mode 100644
index 0000000..943e9bb
--- /dev/null
+++ b/tests/language/field/field5_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test to catch error reporting bugs in class fields declarations.
+// Should be an error because we have a function overriding a field name.
+
+class A {
+  var a;
+  int a() {/*@compile-error=unspecified*/
+    return 1;
+  }
+}
+
+class Field5Test {
+  static testMain() {
+    var a = new A();
+  }
+}
+
+main() {
+  Field5Test.testMain();
+}
diff --git a/tests/language/field/field6_test.dart b/tests/language/field/field6_test.dart
new file mode 100644
index 0000000..fcf0f40
--- /dev/null
+++ b/tests/language/field/field6_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test to catch error reporting bugs in class fields declarations.
+// Should be an error because we have a getter overriding a function name.
+
+class A {
+  int a() { // //# 00: ok
+    return 1;// //# 00: ok
+  }// //# 00: ok
+
+  int get a {// //# 00: compile-time error
+    return 10;// //# 00: ok
+  }// //# 00: ok
+
+  int get a {// //# 01: ok
+    return 10;// //# 01: ok
+  }// //# 01: ok
+
+  int a() {// //# 01: compile-time error
+    return 1;// //# 01: ok
+  }// //# 01: ok
+
+}
+
+class Field6Test {
+  static testMain() {
+    var a = new A();
+  }
+}
+
+main() {
+  Field6Test.testMain();
+}
diff --git a/tests/language/field/field_test.dart b/tests/language/field/field_test.dart
new file mode 100644
index 0000000..b5061ee
--- /dev/null
+++ b/tests/language/field/field_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test program for testing setting/getting of instance fields.
+
+import "package:expect/expect.dart";
+
+class First {
+  First() {}
+  var a;
+  var b;
+
+  addFields() {
+    return a + b;
+  }
+
+  setValues() {
+    a = 24;
+    b = 10;
+    return a + b;
+  }
+}
+
+class Second extends First {
+  var c;
+  get a {
+    return -12;
+  }
+
+  set b(a) {
+    a.c = 12;
+  }
+}
+
+class FieldInitializedToNull {
+  int? x, y;
+
+  static void test() {
+    var f = new FieldInitializedToNull();
+    int? missingArg([int? x = 42]) => x;
+    Expect.isNull(f.x);
+    Expect.isNull(f.y);
+    // Regression tests for a DDC bug, where undefined gets initialized in the
+    // fields, and is incorrect recognized as a missing argument.
+    Expect.isNull(missingArg(f.x));
+    Expect.isNull(missingArg(f.y));
+  }
+}
+
+class FieldTest {
+  static one() {
+    var f = new First();
+    f.a = 3;
+    f.b = f.a;
+    Expect.equals(3, f.a);
+    Expect.equals(f.a, f.b);
+    f.b = (f.a = 10);
+    Expect.equals(10, f.a);
+    Expect.equals(10, f.b);
+    f.b = f.a = 15;
+    Expect.equals(15, f.a);
+    Expect.equals(15, f.b);
+    Expect.equals(30, f.addFields());
+    Expect.equals(34, f.setValues());
+    Expect.equals(24, f.a);
+    Expect.equals(10, f.b);
+  }
+
+  static two() {
+    // The tests below are a little cumbersome because not
+    // everything is implemented yet.
+    var o = new Second();
+    // 'a' getter is overridden, always returns -12.
+    Expect.equals(-12, o.a);
+    o.a = 2;
+    Expect.equals(-12, o.a);
+    // 'b' setter is overridden to write 12 to field 'c'.
+    o.b = o;
+    Expect.equals(12, o.c);
+  }
+}
+
+main() {
+  FieldTest.one();
+  FieldTest.two();
+  FieldInitializedToNull.test();
+}
diff --git a/tests/language/field/increment_bailout_test.dart b/tests/language/field/increment_bailout_test.dart
new file mode 100644
index 0000000..1ee4e5a
--- /dev/null
+++ b/tests/language/field/increment_bailout_test.dart
@@ -0,0 +1,52 @@
+// 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.
+
+// dart2js regression test for issue 8781.
+
+import "package:expect/expect.dart";
+
+class N {
+  var outgoing;
+  var incoming;
+  N(this.outgoing, this.incoming);
+}
+
+class A {
+  int offset = 0;
+  var list;
+  var node;
+
+  A(node)
+      : node = node,
+        list = node.outgoing;
+
+  next() {
+    // dart2js used to update [offset] twice: once in the optimized
+    // version, which would bailout to the non-optimized version
+    // because [list] is not an Array, and once in the non-optimized
+    // version.
+    var edge = list[offset++];
+    if (list == node.outgoing) {
+      list = node.incoming;
+      offset = 0;
+    } else
+      list = null;
+    return edge;
+  }
+}
+
+main() {
+  var o = new A(new N(confuse([1]), confuse([2])));
+
+  for (var i = 1; i <= 2; i++) Expect.equals(i, o.next());
+
+  Expect.equals(null, o.list);
+}
+
+// Use confuse to defeat type inferencing.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) {
+  return x;
+}
diff --git a/tests/language/field/inference_test.dart b/tests/language/field/inference_test.dart
new file mode 100644
index 0000000..7a0132b
--- /dev/null
+++ b/tests/language/field/inference_test.dart
@@ -0,0 +1,52 @@
+// 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.
+
+// Regression test for dart2js and its SsaConstructionFieldTypes
+// phase.
+
+import "package:expect/expect.dart";
+
+class A {
+  var _field;
+  final other;
+  get field => _field;
+  A(this._field) : other = null;
+  A.fromOther(this.other) {
+    _field = other.field;
+  }
+}
+
+class B {
+  var a;
+  B() {
+    try {
+      // Defeat inlining.
+      // An inlined generative constructor call used to confuse
+      // dart2js.
+      a = new A(42);
+    } catch (e) {
+      rethrow;
+    }
+  }
+}
+
+var array = [new A(42), new B()];
+
+main() {
+  // Surround the call to [analyzeAfterB] by two [: new B() :] calls
+  // to ensure the [B] constructor will be analyzed first.
+  new B();
+  var a = analyzeAfterB();
+  new B();
+  Expect.equals(42, a._field);
+}
+
+analyzeAfterB() {
+  try {
+    // Defeat inlining.
+    return new A.fromOther(array[0]);
+  } catch (e) {
+    rethrow;
+  }
+}
diff --git a/tests/language/field/initialization_order_test.dart b/tests/language/field/initialization_order_test.dart
new file mode 100644
index 0000000..832b712
--- /dev/null
+++ b/tests/language/field/initialization_order_test.dart
@@ -0,0 +1,86 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that field initializers are evaluated in the right order.
+
+int counter = 0;
+
+class Mark {
+  static late StringBuffer buffer;
+  Mark(value) {
+    buffer.write('$value.');
+  }
+}
+
+class OneField {
+  var a = new Mark('a');
+
+  OneField();
+
+  OneField.init() : a = new Mark('ai');
+}
+
+class TwoFields {
+  var b = new Mark('b');
+  var a = new Mark('a');
+
+  TwoFields();
+
+  TwoFields.initA() : a = new Mark('ai');
+
+  TwoFields.initB() : b = new Mark('bi');
+
+  TwoFields.initBoth()
+      : a = new Mark('ai'),
+        b = new Mark('bi');
+}
+
+class InheritOneField extends OneField {
+  var b = new Mark('b');
+
+  InheritOneField() : super();
+
+  InheritOneField.init()
+      : b = new Mark('bi'),
+        super();
+
+  InheritOneField.superWithInit() : super.init();
+
+  InheritOneField.initWithSuperInit_correctOrder()
+      : b = new Mark('bi'),
+        super.init();
+
+  InheritOneField.initWithSuperInit_incorrectOrder()
+      :
+        super.init(), //# 01: compile-time error
+        b = new Mark('bi')
+        , super.init() //# none: ok
+  ;
+}
+
+String run(callback) {
+  Mark.buffer = new StringBuffer();
+  callback();
+  return Mark.buffer.toString();
+}
+
+main() {
+  Expect.equals('a.', run(() => new OneField()));
+  Expect.equals('a.ai.', run(() => new OneField.init()));
+
+  Expect.equals('b.a.', run(() => new TwoFields()));
+  Expect.equals('b.a.ai.', run(() => new TwoFields.initA()));
+  Expect.equals('b.a.bi.', run(() => new TwoFields.initB()));
+  Expect.equals('b.a.ai.bi.', run(() => new TwoFields.initBoth()));
+
+  Expect.equals('b.a.', run(() => new InheritOneField()));
+  Expect.equals('b.bi.a.', run(() => new InheritOneField.init()));
+  Expect.equals('b.a.ai.', run(() => new InheritOneField.superWithInit()));
+  Expect.equals(
+      'b.bi.a.ai.', run(() => new InheritOneField.initWithSuperInit_correctOrder()));
+  Expect.equals(
+      'b.bi.a.ai.', run(() => new InheritOneField.initWithSuperInit_incorrectOrder()));
+}
diff --git a/tests/language/field/method4_test.dart b/tests/language/field/method4_test.dart
new file mode 100644
index 0000000..c637241
--- /dev/null
+++ b/tests/language/field/method4_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test to catch error reporting bugs when using a field like a method.
+
+class A {
+  var foo;
+  A() {
+    foo = () {};
+  }
+  void bar(var a) {
+    a.foo();/*@compile-error=unspecified*/ // Tries to invoke the non-existing method 'foo'.
+    /*
+    'a.foo()' is a "Regular instance-method invocation". The guide says:
+    "If no method is found, the result of the invocation expression is
+    equivalent to: $0.noSuchMethod(r"id", [$1, ..., $N])."
+    Invoking noSuchMethod on an instance of A will invoke Object's
+    noSuchMethod (because A doesn't override that method). Object's
+    noSuchMethod will throw an error.
+    */
+  }
+}
+
+class FieldMethod4Test {
+  static testMain() {
+    var a = new A();
+    a.bar();/*@compile-error=unspecified*/
+  }
+}
+
+main() {
+  FieldMethod4Test.testMain();
+}
diff --git a/tests/language/field/method_test.dart b/tests/language/field/method_test.dart
new file mode 100644
index 0000000..012b60a
--- /dev/null
+++ b/tests/language/field/method_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 test. Fields can be invoked directly if they are unqualified.
+
+class A {
+  var foo;
+  A() {
+    foo = () {};
+  }
+  void bar() {
+    foo(); // <= foo is a field, but can still be invoked without parenthesis.
+  }
+}
+
+class FieldMethodTest {
+  static testMain() {
+    new A().bar();
+  }
+}
+
+main() {
+  FieldMethodTest.testMain();
+}
diff --git a/tests/language/field/optimization2_test.dart b/tests/language/field/optimization2_test.dart
new file mode 100644
index 0000000..d0ee6bd
--- /dev/null
+++ b/tests/language/field/optimization2_test.dart
@@ -0,0 +1,26 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test program to test type-based optimization on fields.
+
+class A {
+  var x;
+  A() : x = new B();
+  foo() {
+    x++;
+  }
+}
+
+class B {
+  operator +(other) => 498;
+}
+
+main() {
+  var a = new A();
+  a.foo();
+  a.foo();
+  Expect.equals(499, a.x);
+}
diff --git a/tests/language/field/optimization3_test.dart b/tests/language/field/optimization3_test.dart
new file mode 100644
index 0000000..bf2ec9a
--- /dev/null
+++ b/tests/language/field/optimization3_test.dart
@@ -0,0 +1,39 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test program to test type-based optimization on fields.
+
+class A {
+  dynamic a = 0;
+  var b = 0;
+  foo() {
+    var c = b + 27;
+    for (var i = 0; i < 1; i++) {
+      for (var j = 0; j < 1; j++) {
+        Expect.equals(50, c + 23);
+      }
+    }
+    return a > 0.2;
+  }
+
+  setA(value) {
+    a = value;
+  }
+
+  setB(value) {
+    b = value;
+  }
+
+  operator >(other) => other == 0.2;
+}
+
+main() {
+  var a = new A();
+  Expect.isFalse(a.foo());
+  a.setA(new A());
+  a.setB(0);
+  Expect.isTrue(a.foo());
+}
diff --git a/tests/language/field/optimization_test.dart b/tests/language/field/optimization_test.dart
new file mode 100644
index 0000000..58a1461
--- /dev/null
+++ b/tests/language/field/optimization_test.dart
@@ -0,0 +1,37 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test program to test type-based optimization on fields.
+
+class A {
+  var x;
+  A() : x = 0;
+  foo() {
+    x++;
+  }
+
+  toto() {
+    x = 99;
+  }
+
+  bar(y) {
+    x = y;
+  }
+}
+
+class B {
+  operator +(other) => "ok";
+}
+
+main() {
+  var a = new A();
+  a.foo();
+  a.toto();
+  a.bar("str");
+  a.bar(new B());
+  a.foo();
+  Expect.equals("ok", a.x);
+}
diff --git a/tests/language/field/override2_test.dart b/tests/language/field/override2_test.dart
new file mode 100644
index 0000000..d37a8ba
--- /dev/null
+++ b/tests/language/field/override2_test.dart
@@ -0,0 +1,22 @@
+// 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.
+
+// Test that we are accessing the right field in a method of a super
+// class, when that field is overridden.
+
+import "package:expect/expect.dart";
+
+class A {
+  final a = [42]; /*@compile-error=unspecified*/
+  foo() => a[0];
+}
+
+class B extends A {
+  final a = new Map();
+}
+
+main() {
+  Expect.equals(null, new B().foo());
+  Expect.equals(42, new A().foo());
+}
diff --git a/tests/language/field/override3_test.dart b/tests/language/field/override3_test.dart
new file mode 100644
index 0000000..9b100be
--- /dev/null
+++ b/tests/language/field/override3_test.dart
@@ -0,0 +1,23 @@
+// 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.
+
+// Test that we report a compile-time error when a static field conflicts with
+// an inherited instance member of the same name.
+
+import "package:expect/expect.dart";
+
+class A {
+  var foo = 42; // //# 00: compile-time error
+  get foo => 42; // //# 01: compile-time error
+  foo() => 42; // //# 02: compile-time error
+  set foo(value) { } // //# 03: compile-time error
+}
+
+class B extends A {
+  static var foo = 42;
+}
+
+main() {
+  Expect.equals(42, B.foo);
+}
diff --git a/tests/language/field/override4_test.dart b/tests/language/field/override4_test.dart
new file mode 100644
index 0000000..0ccee61
--- /dev/null
+++ b/tests/language/field/override4_test.dart
@@ -0,0 +1,23 @@
+// 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.
+
+// Test that we report a compile-time error when an instance field conflicts
+// with an inherited instance method of the same name.
+
+import "package:expect/expect.dart";
+
+class A {
+  dynamic foo = 42; // //# 00: ok
+  get foo => 42; // //# 01: ok
+  foo() => 42; // //# 02: compile-time error
+  set foo(value) { } // //# 03: ok
+}
+
+class B extends A {
+  dynamic foo = 42;
+}
+
+main() {
+  Expect.equals(42, new B().foo);
+}
diff --git a/tests/language/field/override_optimization_test.dart b/tests/language/field/override_optimization_test.dart
new file mode 100644
index 0000000..83ad81e
--- /dev/null
+++ b/tests/language/field/override_optimization_test.dart
@@ -0,0 +1,34 @@
+// 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:expect/expect.dart";
+import "package:meta/meta.dart";
+
+class A {
+  @virtual
+  final dynamic flag = true;
+  @virtual
+  final dynamic x = 42;
+}
+
+class B extends A {
+  dynamic flag;
+  dynamic x;
+}
+
+void main() {
+  A a = new B();
+  var exception;
+  try {
+    if (a.flag) {
+      Expect.fail('This should be unreachable');
+    } else {
+      Expect.fail('This should also be unreachable');
+    }
+  } catch (e) {
+    exception = e;
+  }
+  Expect.isTrue(exception is AssertionError || exception is TypeError);
+  Expect.throws(() => a.x + 8);
+}
diff --git a/tests/language/field/override_test.dart b/tests/language/field/override_test.dart
new file mode 100644
index 0000000..187773b
--- /dev/null
+++ b/tests/language/field/override_test.dart
@@ -0,0 +1,50 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Test overriding of fields.
+
+import "package:expect/expect.dart";
+
+class A {}
+
+class B1 extends A {}
+
+class B2 extends A {}
+
+class Super {
+  Super() : super();
+
+  B1 field;
+}
+
+class Sub extends Super {
+  Sub() : super();
+
+  // Invalid override. The type of 'Sub.field' ('() → A') isn't a subtype of
+  // 'Super.field' ('() → B1').
+  A field; // //# 00: compile-time error
+}
+
+class SubSub extends Super {
+  SubSub() : super();
+
+  // B2 not assignable to B1
+  B2 field; // //# 01: compile-time error
+}
+
+main() {
+  SubSub val1 = new SubSub();
+  val1.field = new B2(); //# 02: compile-time error
+  Expect.equals(true, val1.field is B2); //# 02: continued
+
+  Sub val2 = new Sub();
+  val2.field = new A(); //# none: compile-time error
+  Expect.equals(true, val2.field is A);
+  Expect.equals(false, val2.field is B1);
+  Expect.equals(false, val2.field is B2);
+
+  Super val3 = new Super();
+  val3.field = new B1();
+  Expect.equals(true, val3.field is B1);
+  Expect.equals(false, val3.field is B2);
+}
diff --git a/tests/language/field/parameter_test.dart b/tests/language/field/parameter_test.dart
new file mode 100644
index 0000000..58d0639
--- /dev/null
+++ b/tests/language/field/parameter_test.dart
@@ -0,0 +1,39 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing setting/getting of instance fields.
+
+import "package:expect/expect.dart";
+
+class A {
+  int? x = 4;
+  A(this.x);
+  A.named([this.x]);
+  A.named2([this.x = 2]);
+  A.named3();
+}
+
+class B extends A {
+  B(x) : super(x + 10);
+  B.named_() : super.named();
+  B.named(x) : super.named(x + 10);
+  B.named2_() : super.named2();
+  B.named2(x) : super.named2(x + 10);
+  B.named3() : super.named3();
+}
+
+main() {
+  Expect.equals(0, new A(0).x);
+  Expect.equals(null, new A.named().x);
+  Expect.equals(1, new A.named(1).x);
+  Expect.equals(2, new A.named2().x);
+  Expect.equals(3, new A.named2(3).x);
+  Expect.equals(4, new A.named3().x);
+
+  Expect.equals(10, new B(0).x);
+  Expect.equals(null, new B.named_().x);
+  Expect.equals(11, new B.named(1).x);
+  Expect.equals(2, new B.named2_().x);
+  Expect.equals(13, new B.named2(3).x);
+  Expect.equals(4, new B.named3().x);
+}
diff --git a/tests/language/field/super_access2_test.dart b/tests/language/field/super_access2_test.dart
new file mode 100644
index 0000000..e1decf8
--- /dev/null
+++ b/tests/language/field/super_access2_test.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.
+
+// Tests that a super call to access a field in a super class is just a normal
+// field access.
+
+import "package:expect/expect.dart";
+
+class A {
+  final int y = 42;
+}
+
+class B extends A {
+  int get x => super.y;
+  void set x(val) {}
+}
+
+void main() {
+  var b = new B();
+  Expect.equals(42, b.x);
+}
diff --git a/tests/language/field/super_access_test.dart b/tests/language/field/super_access_test.dart
new file mode 100644
index 0000000..7f6bf2d
--- /dev/null
+++ b/tests/language/field/super_access_test.dart
@@ -0,0 +1,25 @@
+// 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 a super call to access a field in a super class is just a normal
+// field access.
+
+import "package:expect/expect.dart";
+
+class A {
+  int? y;
+}
+
+class B extends A {
+  int? get x => super.y;
+  void set x(val) {
+    super.y = val;
+  }
+}
+
+void main() {
+  var b = new B();
+  b.x = 42;
+  Expect.equals(42, b.x);
+}
diff --git a/tests/language/field/type_check2_test.dart b/tests/language/field/type_check2_test.dart
new file mode 100644
index 0000000..3cd1f00
--- /dev/null
+++ b/tests/language/field/type_check2_test.dart
@@ -0,0 +1,20 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  A? a;
+
+  bar(c) {
+    c.a = 2; //# 01: runtime error
+  }
+}
+
+class B {
+  int? a;
+}
+
+main() {
+  new A().bar(new A()); //# 01: continued
+  new A().bar(new B());
+}
diff --git a/tests/language/field/type_check_runtime_test.dart b/tests/language/field/type_check_runtime_test.dart
new file mode 100644
index 0000000..367e950
--- /dev/null
+++ b/tests/language/field/type_check_runtime_test.dart
@@ -0,0 +1,14 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int e = -1;
+}
+
+void main() {
+
+}
diff --git a/tests/language/field/type_check_test.dart b/tests/language/field/type_check_test.dart
new file mode 100644
index 0000000..09b5507
--- /dev/null
+++ b/tests/language/field/type_check_test.dart
@@ -0,0 +1,14 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int e = -1;
+}
+
+void main() {
+  new A().e = "String";
+  //          ^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  // [cfe] A value of type 'String' can't be assigned to a variable of type 'int'.
+}
diff --git a/tests/language/field/wierd_name_test.dart b/tests/language/field/wierd_name_test.dart
new file mode 100644
index 0000000..d76eaa8
--- /dev/null
+++ b/tests/language/field/wierd_name_test.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.
+// Dart test program for testing setting/getting of instance fields.
+
+import "package:expect/expect.dart";
+
+// dart2js used to have a bug where a local called '_' in the constructor
+// shadowed the parameter named after a field. This lead to the field being
+// initialized to 'this' (a cycle) rather than the correct initializer value.
+//
+// This test is in the language tests rather than dart2js specific tests since
+// the dart2js specific tests are not run in all configurations that could
+// tickle this issue.
+
+int ii = 0;
+
+class Thing {
+  var _;
+  var $_;
+  // Extra fields to make use of local in constructor beneficial and to exhaust
+  // single-character names.
+  var a = ++ii, b = ++ii, c = ++ii, d = ++ii, e = ++ii;
+  var f = ++ii, g = ++ii, h = ++ii, i = ++ii, j = ++ii;
+  var k = ++ii, l = ++ii, m = ++ii, n = ++ii, o = ++ii;
+  var p = ++ii, q = ++ii, r = ++ii, s = ++ii, t = ++ii;
+  var u = ++ii, v = ++ii, w = ++ii, x = ++ii, y = ++ii;
+  var z = ++ii;
+  var A = ++ii, B = ++ii, C = ++ii, D = ++ii, E = ++ii;
+  var F = ++ii, G = ++ii, H = ++ii, I = ++ii, J = ++ii;
+  var K = ++ii, L = ++ii, M = ++ii, N = ++ii, O = ++ii;
+  var P = ++ii, Q = ++ii, R = ++ii, S = ++ii, T = ++ii;
+  var U = ++ii, V = ++ii, W = ++ii, X = ++ii, Y = ++ii;
+  var Z = ++ii;
+  var $ = ++ii;
+
+  var f30 = ++ii, f31 = ++ii, f32 = ++ii, f33 = ++ii, f34 = ++ii;
+  var f35 = ++ii, f36 = ++ii, f37 = ++ii, f38 = ++ii, f39 = ++ii;
+  var f40 = ++ii, f41 = ++ii, f42 = ++ii, f43 = ++ii, f44 = ++ii;
+  var f45 = ++ii, f46 = ++ii, f47 = ++ii, f48 = ++ii, f49 = ++ii;
+  var f50 = ++ii, f51 = ++ii, f52 = ++ii, f53 = ++ii, f54 = ++ii;
+  var f55 = ++ii, f56 = ++ii, f57 = ++ii, f58 = ++ii, f59 = ++ii;
+
+  @pragma('dart2js:noInline')
+  Thing(this._, this.$_);
+  toString() {
+    if (depth > 0) return 'recursion!';
+    try {
+      ++depth;
+      var sum = a +
+          b +
+          c +
+          d +
+          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 +
+          D +
+          E +
+          F +
+          G +
+          H +
+          I +
+          J +
+          K +
+          L +
+          M +
+          N +
+          O +
+          P +
+          Q +
+          R +
+          S +
+          T +
+          U +
+          V +
+          W +
+          X +
+          Y +
+          Z +
+          $ +
+          f30 +
+          f31 +
+          f32 +
+          f33 +
+          f34 +
+          f35 +
+          f36 +
+          f37 +
+          f38 +
+          f39 +
+          f40 +
+          f41 +
+          f42 +
+          f43 +
+          f44 +
+          f45 +
+          f46 +
+          f47 +
+          f48 +
+          f49 +
+          f50 +
+          f51 +
+          f52 +
+          f53 +
+          f54 +
+          f55 +
+          f56 +
+          f57 +
+          f58 +
+          f59;
+      return 'Thing(${_}, ${$_}, ${sum})';
+    } finally {
+      --depth;
+    }
+  }
+
+  static int depth = 0;
+}
+
+main() {
+  var t1 = new Thing(1, 2);
+  var t2 = new Thing(3, 4);
+  var t3 = [];
+
+  Expect.equals(
+      '[Thing(1, 2, 3486), Thing(3, 4, 10375), []]', '${[t1, t2, t3]}');
+}
diff --git a/tests/language/final/attempt_reinitialization_runtime_test.dart b/tests/language/final/attempt_reinitialization_runtime_test.dart
new file mode 100644
index 0000000..b16a2c7
--- /dev/null
+++ b/tests/language/final/attempt_reinitialization_runtime_test.dart
@@ -0,0 +1,23 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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.
+
+class Foo {
+
+
+}
+
+class CoffeeShop {
+
+
+
+}
+
+void main() {
+
+
+
+}
diff --git a/tests/language/final/attempt_reinitialization_test.dart b/tests/language/final/attempt_reinitialization_test.dart
new file mode 100644
index 0000000..009998b
--- /dev/null
+++ b/tests/language/final/attempt_reinitialization_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+class Foo {
+  Foo(this.x);
+  //       ^
+  // [analyzer] STATIC_WARNING.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR
+  // [cfe] 'x' is a final instance variable that has already been initialized.
+  final int x = 42;
+}
+
+class CoffeeShop {
+  final String shopName = "Coffee Lab";
+  CoffeeShop.name(String shopName)
+      : this.shopName = shopName;
+      //     ^^^^^^^^
+      // [analyzer] STATIC_WARNING.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION
+      //              ^
+      // [cfe] 'shopName' is a final instance variable that has already been initialized.
+}
+
+void main() {
+  Foo f = new Foo(10);
+  CoffeeShop presidentialCoffee =
+      new CoffeeShop.name("Covfefe Lab");
+}
diff --git a/tests/language/final/field_initialization_order_test.dart b/tests/language/final/field_initialization_order_test.dart
new file mode 100644
index 0000000..69f8b11
--- /dev/null
+++ b/tests/language/final/field_initialization_order_test.dart
@@ -0,0 +1,60 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that initializers for final fields are evaluated in the right
+// order.
+
+int counter = 0;
+
+class Mark {
+  static late StringBuffer buffer;
+  Mark(value) {
+    buffer.write('$value.');
+  }
+}
+
+class OneField {
+  final a = new Mark('a');
+  OneField();
+}
+
+class TwoFields {
+  final a = new Mark('a');
+  final b = new Mark('b');
+  TwoFields();
+}
+
+class InheritOneField extends OneField {
+  final b = new Mark('b');
+  InheritOneField();
+}
+
+class MixedFields extends OneField {
+  final b = new Mark('b');
+  var c = new Mark('c');
+  final d = new Mark('d');
+  MixedFields();
+  MixedFields.c0() : c = new Mark('cc');
+  MixedFields.c1()
+      : c = new Mark('cc'),
+        super();
+}
+
+String run(callback) {
+  Mark.buffer = new StringBuffer();
+  callback();
+  return Mark.buffer.toString();
+}
+
+main() {
+  Expect.equals('a.', run(() => new OneField()));
+  Expect.equals('a.b.', run(() => new TwoFields()));
+  Expect.equals('b.a.', run(() => new InheritOneField()));
+
+  Expect.equals('b.c.d.a.', run(() => new MixedFields()));
+  Expect.equals('b.c.d.cc.a.', run(() => new MixedFields.c0()));
+  Expect.equals('b.c.d.cc.a.', run(() => new MixedFields.c1()));
+}
diff --git a/tests/language/final/field_override_test.dart b/tests/language/final/field_override_test.dart
new file mode 100644
index 0000000..5548bdf
--- /dev/null
+++ b/tests/language/final/field_override_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:expect/expect.dart";
+
+class A {
+  int _x = 42;
+  void set x(int val) {
+    _x = val;
+  }
+
+  int get x => _x;
+}
+
+class B extends A {
+  final x = 3;
+  // we can still get to the super property
+  int get y => _x;
+}
+
+void main() {
+  var b = new B();
+  Expect.equals(3, b.x);
+
+  b.x = 21;
+  Expect.equals(3, b.x);
+  Expect.equals(21, b.y);
+}
diff --git a/tests/language/final/for_in_variable_test.dart b/tests/language/final/for_in_variable_test.dart
new file mode 100644
index 0000000..0365e67
--- /dev/null
+++ b/tests/language/final/for_in_variable_test.dart
@@ -0,0 +1,9 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  for (final i in [1, 2, 3]) {
+    i = 4; /*@compile-error=unspecified*/
+  }
+}
diff --git a/tests/language/final/initializer_instance_reference_test.dart b/tests/language/final/initializer_instance_reference_test.dart
new file mode 100644
index 0000000..1f17dfc
--- /dev/null
+++ b/tests/language/final/initializer_instance_reference_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// Dart2js regression test. Error in initializer might be report with the wrong
+// current element.
+
+class C {
+  const C();
+
+  final x = 1;
+  final y = x; /*@compile-error=unspecified*/
+}
+
+main() {
+  const C().y;
+}
diff --git a/tests/language/final/is_not_const_test.dart b/tests/language/final/is_not_const_test.dart
new file mode 100644
index 0000000..798b40f
--- /dev/null
+++ b/tests/language/final/is_not_const_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+final F0 = 42;
+const C0 = F0; /*@compile-error=unspecified*/
+
+main() {
+  Expect.equals(42, F0);
+  Expect.equals(42, C0);
+}
diff --git a/tests/language/final/param_test.dart b/tests/language/final/param_test.dart
new file mode 100644
index 0000000..197e357
--- /dev/null
+++ b/tests/language/final/param_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Disallow assignment of parameters marked as final.
+
+class A {
+  static void test(final x) {
+    x = 2; /*@compile-error=unspecified*/
+  }
+}
+
+main() {
+  A.test(1);
+}
diff --git a/tests/language/final/super_field_set_test.dart b/tests/language/final/super_field_set_test.dart
new file mode 100644
index 0000000..227b272
--- /dev/null
+++ b/tests/language/final/super_field_set_test.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.
+
+class SuperClass {
+  final field = 0;
+  noSuchMethod(_) => 42;
+}
+
+class Class extends SuperClass {
+  m() {
+    super.field = 87; /*@compile-error=unspecified*/
+  }
+}
+
+main() {
+  new Class().m();
+}
diff --git a/tests/language/final/syntax_test.dart b/tests/language/final/syntax_test.dart
new file mode 100644
index 0000000..42b2163
--- /dev/null
+++ b/tests/language/final/syntax_test.dart
@@ -0,0 +1,77 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  final f0 = 42;
+  final f1; //# 01: compile-time error
+  final int f2 = 87;
+  final int f3; //# 02: compile-time error
+  Expect.equals(42, f0);
+  Expect.equals(87, f2);
+
+  Expect.equals(42, F0);
+  Expect.equals(null, F1); //# 03: continued
+  Expect.equals(87, F2);
+  Expect.equals(null, F3); //# 04: continued
+
+  Expect.isTrue(P0 is Point);
+  Expect.isTrue(P1 is int);
+  Expect.isTrue(P2 is Point);
+  Expect.isTrue(P3 is int);
+
+  Expect.isTrue(A0 is int);
+  Expect.isTrue(A1 is int);
+  Expect.isTrue(A2 is int); //# 08: runtime error
+  Expect.isTrue(A3 is int); //# 08: continued
+
+  Expect.isTrue(C0.X is C1);
+  Expect.isTrue(C0.X.x is C1); //# 09: compile-time error
+
+  Expect.equals("Hello 42", B2);
+  Expect.equals("42Hello", B3); //# 10: compile-time error
+}
+
+final F0 = 42;
+final F1; //                //# 03: syntax error
+final int F2 = 87;
+final int F3; //            //# 04: syntax error
+
+class Point {
+  final x, y;
+  const Point(this.x, this.y);
+  operator +(int other) => x;
+}
+
+// Check that compile time expressions can include invocations of
+// user-defined final constructors.
+final P0 = const Point(0, 0);
+final P1 = const Point(0, 0) + 1;
+final P2 = new Point(0, 0);
+final P3 = new Point(0, 0) + 1;
+
+// Check that we cannot have cyclic references in compile time
+// expressions.
+final A0 = 42;
+final A1 = A0 + 1;
+final dynamic A2 = A3 + 1; //# 08: continued
+final dynamic A3 = A2 + 1; //# 08: continued
+
+class C0 {
+  static final X = const C1();
+}
+
+class C1 {
+  const C1()
+      : x = C0.X //# 09: continued
+  ;
+  final x = null;
+}
+
+// Check that sub-expressions of binary + are numeric.
+final B0 = 42;
+final B1 = "Hello";
+final B2 = "$B1 $B0";
+final B3 = B0 + B1; //# 10: continued
diff --git a/tests/language/final/used_in_try_test.dart b/tests/language/final/used_in_try_test.dart
new file mode 100644
index 0000000..259ba8d
--- /dev/null
+++ b/tests/language/final/used_in_try_test.dart
@@ -0,0 +1,17 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  while (true) {
+    final a = 'fff'.substring(1, 2);
+    try {
+      Expect.equals('f', a);
+    } catch (e) {
+      rethrow;
+    }
+    break;
+  }
+}
diff --git a/tests/language/final/variable_assignment_runtime_test.dart b/tests/language/final/variable_assignment_runtime_test.dart
new file mode 100644
index 0000000..1fabb8b
--- /dev/null
+++ b/tests/language/final/variable_assignment_runtime_test.dart
@@ -0,0 +1,16 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test to make sure we catch assignments to final local variables.
+
+main() {
+  final x = 30;
+
+
+
+
+}
diff --git a/tests/language/final/variable_assignment_test.dart b/tests/language/final/variable_assignment_test.dart
new file mode 100644
index 0000000..f001d40
--- /dev/null
+++ b/tests/language/final/variable_assignment_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Test to make sure we catch assignments to final local variables.
+
+main() {
+  final x = 30;
+  x = 0;
+//^
+// [analyzer] STATIC_WARNING.ASSIGNMENT_TO_FINAL_LOCAL
+// [cfe] Can't assign to the final variable 'x'.
+  x += 1;
+//^
+// [analyzer] STATIC_WARNING.ASSIGNMENT_TO_FINAL_LOCAL
+// [cfe] Can't assign to the final variable 'x'.
+  ++x;
+  //^
+  // [analyzer] STATIC_WARNING.ASSIGNMENT_TO_FINAL_LOCAL
+  // [cfe] Can't assign to the final variable 'x'.
+  x++;
+//^
+// [analyzer] STATIC_WARNING.ASSIGNMENT_TO_FINAL_LOCAL
+// [cfe] Can't assign to the final variable 'x'.
+}
diff --git a/tests/language/nnbd/boolean_conversion/boolean_conversion_error_test.dart b/tests/language/nnbd/boolean_conversion/boolean_conversion_error_test.dart
new file mode 100644
index 0000000..50ca7b0
--- /dev/null
+++ b/tests/language/nnbd/boolean_conversion/boolean_conversion_error_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.
+
+void main() {
+  Never never = throw "Unreachable";
+  bool boolean = true;
+  dynamic any = 3;
+  Null nil = null;
+  Object object = Object();
+  Object? objectOrNull = null;
+
+  {
+    // Check that values of type `Never` are usable as booleans.
+    if (never) {}
+    [if (never) 3];
+    never ? 3 : 4;
+    while (never) {}
+    do {} while (never);
+    never || true;
+    never && true;
+    true || never;
+    true && never;
+    for (int i = 0; never; i++) {}
+    [for (int i = 0; never; i++) 3];
+  }
+  {
+    // Check that values of type `boolean` are usable as booleans.
+    if (boolean) {}
+    [if (boolean) 3];
+    boolean ? 3 : 4;
+    while (boolean) {}
+    do {} while (boolean);
+    boolean || true;
+    boolean && true;
+    true || boolean;
+    true && boolean;
+    for (int i = 0; boolean; i++) {}
+    [for (int i = 0; boolean; i++) 3];
+  }
+  {
+    // Check that values of type `dynamic` are usable as booleans.
+    if (any) {}
+    [if (any) 3];
+    any ? 3 : 4;
+    while (any) {}
+    do {} while (any);
+    any || true;
+    any && true;
+    true || any;
+    true && any;
+    for (int i = 0; any; i++) {}
+    [for (int i = 0; any; i++) 3];
+  }
+  {
+    // Check that values of type `Null` are not usable as booleans.
+    if (nil) {}
+    //  ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    [if (nil) 3];
+    //   ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    nil ? 3 : 4;
+//  ^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+// [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    while (nil) {}
+    //     ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    do {} while (nil);
+    //           ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    nil || true;
+//  ^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+// [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    nil && true;
+//  ^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+// [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    true || nil;
+    //      ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    true && nil;
+    //      ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    for (int i = 0; nil; i++) {}
+    //              ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+    [for (int i = 0; nil; i++) 3];
+    //               ^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Null?' can't be assigned to a variable of type 'bool'.
+  }
+  {
+    // Check that values of type `Object` are not usable as booleans.
+    if (object) {}
+    //  ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    [if (object) 3];
+    //   ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    object ? 3 : 4;
+//  ^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+// [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    while (object) {}
+    //     ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    do {} while (object);
+    //           ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    object || true;
+//  ^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+// [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    object && true;
+//  ^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+// [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    true || object;
+    //      ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    true && object;
+    //      ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    for (int i = 0; object; i++) {}
+    //              ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+    [for (int i = 0; object; i++) 3];
+    //               ^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object' can't be assigned to a variable of type 'bool'.
+  }
+  {
+    // Check that values of type `Object?` are not usable as booleans.
+    if (objectOrNull) {}
+    //  ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    [if (objectOrNull) 3];
+    //   ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    objectOrNull ? 3 : 4;
+//  ^^^^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+// [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    while (objectOrNull) {}
+    //     ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    do {} while (objectOrNull);
+    //           ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    objectOrNull || true;
+//  ^^^^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+// [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    objectOrNull && true;
+//  ^^^^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+// [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    true || objectOrNull;
+    //      ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    true && objectOrNull;
+    //      ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_OPERAND
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    for (int i = 0; objectOrNull; i++) {}
+    //              ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+    [for (int i = 0; objectOrNull; i++) 3];
+    //               ^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_CONDITION
+    // [cfe] A value of type 'Object?' can't be assigned to a variable of type 'bool'.
+  }
+}
diff --git a/tests/language/nnbd/boolean_conversion/boolean_conversion_lib1.dart b/tests/language/nnbd/boolean_conversion/boolean_conversion_lib1.dart
new file mode 100644
index 0000000..4811a87
--- /dev/null
+++ b/tests/language/nnbd/boolean_conversion/boolean_conversion_lib1.dart
@@ -0,0 +1,179 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 library defines a set of test functions 'xxxAsBoolean" and a check
+// combinator called `check` which test the runtime behavior of conversions
+// of values in boolean condional positions (e.g. the condition of a conditional
+// statement).
+//
+// For example: calling `check(dynamicAsBoolean, value, expectation)` tests that
+// using `value` as the condition in a number of different syntactic constructs
+// with static type `dynamic` behaves as expected by `expectation`, where
+// `expectation` should be one of:
+// Expect.throwsAssertionError if a null conversion error is expected
+// Expect.throwsTypeError if an implicit cast error is expected
+// expectOk if no runtime error is expected.
+
+void expectOk(void Function() f) {
+  f();
+}
+
+final int constructsTested = 11;
+
+void check<T>(void Function(T, int) test, T value,
+    void Function(void Function()) expectation) {
+  for (int i = 0; i < constructsTested; i++) {
+    expectation(() => test(value, i));
+  }
+}
+
+void neverAsBoolean(Never value, int index) {
+  // Check that values of type `Never` are boolean converted appropriately
+  // In strong checking mode, this code is unreachable.  In weak checking mode,
+  // we may get passed `null` for `value`, and so we check that the `null` value
+  // causes an assertion error to be thrown appropriately.
+  switch (index) {
+    case 0:
+      if (value) {}
+      break;
+    case 1:
+      [if (value) 3];
+      break;
+    case 2:
+      value ? 3 : 4;
+      break;
+    case 3:
+      while (value) {
+        break;
+      }
+      break;
+    case 4:
+      var done = false;
+      do {
+        if (done) break;
+        done = true;
+      } while (value);
+      break;
+    case 5:
+      value || true;
+      break;
+    case 6:
+      value && true;
+      break;
+    case 7:
+      false || value;
+      break;
+    case 8:
+      true && value;
+      break;
+    case 9:
+      for (int i = 0; value; i++) {
+        break;
+      }
+      break;
+    case 10:
+      [for (int i = 0; value; i++) 3];
+      break;
+    default:
+      throw "Invalid index";
+  }
+}
+
+void booleanAsBoolean(bool value, int index) {
+  // Check that values of type `boolean` are boolean converted appropriately
+  switch (index) {
+    case 0:
+      if (value) {}
+      break;
+    case 1:
+      [if (value) 3];
+      break;
+    case 2:
+      value ? 3 : 4;
+      break;
+    case 3:
+      while (value) {
+        break;
+      }
+      break;
+    case 4:
+      var done = false;
+      do {
+        if (done) break;
+        done = true;
+      } while (value);
+      break;
+    case 5:
+      value || true;
+      break;
+    case 6:
+      value && true;
+      break;
+    case 7:
+      false || value;
+      break;
+    case 8:
+      true && value;
+      break;
+    case 9:
+      for (int i = 0; value; i++) {
+        break;
+      }
+      break;
+    case 10:
+      [for (int i = 0; value; value = false) 3];
+      break;
+    default:
+      throw "Invalid index";
+  }
+}
+
+void dynamicAsBoolean(dynamic value, int index) {
+  // Check that values of type `dynamic` are boolean converted appropriately
+  switch (index) {
+    case 0:
+      if (value) {}
+      break;
+    case 1:
+      [if (value) 3];
+      break;
+    case 2:
+      value ? 3 : 4;
+      break;
+    case 3:
+      while (value) {
+        break;
+      }
+      break;
+    case 4:
+      var done = false;
+      do {
+        if (done) break;
+        done = true;
+      } while (value);
+      break;
+    case 5:
+      value || true;
+      break;
+    case 6:
+      value && true;
+      break;
+    case 7:
+      false || value;
+      break;
+    case 8:
+      true && value;
+      break;
+    case 9:
+      for (int i = 0; value; i++) {
+        break;
+      }
+      break;
+    case 10:
+      [for (int i = 0; value; value = false) 3];
+      break;
+    default:
+      throw "Invalid index";
+  }
+}
diff --git a/tests/language/nnbd/boolean_conversion/boolean_conversion_strong_test.dart b/tests/language/nnbd/boolean_conversion/boolean_conversion_strong_test.dart
new file mode 100644
index 0000000..a64664f
--- /dev/null
+++ b/tests/language/nnbd/boolean_conversion/boolean_conversion_strong_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.
+
+// Requirements=nnbd-strong
+
+// Test implicit casts and null conversions for boolean expressions
+// in strong mode.
+
+import 'package:expect/expect.dart';
+import 'boolean_conversion_lib1.dart';
+
+void main() {
+  check(booleanAsBoolean, true, expectOk);
+  check(booleanAsBoolean, false, expectOk);
+
+  check(dynamicAsBoolean, null, Expect.throwsTypeError);
+  check(dynamicAsBoolean, true, expectOk);
+  check(dynamicAsBoolean, false, expectOk);
+
+  check(dynamicAsBoolean, "", Expect.throwsTypeError);
+  check(dynamicAsBoolean, "true", Expect.throwsTypeError);
+  check(dynamicAsBoolean, "null", Expect.throwsTypeError);
+  check(dynamicAsBoolean, "undefined", Expect.throwsTypeError);
+  check(dynamicAsBoolean, 0, Expect.throwsTypeError);
+  check(dynamicAsBoolean, 1, Expect.throwsTypeError);
+  check(dynamicAsBoolean, [true], Expect.throwsTypeError);
+}
diff --git a/tests/language/nnbd/boolean_conversion/boolean_conversion_weak_test.dart b/tests/language/nnbd/boolean_conversion/boolean_conversion_weak_test.dart
new file mode 100644
index 0000000..c8b0167
--- /dev/null
+++ b/tests/language/nnbd/boolean_conversion/boolean_conversion_weak_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.
+
+// @dart=2.7
+
+// Requirements=nnbd-weak
+
+// Test implicit casts and null conversions for boolean expressions
+// in weak mode.
+
+import 'package:expect/expect.dart';
+import 'boolean_conversion_lib1.dart';
+
+void main() {
+  check(neverAsBoolean, null, Expect.throwsAssertionError);
+
+  check(booleanAsBoolean, null, Expect.throwsAssertionError);
+  check(booleanAsBoolean, true, expectOk);
+  check(booleanAsBoolean, false, expectOk);
+
+  check(dynamicAsBoolean, null, Expect.throwsAssertionError);
+  check(dynamicAsBoolean, true, expectOk);
+  check(dynamicAsBoolean, false, expectOk);
+
+  check(dynamicAsBoolean, "", Expect.throwsTypeError);
+  check(dynamicAsBoolean, "true", Expect.throwsTypeError);
+  check(dynamicAsBoolean, "null", Expect.throwsTypeError);
+  check(dynamicAsBoolean, "undefined", Expect.throwsTypeError);
+  check(dynamicAsBoolean, 0, Expect.throwsTypeError);
+  check(dynamicAsBoolean, 1, Expect.throwsTypeError);
+  check(dynamicAsBoolean, [true], Expect.throwsTypeError);
+}
diff --git a/tests/language/nnbd/extreme_bounds/glb_futureor_test.dart b/tests/language/nnbd/extreme_bounds/glb_futureor_test.dart
new file mode 100644
index 0000000..7ebd3ca
--- /dev/null
+++ b/tests/language/nnbd/extreme_bounds/glb_futureor_test.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/expect.dart';
+
+/*
+ * Set up three synthetic types Left, Right, Bottom, such that
+ * Left and Right are not subtype related, both are
+ * supertypes of Bottom, and GLB(Left, Right) == Bottom
+ */
+typedef Left = void Function(double);
+typedef Right = void Function(int);
+typedef Bottom = void Function(num);
+
+/*
+ * Typedefs which given a type T produce a contra-variant
+ * occurrence of FutureOr<T>, Future<T>, and T respectively.
+ */
+typedef TakesFutureOr<T> = void Function(FutureOr<T>);
+typedef TakesFuture<T> = void Function(Future<T>);
+typedef Takes<T> = void Function(T);
+
+/*
+* Given a type T, produce a type Exactly<T> such that
+* Exactly<S> <: Exactly<T> iff S and T are mutual subtypes.
+*/
+typedef Exactly<T> = T Function(T);
+/*
+* Given an argument of type T, produce a result of type Exactly<T>.
+*/
+Exactly<T> exactly<T>(T t) => (T t) => t;
+
+/*
+* Given a call infer(a, b) where a has type void Function(S0) and b has type
+* void Function(S1), set up an inference constraint system of the form:
+* ? <: T <: S0
+* ? <: T <: S1
+* which merges to:
+* ? <: T <: GLB(S0, S1)
+*/
+Exactly<void Function(T)> infer<T>(void Function(T) x, void Function(T) y) {
+  return (void Function(T) t) => t;
+}
+
+void test(bool b) {
+  // Variables of specific types for input into the GLB algorithm
+  TakesFutureOr<Left> futureOrLeft = (_) {};
+  TakesFutureOr<Right> futureOrRight = (_) {};
+  TakesFuture<Left> futureLeft = (_) {};
+  TakesFuture<Right> futureRight = (_) {};
+  Takes<Left> left = (_) {};
+  Takes<Right> right = (_) {};
+
+  // Check variables of exact type.  Assigning the result of inference
+  // to any of these checks that the result is exactly as expect.
+  Exactly<TakesFutureOr<Bottom>> checkFutureOrBottom = (t) => t;
+  Exactly<TakesFuture<Bottom>> checkFutureBottom = (t) => t;
+  Exactly<Takes<Bottom>> checkBottom = (t) => t;
+
+  // Note: assignments are done in separate steps below to avoid interactions
+  // with downward inference.
+
+  // GLB(FutureOr<A>, FutureOr<B>) = FutureOr<GLB(A, B)>
+  {
+    // Compute the upper bound of the function types, which computes
+    // the GLB of the argument types.
+    var glb = b ? futureOrLeft : futureOrRight;
+    // Capture the inferred type of glb as an exact type.
+    var exactlyGlb = exactly(glb);
+    // Check that the inferred type is exactly as expected.
+    checkFutureOrBottom = exactlyGlb;
+    Expect.type<Exactly<TakesFutureOr<Bottom>>>(exactlyGlb);
+
+    // Compute the upper bound of the function types via inference
+    // constraint merge which computes the GLB of the argument types.
+    var merge = infer(futureOrLeft, futureOrRight);
+    checkFutureOrBottom = merge;
+    Expect.type<Exactly<TakesFutureOr<Bottom>>>(merge);
+  }
+
+  // GLB(FutureOr<A>, Future<B>) = Future<GLB(A, B)>
+  {
+    // Compute the upper bound of the function types, which computes
+    // the GLB of the argument types.
+    var glb = b ? futureOrLeft : futureRight;
+    // Capture the inferred type of glb as an exact type.
+    var exactlyGlb = exactly(glb);
+    // Check that the inferred type is exactly as expected.
+    checkFutureBottom = exactlyGlb;
+    Expect.type<Exactly<TakesFuture<Bottom>>>(exactlyGlb);
+
+    // Compute the upper bound of the function types via inference
+    // constraint merge which computes the GLB of the argument types.
+    var merge = infer(futureOrLeft, futureRight);
+    checkFutureBottom = merge;
+    Expect.type<Exactly<TakesFuture<Bottom>>>(merge);
+  }
+
+  // GLB(Future<A>, FutureOr<B>) = Future<GLB(A, B)>
+  {
+    // Compute the upper bound of the function types, which computes
+    // the GLB of the argument types.
+    var glb = b ? futureLeft : futureOrRight;
+    // Capture the inferred type of glb as an exact type.
+    var exactlyGlb = exactly(glb);
+    // Check that the inferred type is exactly as expected.
+    checkFutureBottom = exactlyGlb;
+    Expect.type<Exactly<TakesFuture<Bottom>>>(exactlyGlb);
+
+    // Compute the upper bound of the function types via inference
+    // constraint merge which computes the GLB of the argument types.
+    var merge = infer(futureLeft, futureOrRight);
+    checkFutureBottom = merge;
+    Expect.type<Exactly<TakesFuture<Bottom>>>(merge);
+  }
+
+  // GLB(FutureOr<A>, B) = GLB(A, B)
+  {
+    // Compute the upper bound of the function types, which computes
+    // the GLB of the argument types.
+    var glb = b ? futureOrLeft : right;
+    // Capture the inferred type of glb as an exact type.
+    var exactlyGlb = exactly(glb);
+    // Check that the inferred type is exactly as expected.
+    checkBottom = exactlyGlb;
+    Expect.type<Exactly<Takes<Bottom>>>(exactlyGlb);
+
+    // Compute the upper bound of the function types via inference
+    // constraint merge which computes the GLB of the argument types.
+    var merge = infer(futureOrLeft, right);
+    checkBottom = merge;
+    Expect.type<Exactly<Takes<Bottom>>>(merge);
+  }
+
+  // GLB(A, FutureOr<B>) = GLB(A, B)
+  {
+    // Compute the upper bound of the function types, which computes
+    // the GLB of the argument types.
+    var glb = b ? left : futureOrRight;
+    // Capture the inferred type of glb as an exact type.
+    var exactlyGlb = exactly(glb);
+    // Check that the inferred type is exactly as expected.
+    checkBottom = exactlyGlb;
+    Expect.type<Exactly<Takes<Bottom>>>(exactlyGlb);
+
+    // Compute the upper bound of the function types via inference
+    // constraint merge which computes the GLB of the argument types.
+    var merge = infer(left, futureOrRight);
+    checkBottom = merge;
+    Expect.type<Exactly<Takes<Bottom>>>(merge);
+  }
+}
+
+main() {
+  test(true);
+  test(false);
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_error_test.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_error_test.dart
new file mode 100644
index 0000000..3566ad6
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_error_test.dart
@@ -0,0 +1,658 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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
+
+// Verifies that a member declared in a null-safe class which overrides
+// a legacy member with the same name gets a null-safe signature instead of
+// inheriting the legacy signature from the super-interface (concretely,
+// it is not the signature from `A<int*>`).
+
+import 'legacy_resolves_conflict_1_lib2.dart';
+
+void main() {
+  // All classes named `De..` override `m`. The ones whose name ends in `q`
+  // do not admit invoking `isEven`; the remaining ones do not admit passing
+  // null as the parameter to `m`.
+
+  De0().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De0q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De1().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De1q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De2().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De2q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De3().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De3q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De4().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De4q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De5().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De5q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De6().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De6q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De7().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De7q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De8().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De8q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De9().m(null).isEven;
+//        ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De9q().m(null).isEven;
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De10().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De10q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De11().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De11q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De12().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De12q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De13().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De13q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De14().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De14q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De15().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De15q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De16().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De16q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De17().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De17q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De18().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De18q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De19().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De19q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De20().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De20q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De21().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De21q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De22().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De22q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De23().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De23q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De24().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De24q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De25().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De25q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De26().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De26q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De27().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De27q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De28().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De28q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De29().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De29q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De30().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De30q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De31().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De31q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De32().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De32q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De33().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De33q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De34().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De34q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De35().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De35q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De36().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De36q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De37().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De37q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De38().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De38q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De39().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De39q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De40().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De40q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De41().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De41q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De42().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De42q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De43().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De43q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De44().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De44q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De45().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De45q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De46().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De46q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De47().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De47q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De48().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De48q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De49().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De49q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De50().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De50q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De51().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De51q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De52().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De52q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De53().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De53q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De54().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De54q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De55().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De55q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De56().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De56q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De57().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De57q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De58().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De58q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De59().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De59q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De60().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De60q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De61().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De61q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De62().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De62q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De63().m(null).isEven;
+//         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  De63q().m(null).isEven;
+//                ^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_legacy_lib.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_legacy_lib.dart
new file mode 100644
index 0000000..5797f56
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_legacy_lib.dart
@@ -0,0 +1,150 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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.6
+
+// Import a null-safe library which defines several classes `B...`, each of
+// which implements either `A<int>` or `A<int?>`, or in the case of `Bwm` and
+// `Bwmq` which implement either `M<int>` or `M<int?>`, respectively. This
+// library then declares legacy classes that create a superinterface conflict,
+// e.g., by having both `A<int>` and `A<int?>` as indirect superinterfaces.
+// The absence of errors in this test verifies that member signature
+// compatibility in legacy libraries is done with respect to the nullability
+// erased signatures.
+
+import 'legacy_resolves_conflict_1_lib.dart';
+
+// Naming conventions: This library iterates over all the ways a legacy class
+// can have conflicting opted-in classes `B...` as superinterfaces. The ones
+// that can be concrete are concrete. The resulting classes are simply named
+// `C#` where `#` is a running counter (it doesn't seem helpful to encode the
+// way in which each of them has said superinterfaces).
+
+class C0 extends Be implements Beq {}
+
+abstract class C1 implements Be, Beq {}
+
+class C2 extends Be implements Biq {}
+
+abstract class C3 implements Be, Biq {}
+
+class C4 extends Be implements Bwcq {}
+
+abstract class C5 implements Be, Bwcq {}
+
+class C6 extends Be implements Bwmq {}
+
+abstract class C7 implements Be, Bwmq {}
+
+class C8 extends Bi implements Beq {}
+
+abstract class C9 implements Bi, Beq {}
+
+class C10 extends Bi implements Biq {}
+
+abstract class C11 implements Bi, Biq {}
+
+class C12 extends Bi implements Bwcq {}
+
+abstract class C13 implements Bi, Bwcq {}
+
+class C14 extends Bi implements Bwmq {}
+
+abstract class C15 implements Bi, Bwmq {}
+
+class C16 extends Bwc implements Beq {}
+
+abstract class C17 implements Bwc, Beq {}
+
+class C18 extends Bwc implements Biq {}
+
+abstract class C19 implements Bwc, Biq {}
+
+class C20 extends Bwc implements Bwcq {}
+
+abstract class C21 implements Bwc, Bwcq {}
+
+class C22 extends Bwc implements Bwmq {}
+
+abstract class C23 implements Bwc, Bwmq {}
+
+class C24 extends Bwm implements Beq {}
+
+abstract class C25 implements Bwm, Beq {}
+
+class C26 extends Bwm implements Biq {}
+
+abstract class C27 implements Bwm, Biq {}
+
+class C28 extends Bwm implements Bwcq {}
+
+abstract class C29 implements Bwm, Bwcq {}
+
+class C30 extends Bwm implements Bwmq {}
+
+abstract class C31 implements Bwm, Bwmq {}
+
+class C32 extends Beq implements Be {}
+
+abstract class C33 implements Beq, Be {}
+
+class C34 extends Beq implements Bi {}
+
+abstract class C35 implements Beq, Bi {}
+
+class C36 extends Beq implements Bwc {}
+
+abstract class C37 implements Beq, Bwc {}
+
+class C38 extends Beq implements Bwm {}
+
+abstract class C39 implements Beq, Bwm {}
+
+class C40 extends Biq implements Be {}
+
+abstract class C41 implements Biq, Be {}
+
+class C42 extends Biq implements Bi {}
+
+abstract class C43 implements Biq, Bi {}
+
+class C44 extends Biq implements Bwc {}
+
+abstract class C45 implements Biq, Bwc {}
+
+class C46 extends Biq implements Bwm {}
+
+abstract class C47 implements Biq, Bwm {}
+
+class C48 extends Bwcq implements Be {}
+
+abstract class C49 implements Bwcq, Be {}
+
+class C50 extends Bwcq implements Bi {}
+
+abstract class C51 implements Bwcq, Bi {}
+
+class C52 extends Bwcq implements Bwc {}
+
+abstract class C53 implements Bwcq, Bwc {}
+
+class C54 extends Bwcq implements Bwm {}
+
+abstract class C55 implements Bwcq, Bwm {}
+
+class C56 extends Bwmq implements Be {}
+
+abstract class C57 implements Bwmq, Be {}
+
+class C58 extends Bwmq implements Bi {}
+
+abstract class C59 implements Bwmq, Bi {}
+
+class C60 extends Bwmq implements Bwc {}
+
+abstract class C61 implements Bwmq, Bwc {}
+
+class C62 extends Bwmq implements Bwm {}
+
+abstract class C63 implements Bwmq, Bwm {}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_lib.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_lib.dart
new file mode 100644
index 0000000..44d61bb
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_lib.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.
+
+// This library sets up various null-safe classes which have as a
+// superinterface one of `A<int>`,`A<int?>`, `M<int>` or `M<int?>`.
+// Each class has a getter, setter, and method; each is concrete; and
+// the method signatures are incompatible (so the signature from `A<int>`
+// and from `A<int?>` do not have a correct override relationship in
+// any direction), thus allowing a test to verify that legacy type
+// mitigation does take place when superinterfaces like `A<int>` and
+// `A<int?>` are brought together, it is not just overriding.
+
+// Naming conventions: Class `A` and mixin `M` are used as the top of every
+// superinterface graph (except Object). Classes named `Be..` extend `A`,
+// classes named `Bwm..` apply the mixin `M` (`w` refers to `with`), and
+// classes named `Bwc..` apply the class `A` as a mixin. Finally, classes
+// named `Bi..` implement `A`. In each case, classes whose name ends in `q`
+// have `A<int?>` as a superinterface and other classes have `A<int>`.
+// All classes are concrete, so a couple of them repeat the member
+// implementation declarations (with the same member signatures, i.e., with
+// no conflicts).
+
+class A<X> {
+  List<X> get a => [];
+  set a(List<X> _) {}
+  X m(X x) => x;
+}
+
+mixin M<X> {
+  List<X> get a => [];
+  set a(List<X> _) {}
+  X m(X x) => x;
+}
+
+class Be extends A<int> {}
+
+class Bi implements A<int> {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class Beq extends A<int?> {}
+
+class Biq implements A<int?> {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+class Bwc with A<int> {}
+
+class Bwcq with A<int?> {}
+
+class Bwm with M<int> {}
+
+class Bwmq with M<int?> {}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_lib2.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_lib2.dart
new file mode 100644
index 0000000..bb473a9
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_lib2.dart
@@ -0,0 +1,918 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Import a legacy library which defines legacy classes each of which brings
+// together conflicting null-safe superinterfaces (e.g. `A<int>` and `A<int?>)
+// and/or brings together members with the same name whose member signatures
+// conflict on nullability.
+
+// Each class defined here overrides all of the members from a legacy class
+// using either nullable or non-nullable types. This test validates that there
+// are no errors triggered by this override: that is, that neither the presence
+// of indirect conflicting interfaces, nor of multiple conflicting member
+// signatures causes an error.
+
+import 'legacy_resolves_conflict_1_legacy_lib.dart';
+
+// Naming conventions: Class `De#` extends `C#`, where `#` stands for a number
+// in 0..63, and declares members whose member signatures use non-nullable
+// types. Class `De#q` extends `C#`, and declares members whose member
+// signatures use nullable types (`q` refers to the question marks). Class
+// `Di#` implements `C#`, is abstract, and does not declare any members.
+
+class De0 extends C0 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De0q extends C0 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di0 implements C0 {}
+
+class De1 extends C1 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De1q extends C1 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di1 implements C1 {}
+
+class De2 extends C2 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De2q extends C2 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di2 implements C2 {}
+
+class De3 extends C3 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De3q extends C3 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di3 implements C3 {}
+
+class De4 extends C4 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De4q extends C4 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di4 implements C4 {}
+
+class De5 extends C5 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De5q extends C5 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di5 implements C5 {}
+
+class De6 extends C6 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De6q extends C6 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di6 implements C6 {}
+
+class De7 extends C7 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De7q extends C7 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di7 implements C7 {}
+
+class De8 extends C8 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De8q extends C8 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di8 implements C8 {}
+
+class De9 extends C9 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De9q extends C9 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di9 implements C9 {}
+
+class De10 extends C10 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De10q extends C10 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di10 implements C10 {}
+
+class De11 extends C11 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De11q extends C11 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di11 implements C11 {}
+
+class De12 extends C12 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De12q extends C12 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di12 implements C12 {}
+
+class De13 extends C13 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De13q extends C13 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di13 implements C13 {}
+
+class De14 extends C14 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De14q extends C14 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di14 implements C14 {}
+
+class De15 extends C15 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De15q extends C15 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di15 implements C15 {}
+
+class De16 extends C16 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De16q extends C16 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di16 implements C16 {}
+
+class De17 extends C17 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De17q extends C17 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di17 implements C17 {}
+
+class De18 extends C18 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De18q extends C18 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di18 implements C18 {}
+
+class De19 extends C19 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De19q extends C19 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di19 implements C19 {}
+
+class De20 extends C20 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De20q extends C20 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di20 implements C20 {}
+
+class De21 extends C21 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De21q extends C21 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di21 implements C21 {}
+
+class De22 extends C22 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De22q extends C22 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di22 implements C22 {}
+
+class De23 extends C23 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De23q extends C23 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di23 implements C23 {}
+
+class De24 extends C24 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De24q extends C24 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di24 implements C24 {}
+
+class De25 extends C25 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De25q extends C25 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di25 implements C25 {}
+
+class De26 extends C26 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De26q extends C26 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di26 implements C26 {}
+
+class De27 extends C27 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De27q extends C27 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di27 implements C27 {}
+
+class De28 extends C28 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De28q extends C28 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di28 implements C28 {}
+
+class De29 extends C29 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De29q extends C29 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di29 implements C29 {}
+
+class De30 extends C30 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De30q extends C30 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di30 implements C30 {}
+
+class De31 extends C31 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De31q extends C31 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di31 implements C31 {}
+
+class De32 extends C32 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De32q extends C32 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di32 implements C32 {}
+
+class De33 extends C33 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De33q extends C33 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di33 implements C33 {}
+
+class De34 extends C34 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De34q extends C34 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di34 implements C34 {}
+
+class De35 extends C35 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De35q extends C35 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di35 implements C35 {}
+
+class De36 extends C36 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De36q extends C36 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di36 implements C36 {}
+
+class De37 extends C37 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De37q extends C37 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di37 implements C37 {}
+
+class De38 extends C38 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De38q extends C38 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di38 implements C38 {}
+
+class De39 extends C39 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De39q extends C39 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di39 implements C39 {}
+
+class De40 extends C40 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De40q extends C40 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di40 implements C40 {}
+
+class De41 extends C41 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De41q extends C41 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di41 implements C41 {}
+
+class De42 extends C42 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De42q extends C42 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di42 implements C42 {}
+
+class De43 extends C43 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De43q extends C43 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di43 implements C43 {}
+
+class De44 extends C44 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De44q extends C44 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di44 implements C44 {}
+
+class De45 extends C45 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De45q extends C45 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di45 implements C45 {}
+
+class De46 extends C46 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De46q extends C46 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di46 implements C46 {}
+
+class De47 extends C47 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De47q extends C47 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di47 implements C47 {}
+
+class De48 extends C48 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De48q extends C48 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di48 implements C48 {}
+
+class De49 extends C49 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De49q extends C49 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di49 implements C49 {}
+
+class De50 extends C50 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De50q extends C50 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di50 implements C50 {}
+
+class De51 extends C51 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De51q extends C51 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di51 implements C51 {}
+
+class De52 extends C52 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De52q extends C52 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di52 implements C52 {}
+
+class De53 extends C53 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De53q extends C53 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di53 implements C53 {}
+
+class De54 extends C54 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De54q extends C54 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di54 implements C54 {}
+
+class De55 extends C55 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De55q extends C55 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di55 implements C55 {}
+
+class De56 extends C56 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De56q extends C56 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di56 implements C56 {}
+
+class De57 extends C57 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De57q extends C57 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di57 implements C57 {}
+
+class De58 extends C58 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De58q extends C58 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di58 implements C58 {}
+
+class De59 extends C59 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De59q extends C59 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di59 implements C59 {}
+
+class De60 extends C60 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De60q extends C60 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di60 implements C60 {}
+
+class De61 extends C61 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De61q extends C61 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di61 implements C61 {}
+
+class De62 extends C62 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De62q extends C62 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di62 implements C62 {}
+
+class De63 extends C63 {
+  List<int> get a => [];
+  set a(List<int> _) {}
+  int m(int x) => x;
+}
+
+class De63q extends C63 {
+  List<int?> get a => [];
+  set a(List<int?> _) {}
+  int? m(int? x) => x;
+}
+
+abstract class Di63 implements C63 {}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_test.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_test.dart
new file mode 100644
index 0000000..157e0a2
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_1_test.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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
+
+// Verify that conflicting implemented interfaces are resolved at a legacy
+// class `C`, and an opted-in class can extend or implement `C` without
+// incurring an error.
+
+import 'package:expect/expect.dart';
+import 'legacy_resolves_conflict_1_legacy_lib.dart';
+import 'legacy_resolves_conflict_1_lib2.dart';
+
+void main() {
+  // Ensure that no class is eliminated by tree-shaking.
+  Expect.isNotNull([
+    De0, De0q, Di0, De1, De1q, Di1, De2, De2q, Di2, De3, //
+    De3q, Di3, De4, De4q, Di4, De5, De5q, Di5, De6, De6q, //
+    Di6, De7, De7q, Di7, De8, De8q, Di8, De9, De9q, Di9, //
+    De10, De10q, Di10, De11, De11q, Di11, De12, De12q, Di12, De13, //
+    De13q, Di13, De14, De14q, Di14, De15, De15q, Di15, De16, De16q, //
+    Di16, De17, De17q, Di17, De18, De18q, Di18, De19, De19q, Di19, //
+    De20, De20q, Di20, De21, De21q, Di21, De22, De22q, Di22, De23, //
+    De23q, Di23, De24, De24q, Di24, De25, De25q, Di25, De26, De26q, //
+    Di26, De27, De27q, Di27, De28, De28q, Di28, De29, De29q, Di29, //
+    De30, De30q, Di30, De31, De31q, Di31, De32, De32q, Di32, De33, //
+    De33q, Di33, De34, De34q, Di34, De35, De35q, Di35, De36, De36q, //
+    Di36, De37, De37q, Di37, De38, De38q, Di38, De39, De39q, Di39, //
+    De40, De40q, Di40, De41, De41q, Di41, De42, De42q, Di42, De43, //
+    De43q, Di43, De44, De44q, Di44, De45, De45q, Di45, De46, De46q, //
+    Di46, De47, De47q, Di47, De48, De48q, Di48, De49, De49q, Di49, //
+    De50, De50q, Di50, De51, De51q, Di51, De52, De52q, Di52, De53, //
+    De53q, Di53, De54, De54q, Di54, De55, De55q, Di55, De56, De56q, //
+    Di56, De57, De57q, Di57, De58, De58q, Di58, De59, De59q, Di59, //
+    De60, De60q, Di60, De61, De61q, Di61, De62, De62q, Di62, De63, //
+    De63q, Di63, //
+  ]);
+
+  // Verify that concrete legacy classes implement `A<int*>`, thus allowing
+  // `m(null).isEven` with no compile-time errors, but expect a dynamic error
+  // because every implementation of `m` returns its argument.
+  Expect.throws(() => C0().m(null).isEven);
+  Expect.throws(() => C2().m(null).isEven);
+  Expect.throws(() => C4().m(null).isEven);
+  Expect.throws(() => C6().m(null).isEven);
+  Expect.throws(() => C8().m(null).isEven);
+  Expect.throws(() => C10().m(null).isEven);
+  Expect.throws(() => C12().m(null).isEven);
+  Expect.throws(() => C14().m(null).isEven);
+  Expect.throws(() => C16().m(null).isEven);
+  Expect.throws(() => C18().m(null).isEven);
+  Expect.throws(() => C20().m(null).isEven);
+  Expect.throws(() => C22().m(null).isEven);
+  Expect.throws(() => C24().m(null).isEven);
+  Expect.throws(() => C26().m(null).isEven);
+  Expect.throws(() => C28().m(null).isEven);
+  Expect.throws(() => C30().m(null).isEven);
+  Expect.throws(() => C32().m(null).isEven);
+  Expect.throws(() => C34().m(null).isEven);
+  Expect.throws(() => C36().m(null).isEven);
+  Expect.throws(() => C38().m(null).isEven);
+  Expect.throws(() => C40().m(null).isEven);
+  Expect.throws(() => C42().m(null).isEven);
+  Expect.throws(() => C44().m(null).isEven);
+  Expect.throws(() => C46().m(null).isEven);
+  Expect.throws(() => C48().m(null).isEven);
+  Expect.throws(() => C50().m(null).isEven);
+  Expect.throws(() => C52().m(null).isEven);
+  Expect.throws(() => C54().m(null).isEven);
+  Expect.throws(() => C56().m(null).isEven);
+  Expect.throws(() => C58().m(null).isEven);
+  Expect.throws(() => C60().m(null).isEven);
+  Expect.throws(() => C62().m(null).isEven);
+
+  // Perform a similar check on the abstract classes.
+  void testAbstractClasses(
+      C1 c1,
+      C3 c3,
+      C5 c5,
+      C7 c7,
+      C9 c9,
+      C11 c11,
+      C13 c13,
+      C15 c15,
+      C17 c17,
+      C19 c19,
+      C21 c21,
+      C23 c23,
+      C25 c25,
+      C27 c27,
+      C29 c29,
+      C31 c31,
+      C33 c33,
+      C35 c35,
+      C37 c37,
+      C39 c39,
+      C41 c41,
+      C43 c43,
+      C45 c45,
+      C47 c47,
+      C49 c49,
+      C51 c51,
+      C53 c53,
+      C55 c55,
+      C57 c57,
+      C59 c59,
+      C61 c61,
+      C63 c63) {
+    c1.m(null).isEven;
+    c3.m(null).isEven;
+    c5.m(null).isEven;
+    c7.m(null).isEven;
+    c9.m(null).isEven;
+    c11.m(null).isEven;
+    c13.m(null).isEven;
+    c15.m(null).isEven;
+    c17.m(null).isEven;
+    c19.m(null).isEven;
+    c21.m(null).isEven;
+    c23.m(null).isEven;
+    c25.m(null).isEven;
+    c27.m(null).isEven;
+    c29.m(null).isEven;
+    c31.m(null).isEven;
+    c33.m(null).isEven;
+    c35.m(null).isEven;
+    c37.m(null).isEven;
+    c39.m(null).isEven;
+    c41.m(null).isEven;
+    c43.m(null).isEven;
+    c45.m(null).isEven;
+    c47.m(null).isEven;
+    c49.m(null).isEven;
+    c51.m(null).isEven;
+    c53.m(null).isEven;
+    c55.m(null).isEven;
+    c57.m(null).isEven;
+    c59.m(null).isEven;
+    c61.m(null).isEven;
+    c63.m(null).isEven;
+  }
+
+  // Ensure that `testAbstractClasses` is not eliminated by tree-shaking,
+  // but don't call it (so we avoid the need for actual arguments).
+  print(testAbstractClasses);
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_legacy_lib.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_legacy_lib.dart
new file mode 100644
index 0000000..f5e88b5
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_legacy_lib.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.
+
+// @dart = 2.6
+
+// Import two null-safe classes `B` and `Bq` which contain the same member
+// names with types which are compatible except that they differ in
+// nullability. Declare legacy classes that embody a conflict by having
+// both `B` and `Bq` as superinterfaces. The absence of errors in this test
+// verifies that member signature compatibility in legacy libraries is done
+// with respect to the nullability erased signatures.
+
+import 'legacy_resolves_conflict_2_lib.dart';
+
+// Naming convention: We iterate over all ways `B` and `Bq` can be direct
+// superinterfaces of a class C, and the latter is named `C#` where `#` is
+// simply a running counter (because it seems to be of limited value to
+// encode the way `B` and `Bq` are used as superinterfaces). Note that `C2`
+// and `C5` must be abstract, because we do not wish to declare any members
+// in these classes such that they can be concrete.
+
+class C0 extends B implements Bq {}
+
+class C1 extends B with Bq {}
+
+abstract class C2 implements B, Bq {}
+
+class C3 extends Bq implements B {}
+
+class C4 extends Bq with B {}
+
+abstract class C5 implements Bq, B {}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_lib.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_lib.dart
new file mode 100644
index 0000000..e354dec
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_lib.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 library declares two null-safe classes `B` and `Bq` with members using
+// non-nullable types respectively nullable types. The member signatures are
+// incompatible (there is no correct override relationship between them in
+// any direction), so subtypes can create a conflict by having both as
+// superinterfaces, cf. 'legacy_resolves_conflict_2_legacy_lib.dart'.
+
+// Naming conventions: Class `B` has members whose member signatures use
+// non-nullable types, and `Bq` has members whose member signatures use
+// nullable types (`b` refers to the question marks).
+
+class B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_test.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_test.dart
new file mode 100644
index 0000000..01b6d42
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_2_test.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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
+
+// Verify that conflicting member signatures are resolved at a legacy
+// class `C`, and an opted-in class can extend or implement `C` without
+// incurring an error, with and without overriding the conflicting member.
+
+import 'package:expect/expect.dart';
+import 'legacy_resolves_conflict_2_legacy_lib.dart';
+
+// Naming convention: Class `De#` extends class `C#` and declares members
+// with member signatures using non-nullable types (so `int*` is overridden
+// by `int` in various manners). Class `De#q` extends class `C#` and declares
+// members with member signatures using nullable types (so `int*` is
+// overridden by `int?` in various manners). The abstract class `Di#`
+// implements class `C#` and does not declare any members; this just serves
+// to ensure that an opted-in class can implement a legacy class with a
+// baked-in conflict in its member signatures.
+
+class De0 extends C0 {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class De0q extends C0 {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+abstract class Di0 implements C0 {}
+
+class De1 extends C1 {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class De1q extends C1 {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+abstract class Di1 implements C1 {}
+
+class De2 extends C2 {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class De2q extends C2 {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+abstract class Di2 implements C2 {}
+
+class De3 extends C3 {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class De3q extends C3 {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+abstract class Di3 implements C3 {}
+
+class De4 extends C4 {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class De4q extends C4 {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+abstract class Di4 implements C4 {}
+
+class De5 extends C5 {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class De5q extends C5 {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+abstract class Di5 implements C5 {}
+
+void main() {
+  // Ensure that no class is eliminated by tree-shaking.
+  Expect.isNotNull([C0, C1, C2, C3, C4, C5]);
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_error_test.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_error_test.dart
new file mode 100644
index 0000000..3fa4375
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_error_test.dart
@@ -0,0 +1,356 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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
+
+// Verify that member signatures are computed correctly for null-safe
+// classes having both a legacy and a null-safe superinterface, and with some
+// classes also overriding declarations in the class itself. The expected
+// member signatures are indicated in comments on each class in the library
+// 'legacy_resolves_conflict_3_lib2.dart'. This test uses lack of assignability
+// to ascertain that a selection of classes that are expected to have a
+// null-safe member signature for `m` do not have a legacy member signature.
+
+// The point is that 'legacy_resolves_conflict_3_test.dart' would succeed even
+// in the case where, say, `DwB0().a` has type `List<int* Function(int*)>`,
+// and similarly for other receiver types, but this test would then fail
+// to have the corresponding compile-time errors.
+
+import 'legacy_resolves_conflict_3_legacy_lib.dart';
+import 'legacy_resolves_conflict_3_lib.dart';
+import 'legacy_resolves_conflict_3_lib2.dart';
+
+// Naming conventions: Please consult 'legacy_resolves_conflict_3_lib2.dart'.
+
+class DiBqO0 implements C0, Bq {
+  List<int Function(int)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int Function(int)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int Function(int) m(int Function(int) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBOq0 implements C0, B {
+  List<int? Function(int?)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int? Function(int?)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int? Function(int?) m(int? Function(int?) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBqO1 implements C1, Bq {
+  List<int Function(int)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int Function(int)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int Function(int) m(int Function(int) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBOq1 implements C1, B {
+  List<int? Function(int?)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int? Function(int?)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int? Function(int?) m(int? Function(int?) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBqO2 implements C2, Bq {
+  List<int Function(int)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int Function(int)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int Function(int) m(int Function(int) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBOq2 implements C2, B {
+  List<int? Function(int?)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int? Function(int?)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int? Function(int?) m(int? Function(int?) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBqO3 implements C3, Bq {
+  List<int Function(int)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int Function(int)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int Function(int) m(int Function(int) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBOq3 implements C3, B {
+  List<int? Function(int?)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int? Function(int?)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int? Function(int?) m(int? Function(int?) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBqO4 implements C4, Bq {
+  List<int Function(int)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int Function(int)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int Function(int) m(int Function(int) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBOq4 implements C4, B {
+  List<int? Function(int?)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int? Function(int?)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int? Function(int?) m(int? Function(int?) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBqO5 implements C5, Bq {
+  List<int Function(int)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int Function(int)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int Function(int) m(int Function(int) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+class DiBOq5 implements C5, B {
+  List<int? Function(int?)> get a => [];
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  set a(List<int? Function(int?)> _) {}
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  int? Function(int?) m(int? Function(int?) x) => x;
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
+
+void main() {
+  // Verify that some classes have a signature which is not as in `Bq`.
+  List<List<int? Function(int?)>> xsBq = [
+    DwB0().a,
+//  ^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBO0().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwB1().a,
+//  ^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBO1().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwB2().a,
+//  ^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBO2().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwB3().a,
+//  ^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBO3().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwB4().a,
+//  ^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBO4().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwB5().a,
+//  ^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBO5().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+  ];
+
+  // Verify that some classes have a signature which is not as in `B`.
+  List<List<int Function(int)>> xsB = [
+    DwBq0().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBqOq0().a,
+//  ^^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwBq1().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBqOq1().a,
+//  ^^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwBq2().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBqOq2().a,
+//  ^^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwBq3().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBqOq3().a,
+//  ^^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwBq4().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBqOq4().a,
+//  ^^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DwBq5().a,
+//  ^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+
+    DiBqOq5().a,
+//  ^^^^^^^^^^
+// [analyzer] STATIC_WARNING.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] unspecified
+  ];
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_legacy_lib.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_legacy_lib.dart
new file mode 100644
index 0000000..1e56adc
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_legacy_lib.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.
+
+// @dart = 2.6
+
+// Import two null-safe classes `B` and `Bq` which contain the same member
+// names with types that are compatible except that they differ in nullability.
+// Declare legacy classes that has either `B` or `Bq` as a superinterface.
+
+// The absence of errors in this test is unremarkable (there are no conflicts),
+// but it allows for a null-safe subtype to declare overriding members, cf.
+// 'legacy_resolves_conflict_3_lib2.dart'.
+
+import 'legacy_resolves_conflict_3_lib.dart';
+
+// Naming convention: Class `C#`, where `#` is just a running counter, has
+// a single legacy class (`B` or `Bq`) as a superinterface. The point is that
+// we wish to test the treatment of a legacy class when there is no conflict
+// among its opted-in superinterfaces: `C#` is considered to implement
+// `A<int*>`, for all `#`.
+
+class C0 extends B {}
+
+class C1 with B {}
+
+abstract class C2 implements B {}
+
+class C3 extends Bq {}
+
+class C4 with Bq {}
+
+abstract class C5 implements Bq {}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_lib.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_lib.dart
new file mode 100644
index 0000000..c936fd2
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_lib.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 library declares two null-safe classes `B` and `Bq` with members
+// using non-nullable types respectively nullable types. Subtypes having
+// either `B` or `Bq` as a superinterface are declared in the library
+// 'legacy_resolves_conflict_3_legacy_lib.dart', and the library
+// 'legacy_resolves_conflict_3_lib2.dart' declares an override. See the
+// comments there for further information.
+
+// Naming convention: Class `B` has member signatures using non-nullable types,
+// and `Bq` has member signatures using nullable types (`q` refers to the
+// question marks).
+
+class B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+class Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_lib2.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_lib2.dart
new file mode 100644
index 0000000..8702ebe
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_lib2.dart
@@ -0,0 +1,188 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Each class defined here has a legacy superinterface as well as a null-safe
+// superinterface, thus bringing together legacy and null-safe member
+// signatures. Some classes also contain overriding member declarations.
+// Each class has a comment indicating the expected member signatures.
+// We use this to test whether the resulting member signature is computed
+// correctly, cf. 'legacy_resolves_conflict_3{,_error}_test.dart'.
+
+import 'legacy_resolves_conflict_3_legacy_lib.dart';
+import 'legacy_resolves_conflict_3_lib.dart';
+
+// Naming conventions: Every class in this library has a name starting with
+// `D`, to identify it as belonging to this group: Opted-in, subtype of a
+// legacy class.
+//
+// Every class name ends in a digit, that we designate as `#`. A class whose
+// name ends in `#` extends or implements the legacy class `C#`.
+//
+// The class `DiX#` implements `X` (`i` refers to `implements`). The class
+// `DwX#` applies `X` as a mixin (`w` refers to `with`). The class `DiXO#`
+// implements `X` and declares overriding members using non-nullable
+// types. Class `DiXOq#` implements `X` and declares overriding members using
+// nullable types.
+
+// When `C#` is considered to implement `A<int*>` it becomes possible for a
+// subtype of `C#` to have a superinterface with members that are compatible
+// with the members of `A<int*>`, even in the case where they conflict with
+// members of `A<int>`/`A<int?>`, which is actually found in the superinterface
+// graph of `C#`. That kind of relationship is created by this library.
+
+// Member signatures: B.
+class DiB0 extends C0 implements B {}
+
+// Member signatures: Bq.
+class DiBq0 extends C0 implements Bq {}
+
+// Member signatures: B.
+class DwB0 extends C0 with B {}
+
+// Member signatures: Bq.
+class DwBq0 extends C0 with Bq {}
+
+// Member signatures: B.
+class DiBO0 implements C0, B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+// Member signatures: Bq.
+class DiBqOq0 implements C0, Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+// Member signatures: B.
+class DiB1 extends C1 implements B {}
+
+// Member signatures: Bq.
+class DiBq1 extends C1 implements Bq {}
+
+// Member signatures: B.
+class DwB1 extends C1 with B {}
+
+// Member signatures: Bq.
+class DwBq1 extends C1 with Bq {}
+
+// Member signatures: B.
+class DiBO1 implements C1, B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+// Member signatures: Bq.
+class DiBqOq1 implements C1, Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+// Member signatures: B.
+abstract class DiB2 extends C2 implements B {}
+
+// Member signatures: Bq.
+abstract class DiBq2 extends C2 implements Bq {}
+
+// Member signatures: B.
+class DwB2 extends C2 with B {}
+
+// Member signatures: Bq.
+class DwBq2 extends C2 with Bq {}
+
+// Member signatures: B.
+class DiBO2 implements C2, B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+// Member signatures: Bq.
+class DiBqOq2 implements C2, Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+// Member signatures: B.
+class DiB3 extends C3 implements B {}
+
+// Member signatures: Bq.
+class DiBq3 extends C3 implements Bq {}
+
+// Member signatures: B.
+class DwB3 extends C3 with B {}
+
+// Member signatures: Bq.
+class DwBq3 extends C3 with Bq {}
+
+// Member signatures: B.
+class DiBO3 implements C3, B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+// Member signatures: Bq.
+class DiBqOq3 implements C3, Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+// Member signatures: B.
+class DiB4 extends C4 implements B {}
+
+// Member signatures: Bq.
+class DiBq4 extends C4 implements Bq {}
+
+// Member signatures: B.
+class DwB4 extends C4 with B {}
+
+// Member signatures: Bq.
+class DwBq4 extends C4 with Bq {}
+
+// Member signatures: B.
+class DiBO4 implements C4, B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+// Member signatures: Bq.
+class DiBqOq4 implements C4, Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
+
+// Member signatures: B.
+abstract class DiB5 extends C5 implements B {}
+
+// Member signatures: Bq.
+abstract class DiBq5 extends C5 implements Bq {}
+
+// Member signatures: B.
+class DwB5 extends C5 with B {}
+
+// Member signatures: Bq.
+class DwBq5 extends C5 with Bq {}
+
+// Member signatures: B.
+class DiBO5 implements C5, B {
+  List<int Function(int)> get a => [];
+  set a(List<int Function(int)> _) {}
+  int Function(int) m(int Function(int) x) => x;
+}
+
+// Member signatures: Bq.
+class DiBqOq5 implements C5, Bq {
+  List<int? Function(int?)> get a => [];
+  set a(List<int? Function(int?)> _) {}
+  int? Function(int?) m(int? Function(int?) x) => x;
+}
diff --git a/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_test.dart b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_test.dart
new file mode 100644
index 0000000..c5ccb58
--- /dev/null
+++ b/tests/language/nnbd/mixed_inheritance/legacy_resolves_conflict_3_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.
+
+// Requirements=nnbd-weak
+
+// Verify that member signatures are computed correctly for null-safe
+// classes having both a legacy and a null-safe superinterface, and with some
+// classes also overriding declarations in the class itself. The expected
+// member signatures are indicated in comments on each class in the library
+// 'legacy_resolves_conflict_3_lib2.dart'. This test uses assignability to
+// confirm that the return type of the getter `a` is assignable to the
+// expected type; 'legacy_resolves_conflict_3_error_test.dart' complements
+// this by ascertaining that said return type is not legacy.
+
+import 'package:expect/expect.dart';
+import 'legacy_resolves_conflict_3_lib.dart';
+import 'legacy_resolves_conflict_3_lib2.dart';
+
+void main() {
+  // Ensure that no class is eliminated by tree-shaking.
+  Expect.isNotNull([
+    DiB0, DiBq0, DwB0, DwBq0, DiBO0, DiBqOq0, //
+    DiB1, DiBq1, DwB1, DwBq1, DiBO1, DiBqOq1, //
+    DiB2, DiBq2, DwB2, DwBq2, DiBO2, DiBqOq2, //
+    DiB3, DiBq3, DwB3, DwBq3, DiBO3, DiBqOq3, //
+    DiB4, DiBq4, DwB4, DwBq4, DiBO4, DiBqOq4, //
+    DiB5, DiBq5, DwB5, DwBq5, DiBO5, DiBqOq5, //
+  ]);
+
+  // Verify that some classes have a signature as in `B`.
+  List<List<int Function(int)>> xsB = [
+    DiB0().a, DwB0().a, DiBO0().a, DiB1().a, DwB1().a, DiBO1().a, //
+    /*DiB2,*/ DwB2().a, DiBO2().a, DiB3().a, DwB3().a, DiBO3().a, //
+    DiB4().a, DwB4().a, DiBO4().a, /*DiB5,*/ DwB5().a, DiBO5().a, //
+  ];
+
+  // Verify that some classes have a signature as in `Bq`.
+  List<List<int? Function(int?)>> xsBq = [
+    DiBq0().a, DwBq0().a, DiBqOq0().a, DiBq1().a, DwBq1().a, DiBqOq1().a, //
+    /*DiBq2,*/ DwBq2().a, DiBqOq2().a, DiBq3().a, DwBq3().a, DiBqOq3().a, //
+    DiBq4().a, DwBq4().a, DiBqOq4().a, /*DiBq5,*/ DwBq5().a, DiBqOq5().a, //
+  ];
+
+  void testAbstractClasses(DiB2 diB2, DiBq2 diBq2, DiB5 diB5, DiBq5 diBq5) {
+    List<List<int Function(int)>> xsB = [diB2.a, diB5.a];
+    List<List<int? Function(int?)>> xsBq = [diBq2.a, diBq5.a];
+    print("$xsB, $xsBq");
+  }
+}
diff --git a/tests/language/nnbd/static_errors/default_list_constructor_test.dart b/tests/language/nnbd/static_errors/default_list_constructor_test.dart
index c15b01e..396a087 100644
--- a/tests/language/nnbd/static_errors/default_list_constructor_test.dart
+++ b/tests/language/nnbd/static_errors/default_list_constructor_test.dart
@@ -2,22 +2,35 @@
 // for 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=--enable-experiment=non-nullable
-
-import 'opted_out_library.dart';
-
 // Test that it is an error to call the default List constructor.
 main() {
-  var a = new List<int>(3); //# 01: compile-time error
-  var b = new List<int?>(3); //# 02: compile-time-error
-  var c = new List<int>(); //# 03: compile-time error
-  var d = new List<int?>(); //# 04: compile-time error
-  List<C> c = new List(5); //# 05: compile-time error
-  consumeListOfStringStar(new List(3)); //# 06: compile-time error
+  var a = new List<int>(3);
+  //          ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_LIST_CONSTRUCTOR
+  // [cfe] Can't use the default List constructor.
+  var b = new List<int?>(3);
+  //          ^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_LIST_CONSTRUCTOR
+  // [cfe] Can't use the default List constructor.
+  var c = new List<int>();
+  //          ^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_LIST_CONSTRUCTOR
+  // [cfe] Can't use the default List constructor.
+  var d = new List<int?>();
+  //          ^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_LIST_CONSTRUCTOR
+  // [cfe] Can't use the default List constructor.
+  List<C> e = new List(5);
+  //              ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_LIST_CONSTRUCTOR
+  // [cfe] Can't use the default List constructor.
 }
 
 class A<T> {
-  var l = new List<T>(3); //# 07: compile-time error
+  var l = new List<T>(3);
+  //          ^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_LIST_CONSTRUCTOR
+  // [cfe] Can't use the default List constructor.
 }
 
 class C {}
diff --git a/tests/language/nnbd/static_errors/nullable_in_on_clause_test.dart b/tests/language/nnbd/static_errors/nullable_in_on_clause_test.dart
deleted file mode 100644
index ac7db83..0000000
--- a/tests/language/nnbd/static_errors/nullable_in_on_clause_test.dart
+++ /dev/null
@@ -1,31 +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.
-
-// SharedOptions=--enable-experiment=non-nullable
-
-// Test that it is an error if the type `T` in the on-catch clause `on T catch`
-// is potentially nullable.
-import 'package:expect/expect.dart';
-import 'dart:core';
-import 'dart:core' as core;
-
-main() {
-  try {} catch (e) {}
-  try {} on A catch (e) {}
-  try {} on A? {} //# 01: compile-time error
-}
-
-class A {}
-
-class B<C> {
-  m() {
-    try {} on C {} //# 02: compile-time error
-  }
-}
-
-class D<E extends Object> {
-  m() {
-    try {} on E {}
-  }
-}
\ No newline at end of file
diff --git a/tests/language/nnbd/static_errors/opted_out_library.dart b/tests/language/nnbd/static_errors/opted_out_library.dart
deleted file mode 100644
index fefacf5..0000000
--- a/tests/language/nnbd/static_errors/opted_out_library.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-// @dart=2.3
-
-void consumeListOfStringStar(List<String> l) {}
diff --git a/tests/language/nnbd/static_errors/throw_of_invalid_type_test.dart b/tests/language/nnbd/static_errors/throw_of_invalid_type_test.dart
new file mode 100644
index 0000000..564a7b4
--- /dev/null
+++ b/tests/language/nnbd/static_errors/throw_of_invalid_type_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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error if the static type of `e` in the expression
+// `throw e` is not assignable to `Object`.
+import 'package:expect/expect.dart';
+
+main() {
+  f1(0);
+  f2(0);
+  f3();
+}
+
+void f1(int a) {
+  try {
+    throw a;
+  } catch (e) {}
+}
+
+void f2(int? a) {
+  try {
+    throw a; //# 01: compile-time error
+  } catch (e) {}
+}
+
+void f3() {
+  try {
+    throw null; //# 02: compile-time error
+  } catch (e) {}
+}
diff --git a/tests/language/nnbd/subtyping/regress41272_test.dart b/tests/language/nnbd/subtyping/regress41272_test.dart
new file mode 100644
index 0000000..2519404
--- /dev/null
+++ b/tests/language/nnbd/subtyping/regress41272_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=--optimization_counter_threshold=10 --deterministic
+// Requirements=nnbd-strong
+
+// Verifies that null cannot be casted to Object.
+// Regression test for https://github.com/dart-lang/sdk/issues/41272.
+
+import 'package:expect/expect.dart';
+
+doTest() {
+  dynamic x;
+  Expect.throwsTypeError(() {
+    x as Object;
+  });
+}
+
+main() {
+  for (int i = 0; i < 20; ++i) {
+    doTest();
+  }
+}
diff --git a/tests/language/nnbd/top_merge/top_merge_interfaces_direct_error_test.dart b/tests/language/nnbd/top_merge/top_merge_interfaces_direct_error_test.dart
new file mode 100644
index 0000000..311fe6e
--- /dev/null
+++ b/tests/language/nnbd/top_merge/top_merge_interfaces_direct_error_test.dart
@@ -0,0 +1,490 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+// Tests several aspects of the TOP_MERGE algorithm for merging super-interfaces.
+
+class A<T> {}
+
+class B<T> extends A<T> {}
+
+T deconstruct<T>(A<T> x) => throw "Unreachable";
+
+void takesObject(Object x) {}
+
+class D0 extends A<dynamic> implements B<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D1 extends A<Object?> implements B<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D2 extends A<void> implements B<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D3 extends A<Object?> implements B<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D4 extends A<void> implements B<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D5 extends A<dynamic> implements B<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D6 extends A<void> implements B<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object?>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D7 extends A<dynamic> implements B<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we implement A<dynamic>
+  }
+}
+
+// Test the same examples with top level normalization
+
+class ND0 extends A<FutureOr<dynamic>> implements B<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND1 extends A<FutureOr<Object?>> implements B<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND2 extends A<FutureOr<void>> implements B<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND3 extends A<FutureOr<Object?>> implements B<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND4 extends A<FutureOr<void>> implements B<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND5 extends A<FutureOr<dynamic>> implements B<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND6 extends A<FutureOr<void>> implements B<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object?>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND7 extends A<FutureOr<dynamic>> implements B<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we implement A<dynamic>
+  }
+}
+
+// Test the same examples with deep normalization
+
+class DND0 extends A<FutureOr<dynamic> Function()>
+    implements B<Object? Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND1 extends A<FutureOr<Object?> Function()>
+    implements B<dynamic Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND2 extends A<FutureOr<void> Function()>
+    implements B<Object? Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND3 extends A<FutureOr<Object?> Function()>
+    implements B<void Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND4 extends A<FutureOr<void> Function()>
+    implements B<dynamic Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND5 extends A<FutureOr<dynamic> Function()>
+    implements B<void Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND6 extends A<FutureOr<void> Function()> implements B<void Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object? Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND7 extends A<FutureOr<dynamic> Function()>
+    implements B<dynamic Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we implement A<dynamic Function()>
+  }
+}
+
+// Test the same examples with deep normalization + typedefs
+
+typedef Wrap<T> = FutureOr<T>? Function();
+
+class WND0 extends A<Wrap<FutureOr<dynamic>>> implements B<Wrap<Object?>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND1 extends A<Wrap<FutureOr<Object?>>> implements B<Wrap<dynamic>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND2 extends A<Wrap<FutureOr<void>>> implements B<Wrap<Object?>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND3 extends A<Wrap<FutureOr<Object?>>> implements B<Wrap<void>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND4 extends A<Wrap<FutureOr<void>>> implements B<Wrap<dynamic>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND5 extends A<Wrap<FutureOr<dynamic>>> implements B<Wrap<void>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND6 extends A<Wrap<FutureOr<void>>> implements B<Wrap<void>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object? Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND7 extends A<Wrap<FutureOr<dynamic>>> implements B<Wrap<dynamic>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we implement A<dynamic Function()>
+  }
+}
diff --git a/tests/language/nnbd/top_merge/top_merge_interfaces_mixin_error_test.dart b/tests/language/nnbd/top_merge/top_merge_interfaces_mixin_error_test.dart
new file mode 100644
index 0000000..e7241c5
--- /dev/null
+++ b/tests/language/nnbd/top_merge/top_merge_interfaces_mixin_error_test.dart
@@ -0,0 +1,483 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+// Tests several aspects of the TOP_MERGE algorithm for merging super-interfaces.
+
+class A<T> {}
+
+mixin M<T> implements A<T> {}
+
+T deconstruct<T>(A<T> x) => throw "Unreachable";
+
+void takesObject(Object x) {}
+
+class D0 extends A<dynamic> with M<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D1 extends A<Object?> with M<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D2 extends A<void> with M<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D3 extends A<Object?> with M<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D4 extends A<void> with M<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D5 extends A<dynamic> with M<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D6 extends A<void> with M<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object?>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D7 extends A<dynamic> with M<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we implement A<dynamic>
+  }
+}
+
+// Test the same examples with top level normalization
+
+class ND0 extends A<FutureOr<dynamic>> with M<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND1 extends A<FutureOr<Object?>> with M<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND2 extends A<FutureOr<void>> with M<Object?> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND3 extends A<FutureOr<Object?>> with M<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND4 extends A<FutureOr<void>> with M<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND5 extends A<FutureOr<dynamic>> with M<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void>
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND6 extends A<FutureOr<void>> with M<void> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we do not implement A<dynamic>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object?>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND7 extends A<FutureOr<dynamic>> with M<dynamic> {
+  void test() {
+    var x = deconstruct(this);
+    x.foo; // Check that we implement A<dynamic>
+  }
+}
+
+// Test the same examples with deep normalization
+
+class DND0 extends A<FutureOr<dynamic> Function()> with M<Object? Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND1 extends A<FutureOr<Object?> Function()> with M<dynamic Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND2 extends A<FutureOr<void> Function()> with M<Object? Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND3 extends A<FutureOr<Object?> Function()> with M<void Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND4 extends A<FutureOr<void> Function()> with M<dynamic Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND5 extends A<FutureOr<dynamic> Function()> with M<void Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND6 extends A<FutureOr<void> Function()> with M<void Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object? Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND7 extends A<FutureOr<dynamic> Function()> with M<dynamic Function()> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we implement A<dynamic Function()>
+  }
+}
+
+// Test the same examples with deep normalization + typedefs
+
+typedef Wrap<T> = FutureOr<T>? Function();
+
+class WND0 extends A<Wrap<FutureOr<dynamic>>> with M<Wrap<Object?>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND1 extends A<Wrap<FutureOr<Object?>>> with M<Wrap<dynamic>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND2 extends A<Wrap<FutureOr<void>>> with M<Wrap<Object?>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND3 extends A<Wrap<FutureOr<Object?>>> with M<Wrap<void>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND4 extends A<Wrap<FutureOr<void>>> with M<Wrap<dynamic>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND5 extends A<Wrap<FutureOr<dynamic>>> with M<Wrap<void>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<void Function()>
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND6 extends A<Wrap<FutureOr<void>>> with M<Wrap<void>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we do not implement A<dynamic Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that we do not implement A<Object? Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that we do not implement A<Object Function()>
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND7 extends A<Wrap<FutureOr<dynamic>>> with M<Wrap<dynamic>> {
+  void test() {
+    var x = deconstruct(this)();
+    x.foo; // Check that we implement A<dynamic Function()>
+  }
+}
diff --git a/tests/language/nnbd/top_merge/top_merge_members_direct_error_test.dart b/tests/language/nnbd/top_merge/top_merge_members_direct_error_test.dart
new file mode 100644
index 0000000..79beb98
--- /dev/null
+++ b/tests/language/nnbd/top_merge/top_merge_members_direct_error_test.dart
@@ -0,0 +1,528 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+// Tests several aspects of the TOP_MERGE algorithm for merging members
+
+class A<T> {
+  T member() {
+    throw "Unreachable";
+  }
+}
+
+class B<T> {
+  T member() {
+    throw "Unreachable";
+  }
+}
+
+void takesObject(Object x) {}
+
+class D0 extends A<dynamic> implements B<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D1 extends A<Object?> implements B<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D2 extends A<void> implements B<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D3 extends A<Object?> implements B<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D4 extends A<void> implements B<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D5 extends A<dynamic> implements B<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D6 extends A<void> implements B<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return Object?
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D7 extends A<dynamic> implements B<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns dynamic
+  }
+}
+
+// Test the same examples with top level normalization
+
+class ND0 extends A<FutureOr<dynamic>> implements B<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND1 extends A<FutureOr<Object?>> implements B<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND2 extends A<FutureOr<void>> implements B<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND3 extends A<FutureOr<Object?>> implements B<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND4 extends A<FutureOr<void>> implements B<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND5 extends A<FutureOr<dynamic>> implements B<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND6 extends A<FutureOr<void>> implements B<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return dynamic
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return Object?
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return Object
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND7 extends A<FutureOr<dynamic>> implements B<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns dynamic
+  }
+}
+
+// Test the same examples with deep normalization
+
+class DND0 extends A<FutureOr<dynamic> Function()>
+    implements B<Object? Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND1 extends A<FutureOr<Object?> Function()>
+    implements B<dynamic Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND2 extends A<FutureOr<void> Function()>
+    implements B<Object? Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND3 extends A<FutureOr<Object?> Function()>
+    implements B<void Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND4 extends A<FutureOr<void> Function()>
+    implements B<dynamic Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND5 extends A<FutureOr<dynamic> Function()>
+    implements B<void Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND6 extends A<FutureOr<void> Function()> implements B<void Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return Object? Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND7 extends A<FutureOr<dynamic> Function()>
+    implements B<dynamic Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns dynamic Function()
+  }
+}
+
+// Test the same examples with deep normalization + typedefs
+
+typedef Wrap<T> = FutureOr<T>? Function();
+
+class WND0 extends A<Wrap<FutureOr<dynamic>>> implements B<Wrap<Object?>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND1 extends A<Wrap<FutureOr<Object?>>> implements B<Wrap<dynamic>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND2 extends A<Wrap<FutureOr<void>>> implements B<Wrap<Object?>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND3 extends A<Wrap<FutureOr<Object?>>> implements B<Wrap<void>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND4 extends A<Wrap<FutureOr<void>>> implements B<Wrap<dynamic>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND5 extends A<Wrap<FutureOr<dynamic>>> implements B<Wrap<void>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return void Function()
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND6 extends A<Wrap<FutureOr<void>>> implements B<Wrap<void>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return dynamic Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return Object? Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return Object Function()
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND7 extends A<Wrap<FutureOr<dynamic>>> implements B<Wrap<dynamic>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns dynamic Function()
+  }
+}
diff --git a/tests/language/nnbd/top_merge/top_merge_members_mixin_error_test.dart b/tests/language/nnbd/top_merge/top_merge_members_mixin_error_test.dart
new file mode 100644
index 0000000..4be0ef7
--- /dev/null
+++ b/tests/language/nnbd/top_merge/top_merge_members_mixin_error_test.dart
@@ -0,0 +1,504 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+// Tests several aspects of the TOP_MERGE algorithm for merging super-interfaces.
+// This tests that TOP_MERGE is not applied when a mixin causes an override.
+// Instead, the signature of the mixed in method should apply.
+
+class A<T> {
+  T member() {
+    throw "Unreachable";
+  }
+}
+
+mixin M<T> {
+  T member() {
+    throw "Unreachable";
+  }
+}
+
+void takesObject(Object x) {}
+
+class D0 extends A<dynamic> with M<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D1 extends A<Object?> with M<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class D2 extends A<void> with M<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D3 extends A<Object?> with M<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D4 extends A<void> with M<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class D5 extends A<dynamic> with M<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D6 extends A<void> with M<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D7 extends A<dynamic> with M<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+// Test the same examples with top level normalization
+
+class ND0 extends A<FutureOr<dynamic>> with M<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND1 extends A<FutureOr<Object?>> with M<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class ND2 extends A<FutureOr<void>> with M<Object?> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND3 extends A<FutureOr<Object?>> with M<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND4 extends A<FutureOr<void>> with M<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class ND5 extends A<FutureOr<dynamic>> with M<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND6 extends A<FutureOr<void>> with M<void> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND7 extends A<FutureOr<dynamic>> with M<dynamic> {
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+// Test the same examples with deep normalization
+
+class DND0 extends A<FutureOr<dynamic> Function()> with M<Object? Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND1 extends A<FutureOr<Object?> Function()> with M<dynamic Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns `dynamic Function()`
+  }
+}
+
+class DND2 extends A<FutureOr<void> Function()> with M<Object? Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND3 extends A<FutureOr<Object?> Function()> with M<void Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object? Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND4 extends A<FutureOr<void> Function()> with M<dynamic Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns `dynamic Function()`
+  }
+}
+
+class DND5 extends A<FutureOr<dynamic> Function()> with M<void Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object? Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND6 extends A<FutureOr<void> Function()> with M<void Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object? Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND7 extends A<FutureOr<dynamic> Function()> with M<dynamic Function()> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns `dynamic Function()`
+  }
+}
+
+// Test the same examples with deep normalization + typedefs
+
+// With all mixin examples, no normalization is specified, and so
+// all errors and warnings should look like the `Object?` errors and
+// warnings (we don't distinguish between the method sets on `Object?`
+// and `FutureOr<T>` for any `T`).
+
+typedef Wrap<T> = FutureOr<T>? Function();
+
+class WND0 extends A<Wrap<FutureOr<dynamic>>> with M<Wrap<Object?>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND1 extends A<Wrap<FutureOr<Object?>>> with M<Wrap<dynamic>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND2 extends A<Wrap<FutureOr<void>>> with M<Wrap<Object?>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND3 extends A<Wrap<FutureOr<Object?>>> with M<Wrap<void>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND4 extends A<Wrap<FutureOr<void>>> with M<Wrap<dynamic>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND5 extends A<Wrap<FutureOr<dynamic>>> with M<Wrap<void>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND6 extends A<Wrap<FutureOr<void>>> with M<Wrap<void>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND7 extends A<Wrap<FutureOr<dynamic>>> with M<Wrap<dynamic>> {
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
diff --git a/tests/language/nnbd/top_merge/top_merge_members_override_error_test.dart b/tests/language/nnbd/top_merge/top_merge_members_override_error_test.dart
new file mode 100644
index 0000000..85a5efb
--- /dev/null
+++ b/tests/language/nnbd/top_merge/top_merge_members_override_error_test.dart
@@ -0,0 +1,626 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+// Tests several aspects of the TOP_MERGE algorithm for merging super-interfaces.
+// This tests that TOP_MERGE is not applied when a class directly overrides a
+// method. Instead, the signature of the overriding method should apply.
+
+class A<T> {
+  T member() {
+    throw "Unreachable";
+  }
+}
+
+void takesObject(Object x) {}
+
+class D0 extends A<dynamic> {
+  Object? member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D1 extends A<Object?> {
+  dynamic member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class D2 extends A<void> {
+  Object? member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D3 extends A<Object?> {
+  void member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D4 extends A<void> {
+  dynamic member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class D5 extends A<dynamic> {
+  void member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D6 extends A<void> {
+  void member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class D7 extends A<dynamic> {
+  dynamic member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+// Test the same examples with top level normalization
+
+class ND0 extends A<FutureOr<dynamic>> {
+  Object? member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND1 extends A<FutureOr<Object?>> {
+  dynamic member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class ND2 extends A<FutureOr<void>> {
+  Object? member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void`
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND3 extends A<FutureOr<Object?>> {
+  void member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND4 extends A<FutureOr<void>> {
+  dynamic member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+class ND5 extends A<FutureOr<dynamic>> {
+  void member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND6 extends A<FutureOr<void>> {
+  void member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member does not return `dynamic`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object?`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class ND7 extends A<FutureOr<dynamic>> {
+  dynamic member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member();
+    x.foo; // Check that member returns `dynamic`
+  }
+}
+
+// Test the same examples with deep normalization
+
+class DND0 extends A<FutureOr<dynamic> Function()> {
+  Object? Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND1 extends A<FutureOr<Object?> Function()> {
+  dynamic Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns `dynamic Function()`
+  }
+}
+
+class DND2 extends A<FutureOr<void> Function()> {
+  Object? Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND3 extends A<FutureOr<Object?> Function()> {
+  void Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object? Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND4 extends A<FutureOr<void> Function()> {
+  dynamic Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns `dynamic Function()`
+  }
+}
+
+class DND5 extends A<FutureOr<dynamic> Function()> {
+  void Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object? Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND6 extends A<FutureOr<void> Function()> {
+  void Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `Object? Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class DND7 extends A<FutureOr<dynamic> Function()> {
+  dynamic Function() member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member returns `dynamic Function()`
+  }
+}
+
+// Test the same examples with deep normalization + typedefs
+
+// With all override examples, no normalization is specified, and so
+// all errors and warnings should look like the `Object?` errors and
+// warnings (we don't distinguish between the method sets on `Object?`
+// and `FutureOr<T>` for any `T`).
+
+typedef Wrap<T> = FutureOr<T>? Function();
+
+class WND0 extends A<Wrap<FutureOr<dynamic>>> {
+  Wrap<FutureOr<Object?>> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND1 extends A<Wrap<FutureOr<Object?>>> {
+  Wrap<dynamic> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND2 extends A<Wrap<FutureOr<void>>> {
+  Wrap<Object?> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND3 extends A<Wrap<FutureOr<Object?>>> {
+  Wrap<void> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND4 extends A<Wrap<FutureOr<void>>> {
+  Wrap<dynamic> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND5 extends A<Wrap<FutureOr<dynamic>>> {
+  Wrap<void> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND6 extends A<Wrap<FutureOr<void>>> {
+  Wrap<void> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
+
+class WND7 extends A<Wrap<FutureOr<dynamic>>> {
+  Wrap<dynamic> member() {
+    throw "Unreachable";
+  }
+
+  void test() {
+    var self = this;
+    var x = self.member()();
+    x.foo; // Check that member does not return `dynamic Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+    x.toString; // Check that member does not return `void Function()`
+    takesObject(x); // Check that member does not return `Object Function()`
+    //   ^
+    // [analyzer] unspecified
+    // [cfe] unspecified
+  }
+}
diff --git a/tests/language/operator/invalid_operators_test.dart b/tests/language/operator/invalid_operators_test.dart
index 5faf742..4e90b5b 100644
--- a/tests/language/operator/invalid_operators_test.dart
+++ b/tests/language/operator/invalid_operators_test.dart
@@ -162,7 +162,7 @@
 
 class Operators3 {
   operator ==([dynamic a]) => true;
-  //           ^
+  //           ^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
   //                   ^
   // [cfe] An operator can't have optional parameters.
diff --git a/tests/language/regress/regress40765_test.dart b/tests/language/regress/regress40765_test.dart
new file mode 100644
index 0000000..175be2d
--- /dev/null
+++ b/tests/language/regress/regress40765_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.
+
+class Something {
+  final int x;
+  Something({required this.x});
+}
+
+abstract class Base {
+  Something get x;
+}
+
+class Child1 extends Base {
+  final Something x;
+  Child1({required this.x});
+}
+
+class Child2 extends Base {
+  final int y;
+  final Something x;
+  Child2({required this.x, required this.y});
+}
+
+@pragma('vm:never-inline')
+int foo(int k, Base x) {
+  var y = 0;
+  for (var i = 0; i < k; i++) {
+    x as Child1;
+    // Next line will be hoisted out as x.{Child1::x}.{Something::x}
+    // and at foo(0, Child2(..., y: 24)) will end up executing as
+    // x.{Child1::x} -> will load Child2::y (24) and then segfault.
+    y = x.x.x;
+  }
+  return y;
+}
+
+void main() {
+  print(foo(1, Child1(x: Something(x: 1))));
+  print(foo(1, Child1(x: Something(x: 2))));
+  print(foo(0, Child2(x: Something(x: 42), y: 24)));
+}
diff --git a/tests/language_2/async/return_types_test.dart b/tests/language_2/async/return_types_test.dart
index 473150f..659d275 100644
--- a/tests/language_2/async/return_types_test.dart
+++ b/tests/language_2/async/return_types_test.dart
@@ -27,22 +27,16 @@
 // [analyzer] STATIC_TYPE_WARNING.WRONG_NUMBER_OF_TYPE_ARGUMENTS
 // [cfe] Expected 1 type arguments.
 foo4() async {
-// [error line 29, column 1]
-// [cfe] Functions marked 'async' must have a return type assignable to 'Future'.
   return "String";
-  //     ^
-  // [cfe] A value of type 'String' can't be assigned to a variable of type 'FutureOr<invalid-type>'.
 }
 
 int
-// [error line 37, column 1, length 3]
+// [error line 33, column 1, length 3]
 // [analyzer] STATIC_TYPE_WARNING.ILLEGAL_ASYNC_RETURN_TYPE
 foo5() async {
-// [error line 40, column 1]
+// [error line 36, column 1]
 // [cfe] Functions marked 'async' must have a return type assignable to 'Future'.
   return 3;
-  //     ^
-  // [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
 }
 
 Future<int> foo6() async {
diff --git a/tests/language_2/const/inference_test.dart b/tests/language_2/const/inference_test.dart
index 2e556bf..b925f20 100644
--- a/tests/language_2/const/inference_test.dart
+++ b/tests/language_2/const/inference_test.dart
@@ -122,10 +122,10 @@
   expectOfType<Null Function(Object)>(getFunction());
 }
 
-/// Tests that type inference for constants does not reference the type
-/// parameter. Instead, free type parameters should substituted to obtain the
+/// Tests that use type inference for constants do not reference the type
+/// parameter. Instead, free type parameters are substituted to obtain the
 /// least closure (e.g. `List<T>` becomes `List<Null>` and `R Function(T)`
-/// becomes `Null Function(Object)`).
+/// becomes `Null Function(Object?)`).
 main() {
   testClassInstance();
   testImplicitConstClassInstance();
diff --git a/tests/language_2/const/runtime_test.dart b/tests/language_2/const/runtime_test.dart
deleted file mode 100644
index bb84f01..0000000
--- a/tests/language_2/const/runtime_test.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// TODO(multitest): This was automatically migrated from a multitest and may
-// contain strange or dead code.
-
-// 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.
-
-class C {
-  factory C() => null;
-}
-
-
-t() => null;
-
-
-get v => null;
-
-main() {
-
-      dynamic x = t();
-
-
-      dynamic z = v;
-}
diff --git a/tests/language_2/control_flow_collections/await_for_null_test.dart b/tests/language_2/control_flow_collections/await_for_null_test.dart
index f1c1460..b176ea0 100644
--- a/tests/language_2/control_flow_collections/await_for_null_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_null_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.
 
-// Test that a null stream expression procudes a runtime error.
+// Test that a null stream expression produces a runtime error.
 import 'package:async_helper/async_helper.dart';
 
 void main() {
diff --git a/tests/language_2/covariant/tear_off_type_test.dart b/tests/language_2/covariant/tear_off_type_test.dart
index c3a848c..ba52670e 100644
--- a/tests/language_2/covariant/tear_off_type_test.dart
+++ b/tests/language_2/covariant/tear_off_type_test.dart
@@ -16,10 +16,10 @@
 
 void main() {
   var tearoff = g(new C<int>());
-  // Since C.f's x parameter is covariant, its type is changed to Object when
+  // Since C.f's x parameter is covariant, its type is changed to `Object?` when
   // determining the type of the tearoff.  So the type of the tearoff should be
-  // `(Object) -> int`.  (Not, for example, `(List<Object>) -> int` or
-  // `(List<Object>) -> Object`)
+  // `(Object?) -> int`.  (Not, for example, `(List<Object?>) -> int` or
+  // `(List<Object?>) -> Object?`)
   Expect.isTrue(tearoff is F<Object, int>);
   // Because the function accepts any object, we can pass strings to it.  This
   // will not work in Dart 1.
diff --git a/tests/language_2/double/to_string_as_fixed2_test.dart b/tests/language_2/double/to_string_as_fixed2_test.dart
index bc76e63..3040a30 100644
--- a/tests/language_2/double/to_string_as_fixed2_test.dart
+++ b/tests/language_2/double/to_string_as_fixed2_test.dart
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 // Test basic integer operations.
 
+// [NNBD non-migrated]: This test has no language/ counterpart. The static
+// errors are just redundant tests of the static type system, and the runtime
+// errors are redundant with to_string_as_fixed2_runtime_test.dart.
+
 import "package:expect/expect.dart";
 
 main() {
diff --git a/tests/language_2/double/to_string_as_precision2_test.dart b/tests/language_2/double/to_string_as_precision2_test.dart
index e69d0c9..4ce0c34 100644
--- a/tests/language_2/double/to_string_as_precision2_test.dart
+++ b/tests/language_2/double/to_string_as_precision2_test.dart
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 // Test basic integer operations.
 
+// [NNBD non-migrated]: This test has no language/ counterpart. The static
+// errors are just redundant tests of the static type system, and the runtime
+// errors are redundant with to_string_as_precision2_runtime_test.dart.
+
 import "package:expect/expect.dart";
 
 main() {
diff --git a/tests/language_2/dynamic/prefix_core_test.dart b/tests/language_2/dynamic/prefix_core_test.dart
index 7823543..65da032 100644
--- a/tests/language_2/dynamic/prefix_core_test.dart
+++ b/tests/language_2/dynamic/prefix_core_test.dart
@@ -9,10 +9,10 @@
 import "dart:core" as mycore;
 
 void main() {
-  // Should still be available because it is not a member of dart:core.
-  Expect.isTrue(dynamic is mycore.Type);
+  // The built-in type declaration `dynamic`, which is declared in the
+  // library `dart:core`, denotes the `dynamic` type. So, in this library
+  // it must be reference with the prefix.
+  dynamic; //# 01: compile-time error
 
-  Expect.throws(() => mycore.dynamic is mycore.Type, //    //# 01: compile-time error
-                (e) => e is mycore.NoSuchMethodError, //   //# 01: continued
-                'dynamic is not a member of dart:core'); //# 01: continued
+  Expect.isTrue(mycore.dynamic is mycore.Type); //# 02: ok
 }
diff --git a/tests/language_2/extension_methods/static_extension_constant_error_test.dart b/tests/language_2/extension_methods/static_extension_constant_error_test.dart
new file mode 100644
index 0000000..e7a0d0c
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_constant_error_test.dart
@@ -0,0 +1,90 @@
+// 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.
+
+// SharedOptions=--enable-experiment=extension-methods
+
+import 'static_extension_constant_lib.dart';
+
+// Tests that it is an error to invoke an extension method during constant
+// expression evaluation. The expressions should be the same as those in
+// `runtimeExtensionCalls`, so that it is verified that each of them will
+// invoke an extension method.
+
+void main() {
+  // The initializing expressions should be identical to the elements in
+  // `runtimeExtensionCalls`.
+
+  const c01 = ~i;
+  //          ^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c02 = b & b;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c03 = b | b;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c04 = b ^ b;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c05 = i ~/ i;
+  //          ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c06 = i >> i;
+  //          ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c08 = i << i;
+  //          ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c09 = i + i;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c10 = -i;
+  //          ^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c11 = d - d;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c12 = d * d;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c13 = d / d;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c14 = d % d;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c15 = d < i;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c16 = i <= d;
+  //          ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c17 = d > i;
+  //          ^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c18 = i >= i;
+  //          ^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  const c19 = s.length;
+  //          ^^^^^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+}
diff --git a/tests/language_2/extension_methods/static_extension_constant_lib.dart b/tests/language_2/extension_methods/static_extension_constant_lib.dart
new file mode 100644
index 0000000..23d6de9
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_constant_lib.dart
@@ -0,0 +1,55 @@
+// 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.
+
+extension ExtendObject on Object {
+  int operator ~() => 1;
+  bool operator &(Object other) => false;
+  bool operator |(Object other) => false;
+  bool operator ^(Object other) => true;
+  int operator ~/(Object other) => 0;
+  int operator >>(Object other) => 1;
+  // int operator >>>(Object other) => 2; // Requires triple-shift.
+  int operator <<(Object other) => 0;
+  int operator +(Object other) => 0;
+  double operator -() => 1.0;
+  double operator -(Object other) => 1.0;
+  double operator *(Object other) => 1.0;
+  double operator /(Object other) => 2.0;
+  double operator %(Object other) => 1.0;
+  bool operator <(Object other) => false;
+  bool operator <=(Object other) => true;
+  bool operator >(Object other) => true;
+  bool operator >=(Object other) => false;
+  int get length => 1;
+}
+
+const Object b = true;
+const Object i = 3;
+const Object d = 2.4;
+const Object s = 'Hello!';
+
+// These expressions should be identical to the ones in
+// static_extension_constant_{,error}_test.dart, to ensure that
+// they invoke an extension method, and that this is an error.
+var runtimeExtensionCalls = <Object>[
+  ~i,
+  b & b,
+  b | b,
+  b ^ b,
+  i ~/ i,
+  i >> i,
+  // i >>> i, // Requries triple-shift.
+  i << i,
+  i + i,
+  -i,
+  d - d,
+  d * d,
+  d / d,
+  d % d,
+  d < i,
+  i <= d,
+  d > i,
+  i >= i,
+  s.length,
+];
diff --git a/tests/language_2/extension_methods/static_extension_constant_test.dart b/tests/language_2/extension_methods/static_extension_constant_test.dart
new file mode 100644
index 0000000..1295d4a
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_constant_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+// SharedOptions=--enable-experiment=extension-methods
+
+import 'package:expect/expect.dart';
+import 'static_extension_constant_lib.dart' hide b, i, d, s;
+import 'static_extension_constant_lib.dart' as lib show b, i, d, s;
+
+// Ensure that all expressions in runtimeExtensionCalls invoke
+// an extension method rather than an instance method, such that
+// static_extension_constant_error_test gets an error for them all.
+
+const dynamic b = lib.b;
+const dynamic i = lib.i;
+const dynamic d = lib.d;
+const dynamic s = lib.s;
+
+// These expressions should be identical to those in
+// `lib.runtimeExtensionCalls`.
+var dynamicInstanceCalls = <Object>[
+  ~i,
+  b & b,
+  b | b,
+  b ^ b,
+  i ~/ i,
+  i >> i,
+  // i >>> i, // Requries triple-shift.
+  i << i,
+  i + i,
+  -i,
+  d - d,
+  d * d,
+  d / d,
+  d % d,
+  d < i,
+  i <= d,
+  d > i,
+  i >= i,
+  s.length,
+];
+
+void main() {
+  for (int i = 0; i < dynamicInstanceCalls.length; ++i) {
+    Expect.notEquals(dynamicInstanceCalls[i], runtimeExtensionCalls[i]);
+  }
+}
diff --git a/tests/language_2/function/type_alias9_test.dart b/tests/language_2/function/type_alias9_test.dart
index d7e4c1f..fa15400 100644
--- a/tests/language_2/function/type_alias9_test.dart
+++ b/tests/language_2/function/type_alias9_test.dart
@@ -14,7 +14,5 @@
 
 main() {
   F foo(G g) => g;
-  //            ^
-  // [cfe] A value of type 'void Function(List<invalid-type>)' can't be assigned to a variable of type 'void Function(List<void Function(List<invalid-type>)>)'.
   foo(null);
 }
diff --git a/tests/language_2/mixin/invalid_override_in_mixin_test.dart b/tests/language_2/mixin/invalid_override_in_mixin_test.dart
index b8edfea..bd79f66 100644
--- a/tests/language_2/mixin/invalid_override_in_mixin_test.dart
+++ b/tests/language_2/mixin/invalid_override_in_mixin_test.dart
@@ -13,7 +13,6 @@
 
 class C extends Object with A {
 //    ^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'A' to 'Object' introduces an erroneous override of 'noSuchMethod'.
 //    ^
 // [cfe] Class 'Object with A' inherits multiple members named 'noSuchMethod' with incompatible signatures.
diff --git a/tests/language_2/mixin/method_override_test.dart b/tests/language_2/mixin/method_override_test.dart
index 3b8e104..3987455 100644
--- a/tests/language_2/mixin/method_override_test.dart
+++ b/tests/language_2/mixin/method_override_test.dart
@@ -22,7 +22,6 @@
 // Wrong return type.
 abstract class C1 = CII with CIS;
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'C1' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C1' introduces an erroneous override of 'id'.
@@ -30,7 +29,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C2 extends CII with CIS {}
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'CIS' to 'CII' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'CII with CIS' inherits multiple members named 'id' with incompatible signatures.
@@ -41,7 +39,6 @@
 // Wrong argument type.
 abstract class C3 = CII with CSI;
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'C3' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C3' introduces an erroneous override of 'id'.
@@ -49,7 +46,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C4 extends CII with CSI {}
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'CSI' to 'CII' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'CII with CSI' inherits multiple members named 'id' with incompatible signatures.
@@ -61,7 +57,6 @@
 abstract class C6 extends CII with CTT<int> {}
 abstract class C7  = CII with CTT<String>;
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'C7' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C7' introduces an erroneous override of 'id'.
@@ -69,7 +64,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C8 extends CII with CTT<String> {}
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'CTT' to 'CII' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'CII with CTT<String>' inherits multiple members named 'id' with incompatible signatures.
@@ -99,7 +93,6 @@
 // It's NOT OK to rename named parameters.
 abstract class N3 = NIIx with NIIy;
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'N3' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N3' introduces an erroneous override of 'id'.
@@ -107,7 +100,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N4 extends NIIx with NIIy {}
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'NIIy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'NIIx with NIIy' inherits multiple members named 'id' with incompatible signatures.
@@ -118,7 +110,6 @@
 // It's NOT OK to drop named parameters.
 abstract class N5 = NIIx with NII;
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'N5' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N5' introduces an erroneous override of 'id'.
@@ -126,7 +117,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N6 extends NIIx with NII {}
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'NII' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'NIIx with NII' inherits multiple members named 'id' with incompatible signatures.
@@ -150,7 +140,6 @@
 abstract class N8 extends NIIx with NBABxy<int, int> {}
 abstract class N9 = NIIx with NBABxy<String, int>;
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'N9' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N9' introduces an erroneous override of 'id'.
@@ -158,7 +147,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N10 extends NIIx with NBABxy<String, int> {}
 //             ^^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'NBABxy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'NIIx with NBABxy<String, int>' inherits multiple members named 'id' with incompatible signatures.
@@ -166,7 +154,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N11 = NIIx with NTTy<int>;
 //             ^^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'N11' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N11' introduces an erroneous override of 'id'.
@@ -174,7 +161,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N12 extends NIIx with NTTy<int> {}
 //             ^^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'NTTy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'NIIx with NTTy<int>' inherits multiple members named 'id' with incompatible signatures.
@@ -182,7 +168,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N13 = NIIx with NTTx<int>;
 //             ^^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'N13' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N13' introduces an erroneous override of 'id'.
@@ -190,7 +175,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N14 extends NIIx with NTTx<int> {}
 //             ^^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'NTTx' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'NIIx with NTTx<int>' inherits multiple members named 'id' with incompatible signatures.
@@ -249,7 +233,6 @@
 abstract class O8 extends OII with OBAB<int, int> {}
 abstract class O9 = OII with OBAB<String, int>;
 //             ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'O9' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'O9' introduces an erroneous override of 'id'.
@@ -257,7 +240,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class O10 extends OII with OBAB<String, int> {}
 //             ^^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Applying the mixin 'OBAB' to 'OII' introduces an erroneous override of 'id'.
 //             ^
 // [cfe] Class 'OII with OBAB<String, int>' inherits multiple members named 'id' with incompatible signatures.
@@ -299,7 +281,6 @@
 class G1 = GTTnum with MTTnum;
 class G2 = GTTnum with MTTint;
 //    ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'G2' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G2' introduces an erroneous override of 'id'.
@@ -307,7 +288,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 class G3 = GTTnum with MTT;
 //    ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'G3' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G3' introduces an erroneous override of 'id'.
@@ -315,7 +295,6 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 class G4 = GTTnum with MTTnumR;
 //    ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
 // [cfe] Class 'G4' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G4' introduces an erroneous override of 'id'.
@@ -323,7 +302,7 @@
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 class G5 = GTTnum with CII;
 //    ^^
-// [analyzer] COMPILE_TIME_ERROR.INCONSISTENT_INHERITANCE
+// [analyzer] STATIC_WARNING.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
 // [cfe] The mixin application class 'G5' introduces an erroneous override of 'id'.
 //    ^
 // [cfe] The non-abstract class 'G5' is missing implementations for these members:
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart
index 49b9cf3..80b22b7 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart
@@ -13,9 +13,9 @@
 // Use the aliased type.
 
 abstract class C {
-  final T<Null> v7;
+  final T<Map> v7;
 
-  C(): v7 = T<D>();
+  C(): v7 = T<Map>();
   //        ^
   // [analyzer] unspecified
   // [cfe] unspecified
@@ -45,7 +45,7 @@
 
 main() {
   var v9 = <Set<T<T>>, Set<T<T>>>{{}: {}};
-  v9[{}] = {T<D>()};
+  v9[{}] = {T<C>()};
   //        ^
   // [analyzer] unspecified
   // [cfe] unspecified
@@ -75,7 +75,7 @@
 // [analyzer] unspecified
 // [cfe] unspecified
 
-  T<C>.name1(D(), null);
+  T<C>.name1(C(), null);
 //^^^^^^^^^^^^^^^^^^^^^
 // [analyzer] unspecified
 // [cfe] unspecified
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart
index ffb06d2..1c2604c 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart
@@ -28,6 +28,7 @@
   List<T<T>> v6 = [];
   final T<Null> v7;
 
+  C(): v7 = null;
   C.name1(this.v5, this.v7);
   factory C.name2(T<D> arg1, T<Null> arg2) = C.name1;
 
diff --git a/tests/language_2/nonfunction_type_aliases/usage_type_variable_error_test.dart b/tests/language_2/nonfunction_type_aliases/usage_type_variable_error_test.dart
index efd4162..b24e824 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_type_variable_error_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_type_variable_error_test.dart
@@ -16,6 +16,14 @@
 
 // Use the aliased type.
 
+class C {
+  final T v12;
+
+  C(): v12 = T();
+  //         ^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+}
 
 abstract class D2 extends C with T {}
 //             ^
@@ -28,6 +36,22 @@
 // [cfe] unspecified
 
 main() {
+  var v14 = <Set<T>, Set<T>>{{}: {}};
+  v14[{}] = {T()};
+  //         ^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  T();
+//^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+  T v17 = foo<T>(T());
+  //             ^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
   T.named();
 //^
 // [analyzer] unspecified
diff --git a/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart b/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart
index 3e10b20..ffd1e16 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart
@@ -32,7 +32,7 @@
   List<T> v11 = [];
   final T v12;
 
-  C(): v12 = T();
+  C(): v12 = null;
   C.name1(this.v10, this.v12);
   factory C.name2(T arg1, T arg2) = C.name1;
 
@@ -57,11 +57,10 @@
 main() {
   var v13 = <T>[];
   var v14 = <Set<T>, Set<T>>{{}: {}};
-  v14[{}] = {T()};
+  v14[{}] = {D1()};
   var v15 = {v13};
   Set<List<T>> v16 = v15;
   v15 = v16;
-  T();
-  T v17 = foo<T>(T());
+  T v17 = foo<T>(null);
   id(v17);
 }
diff --git a/tests/language_2/regress/regress22976_test.dart b/tests/language_2/regress/regress22976_test.dart
index 7b54b5d..63180f8 100644
--- a/tests/language_2/regress/regress22976_test.dart
+++ b/tests/language_2/regress/regress22976_test.dart
@@ -19,6 +19,8 @@
   C<String, int> c2 = new C<String, int>();
   A<int> a0 = c1;
   A<int> a1 = c2;
+  //          ^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
   //          ^
   // [cfe] A value of type 'C<String, int>' can't be assigned to a variable of type 'A<int>'.
 }
diff --git a/tests/language_2/regress/regress34235_test.dart b/tests/language_2/regress/regress34235_test.dart
index d8bf539..7451dc5 100644
--- a/tests/language_2/regress/regress34235_test.dart
+++ b/tests/language_2/regress/regress34235_test.dart
@@ -21,7 +21,6 @@
 
 class Derived extends BaseWithM1 with M2 {}
 //    ^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 // [cfe] Applying the mixin 'M2' to 'BaseWithM1' introduces an erroneous override of 'foo'.
 //                                    ^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
diff --git a/tests/language_2/regress/regress40765_test.dart b/tests/language_2/regress/regress40765_test.dart
new file mode 100644
index 0000000..711cf10
--- /dev/null
+++ b/tests/language_2/regress/regress40765_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.
+
+class Something {
+  final int x;
+  Something({this.x});
+}
+
+abstract class Base {
+  Something get x;
+}
+
+class Child1 extends Base {
+  final Something x;
+  Child1({this.x});
+}
+
+class Child2 extends Base {
+  final int y;
+  final Something x;
+  Child2({this.x, this.y});
+}
+
+@pragma('vm:never-inline')
+int foo(int k, Base x) {
+  var y = 0;
+  for (var i = 0; i < k; i++) {
+    x as Child1;
+    // Next line will be hoisted out as x.{Child1::x}.{Something::x}
+    // and at foo(0, Child2(..., y: 24)) will end up executing as
+    // x.{Child1::x} -> will load Child2::y (24) and then segfault.
+    y = x.x.x;
+  }
+  return y;
+}
+
+void main() {
+  print(foo(1, Child1(x: Something(x: 1))));
+  print(foo(1, Child1(x: Something(x: 2))));
+  print(foo(0, Child2(x: Something(x: 42), y: 24)));
+}
diff --git a/tests/language_2/type_variable/scope_test.dart b/tests/language_2/type_variable/scope_test.dart
index f4c04ca..10051d0 100644
--- a/tests/language_2/type_variable/scope_test.dart
+++ b/tests/language_2/type_variable/scope_test.dart
@@ -25,8 +25,6 @@
     // [cfe] Type variables can't be used in static members.
     //         ^^^^^^^^^^^^^^^^^
     // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
-    //             ^
-    // [cfe] A value of type 'Foo<String>' can't be assigned to a variable of type 'Foo<invalid-type>'.
     return new Foo<String>();
     //     ^^^^^^^^^^^^^^^^^
     // [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
diff --git a/tests/lib/async/catch_errors.dart b/tests/lib/async/catch_errors.dart
index ff9260d..02c403c 100644
--- a/tests/lib/async/catch_errors.dart
+++ b/tests/lib/async/catch_errors.dart
@@ -3,7 +3,7 @@
 import 'dart:async';
 
 Stream catchErrors(dynamic body()) {
-  StreamController controller;
+  late StreamController controller;
 
   bool onError(e, st) {
     controller.add(e);
@@ -19,16 +19,16 @@
 }
 
 runZonedScheduleMicrotask(body(),
-    {void onScheduleMicrotask(void callback()), Function? onError}) {
+    {void onScheduleMicrotask(void callback())?, Function? onError}) {
   if (onScheduleMicrotask == null) {
-    return runZonedGuarded(body, onError);
+    return runZonedGuarded(body, onError as void Function(Object, StackTrace));
   }
-  HandleUncaughtErrorHandler errorHandler;
+  HandleUncaughtErrorHandler? errorHandler;
   if (onError != null) {
     errorHandler = (Zone self, ZoneDelegate parent, Zone zone, error,
         StackTrace stackTrace) {
       try {
-        return self.parent.runUnary(onError, error);
+        return self.parent!.runUnary(onError as void Function(Object), error);
       } catch (e, s) {
         if (identical(e, error)) {
           return parent.handleUncaughtError(zone, error, stackTrace);
@@ -38,10 +38,10 @@
       }
     };
   }
-  ScheduleMicrotaskHandler asyncHandler;
+  ScheduleMicrotaskHandler? asyncHandler;
   if (onScheduleMicrotask != null) {
     asyncHandler = (Zone self, ZoneDelegate parent, Zone zone, f()) {
-      self.parent.runUnary(onScheduleMicrotask, () => zone.runGuarded(f));
+      self.parent!.runUnary(onScheduleMicrotask, () => zone.runGuarded(f));
     };
   }
   ZoneSpecification specification = new ZoneSpecification(
diff --git a/tests/lib/async/event_helper.dart b/tests/lib/async/event_helper.dart
index 671e724..6699366 100644
--- a/tests/lib/async/event_helper.dart
+++ b/tests/lib/async/event_helper.dart
@@ -151,7 +151,7 @@
 }
 
 class CaptureEvents extends Events {
-  StreamSubscription subscription;
+  late StreamSubscription subscription;
   bool cancelOnError = false;
 
   CaptureEvents(Stream stream, {bool cancelOnError: false}) {
diff --git a/tests/lib/async/future_or_type_test.dart b/tests/lib/async/future_or_type_test.dart
index ed6b36e..2ecb31c 100644
--- a/tests/lib/async/future_or_type_test.dart
+++ b/tests/lib/async/future_or_type_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // In strong mode, `FutureOr` should be a valid type in most locations.
+// Requirements=nnbd-strong
 
 import 'dart:async';
 import 'package:expect/expect.dart';
@@ -65,10 +66,10 @@
     nullableVariable = nullableNumFutureDouble;
     nullableVariable = nullableIntFuture;
     nullableVariable = nullableDoubleFuture;
-    nullableVariable = nullableObjectFuture;
 
     // Disallows invalid values.
     // These are all valid down-casts that fail at runtime.
+    Expect.throws(() => nullableVariable = nullableObjectFuture);
     Expect.throws(() => nullableVariable = objectValue);
     Expect.throws(() => nullableVariable = objectFuture);
     Expect.throws(() => nullableVariable = objectFutureInt);
@@ -108,10 +109,10 @@
     nullableFun(nullableNumFutureDouble);
     nullableFun(nullableIntFuture);
     nullableFun(nullableDoubleFuture);
-    nullableFun(nullableObjectFuture);
 
     // Disallows invalid values.
     // These are all valid down-casts that fail at runtime.
+    Expect.throws(() => nullableFun(nullableObjectFuture));
     Expect.throws(() => nullableFun(objectValue));
     Expect.throws(() => nullableFun(objectFuture));
     Expect.throws(() => nullableFun(objectFutureInt));
@@ -138,7 +139,7 @@
     Expect.throws(() => fun2(nullableObjectFuture));
 
     // Implicit down-cast to return type.
-    FutureOr<num> nullableFun2(dynamic objectValue) => objectValue;
+    FutureOr<num?> nullableFun2(dynamic objectValue) => objectValue;
     nullableFun2(nullValue);
     nullableFun2(intValue);
     nullableFun2(doubleValue);
@@ -151,15 +152,15 @@
     nullableFun2(nullableNumFutureDouble);
     nullableFun2(nullableIntFuture);
     nullableFun2(nullableDoubleFuture);
-    nullableFun2(nullableObjectFuture);
 
-    Expect.throws(() => fun2(objectValue));
-    Expect.throws(() => fun2(objectFuture));
-    Expect.throws(() => fun2(objectFutureInt));
+    Expect.throws(() => nullableFun2(nullableObjectFuture));
+    Expect.throws(() => nullableFun2(objectValue));
+    Expect.throws(() => nullableFun2(objectFuture));
+    Expect.throws(() => nullableFun2(objectFutureInt));
   }
 
   {
-    List<Object> list = new List<FutureOr<num>>();
+    List<Object> list = <FutureOr<num>>[];
     list.add(intValue);
     list.add(doubleValue);
     list.add(numFutureInt);
@@ -178,7 +179,7 @@
     Expect.throws(() => list.add(nullableDoubleFuture));
     Expect.throws(() => list.add(nullableObjectFuture));
 
-    List<Object?> nullableList = new List<FutureOr<num?>>();
+    List<Object?> nullableList = <FutureOr<num?>>[];
     nullableList.add(nullValue);
     nullableList.add(intValue);
     nullableList.add(doubleValue);
@@ -191,8 +192,8 @@
     nullableList.add(nullableNumFutureDouble);
     nullableList.add(nullableIntFuture);
     nullableList.add(nullableDoubleFuture);
-    nullableList.add(nullableObjectFuture);
 
+    Expect.throws(() => nullableList.add(nullableObjectFuture));
     Expect.throws(() => nullableList.add(objectValue));
     Expect.throws(() => nullableList.add(objectFuture));
     Expect.throws(() => nullableList.add(objectFutureInt));
@@ -233,10 +234,10 @@
     nullableNumFutureDouble as FutureOr<num?>;
     nullableIntFuture as FutureOr<num?>;
     nullableDoubleFuture as FutureOr<num?>;
-    nullableObjectFuture as FutureOr<num?>;
 
     // Disallows invalid values.
     // These are all valid down-casts that fail at runtime.
+    Expect.throws(() => nullableObjectFuture as FutureOr<num?>);
     Expect.throws(() => objectValue as FutureOr<num?>);
     Expect.throws(() => objectFuture as FutureOr<num?>);
     Expect.throws(() => objectFutureInt as FutureOr<num?>);
@@ -442,7 +443,7 @@
     Expect.isFalse(new C<Null>().isCheck(objectFuture));
     Expect.isFalse(new C<Null>().isCheck(objectFutureInt));
 
-    Expect.isFalse(new C<FutureOr<num?>>().isCheck(nullValue));
+    Expect.isTrue(new C<FutureOr<num?>>().isCheck(nullValue));
     Expect.isTrue(new C<FutureOr<num?>>().isCheck(intValue));
     Expect.isTrue(new C<FutureOr<num?>>().isCheck(doubleValue));
     Expect.isTrue(new C<FutureOr<num?>>().isCheck(numFutureInt));
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index c38da0f..e65d28a 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -41,7 +41,7 @@
   Future val = new Future.value(42);
   Future err1 = new Future.error("Error")..catchError((_) {});
   try {
-    throw new List(0);
+    throw [];
   } catch (e, st) {
     Future err2 = new Future.error(e, st)..catchError((_) {});
   }
@@ -83,7 +83,7 @@
   final completer = new Completer<int>();
   final future = completer.future;
 
-  late int after;
+  int? after;
 
   asyncStart();
   future.then((int v) {
@@ -101,7 +101,7 @@
   final completer = new Completer<int>();
   final future = completer.future;
 
-  late int after;
+  int? after;
   completer.complete(3);
   Expect.isNull(after);
 
@@ -148,13 +148,14 @@
 // Tests for [catchError]
 
 void testException() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   final ex = new Exception();
 
   asyncStart();
   future.then((v) {
     throw "Value not expected";
+    return null;
   }).catchError((error) {
     Expect.equals(error, ex);
     asyncEnd();
@@ -163,7 +164,7 @@
 }
 
 void testExceptionHandler() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   final ex = new Exception();
 
@@ -184,7 +185,7 @@
 }
 
 void testExceptionHandlerReturnsTrue() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   final ex = new Exception();
 
@@ -200,7 +201,7 @@
 }
 
 void testExceptionHandlerReturnsTrue2() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   final ex = new Exception();
 
@@ -218,7 +219,7 @@
 }
 
 void testExceptionHandlerReturnsFalse() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   final ex = new Exception();
 
@@ -515,13 +516,14 @@
 }
 
 void testFutureThenThrowsAsync() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   int error = 42;
 
   asyncStart();
   future.then((v) {
     throw error;
+    return null;
   }).catchError((e) {
     Expect.identical(error, e);
     asyncEnd();
@@ -530,7 +532,7 @@
 }
 
 void testFutureCatchThrowsAsync() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   int error = 42;
 
@@ -545,7 +547,7 @@
 }
 
 void testFutureCatchRethrowsAsync() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   var error;
 
@@ -561,7 +563,7 @@
 }
 
 void testFutureWhenThrowsAsync() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   var error = 42;
 
@@ -576,7 +578,7 @@
 }
 
 void testCompleteWithError() {
-  final completer = new Completer<int>();
+  final completer = new Completer<int?>();
   final future = completer.future;
   var error = 42;
 
@@ -660,7 +662,7 @@
   asyncStart();
   final completer = new Completer<int>();
   final completer2 = new Completer<int>();
-  completer.complete(new CustomFuture(completer2.future));
+  completer.complete(new CustomFuture<int>(completer2.future));
   completer.future.then((v) {
     Expect.equals(42, v);
     asyncEnd();
@@ -672,7 +674,7 @@
   asyncStart();
   final completer = new Completer<int>();
   final completer2 = new Completer<int>();
-  completer.complete(new CustomFuture(completer2.future));
+  completer.complete(new CustomFuture<int>(completer2.future));
   completer.future.then((v) {
     Expect.fail("Should not happen");
     asyncEnd();
@@ -686,7 +688,7 @@
 void testCompleteErrorWithCustomFuture() {
   asyncStart();
   final completer = new Completer<int>();
-  var future = new CustomFuture(new Future.value(42));
+  var future = new CustomFuture<int>(new Future.value(42));
   completer.completeError(future);
   completer.future.then((_) {
     Expect.fail("Shouldn't happen");
@@ -770,8 +772,8 @@
   void doTest(int mask, int permute) {
     asyncStart();
     String stringId = "waitCleanup-$mask-$permute";
-    List<Future?> futures = new List(3);
-    List cleanup = new List(3);
+    List<Future?> futures = <Future?>[null, null, null];
+    List cleanup = [null, null, null];
     int permuteTmp = permute;
     for (int i = 0; i < 3; i++) {
       bool throws = (mask & (1 << i)) != 0;
@@ -815,8 +817,8 @@
     asyncStart();
     bool done = false;
     String stringId = "waitCleanup-$mask-$permute";
-    List<Future?> futures = new List<Future?>(3);
-    List cleanup = new List(3);
+    List<Future?> futures = <Future?>[null, null, null];
+    List cleanup = [null, null, null];
     int permuteTmp = permute;
     for (int i = 0; i < 3; i++) {
       bool throws = (mask & (1 << i)) != 0;
@@ -845,7 +847,8 @@
     }
 
     Future.wait(futures.map((future) => future!),
-          eagerError: true, cleanUp: cleanUp).then((_) {
+            eagerError: true, cleanUp: cleanUp)
+        .then((_) {
       Expect.fail("No error: $stringId");
     }, onError: (e, s) {
       asyncEnd();
@@ -869,7 +872,7 @@
   asyncStart();
   asyncStart();
   runZonedGuarded(() {
-    Future.wait([
+    Future<List<int>?>.value(Future.wait([
       new Future.delayed(cms, () => 0),
       new Future.delayed(cms * 2, () => throw 1),
       new Future.delayed(cms * 3, () => 2)
@@ -878,12 +881,12 @@
       Expect.isFalse(cleanups[index]);
       cleanups[index] = true;
       throw index;
-    }).catchError((e) {
+    })).catchError((e) {
       Expect.equals(e, 1);
       asyncEnd();
     });
   }, (e, s) {
-    int index = e;
+    int index = e as int;
     Expect.isTrue(index == 0 || index == 2, "$index");
     Expect.isFalse(uncaughts[index]);
     uncaughts[index] = true;
@@ -919,7 +922,7 @@
 
 void testWaitSyncError2() {
   asyncStart();
-  Future.wait(badIterable()).catchError((e, st) {
+  Future<List?>.value(Future.wait(badIterable())).catchError((e, st) {
     // Makes sure that the `catchError` is invoked.
     // Regression test: an earlier version of `Future.wait` would propagate
     // the error too soon for the code to install an error handler.
@@ -945,7 +948,7 @@
 
   asyncStart();
   runZoned(() {
-    Future.wait(badIterable()).catchError((e, st) {
+    Future<List?>.value(Future.wait(badIterable())).catchError((e, st) {
       Expect.identical(e, caughtError);
       Expect.equals(1, count);
       asyncEnd();
@@ -1000,9 +1003,10 @@
     testType("Future.sync(future($value))",
         new Future<int>.sync(() => new Future<int>.value(value)));
     testType("Future.value($value)", new Future<int>.value(value));
+    testType(
+        "Future.error", new Future<int>.error("ERR")..catchError((_) => value));
   }
   testType("Completer.future", new Completer<int>().future);
-  testType("Future.error", new Future<int>.error("ERR")..catchError((_) {}));
 }
 
 void testAnyValue() {
@@ -1248,7 +1252,7 @@
       : _result = (badness == 0) ? 42 : new UglyFuture(badness - 1);
   Future<S> then<S>(action(value), {Function? onError}) {
     var c = new Completer<S>();
-    c.complete(new Future.microtask(() => action(_result)));
+    c.complete(new Future<S>.microtask(() => action(_result)));
     return c.future;
   }
 
diff --git a/tests/lib/async/futures_test.dart b/tests/lib/async/futures_test.dart
index 1fd0648..88c8d7a 100644
--- a/tests/lib/async/futures_test.dart
+++ b/tests/lib/async/futures_test.dart
@@ -9,12 +9,12 @@
 import 'dart:async';
 
 Future testWaitEmpty() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   return Future.wait(futures);
 }
 
 Future testCompleteAfterWait() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c = new Completer<Object?>();
   futures.add(c.future);
   Future future = Future.wait(futures);
@@ -23,7 +23,7 @@
 }
 
 Future testCompleteBeforeWait() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c = new Completer();
   futures.add(c.future);
   c.complete(null);
@@ -31,7 +31,7 @@
 }
 
 Future testWaitWithMultipleValues() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c1 = new Completer();
   final c2 = new Completer();
   futures.add(c1.future);
@@ -44,7 +44,7 @@
 }
 
 Future testWaitWithSingleError() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c1 = new Completer();
   final c2 = new Completer();
   futures.add(c1.future);
@@ -52,7 +52,7 @@
   c1.complete();
   c2.completeError('correct error');
 
-  return Future.wait(futures).then((_) {
+  return Future.wait(futures).then<void>((_) {
     throw 'incorrect error';
   }).catchError((error, stackTrace) {
     Expect.equals('correct error', error);
@@ -61,7 +61,7 @@
 }
 
 Future testWaitWithMultipleErrors() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c1 = new Completer();
   final c2 = new Completer();
   futures.add(c1.future);
@@ -69,7 +69,7 @@
   c1.completeError('correct error');
   c2.completeError('incorrect error 1');
 
-  return Future.wait(futures).then((_) {
+  return Future.wait(futures).then<void>((_) {
     throw 'incorrect error 2';
   }).catchError((error, stackTrace) {
     Expect.equals('correct error', error);
@@ -78,7 +78,7 @@
 }
 
 Future testWaitWithMultipleErrorsEager() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c1 = new Completer();
   final c2 = new Completer();
   futures.add(c1.future);
@@ -86,7 +86,7 @@
   c1.completeError('correct error');
   c2.completeError('incorrect error 1');
 
-  return Future.wait(futures, eagerError: true).then((_) {
+  return Future.wait(futures, eagerError: true).then<void>((_) {
     throw 'incorrect error 2';
   }).catchError((error, stackTrace) {
     Expect.equals('correct error', error);
@@ -103,7 +103,7 @@
 }
 
 Future testWaitWithSingleErrorWithStackTrace() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c1 = new Completer();
   final c2 = new Completer();
   futures.add(c1.future);
@@ -111,7 +111,7 @@
   c1.complete();
   c2.completeError('correct error', currentStackTrace);
 
-  return Future.wait(futures).then((_) {
+  return Future.wait(futures).then<void>((_) {
     throw 'incorrect error';
   }).catchError((error, stackTrace) {
     Expect.equals('correct error', error);
@@ -120,7 +120,7 @@
 }
 
 Future testWaitWithMultipleErrorsWithStackTrace() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c1 = new Completer();
   final c2 = new Completer();
   futures.add(c1.future);
@@ -128,7 +128,7 @@
   c1.completeError('correct error', currentStackTrace);
   c2.completeError('incorrect error 1');
 
-  return Future.wait(futures).then((_) {
+  return Future.wait(futures).then<void>((_) {
     throw 'incorrect error 2';
   }).catchError((error, stackTrace) {
     Expect.equals('correct error', error);
@@ -137,7 +137,7 @@
 }
 
 Future testWaitWithMultipleErrorsWithStackTraceEager() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
   final c1 = new Completer();
   final c2 = new Completer();
   futures.add(c1.future);
@@ -145,7 +145,7 @@
   c1.completeError('correct error', currentStackTrace);
   c2.completeError('incorrect error 1');
 
-  return Future.wait(futures, eagerError: true).then((_) {
+  return Future.wait(futures, eagerError: true).then<void>((_) {
     throw 'incorrect error 2';
   }).catchError((error, stackTrace) {
     Expect.equals('correct error', error);
@@ -164,7 +164,7 @@
   final c2 = new Completer();
   final futures = <Future>[c1.future, c2.future];
   final waited = Future.wait(futures, eagerError: true);
-  final result = waited.then((v) {
+  final result = waited.then<void>((v) {
     throw "should not be called";
   }, onError: (e, s) {
     Expect.equals(e, 42);
@@ -202,7 +202,7 @@
     if (n == 4) throw 'correct exception';
     seen.add(n);
     return new Future.value();
-  }).then((_) {
+  }).then<void>((_) {
     throw 'incorrect exception';
   }).catchError((error) {
     Expect.equals('correct exception', error);
@@ -231,7 +231,7 @@
     count++;
     if (count == 4) throw 'correct exception';
     return new Future(() => true);
-  }).then((_) {
+  }).then<void>((_) {
     throw 'incorrect exception';
   }).catchError((error) {
     Expect.equals('correct exception', error);
@@ -241,7 +241,7 @@
 }
 
 main() {
-  final futures = new List<Future>();
+  final futures = <Future>[];
 
   futures.add(testWaitEmpty());
   futures.add(testCompleteAfterWait());
diff --git a/tests/lib/async/run_zoned8_test.dart b/tests/lib/async/run_zoned8_test.dart
index 9a6b917..5e10118 100644
--- a/tests/lib/async/run_zoned8_test.dart
+++ b/tests/lib/async/run_zoned8_test.dart
@@ -24,7 +24,7 @@
       events.add(counter);
       throw counter;
     });
-  }, (e, [s]) {
+  }, (e, [StackTrace? s]) {
     events.add("error: $e");
     Expect.isNotNull(s); // Regression test for http://dartbug.com/33589
   });
diff --git a/tests/lib/async/slow_consumer_test.dart b/tests/lib/async/slow_consumer_test.dart
index 81f811b..56b83b4 100644
--- a/tests/lib/async/slow_consumer_test.dart
+++ b/tests/lib/async/slow_consumer_test.dart
@@ -89,7 +89,7 @@
       listSize -= sentCount - targetCount;
       sentCount = targetCount;
     }
-    controller.add(new List(listSize));
+    controller.add(new List.filled(listSize, null));
     int ms = listSize * 1000 ~/ bytesPerSecond;
     Duration duration = new Duration(milliseconds: ms);
     if (!controller.isPaused) {
diff --git a/tests/lib/async/stream_state_helper.dart b/tests/lib/async/stream_state_helper.dart
index 6178495..5d0471d 100644
--- a/tests/lib/async/stream_state_helper.dart
+++ b/tests/lib/async/stream_state_helper.dart
@@ -12,35 +12,38 @@
 class SubscriptionProtocolTest {
   final StreamProtocolTest _streamTest;
   final int id;
-  StreamSubscription _subscription;
+  StreamSubscription? _subscription;
 
   SubscriptionProtocolTest(this.id, this._subscription, this._streamTest);
 
-  void pause([Future resumeSignal]) {
-    if (_subscription == null) throw new StateError("Not subscribed");
-    _subscription.pause(resumeSignal);
+  void pause([Future? resumeSignal]) {
+    var subscription = _subscription;
+    if (subscription == null) throw new StateError("Not subscribed");
+    subscription.pause(resumeSignal);
   }
 
   void resume() {
-    if (_subscription == null) throw new StateError("Not subscribed");
-    _subscription.resume();
+    var subscription = _subscription;
+    if (subscription == null) throw new StateError("Not subscribed");
+    subscription.resume();
   }
 
   void cancel() {
-    if (_subscription == null) throw new StateError("Not subscribed");
-    _subscription.cancel();
+    var subscription = _subscription;
+    if (subscription == null) throw new StateError("Not subscribed");
+    subscription.cancel();
     _subscription = null;
   }
 
-  void expectData(var data, [void action()]) {
+  void expectData(var data, [void action()?]) {
     _streamTest._expectData(this, data, action);
   }
 
-  void expectError(var error, [void action()]) {
+  void expectError(var error, [void action()?]) {
     _streamTest._expectError(this, error, action);
   }
 
-  void expectDone([void action()]) {
+  void expectDone([void action()?]) {
     _streamTest._expectDone(this, action);
   }
 }
@@ -49,14 +52,14 @@
   bool trace = false;
   final bool isBroadcast;
   final bool isAsBroadcast;
-  StreamController _controller;
-  Stream _controllerStream;
+  late StreamController _controller;
+  late Stream _controllerStream;
   // Most recent subscription created. Used as default for pause/resume.
-  SubscriptionProtocolTest _latestSubscription;
-  List<Event> _expectations = new List<Event>();
+  SubscriptionProtocolTest? _latestSubscription;
+  List<Event> _expectations = <Event>[];
   int _nextExpectationIndex = 0;
   int _subscriptionIdCounter = 0;
-  Function _onComplete;
+  Function? _onComplete;
 
   StreamProtocolTest.broadcast({bool sync: false})
       : isBroadcast = true,
@@ -128,20 +131,20 @@
     if (trace) {
       print("[Listen #$subscriptionId(#${_latestSubscription.hashCode})]");
     }
-    return _latestSubscription;
+    return _latestSubscription!;
   }
 
   // Actions on the most recently created subscription.
-  void pause([Future resumeSignal]) {
-    _latestSubscription.pause(resumeSignal);
+  void pause([Future? resumeSignal]) {
+    _latestSubscription!.pause(resumeSignal);
   }
 
   void resume() {
-    _latestSubscription.resume();
+    _latestSubscription!.resume();
   }
 
   void cancel() {
-    _latestSubscription.cancel();
+    _latestSubscription!.cancel();
     _latestSubscription = null;
   }
 
@@ -155,7 +158,7 @@
             "Found   : Early termination.\n${expect._stackTrace}");
       });
     }
-    _onComplete();
+    _onComplete!();
   }
 
   // Handling of stream events.
@@ -260,75 +263,75 @@
   }
 
   // Adds _expectations.
-  void expectAny([void action()]) {
+  void expectAny([void action()?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new LogAnyEvent(action));
   }
 
-  void expectData(var data, [void action()]) {
+  void expectData(var data, [void action()?]) {
     _expectData(null, data, action);
   }
 
-  void _expectData(SubscriptionProtocolTest sub, var data, void action()) {
+  void _expectData(SubscriptionProtocolTest? sub, var data, void action()?) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new DataEvent(sub, data, action));
   }
 
-  void expectError(var error, [void action()]) {
+  void expectError(var error, [void action()?]) {
     _expectError(null, error, action);
   }
 
-  void _expectError(SubscriptionProtocolTest sub, var error, void action()) {
+  void _expectError(SubscriptionProtocolTest? sub, var error, void action()?) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new ErrorEvent(sub, error, action));
   }
 
-  void expectDone([void action()]) {
+  void expectDone([void action()?]) {
     _expectDone(null, action);
   }
 
-  void _expectDone(SubscriptionProtocolTest sub, [void action()]) {
+  void _expectDone(SubscriptionProtocolTest? sub, [void action()?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new DoneEvent(sub, action));
   }
 
-  void expectPause([void action()]) {
+  void expectPause([void action()?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new PauseCallbackEvent(action));
   }
 
-  void expectResume([void action()]) {
+  void expectResume([void action()?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new ResumeCallbackEvent(action));
   }
 
-  void expectListen([void action()]) {
+  void expectListen([void action()?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new SubscriptionCallbackEvent(action));
   }
 
-  void expectCancel([void action()]) {
+  void expectCancel([void action()?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new CancelCallbackEvent(action));
   }
 
-  void expectBroadcastListen([void action(StreamSubscription sub)]) {
+  void expectBroadcastListen([void action(StreamSubscription sub)?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
@@ -336,7 +339,7 @@
     _expectations.add(new BroadcastListenCallbackEvent(action));
   }
 
-  void expectBroadcastCancel([void action(StreamSubscription sub)]) {
+  void expectBroadcastCancel([void action(StreamSubscription sub)?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
@@ -344,7 +347,7 @@
     _expectations.add(new BroadcastCancelCallbackEvent(action));
   }
 
-  void expectBroadcastListenOpt([void action(StreamSubscription sub)]) {
+  void expectBroadcastListenOpt([void action(StreamSubscription sub)?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
@@ -352,7 +355,7 @@
     _expectations.add(new BroadcastListenCallbackEvent(action));
   }
 
-  void expectBroadcastCancelOpt([void action(StreamSubscription sub)]) {
+  void expectBroadcastCancelOpt([void action(StreamSubscription sub)?]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
@@ -379,9 +382,9 @@
 }
 
 class Event {
-  Function _action;
-  StackTrace _stackTrace;
-  Event(void action())
+  Function? _action;
+  StackTrace? _stackTrace;
+  Event(void action()?)
       : _action = (action == null) ? null : expectAsync(action) {
     try {
       throw 0;
@@ -389,7 +392,7 @@
       _stackTrace = s;
     }
   }
-  Event.broadcast(void action(StreamSubscription sub))
+  Event.broadcast(void action(StreamSubscription sub)?)
       : _action = (action == null) ? null : expectAsync(action) {
     try {
       throw 0;
@@ -412,37 +415,37 @@
 
   bool matchPause() {
     if (!_testPause()) return false;
-    if (_action != null) _action();
+    _action?.call();
     return true;
   }
 
   bool matchResume() {
     if (!_testResume()) return false;
-    if (_action != null) _action();
+    _action?.call();
     return true;
   }
 
   bool matchSubscribe() {
     if (!_testSubscribe()) return false;
-    if (_action != null) _action();
+    _action?.call();
     return true;
   }
 
   bool matchCancel() {
     if (!_testCancel()) return false;
-    if (_action != null) _action();
+    _action?.call();
     return true;
   }
 
   bool matchBroadcastListen(StreamSubscription sub) {
     if (!_testBroadcastListen()) return false;
-    if (_action != null) _action(sub);
+    _action?.call(sub);
     return true;
   }
 
   bool matchBroadcastCancel(StreamSubscription sub) {
     if (!_testBroadcastCancel()) return false;
-    if (_action != null) _action(sub);
+    _action?.call(sub);
     return true;
   }
 
@@ -458,31 +461,31 @@
 }
 
 class SubscriptionEvent extends Event {
-  SubscriptionProtocolTest subscription;
-  SubscriptionEvent(this.subscription, void action()) : super(action);
+  SubscriptionProtocolTest? subscription;
+  SubscriptionEvent(this.subscription, void action()?) : super(action);
 
   bool matchData(int id, var data) {
-    if (subscription != null && subscription.id != id) return false;
+    if (subscription != null && subscription!.id != id) return false;
     if (!_testData(data)) return false;
-    if (_action != null) _action();
+    _action?.call();
     return true;
   }
 
   bool matchError(int id, e) {
-    if (subscription != null && subscription.id != id) return false;
+    if (subscription != null && subscription!.id != id) return false;
     if (!_testError(e)) return false;
-    if (_action != null) _action();
+    _action?.call();
     return true;
   }
 
   bool matchDone(int id) {
-    if (subscription != null && subscription.id != id) return false;
+    if (subscription != null && subscription!.id != id) return false;
     if (!_testDone()) return false;
-    if (_action != null) _action();
+    _action?.call();
     return true;
   }
 
-  String get _id => (subscription == null) ? "" : "#${subscription.id}";
+  String get _id => (subscription == null) ? "" : "#${subscription!.id}";
 }
 
 class MismatchEvent extends Event {
@@ -492,7 +495,7 @@
 
 class DataEvent extends SubscriptionEvent {
   final data;
-  DataEvent(SubscriptionProtocolTest sub, this.data, void action())
+  DataEvent(SubscriptionProtocolTest? sub, this.data, void action()?)
       : super(sub, action);
   bool _testData(var data) => this.data == data;
   String toString() => "[Data$_id: $data]";
@@ -500,51 +503,51 @@
 
 class ErrorEvent extends SubscriptionEvent {
   final error;
-  ErrorEvent(SubscriptionProtocolTest sub, this.error, void action())
+  ErrorEvent(SubscriptionProtocolTest? sub, this.error, void action()?)
       : super(sub, action);
   bool _testError(error) => this.error == error;
   String toString() => "[Error$_id: $error]";
 }
 
 class DoneEvent extends SubscriptionEvent {
-  DoneEvent(SubscriptionProtocolTest sub, void action()) : super(sub, action);
+  DoneEvent(SubscriptionProtocolTest? sub, void action()?) : super(sub, action);
   bool _testDone() => true;
   String toString() => "[Done$_id]";
 }
 
 class PauseCallbackEvent extends Event {
-  PauseCallbackEvent(void action()) : super(action);
+  PauseCallbackEvent(void action()?) : super(action);
   bool _testPause() => true;
   String toString() => "[Paused]";
 }
 
 class ResumeCallbackEvent extends Event {
-  ResumeCallbackEvent(void action()) : super(action);
+  ResumeCallbackEvent(void action()?) : super(action);
   bool _testResume() => true;
   String toString() => "[Resumed]";
 }
 
 class SubscriptionCallbackEvent extends Event {
-  SubscriptionCallbackEvent(void action()) : super(action);
+  SubscriptionCallbackEvent(void action()?) : super(action);
   bool _testSubscribe() => true;
   String toString() => "[Subscribed]";
 }
 
 class CancelCallbackEvent extends Event {
-  CancelCallbackEvent(void action()) : super(action);
+  CancelCallbackEvent(void action()?) : super(action);
   bool _testCancel() => true;
   String toString() => "[Cancelled]";
 }
 
 class BroadcastCancelCallbackEvent extends Event {
-  BroadcastCancelCallbackEvent(void action(StreamSubscription sub))
+  BroadcastCancelCallbackEvent(void action(StreamSubscription sub)?)
       : super.broadcast(action);
   bool _testBroadcastCancel() => true;
   String toString() => "[BroadcastCancel]";
 }
 
 class BroadcastListenCallbackEvent extends Event {
-  BroadcastListenCallbackEvent(void action(StreamSubscription sub))
+  BroadcastListenCallbackEvent(void action(StreamSubscription sub)?)
       : super.broadcast(action);
   bool _testBroadcastListen() => true;
   String toString() => "[BroadcastListen]";
@@ -554,7 +557,7 @@
 class LogAnyEvent extends Event {
   String _actual = "*Not matched yet*";
 
-  LogAnyEvent(void action()) : super(action);
+  LogAnyEvent(void action()?) : super(action);
 
   bool _testData(var data) {
     _actual = "*[Data $data]";
diff --git a/tests/lib/async/zone_error_callback_test.dart b/tests/lib/async/zone_error_callback_test.dart
index 8961b67..7b81e7e 100644
--- a/tests/lib/async/zone_error_callback_test.dart
+++ b/tests/lib/async/zone_error_callback_test.dart
@@ -226,14 +226,16 @@
   {
     asyncStart();
     StreamController controller = new StreamController();
-    controller.stream.every((x) => throw error1).catchError(expectErrorOnly);
+    Future<bool?>.value(controller.stream.every((x) => throw error1))
+        .catchError(expectErrorOnly);
     controller.add(null);
   }
 
   {
     asyncStart();
     StreamController controller = new StreamController();
-    controller.stream.any((x) => throw error1).catchError(expectErrorOnly);
+    Future<bool?>.value(controller.stream.any((x) => throw error1))
+        .catchError(expectErrorOnly);
     controller.add(null);
   }
 
diff --git a/tests/lib/convert/base64_test.dart b/tests/lib/convert/base64_test.dart
index 6e85a7c..40867fc 100644
--- a/tests/lib/convert/base64_test.dart
+++ b/tests/lib/convert/base64_test.dart
@@ -118,7 +118,7 @@
       for (int j = i; j < encoded.length; j += increment) {
         {
           // Using add/close
-          List<List<int>> results;
+          late List<List<int>> results;
           var sink = new ChunkedConversionSink<List<int>>.withCallback((v) {
             results = v;
           });
@@ -132,7 +132,7 @@
         }
         {
           // Using addSlice
-          List<List<int>> results;
+          late List<List<int>> results;
           var sink = new ChunkedConversionSink<List<int>>.withCallback((v) {
             results = v;
           });
diff --git a/tests/lib/convert/chunked_conversion_utf88_test.dart b/tests/lib/convert/chunked_conversion_utf88_test.dart
index 932682d..c0a63d7 100644
--- a/tests/lib/convert/chunked_conversion_utf88_test.dart
+++ b/tests/lib/convert/chunked_conversion_utf88_test.dart
@@ -120,8 +120,8 @@
   var codeUnits = <int>[];
   for (int i = 0; i < 2049; i++) {
     // Invariant: codeUnits[0..i - 1] is filled with CHAR_A (character 'a').
-    codeUnits.length = i + 1;
-    codeUnits[i] = CHAR_A;
+    codeUnits.add(CHAR_A);
+    Expect.equals(i + 1, codeUnits.length);
 
     // Only test for problem zones, close to powers of two.
     if (i > 20 && _nextPowerOf2(i - 2) - i > 10) continue;
@@ -142,7 +142,8 @@
     bytes[i + 2] = UTF8_TRAILING[2];
     runTest([bytes, str]);
 
-    codeUnits.length = i + 2;
+    codeUnits.add(CHAR_A);
+    Expect.equals(i + 2, codeUnits.length);
     codeUnits[i] = LEADING_SURROGATE;
     codeUnits[i + 1] = TRAILING_SURROGATE;
     str = new String.fromCharCodes(codeUnits);
@@ -189,7 +190,8 @@
     bytes[i + 5] = UTF8_LEADING[2];
     runTest([bytes, str]);
 
-    codeUnits.length = i + 3;
+    codeUnits.add(CHAR_A);
+    Expect.equals(i + 3, codeUnits.length);
     codeUnits[i] = LEADING_SURROGATE;
     codeUnits[i + 1] = TRAILING_SURROGATE;
     codeUnits[i + 2] = CHAR_A; // Add trailing 'a'.
@@ -243,6 +245,7 @@
     runTest([bytes, str]);
 
     // Make sure the invariant is correct.
+    codeUnits.length = i + 1;
     codeUnits[i] = CHAR_A;
   }
 }
diff --git a/tests/lib/convert/json_lib_test.dart b/tests/lib/convert/json_lib_test.dart
index 29aa3f0..faad0cf 100644
--- a/tests/lib/convert/json_lib_test.dart
+++ b/tests/lib/convert/json_lib_test.dart
@@ -104,8 +104,8 @@
 
   // Lists.
   Expect.equals('[]', json.encode([]));
-  Expect.equals('[]', json.encode(new List(0)));
-  Expect.equals('[null,null,null]', json.encode(new List(3)));
+  Expect.equals('[]', json.encode(new List.empty()));
+  Expect.equals('[null,null,null]', json.encode(new List.filled(3, null)));
   validateRoundTrip([3, -4.5, null, true, 'hi', false]);
   Expect.equals(
       '[[3],[],[null],["hi",true]]',
diff --git a/tests/lib/convert/unicode_tests.dart b/tests/lib/convert/unicode_tests.dart
index 9f0493b..82d7f17 100644
--- a/tests/lib/convert/unicode_tests.dart
+++ b/tests/lib/convert/unicode_tests.dart
@@ -227,8 +227,8 @@
   var tests = <List>[];
   tests.addAll(_TEST_PAIRS);
   tests.addAll(_TEST_PAIRS.map((test) {
-    var bytes = test[0];
-    var string = test[1];
+    var bytes = test[0] as List<int>;
+    var string = test[1] as String;
     var longBytes = <int>[];
     var longString = "";
     for (int i = 0; i < 100; i++) {
diff --git a/tests/lib/html/Ahem.ttf b/tests/lib/html/Ahem.ttf
new file mode 100644
index 0000000..ac81cb0
--- /dev/null
+++ b/tests/lib/html/Ahem.ttf
Binary files differ
diff --git a/tests/lib/html/async_cancellingisolate.dart b/tests/lib/html/async_cancellingisolate.dart
new file mode 100644
index 0000000..b04c5b1
--- /dev/null
+++ b/tests/lib/html/async_cancellingisolate.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.
+
+library async_cancellingisolate;
+
+import 'dart:async';
+import 'package:expect/minitest.dart';
+
+main(message, replyTo) {
+  var command = message.first;
+  expect(command, 'START');
+  var shot = false;
+  var oneshot;
+  var periodic;
+  periodic = new Timer.periodic(const Duration(milliseconds: 10), (timer) {
+    expect(shot, isFalse);
+    shot = true;
+    expect(timer, same(periodic));
+    periodic.cancel();
+    oneshot.cancel();
+    // Wait some more time to be sure callbacks won't be invoked any
+    // more.
+    new Timer(const Duration(milliseconds: 50), () {
+      replyTo.send('DONE');
+    });
+  });
+  // We launch the oneshot timer after the periodic timer. Otherwise a
+  // (very long) context switch could make this test flaky: assume the
+  // oneshot timer is created first and then there is a 30ms context switch.
+  // when the periodic timer is scheduled it would execute after the oneshot.
+  oneshot = new Timer(const Duration(milliseconds: 30), () {
+    fail('Should never be invoked');
+  });
+}
diff --git a/tests/lib/html/async_oneshot.dart b/tests/lib/html/async_oneshot.dart
new file mode 100644
index 0000000..475efe3
--- /dev/null
+++ b/tests/lib/html/async_oneshot.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 'dart:async';
+import 'package:expect/minitest.dart';
+
+main(message, replyTo) {
+  var command = message.first;
+  expect(command, 'START');
+  new Timer(const Duration(milliseconds: 10), () {
+    replyTo.send('DONE');
+  });
+}
diff --git a/tests/lib/html/async_periodictimer.dart b/tests/lib/html/async_periodictimer.dart
new file mode 100644
index 0000000..9837ae5
--- /dev/null
+++ b/tests/lib/html/async_periodictimer.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.
+
+library async_periodictimer;
+
+import 'dart:async';
+import 'package:expect/minitest.dart';
+
+main(message, replyTo) {
+  var command = message.first;
+  expect(command, 'START');
+  int counter = 0;
+  new Timer.periodic(const Duration(milliseconds: 10), (timer) {
+    if (counter == 3) {
+      counter = 1024;
+      timer.cancel();
+      // Wait some more time to be sure callback won't be invoked any
+      // more.
+      new Timer(const Duration(milliseconds: 30), () {
+        replyTo.send('DONE');
+      });
+      return;
+    }
+    assert(counter < 3);
+    counter++;
+  });
+}
diff --git a/tests/lib/html/async_test.dart b/tests/lib/html/async_test.dart
new file mode 100644
index 0000000..7720d5a
--- /dev/null
+++ b/tests/lib/html/async_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 async_test;
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:html';
+
+import 'async_oneshot.dart' as oneshot_test show main;
+import 'async_periodictimer.dart' as periodictimer_test show main;
+import 'async_cancellingisolate.dart' as cancelling_test show main;
+
+oneshot(message) => oneshot_test.main(message.first, message.last);
+periodicTimerIsolate(message) =>
+    periodictimer_test.main(message.first, message.last);
+cancellingIsolate(message) => cancelling_test.main(message.first, message.last);
+
+main() {
+  test('one shot timer in pure isolate', () {
+    var response = new ReceivePort();
+    var remote = Isolate.spawn(oneshot, [
+      ['START'],
+      response.sendPort
+    ]);
+    expect(remote.then((_) => response.first), completion('DONE'));
+  });
+
+  test('periodic timer in pure isolate', () {
+    var response = new ReceivePort();
+    var remote = Isolate.spawn(periodicTimerIsolate, [
+      ['START'],
+      response.sendPort
+    ]);
+    expect(remote.then((_) => response.first), completion('DONE'));
+  });
+
+  test('cancellation in pure isolate', () {
+    var response = new ReceivePort();
+    var remote = Isolate.spawn(cancellingIsolate, [
+      ['START'],
+      response.sendPort
+    ]);
+    expect(remote.then((_) => response.first), completion('DONE'));
+  });
+}
diff --git a/tests/lib/html/audiobuffersourcenode_test.dart b/tests/lib/html/audiobuffersourcenode_test.dart
new file mode 100644
index 0000000..fd6fa86
--- /dev/null
+++ b/tests/lib/html/audiobuffersourcenode_test.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.
+
+import 'dart:web_audio';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(AudioContext.supported, isTrue);
+    });
+  });
+
+  group('functional', () {
+    test('createBuffer', () {
+      if (AudioContext.supported) {
+        var ctx = new AudioContext();
+        AudioBufferSourceNode node = ctx.createBufferSource();
+        expect(node is AudioBufferSourceNode, isTrue);
+        node.start(ctx.currentTime, 0, 2);
+        expect(node is AudioBufferSourceNode, isTrue);
+      }
+    });
+  });
+}
diff --git a/tests/lib/html/audiocontext_test.dart b/tests/lib/html/audiocontext_test.dart
new file mode 100644
index 0000000..8316130
--- /dev/null
+++ b/tests/lib/html/audiocontext_test.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 'dart:async';
+import 'dart:html';
+import 'dart:typed_data';
+import 'dart:web_audio';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isAudioContext =
+      predicate((x) => x is AudioContext, 'is an AudioContext');
+
+  group('supported', () {
+    test('supported', () {
+      expect(AudioContext.supported, true);
+    });
+  });
+
+  group('functional', () {
+    var context;
+    if (AudioContext.supported) {
+      context = new AudioContext();
+    }
+
+    test('constructorTest', () {
+      if (AudioContext.supported) {
+        expect(context, isNotNull);
+        expect(context, isAudioContext);
+      }
+    });
+
+    test('audioRenames', () {
+      if (AudioContext.supported) {
+        GainNode gainNode = context.createGain();
+        gainNode.connectNode(context.destination);
+        expect(gainNode is GainNode, isTrue);
+
+        expect(context.createAnalyser() is AnalyserNode, isTrue);
+        expect(context.createChannelMerger() is AudioNode, isTrue);
+        expect(context.createChannelSplitter() is AudioNode, isTrue);
+        expect(context.createOscillator() is OscillatorNode, isTrue);
+        expect(context.createPanner() is PannerNode, isTrue);
+        expect(
+            context.createScriptProcessor(4096) is ScriptProcessorNode, isTrue);
+      }
+    });
+
+    // TODO(9322): This test times out.
+    /*
+    test('onAudioProcess', () {
+      if(AudioContext.supported) {
+        var completer = new Completer<bool>();
+        var context = new AudioContext();
+        var scriptProcessor = context.createScriptProcessor(1024, 1, 2);
+        scriptProcessor.connectNode(context.destination);
+        bool alreadyCalled = false;
+        scriptProcessor.onAudioProcess.listen((event) {
+          if (!alreadyCalled) {
+            completer.complete(true);
+          }
+          alreadyCalled = true;
+        });
+        return completer.future;
+      }
+    });
+    */
+
+    test('oscillatorTypes', () {
+      if (AudioContext.supported) {
+        OscillatorNode oscillator = context.createOscillator();
+        oscillator.connectNode(context.destination);
+
+        oscillator.type = 'sawtooth';
+        expect(oscillator.type, equals('sawtooth'));
+
+        oscillator.type = 'sine';
+        expect(oscillator.type, equals('sine'));
+
+        oscillator.type = 'square';
+        expect(oscillator.type, equals('square'));
+
+        oscillator.type = 'triangle';
+        expect(oscillator.type, equals('triangle'));
+
+        //expect(() => oscillator.type = 7, throws); Firefox does not throw, it
+        //simply ignores this value.
+        expect(oscillator.type, equals('triangle'));
+
+        // Firefox does not throw when it receives invalid values; it simply
+        // ignores them.
+        //expect(() => oscillator.type = ['heap object not a string'], throws);
+        expect(oscillator.type, equals('triangle'));
+      }
+    });
+  });
+}
diff --git a/tests/lib/html/audioelement_test.dart b/tests/lib/html/audioelement_test.dart
new file mode 100644
index 0000000..e45f1bc
--- /dev/null
+++ b/tests/lib/html/audioelement_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:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('constructorTest1', () {
+    var audio = new AudioElement();
+    expect(audio, isNotNull);
+    expect(audio is AudioElement, isTrue);
+  });
+
+  test('constructorTest2', () {
+    var audio = new AudioElement('IntentionallyMissingFileURL');
+    expect(audio, isNotNull);
+    expect(audio is AudioElement, isTrue);
+    expect(audio.src.contains('IntentionallyMissingFileURL'), isTrue);
+  });
+
+  test('canPlayTypeTest', () {
+    var audio = new AudioElement();
+    var canPlay = audio.canPlayType("audio/mp4");
+    expect(canPlay, isNotNull);
+    expect(canPlay is String, isTrue);
+  });
+}
diff --git a/tests/lib/html/b_element_test.dart b/tests/lib/html/b_element_test.dart
new file mode 100644
index 0000000..f60b633
--- /dev/null
+++ b/tests/lib/html/b_element_test.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.
+
+import 'dart:html';
+
+main() {
+  new Element.tag('b');
+}
diff --git a/tests/lib/html/blob_constructor_test.dart b/tests/lib/html/blob_constructor_test.dart
new file mode 100644
index 0000000..d5f5d34
--- /dev/null
+++ b/tests/lib/html/blob_constructor_test.dart
@@ -0,0 +1,60 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('basic', () {
+    var b = new Blob([]);
+    expect(b.size, 0);
+  });
+
+  test('type1', () {
+    // OPTIONALS var b = new Blob(['Harry'], type: 'text');
+    var b = new Blob(['Harry'], 'text');
+    expect(b.size, 5);
+    expect(b.type, 'text');
+  });
+
+  test('endings1', () {
+    // OPTIONALS var b = new Blob(['A\nB\n'], endings: 'transparent');
+    var b = new Blob(['A\nB\n'], null, 'transparent');
+    expect(b.size, 4);
+  });
+
+  test('endings2', () {
+    // OPTIONALS var b = new Blob(['A\nB\n'], endings: 'native');
+    var b = new Blob(['A\nB\n'], null, 'native');
+    expect(b.size, predicate((x) => x == 4 || x == 6),
+        reason: "b.size should be 4 or 6");
+  });
+
+  test('twoStrings', () {
+    // OPTIONALS var b = new Blob(['123', 'xyz'], type: 'text/plain;charset=UTF-8');
+    var b = new Blob(['123', 'xyz'], 'text/plain;charset=UTF-8');
+    expect(b.size, 6);
+  });
+
+  test('fromBlob1', () {
+    var b1 = new Blob([]);
+    var b2 = new Blob([b1]);
+    expect(b2.size, 0);
+  });
+
+  test('fromBlob2', () {
+    var b1 = new Blob(['x']);
+    var b2 = new Blob([b1, b1]);
+    expect(b1.size, 1);
+    expect(b2.size, 2);
+  });
+
+  test('fromArrayBuffer', () {
+    var a = new Uint8List(100).buffer; // i.e. new ArrayBuffer(100);
+    var b = new Blob([a, a]);
+    expect(b.size, 200);
+  });
+}
diff --git a/tests/lib/html/cache_test.dart b/tests/lib/html/cache_test.dart
new file mode 100644
index 0000000..2e0991b
--- /dev/null
+++ b/tests/lib/html/cache_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:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(ApplicationCache.supported, isTrue);
+    });
+  });
+
+  group('ApplicationCache', () {
+    test('ApplicationCache', () {
+      var expectation = ApplicationCache.supported ? returnsNormally : throws;
+      expect(() {
+        ApplicationCache appCache = window.applicationCache;
+        expect(cacheStatusToString(appCache.status), "UNCACHED");
+      }, expectation);
+    });
+  });
+}
+
+String cacheStatusToString(int status) {
+  switch (status) {
+    case ApplicationCache.UNCACHED: // UNCACHED == 0
+      return 'UNCACHED';
+    case ApplicationCache.IDLE: // IDLE == 1
+      return 'IDLE';
+    case ApplicationCache.CHECKING: // CHECKING == 2
+      return 'CHECKING';
+    case ApplicationCache.DOWNLOADING: // DOWNLOADING == 3
+      return 'DOWNLOADING';
+    case ApplicationCache.UPDATEREADY: // UPDATEREADY == 4
+      return 'UPDATEREADY';
+    case ApplicationCache.OBSOLETE: // OBSOLETE == 5
+      return 'OBSOLETE';
+    default:
+      return 'UNKNOWN CACHE STATUS';
+  }
+  ;
+}
diff --git a/tests/lib/html/callback_list_test.dart b/tests/lib/html/callback_list_test.dart
new file mode 100644
index 0000000..d6390b1
--- /dev/null
+++ b/tests/lib/html/callback_list_test.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.
+
+library callback_list_test;
+
+import 'dart:html';
+import 'dart:async';
+
+import 'package:expect/minitest.dart';
+
+var callbackDone = false;
+bool isCallbackDone() => callbackDone;
+
+Future waitUntilCallbackDone(bool test()) async {
+  var completer = new Completer();
+  check() {
+    if (test()) {
+      completer.complete();
+    } else {
+      new Timer(Duration.zero, check);
+    }
+  }
+
+  check();
+  return completer.future;
+}
+
+void main() async {
+  window.navigator.persistentStorage.requestQuota(1024 * 1024, _quotaHandler);
+
+  await waitUntilCallbackDone(isCallbackDone);
+  expect(true, isCallbackDone());
+}
+
+Future _quotaHandler(int byteCount) async {
+  FileSystem filesystem =
+      await window.requestFileSystem(1024 * 1024, persistent: true);
+  DirectoryEntry dir = await filesystem.root;
+  DirectoryReader dirReader = dir.createReader();
+  await dirReader.readEntries();
+  List<Entry> secondEntries = await dirReader.readEntries();
+  callbackDone = true;
+}
diff --git a/tests/lib/html/callbacks_test.dart b/tests/lib/html/callbacks_test.dart
new file mode 100644
index 0000000..e7402fe
--- /dev/null
+++ b/tests/lib/html/callbacks_test.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.
+
+import 'dart:html';
+
+main() {
+  window.requestAnimationFrame((num time) => false);
+}
diff --git a/tests/lib/html/canvas_pixel_array_type_alias_test.dart b/tests/lib/html/canvas_pixel_array_type_alias_test.dart
new file mode 100644
index 0000000..3c992de
--- /dev/null
+++ b/tests/lib/html/canvas_pixel_array_type_alias_test.dart
@@ -0,0 +1,114 @@
+// 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:typed_data';
+
+import 'package:expect/minitest.dart';
+
+// We have aliased the legacy type CanvasPixelArray with the new type
+// Uint8ClampedArray by mapping the CanvasPixelArray type tag to
+// Uint8ClampedArray.  It is not a perfect match since CanvasPixelArray is
+// missing the ArrayBufferView members.  These should appear to be null.
+
+var inscrutable;
+
+main() {
+  inscrutable = (x) => x;
+
+  int width = 100;
+  int height = 100;
+
+  CanvasElement canvas = new CanvasElement(width: width, height: height);
+  document.body!.append(canvas);
+
+  CanvasRenderingContext2D context = canvas.context2D;
+
+  group('basic', () {
+    test('CreateImageData', () {
+      ImageData image = context.createImageData(canvas.width, canvas.height);
+      List<int> data = image.data;
+      // It is legal for the dart2js compiler to believe the type of the native
+      //   ImageData.data and elides the check, so check the type explicitly:
+      expect(inscrutable(data) is List<int>, isTrue,
+          reason: 'canvas array type');
+
+      expect(data.length, 40000);
+      checkPixel(data, 0, [0, 0, 0, 0]);
+      checkPixel(data, width * height - 1, [0, 0, 0, 0]);
+
+      data[100] = 200;
+      expect(data[100], equals(200));
+    });
+  });
+
+  group('types1', () {
+    test('isList', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect(inscrutable(data) is List, true);
+    });
+
+    test('isListT_pos', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect(inscrutable(data) is List<int>, true);
+    });
+  });
+
+  group('types2', () {
+    test('isListT_neg', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect(inscrutable(data) is List<String>, false);
+    });
+
+    test('isUint8ClampedList', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect(inscrutable(data) is Uint8ClampedList, true);
+    });
+
+    test('consistent_isUint8ClampedList', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      // Static and dynamic values consistent?  Type inference should be able to
+      // constant-fold 'data is Uint8ClampedList' to 'true'.
+      expect(inscrutable(data) is Uint8ClampedList == data is Uint8ClampedList,
+          isTrue);
+    });
+
+    // TODO(sra): Why does this fail on Dartium? There are two types with the
+    // same print string:
+    //
+    //     Expected: ?:<Uint8ClampedList> Actual: ?:<Uint8ClampedList>
+    /*
+    test('runtimeType', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect(inscrutable(data).runtimeType, Uint8ClampedList);
+    });
+    */
+
+    test('consistent_runtimeType', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect(inscrutable(data).runtimeType == data.runtimeType, isTrue);
+    });
+  });
+
+  group('types2_runtimeTypeName', () {
+    test('runtimeTypeName', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect('${inscrutable(data).runtimeType}', 'Uint8ClampedList');
+    });
+  });
+
+  group('typed_data', () {
+    test('elementSizeInBytes', () {
+      var data = context.createImageData(canvas.width, canvas.height).data;
+      expect(inscrutable(data).elementSizeInBytes, 1);
+    });
+  });
+}
+
+void checkPixel(List<int> data, int offset, List<int> rgba) {
+  offset *= 4;
+  for (var i = 0; i < 4; ++i) {
+    expect(rgba[i], equals(data[offset + i]));
+  }
+}
diff --git a/tests/lib/html/canvas_test.dart b/tests/lib/html/canvas_test.dart
new file mode 100644
index 0000000..dd3910f
--- /dev/null
+++ b/tests/lib/html/canvas_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.
+
+library CanvasTest;
+
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  CanvasElement canvas;
+  CanvasRenderingContext2D context;
+  int width = 100;
+  int height = 100;
+
+  canvas = new CanvasElement(width: width, height: height);
+  document.body!.append(canvas);
+
+  context = canvas.context2D;
+
+  test('CreateImageData', () {
+    ImageData image = context.createImageData(canvas.width, canvas.height);
+    List<int> data = image.data;
+
+    expect(data.length, 40000);
+    checkPixel(data, 0, [0, 0, 0, 0]);
+    checkPixel(data, width * height - 1, [0, 0, 0, 0]);
+
+    data[100] = 200;
+    expect(data[100], equals(200));
+  });
+
+  test('toDataUrl', () {
+    var canvas = new CanvasElement(width: 100, height: 100);
+    var context = canvas.context2D;
+    context.fillStyle = 'red';
+    context.fill();
+
+    var url = canvas.toDataUrl();
+
+    var img = new ImageElement();
+    img.onLoad.listen(expectAsync((_) {
+      expect(img.complete, true);
+    }));
+    img.onError.listen((_) {
+      fail('URL failed to load.');
+    });
+    img.src = url;
+  });
+}
+
+void checkPixel(List<int> data, int offset, List<int> rgba) {
+  offset *= 4;
+  for (var i = 0; i < 4; ++i) {
+    expect(data[offset + i], equals(rgba[i]));
+  }
+}
diff --git a/tests/lib/html/canvasrendering/arc_test.dart b/tests/lib/html/canvasrendering/arc_test.dart
new file mode 100644
index 0000000..d60fb1e
--- /dev/null
+++ b/tests/lib/html/canvasrendering/arc_test.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.
+
+library canvas_rendering_context_2d_test;
+
+import 'dart:html';
+import 'dart:math';
+
+import 'canvas_rendering_util.dart';
+import 'package:expect/minitest.dart';
+
+main() {
+  setUp(setupFunc);
+  tearDown(tearDownFunc);
+
+  test('default arc should be clockwise', () {
+    context.beginPath();
+    final r = 10;
+
+    // Center of arc.
+    final cx = 20;
+    final cy = 20;
+    // Arc centered at (20, 20) with radius 10 will go clockwise
+    // from (20 + r, 20) to (20, 20 + r), which is 1/4 of a circle.
+    context.arc(cx, cy, r, 0, pi / 2);
+
+    context.strokeStyle = 'green';
+    context.lineWidth = 2;
+    context.stroke();
+
+    // Center should not be filled.
+    expectPixelUnfilled(cx, cy);
+
+    // (cx + r, cy) should be filled.
+    expectPixelFilled(cx + r, cy, true);
+    // (cx, cy + r) should be filled.
+    expectPixelFilled(cx, cy + r, true);
+    // (cx - r, cy) should be empty.
+    expectPixelFilled(cx - r, cy, false);
+    // (cx, cy - r) should be empty.
+    expectPixelFilled(cx, cy - r, false);
+
+    // (cx + r/SQRT2, cy + r/SQRT2) should be filled.
+    expectPixelFilled((cx + r / sqrt2).toInt(), (cy + r / sqrt2).toInt(), true);
+
+    // (cx - r/SQRT2, cy - r/SQRT2) should be empty.
+    expectPixelFilled(
+        (cx - r / sqrt2).toInt(), (cy + r / sqrt2).toInt(), false);
+
+    // (cx + r/SQRT2, cy + r/SQRT2) should be empty.
+    expectPixelFilled(
+        (cx - r / sqrt2).toInt(), (cy - r / sqrt2).toInt(), false);
+
+    // (cx - r/SQRT2, cy - r/SQRT2) should be empty.
+    expectPixelFilled(
+        (cx + r / sqrt2).toInt(), (cy - r / sqrt2).toInt(), false);
+  });
+
+  test('arc anticlockwise', () {
+    context.beginPath();
+    final r = 10;
+
+    // Center of arc.
+    final cx = 20;
+    final cy = 20;
+    // Arc centered at (20, 20) with radius 10 will go anticlockwise
+    // from (20 + r, 20) to (20, 20 + r), which is 3/4 of a circle.
+    // Because of the way arc work, when going anti-clockwise, the end points
+    // are not included, so small values are added to radius to make a little
+    // more than a 3/4 circle.
+    context.arc(cx, cy, r, .1, pi / 2 - .1, true);
+
+    context.strokeStyle = 'green';
+    context.lineWidth = 2;
+    context.stroke();
+
+    // Center should not be filled.
+    expectPixelUnfilled(cx, cy);
+
+    // (cx + r, cy) should be filled.
+    expectPixelFilled(cx + r, cy, true);
+    // (cx, cy + r) should be filled.
+    expectPixelFilled(cx, cy + r, true);
+    // (cx - r, cy) should be filled.
+    expectPixelFilled(cx - r, cy, true);
+    // (cx, cy - r) should be filled.
+    expectPixelFilled(cx, cy - r, true);
+
+    // (cx + r/SQRT2, cy + r/SQRT2) should be empty.
+    expectPixelFilled(
+        (cx + r / sqrt2).toInt(), (cy + r / sqrt2).toInt(), false);
+
+    // (cx - r/SQRT2, cy - r/SQRT2) should be filled.
+    expectPixelFilled((cx - r / sqrt2).toInt(), (cy + r / sqrt2).toInt(), true);
+
+    // (cx + r/SQRT2, cy + r/SQRT2) should be filled.
+    expectPixelFilled((cx - r / sqrt2).toInt(), (cy - r / sqrt2).toInt(), true);
+
+    // (cx - r/SQRT2, cy - r/SQRT2) should be filled.
+    expectPixelFilled((cx + r / sqrt2).toInt(), (cy - r / sqrt2).toInt(), true);
+  });
+}
diff --git a/tests/lib/html/canvasrendering/canvas_rendering_util.dart b/tests/lib/html/canvasrendering/canvas_rendering_util.dart
new file mode 100644
index 0000000..037da9e
--- /dev/null
+++ b/tests/lib/html/canvasrendering/canvas_rendering_util.dart
@@ -0,0 +1,80 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library canvas_rendering_context_2d_test;
+
+import 'dart:html';
+import 'dart:math';
+
+import 'package:expect/minitest.dart';
+
+// Some rounding errors in the browsers.
+checkPixel(List<int> pixel, List<int> expected) {
+  expect(pixel[0], closeTo(expected[0], 2));
+  expect(pixel[1], closeTo(expected[1], 2));
+  expect(pixel[2], closeTo(expected[2], 2));
+  expect(pixel[3], closeTo(expected[3], 2));
+}
+
+var canvas;
+var context;
+var otherCanvas;
+var otherContext;
+var video;
+
+void createCanvas() {
+  canvas = new CanvasElement();
+  canvas.width = 100;
+  canvas.height = 100;
+
+  context = canvas.context2D;
+}
+
+void createOtherCanvas() {
+  otherCanvas = new CanvasElement();
+  otherCanvas.width = 10;
+  otherCanvas.height = 10;
+  otherContext = otherCanvas.context2D;
+  otherContext.fillStyle = "red";
+  otherContext.fillRect(0, 0, otherCanvas.width, otherCanvas.height);
+}
+
+void setupFunc() {
+  createCanvas();
+  createOtherCanvas();
+  video = new VideoElement();
+}
+
+void tearDownFunc() {
+  canvas = null;
+  context = null;
+  otherCanvas = null;
+  otherContext = null;
+  video = null;
+}
+
+List<int> readPixel(int x, int y) {
+  var imageData = context.getImageData(x, y, 1, 1);
+  return imageData.data;
+}
+
+/// Returns true if the pixel has some data in it, false otherwise.
+bool isPixelFilled(int x, int y) => readPixel(x, y).any((p) => p != 0);
+
+String pixelDataToString(List<int> data, int x, int y) {
+  return '[${data.join(", ")}]';
+}
+
+String _filled(bool v) => v ? "filled" : "unfilled";
+
+void expectPixelFilled(int x, int y, [bool filled = true]) {
+  expect(isPixelFilled(x, y), filled,
+      reason: 'Pixel at ($x, $y) was expected to'
+          ' be: <${_filled(filled)}> but was: <${_filled(!filled)}> with data: '
+          '${pixelDataToString(readPixel(x, y), x, y)}');
+}
+
+void expectPixelUnfilled(int x, int y) {
+  expectPixelFilled(x, y, false);
+}
diff --git a/tests/lib/html/canvasrendering/draw_image_canvas_element_test.dart b/tests/lib/html/canvasrendering/draw_image_canvas_element_test.dart
new file mode 100644
index 0000000..942c8f6
--- /dev/null
+++ b/tests/lib/html/canvasrendering/draw_image_canvas_element_test.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 canvas_rendering_context_2d_test;
+
+import 'dart:html';
+import 'dart:math';
+
+import 'canvas_rendering_util.dart';
+import 'package:expect/minitest.dart';
+
+main() {
+  setUp(setupFunc);
+  tearDown(tearDownFunc);
+
+  test('with 3 params', () {
+    // Draw an image to the canvas from a canvas element.
+    context.drawImage(otherCanvas, 50, 50);
+
+    expectPixelFilled(50, 50);
+    expectPixelFilled(55, 55);
+    expectPixelFilled(59, 59);
+    expectPixelUnfilled(60, 60);
+    expectPixelUnfilled(0, 0);
+    expectPixelUnfilled(70, 70);
+  });
+  test('with 5 params', () {
+    // Draw an image to the canvas from a canvas element.
+    context.drawImageToRect(otherCanvas, new Rectangle(50, 50, 20, 20));
+
+    expectPixelFilled(50, 50);
+    expectPixelFilled(55, 55);
+    expectPixelFilled(59, 59);
+    expectPixelFilled(60, 60);
+    expectPixelFilled(69, 69);
+    expectPixelUnfilled(70, 70);
+    expectPixelUnfilled(0, 0);
+    expectPixelUnfilled(80, 80);
+  });
+  test('with 9 params', () {
+    // Draw an image to the canvas from a canvas element.
+    otherContext.fillStyle = "blue";
+    otherContext.fillRect(5, 5, 5, 5);
+    context.drawImageToRect(otherCanvas, new Rectangle(50, 50, 20, 20),
+        sourceRect: new Rectangle(2, 2, 6, 6));
+
+    checkPixel(readPixel(50, 50), [255, 0, 0, 255]);
+    checkPixel(readPixel(55, 55), [255, 0, 0, 255]);
+    checkPixel(readPixel(60, 50), [255, 0, 0, 255]);
+    checkPixel(readPixel(65, 65), [0, 0, 255, 255]);
+    checkPixel(readPixel(69, 69), [0, 0, 255, 255]);
+    expectPixelFilled(50, 50);
+    expectPixelFilled(55, 55);
+    expectPixelFilled(59, 59);
+    expectPixelFilled(60, 60);
+    expectPixelFilled(69, 69);
+    expectPixelUnfilled(70, 70);
+    expectPixelUnfilled(0, 0);
+    expectPixelUnfilled(80, 80);
+  });
+
+  test('createImageData', () {
+    var imageData = context.createImageData(15, 15);
+    expect(imageData.width, 15);
+    expect(imageData.height, 15);
+
+    var other = context.createImageDataFromImageData(imageData);
+    expect(other.width, 15);
+    expect(other.height, 15);
+  });
+
+  test('createPattern', () {
+    var pattern = context.createPattern(new CanvasElement(), '');
+    //var pattern2 = context.createPatternFromImage(new ImageElement(), '');
+  });
+}
diff --git a/tests/lib/html/canvasrendering/draw_image_video_element_test.dart b/tests/lib/html/canvasrendering/draw_image_video_element_test.dart
new file mode 100644
index 0000000..9ae591e
--- /dev/null
+++ b/tests/lib/html/canvasrendering/draw_image_video_element_test.dart
@@ -0,0 +1,223 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 canvas_rendering_context_2d_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math';
+
+import 'canvas_rendering_util.dart';
+import 'package:async_helper/async_helper.dart';
+
+// These videos and base64 strings are the same video, representing 2
+// frames of 8x8 red pixels.
+// The videos were created with:
+//   convert -size 8x8 xc:red blank1.jpg
+//   convert -size 8x8 xc:red blank2.jpg
+//   avconv -f image2  -i "blank%d.jpg" -c:v libx264 small.mp4
+//   avconv -i small.mp4 small.webm
+//   python -m base64 -e small.mp4
+//   python -m base64 -e small.webm
+var mp4VideoUrl = '/root_dart/tests/lib/html/small.mp4';
+var webmVideoUrl = '/root_dart/tests/lib/html/small.webm';
+var mp4VideoDataUrl =
+    'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAA'
+    'AIZnJlZQAAAsdtZGF0AAACmwYF//+X3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlID'
+    'EyMCByMjE1MSBhM2Y0NDA3IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZW'
+    'Z0IDIwMDMtMjAxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG'
+    '9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweD'
+    'ExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj'
+    '0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MC'
+    'BkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aH'
+    'JlYWRzPTE4IHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZW'
+    'Q9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl'
+    '9weXJhbWlkPTAgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MCBvcG'
+    'VuX2dvcD0xIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleWludF9taW49MjUgc2NlbmVjdX'
+    'Q9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPT'
+    'EgY3JmPTUxLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IGlwX3'
+    'JhdGlvPTEuMjUgYXE9MToxLjAwAIAAAAARZYiEB//3aoK5/tP9+8yeuIEAAAAHQZoi2P'
+    '/wgAAAAzxtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAUAABAAABAAAAAAAAAA'
+    'AAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT/////7/AAACUHRyYWsAAA'
+    'BcdGtoZAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAQAAAA'
+    'AAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAACAAAAAgAAAAAACRlZHRzAAAAHG'
+    'Vsc3QAAAAAAAAAAQAAAFAAAAABAAEAAAAAAchtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAA'
+    'AAAAAZAAAAAlXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSG'
+    'FuZGxlcgAAAAFzbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZg'
+    'AAAAAAAAABAAAADHVybCAAAAABAAABM3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2Yz'
+    'EAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAAIAEgAAABIAAAAAAAAAAEAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwFNQAr/4QAYZ01ACuiPyy'
+    '4C2QAAAwABAAADADIPEiUSAQAGaOvAZSyAAAAAGHN0dHMAAAAAAAAAAQAAAAIAAAABAA'
+    'AAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cwAAAAAAAAABAAAAAgAAAAEAAAAcc3RzYw'
+    'AAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAK0AAAACwAAAB'
+    'hzdGNvAAAAAAAAAAIAAAAwAAAC5AAAAGB1ZHRhAAAAWG1ldGEAAAAAAAAAIWhkbHIAAA'
+    'AAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqXRvbwAAABtkYXRhAAAAAQ'
+    'AAAABMYXZmNTMuMjEuMQ==';
+var webmVideoDataUrl =
+    'data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlY'
+    'm1Ch4ECQoWBAhhTgGcBAAAAAAAB/hFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua'
+    '1OsggEsTbuMU6uEHFO7a1OsggHk7AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAA'
+    'EEq17GDD0JATYCLTGF2ZjUzLjIxLjFXQYtMYXZmNTMuMjEuMXOkkJatuHwTJ7cvFLSzB'
+    'Smxbp5EiYhAVAAAAAAAABZUrmsBAAAAAAAAR64BAAAAAAAAPteBAXPFgQGcgQAitZyDd'
+    'W5khoVWX1ZQOIOBASPjg4QCYloA4AEAAAAAAAASsIEIuoEIVLCBCFS6gQhUsoEDH0O2d'
+    'QEAAAAAAABZ54EAo72BAACA8AIAnQEqCAAIAABHCIWFiIWEiAICAnWqA/gD+gINTRgA/'
+    'v0hRf/kb+PnRv/I4//8WE8DijI//FRAo5WBACgAsQEAARAQABgAGFgv9AAIAAAcU7trA'
+    'QAAAAAAAA67jLOBALeH94EB8YIBfw==';
+
+Future testWithThreeParams() async {
+  setupFunc();
+
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoUrl;
+  } else {
+    window.console.log('Video is not supported on this system.');
+  }
+
+  // Without user interaction, playing the video requires autoplay to be enabled
+  // and autoplay can only be enabled if muted. We loop the video so there is
+  // always an active frame that can be drawn.
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
+  context.drawImage(video, 50, 50);
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(54, 54);
+  expectPixelFilled(57, 57);
+  expectPixelUnfilled(58, 58);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(70, 70);
+  tearDownFunc();
+}
+
+Future testWithFiveParams() async {
+  setupFunc();
+
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoUrl;
+  } else {
+    // TODO(amouravski): Better fallback?
+    window.console.log('Video is not supported on this system.');
+  }
+
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
+  context.drawImageToRect(video, new Rectangle(50, 50, 20, 20));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+Future testWithNineParams() async {
+  setupFunc();
+
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoUrl;
+  } else {
+    // TODO(amouravski): Better fallback?
+    window.console.log('Video is not supported on this system.');
+  }
+
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
+  context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
+      sourceRect: new Rectangle(2, 2, 6, 6));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+Future testDataUrlWithNineParams() async {
+  setupFunc();
+
+  video = new VideoElement();
+  canvas = new CanvasElement();
+
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoDataUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoDataUrl;
+  } else {
+    // TODO(amouravski): Better fallback?
+    window.console.log('Video is not supported on this system.');
+  }
+
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
+  context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
+      sourceRect: new Rectangle(2, 2, 6, 6));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+main() {
+  asyncTest(() async {
+    await testWithThreeParams();
+    await testWithFiveParams();
+    await testWithNineParams();
+    await testDataUrlWithNineParams();
+  });
+}
diff --git a/tests/lib/html/canvasrendering/fill_text_test.dart b/tests/lib/html/canvasrendering/fill_text_test.dart
new file mode 100644
index 0000000..49e3c17
--- /dev/null
+++ b/tests/lib/html/canvasrendering/fill_text_test.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.
+
+library canvas_rendering_context_2d_test;
+
+import 'dart:html';
+import 'dart:math';
+
+import 'canvas_rendering_util.dart';
+import 'package:expect/minitest.dart';
+
+main() {
+  setUp(setupFunc);
+  tearDown(tearDownFunc);
+
+  final x = 20;
+  final y = 20;
+
+  test('without maxWidth', () {
+    context.font = '40pt Garamond';
+    context.fillStyle = 'blue';
+
+    // Draw a blue box.
+    context.fillText('█', x, y);
+
+    var width = context.measureText('█').width.ceil();
+
+    checkPixel(readPixel(x, y), [0, 0, 255, 255]);
+    checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]);
+
+    expectPixelUnfilled(x - 10, y);
+    expectPixelFilled(x, y);
+    expectPixelFilled(x + 10, y);
+
+    // The box does not draw after `width` pixels.
+    // Check -2 rather than -1 because this seems
+    // to run into a rounding error on Mac bots.
+    expectPixelFilled((x + width - 2).toInt(), y);
+    expectPixelUnfilled((x + width + 1).toInt(), y);
+  });
+
+  test('with maxWidth null', () {
+    context.font = '40pt Garamond';
+    context.fillStyle = 'blue';
+
+    // Draw a blue box with null maxWidth.
+    context.fillText('█', x, y, null);
+
+    var width = context.measureText('█').width.ceil();
+
+    checkPixel(readPixel(x, y), [0, 0, 255, 255]);
+    checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]);
+
+    expectPixelUnfilled(x - 10, y);
+    expectPixelFilled(x, y);
+    expectPixelFilled(x + 10, y);
+
+    // The box does not draw after `width` pixels.
+    // Check -2 rather than -1 because this seems
+    // to run into a rounding error on Mac bots.
+    expectPixelFilled((x + width - 2).toInt(), y);
+    expectPixelUnfilled((x + width + 1).toInt(), y);
+  });
+
+  test('with maxWidth defined', () {
+    context.font = '40pt Garamond';
+    context.fillStyle = 'blue';
+
+    final maxWidth = 20;
+
+    // Draw a blue box that's at most 20 pixels wide.
+    context.fillText('█', x, y, maxWidth);
+
+    checkPixel(readPixel(x, y), [0, 0, 255, 255]);
+    checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]);
+
+    // The box does not draw after 20 pixels.
+    expectPixelUnfilled(x - 10, y);
+    expectPixelUnfilled(x + maxWidth + 1, y);
+    expectPixelUnfilled(x + maxWidth + 20, y);
+    expectPixelFilled(x, y);
+    expectPixelFilled(x + 10, y);
+  });
+}
diff --git a/tests/lib/html/canvasrendering/image_element_test.dart b/tests/lib/html/canvasrendering/image_element_test.dart
new file mode 100644
index 0000000..a1d8040
--- /dev/null
+++ b/tests/lib/html/canvasrendering/image_element_test.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.
+
+library canvas_rendering_context_2d_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math';
+
+import 'canvas_rendering_util.dart';
+import 'package:async_helper/async_helper.dart';
+
+Future testWithThreeParams() async {
+  setupFunc();
+  // Draw an image to the canvas from an image element.
+  var dataUrl = otherCanvas.toDataUrl('image/gif');
+  var img = new ImageElement();
+
+  var loadedFuture = img.onLoad.first;
+  img.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  img.src = dataUrl;
+
+  await loadedFuture;
+  context.drawImage(img, 50, 50);
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelUnfilled(60, 60);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(70, 70);
+  tearDownFunc();
+}
+
+Future testWithFiveParams() async {
+  setupFunc();
+  // Draw an image to the canvas from an image element and scale it.
+  var dataUrl = otherCanvas.toDataUrl('image/gif');
+  var img = new ImageElement();
+
+  var loadedFuture = img.onLoad.first;
+  img.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  img.src = dataUrl;
+
+  await loadedFuture;
+  context.drawImageToRect(img, new Rectangle(50, 50, 20, 20));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+Future testWithNineParams() async {
+  setupFunc();
+  // Draw an image to the canvas from an image element and scale it.
+  otherContext.fillStyle = "blue";
+  otherContext.fillRect(5, 5, 5, 5);
+  var dataUrl = otherCanvas.toDataUrl('image/gif');
+  var img = new ImageElement();
+
+  var loadedFuture = img.onLoad.first;
+  img.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  img.src = dataUrl;
+
+  await loadedFuture;
+  // This will take a 6x6 square from the first canvas from position 2,2
+  // and then scale it to a 20x20 square and place it to the second
+  // canvas at 50,50.
+  context.drawImageToRect(img, new Rectangle(50, 50, 20, 20),
+      sourceRect: new Rectangle(2, 2, 6, 6));
+
+  checkPixel(readPixel(50, 50), [255, 0, 0, 255]);
+  checkPixel(readPixel(55, 55), [255, 0, 0, 255]);
+  checkPixel(readPixel(60, 50), [255, 0, 0, 255]);
+  checkPixel(readPixel(65, 65), [0, 0, 255, 255]);
+  checkPixel(readPixel(69, 69), [0, 0, 255, 255]);
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+main() {
+  asyncTest(() async {
+    await testWithThreeParams();
+    await testWithFiveParams();
+    await testWithNineParams();
+  });
+}
diff --git a/tests/lib/html/canvasrendering/pixel_manipulation_test.dart b/tests/lib/html/canvasrendering/pixel_manipulation_test.dart
new file mode 100644
index 0000000..586072a
--- /dev/null
+++ b/tests/lib/html/canvasrendering/pixel_manipulation_test.dart
@@ -0,0 +1,171 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 canvas_rendering_context_2d_test;
+
+import 'dart:html';
+import 'dart:math';
+
+import 'canvas_rendering_util.dart';
+import 'package:expect/minitest.dart';
+
+main() {
+  setUp(setupFunc);
+  tearDown(tearDownFunc);
+
+  test('setFillColorRgb', () {
+    context.setFillColorRgb(255, 0, 255, 1);
+    context.fillRect(0, 0, canvas.width, canvas.height);
+    expect(readPixel(2, 2), [255, 0, 255, 255]);
+  });
+
+  test('setFillColorHsl hue', () {
+    context.setFillColorHsl(0, 100, 50);
+    context.fillRect(0, 0, canvas.width, canvas.height);
+    checkPixel(readPixel(2, 2), [255, 0, 0, 255]);
+  });
+
+  test('setFillColorHsl hue 2', () {
+    context.setFillColorHsl(240, 100, 50);
+    context.fillRect(0, 0, canvas.width, canvas.height);
+    checkPixel(readPixel(2, 2), [0, 0, 255, 255]);
+  });
+
+  test('setFillColorHsl sat', () {
+    context.setFillColorHsl(0, 0, 50);
+    context.fillRect(0, 0, canvas.width, canvas.height);
+    checkPixel(readPixel(2, 2), [127, 127, 127, 255]);
+  });
+
+  test('setStrokeColorRgb', () {
+    context.setStrokeColorRgb(255, 0, 255, 1);
+    context.lineWidth = 10;
+    context.strokeRect(0, 0, canvas.width, canvas.height);
+    expect(readPixel(2, 2), [255, 0, 255, 255]);
+  });
+
+  test('setStrokeColorHsl hue', () {
+    context.setStrokeColorHsl(0, 100, 50);
+    context.lineWidth = 10;
+    context.strokeRect(0, 0, canvas.width, canvas.height);
+    expect(readPixel(2, 2), [255, 0, 0, 255]);
+  });
+
+  test('setStrokeColorHsl hue 2', () {
+    context.setStrokeColorHsl(240, 100, 50);
+    context.lineWidth = 10;
+    context.strokeRect(0, 0, canvas.width, canvas.height);
+    expect(readPixel(2, 2), [0, 0, 255, 255]);
+  });
+
+  test('setStrokeColorHsl sat', () {
+    context.setStrokeColorHsl(0, 0, 50);
+    context.lineWidth = 10;
+    context.strokeRect(0, 0, canvas.width, canvas.height);
+    checkPixel(readPixel(2, 2), [127, 127, 127, 255]);
+  });
+
+  test('fillStyle', () {
+    context.fillStyle = "red";
+    context.fillRect(0, 0, canvas.width, canvas.height);
+    checkPixel(readPixel(2, 2), [255, 0, 0, 255]);
+  });
+
+  test('strokeStyle', () {
+    context.strokeStyle = "blue";
+    context.lineWidth = 10;
+    context.strokeRect(0, 0, canvas.width, canvas.height);
+    expect(readPixel(2, 2), [0, 0, 255, 255]);
+  });
+
+  test('fillStyle linearGradient', () {
+    var gradient = context.createLinearGradient(0, 0, 20, 20);
+    gradient.addColorStop(0, 'red');
+    gradient.addColorStop(1, 'blue');
+    context.fillStyle = gradient;
+    context.fillRect(0, 0, canvas.width, canvas.height);
+    expect(context.fillStyle is CanvasGradient, isTrue);
+  });
+
+  test('putImageData', () {
+    context.fillStyle = 'green';
+    context.fillRect(0, 0, canvas.width, canvas.height);
+
+    ImageData expectedData = context.getImageData(0, 0, 10, 10);
+    expectedData.data[0] = 25;
+    expectedData.data[1] = 65;
+    expectedData.data[2] = 255;
+    // Set alpha to 255 to make the pixels show up.
+    expectedData.data[3] = 255;
+
+    context.putImageData(expectedData, 0, 0);
+
+    var resultingData = context.getImageData(0, 0, 10, 10);
+    // Make sure that we read back what we wrote.
+    expect(resultingData.data, expectedData.data);
+  });
+
+  test('putImageData dirty rectangle', () {
+    context.fillStyle = 'green';
+    context.fillRect(0, 0, canvas.width, canvas.height);
+
+    ImageData drawnData = context.getImageData(0, 0, 10, 10);
+    drawnData.data[0] = 25;
+    drawnData.data[1] = 65;
+    drawnData.data[2] = 255;
+    drawnData.data[3] = 255;
+
+    // Draw these pixels to the 2nd pixel.
+    drawnData.data[2 * 4 + 0] = 25;
+    drawnData.data[2 * 4 + 1] = 65;
+    drawnData.data[2 * 4 + 2] = 255;
+    drawnData.data[2 * 4 + 3] = 255;
+
+    // Draw these pixels to the 8th pixel.
+    drawnData.data[7 * 4 + 0] = 25;
+    drawnData.data[7 * 4 + 1] = 65;
+    drawnData.data[7 * 4 + 2] = 255;
+    drawnData.data[7 * 4 + 3] = 255;
+
+    // Use a dirty rectangle to limit what pixels are drawn.
+    context.putImageData(drawnData, 0, 0, 1, 0, 5, 5);
+
+    // Expect the data to be all green, as we skip all drawn pixels.
+    ImageData expectedData = context.createImageData(10, 10);
+    for (int i = 0; i < expectedData.data.length; i++) {
+      switch (i % 4) {
+        case 0:
+          expectedData.data[i] = 0;
+          break;
+        case 1:
+          expectedData.data[i] = 128;
+          break;
+        case 2:
+          expectedData.data[i] = 0;
+          break;
+        case 3:
+          expectedData.data[i] = 255;
+          break;
+      }
+    }
+    // Third pixel was copied.
+    expectedData.data[2 * 4 + 0] = 25;
+    expectedData.data[2 * 4 + 1] = 65;
+    expectedData.data[2 * 4 + 2] = 255;
+    expectedData.data[2 * 4 + 3] = 255;
+
+    // Make sure that our data is all green.
+    var resultingData = context.getImageData(0, 0, 10, 10);
+    expect(resultingData.data, expectedData.data);
+  });
+
+  test('putImageData throws with wrong number of arguments', () {
+    ImageData expectedData = context.getImageData(0, 0, 10, 10);
+
+    // TODO(antonm): in Dartium ArgumentError should be thrown too.
+    expect(() => context.putImageData(expectedData, 0, 0, 1), throws);
+    expect(() => context.putImageData(expectedData, 0, 0, 1, 1), throws);
+    expect(() => context.putImageData(expectedData, 0, 0, 1, 1, 5), throws);
+  });
+}
diff --git a/tests/lib/html/cdata_test.dart b/tests/lib/html/cdata_test.dart
new file mode 100644
index 0000000..60c311a
--- /dev/null
+++ b/tests/lib/html/cdata_test.dart
@@ -0,0 +1,20 @@
+// 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:expect/minitest.dart';
+
+main() {
+  test('remove', () {
+    var div = new Element.html('<div>content</div>');
+    var cdata = div.nodes[0];
+    expect(cdata is CharacterData, true);
+    expect(cdata, isNotNull);
+    expect(div.innerHtml, 'content');
+
+    cdata.remove();
+    expect(div.innerHtml, '');
+  });
+}
diff --git a/tests/lib/html/client_rect_test.dart b/tests/lib/html/client_rect_test.dart
new file mode 100644
index 0000000..a02fb0d
--- /dev/null
+++ b/tests/lib/html/client_rect_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:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isRectList =
+      predicate((x) => x is DomRectList, 'should be a DomRectList');
+  var isListOfRectangle =
+      predicate((x) => x is List<Rectangle>, 'should be a List<Rectangle>');
+
+  var isRectangle = predicate((x) => x is Rectangle, 'should be a Rectangle');
+  var isDomRectReadOnly =
+      predicate((x) => x is DomRectReadOnly, 'should be a DomRectReadOnly');
+
+  insertTestDiv() {
+    var element = new Element.tag('div');
+    element.innerHtml = r'''
+    A large block of text should go here. Click this
+    block of text multiple times to see each line
+    highlight with every click of the mouse button.
+    ''';
+    document.body!.append(element);
+    return element;
+  }
+
+  test("DomRectList test", () {
+    insertTestDiv();
+    var range = new Range();
+    var rects = range.getClientRects();
+    expect(rects, isListOfRectangle);
+    expect(rects, isRectList);
+  });
+
+  test("ClientRect ==", () {
+    var rect1 = document.body!.getBoundingClientRect();
+    var rect2 = document.body!.getBoundingClientRect();
+    expect(rect1, isRectangle);
+    expect(rect1, isDomRectReadOnly);
+    expect(rect1, equals(rect2));
+  });
+}
diff --git a/tests/lib/html/cross_domain_iframe_script.html b/tests/lib/html/cross_domain_iframe_script.html
new file mode 100644
index 0000000..b626071
--- /dev/null
+++ b/tests/lib/html/cross_domain_iframe_script.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+
+<html>
+  <head>
+  	<meta charset="utf-8">
+    <title>cross_domain_iframe_script</title>
+  </head>
+
+  <body>
+    <script type="application/javascript"
+            src="/root_dart/tests/lib/html/cross_domain_iframe_script.js">
+    </script>
+  </body>
+</html>
diff --git a/tests/lib/html/cross_domain_iframe_script.js b/tests/lib/html/cross_domain_iframe_script.js
new file mode 100644
index 0000000..9dcdc75
--- /dev/null
+++ b/tests/lib/html/cross_domain_iframe_script.js
@@ -0,0 +1 @@
+window.parent.postMessage('foobar', '*');
\ No newline at end of file
diff --git a/tests/lib/html/cross_domain_iframe_test.dart b/tests/lib/html/cross_domain_iframe_test.dart
new file mode 100644
index 0000000..cbd2726
--- /dev/null
+++ b/tests/lib/html/cross_domain_iframe_test.dart
@@ -0,0 +1,29 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:expect/minitest.dart';
+
+main() {
+  var uri = Uri.parse(window.location.href);
+
+  var crossOriginPort = int.parse(uri.queryParameters['crossOriginPort']!);
+  var crossOrigin = '${uri.scheme}://${uri.host}:$crossOriginPort';
+  var crossOriginUrl =
+      '$crossOrigin/root_dart/tests/lib/html/cross_domain_iframe_script.html';
+
+  var iframe = new IFrameElement();
+  iframe.src = crossOriginUrl;
+  document.body!.append(iframe);
+
+  return window.onMessage
+      .where((MessageEvent event) {
+        return event.origin == crossOrigin;
+      })
+      .first
+      .then((MessageEvent event) {
+        expect(event.data, equals('foobar'));
+        expect(event.source, isNotNull);
+      });
+}
diff --git a/tests/lib/html/cross_frame_test.dart b/tests/lib/html/cross_frame_test.dart
new file mode 100644
index 0000000..def8d71
--- /dev/null
+++ b/tests/lib/html/cross_frame_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+main() {
+  var isWindowBase = predicate((x) => x is WindowBase, 'is a WindowBase');
+  var isWindow = predicate((x) => x is Window, 'is a Window');
+  var isLocationBase = predicate((x) => x is LocationBase, 'is a LocationBase');
+  var isLocation = predicate((x) => x is Location, 'is a Location');
+  var isHistoryBase = predicate((x) => x is HistoryBase, 'is a HistoryBase');
+  var isHistory = predicate((x) => x is History, 'is a History');
+
+  final dynamic iframe = new IFrameElement();
+  document.body!.append(iframe);
+
+  test('window', () {
+    expect(window, isWindow);
+    expect(window.document, document);
+  });
+
+  test('iframe', () {
+    final frameWindow = iframe.contentWindow;
+    expect(frameWindow, isWindowBase);
+    //TODO(gram) The next test should be written as:
+    //    expect(frameWindow, isNot(isWindow));
+    // but that will cause problems now until is/is! work
+    // properly in dart2js instead of always returning true.
+    expect(frameWindow is! Window, isTrue);
+    expect(frameWindow.parent, isWindow);
+
+    // Ensure that the frame's document is inaccessible via window.
+    expect(() => frameWindow.document, throws);
+  });
+
+  test('contentDocument', () {
+    // Ensure that the frame's document is inaccessible.
+    expect(() => iframe.contentDocument, throws);
+  });
+
+  test('location', () {
+    expect(window.location, isLocation);
+    final frameLocation = iframe.contentWindow.location;
+    expect(frameLocation, isLocationBase);
+    // TODO(gram) Similar to the above, the next test should be:
+    //     expect(frameLocation, isNot(isLocation));
+    expect(frameLocation is! Location, isTrue);
+
+    expect(() => frameLocation.href, throws);
+    expect(() => frameLocation.hash, throws);
+
+    final frameParentLocation = iframe.contentWindow.parent.location;
+    expect(frameParentLocation, isLocation);
+  });
+
+  test('history', () {
+    expect(window.history, isHistory);
+    final frameHistory = iframe.contentWindow.history;
+    expect(frameHistory, isHistoryBase);
+    // See earlier comments.
+    //expect(frameHistory, isNot(isHistory));
+    expect(frameHistory is! History, isTrue);
+
+    // Valid methods.
+    frameHistory.forward();
+
+    expect(() => frameHistory.length, throws);
+
+    final frameParentHistory = iframe.contentWindow.parent.history;
+    expect(frameParentHistory, isHistory);
+  });
+}
diff --git a/tests/lib/html/crypto_test.dart b/tests/lib/html/crypto_test.dart
new file mode 100644
index 0000000..9cb63ab
--- /dev/null
+++ b/tests/lib/html/crypto_test.dart
@@ -0,0 +1,46 @@
+// 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:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(Crypto.supported, true);
+    });
+  });
+
+  group('functional', () {
+    if (Crypto.supported) {
+      // This will actually pass on FF since it has a Crypto API, but it is
+      // incompatible.
+      test('exists', () {
+        var crypto = window.crypto;
+        expect(crypto is Crypto, isTrue);
+      });
+
+      test('successful call', () {
+        var crypto = window.crypto;
+        var data = new Uint8List(100);
+        expect(data.every((e) => e == 0), isTrue);
+        crypto.getRandomValues(data);
+        // In theory this is flaky. However, in practice you will get 100 zeroes
+        // in a row from a cryptographically secure random number generator so
+        // rarely that we don't have to worry about it.
+        expect(data.any((e) => e != 0), isTrue);
+      });
+
+      test('type mismatch', () {
+        var crypto = window.crypto;
+        var data = new Float32List(100);
+        expect(() {
+          crypto.getRandomValues(data);
+        }, throws, reason: 'Only typed array views with integer types allowed');
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/css_rule_list_test.dart b/tests/lib/html/css_rule_list_test.dart
new file mode 100644
index 0000000..596e2d8
--- /dev/null
+++ b/tests/lib/html/css_rule_list_test.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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isCssRuleList =
+      predicate((x) => x is List<CssRule>, 'is a List<CssRule>');
+
+  test("ClientRectList test", () {
+    var sheet = document.styleSheets[0] as CssStyleSheet;
+    List<CssRule> rulesList = sheet.cssRules;
+    expect(rulesList, isCssRuleList);
+  });
+}
diff --git a/tests/lib/html/css_selector_test.dart b/tests/lib/html/css_selector_test.dart
new file mode 100644
index 0000000..9d82842
--- /dev/null
+++ b/tests/lib/html/css_selector_test.dart
@@ -0,0 +1,48 @@
+// 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:expect/expect.dart';
+import 'utils.dart';
+
+main() {
+  final String htmlPayload = "<div>"
+      "<div>"
+      "<p class='a'>"
+      "<span>Test #1</span>"
+      "</p>"
+      "</div>"
+      "<div>"
+      "<p class='b'>"
+      "<span>Test #2</span>"
+      "</p>"
+      "</div>"
+      "</div>";
+
+  final elements =
+      new Element.html(htmlPayload, treeSanitizer: new NullTreeSanitizer());
+  document.body!.nodes.add(elements);
+
+  var para = document.body!.querySelector('p') as ParagraphElement;
+  para.classes.removeAll(['a', 'b']);
+
+  para = document.body!.querySelector('p') as ParagraphElement;
+  Expect.equals('<p class=""><span>Test #1</span></p>', para.outerHtml);
+
+  para = document.body!.querySelector('p') as ParagraphElement;
+  para.classes.addAll(['c']);
+
+  para = document.body!.querySelector('p') as ParagraphElement;
+  Expect.equals('<p class="c"><span>Test #1</span></p>', para.outerHtml);
+
+  var allPara = document.body!.querySelectorAll('p');
+  allPara.classes.removeAll(['b', 'c']);
+
+  var checkAllPara = document.body!.querySelectorAll('p');
+  Expect.equals(
+      '<p class=""><span>Test #1</span></p>', checkAllPara[0].outerHtml);
+  Expect.equals(
+      '<p class=""><span>Test #2</span></p>', checkAllPara[1].outerHtml);
+}
diff --git a/tests/lib/html/css_test.dart b/tests/lib/html/css_test.dart
new file mode 100644
index 0000000..a3a00f9
--- /dev/null
+++ b/tests/lib/html/css_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 CssTest;
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supportsPointConversions', () {
+    test('supported', () {
+      expect(Window.supportsPointConversions, true);
+    });
+  });
+
+  group('functional', () {
+    test('DomPoint', () {
+      var expectation =
+          Window.supportsPointConversions ? returnsNormally : throws;
+      expect(() {
+        Element element = new Element.tag('div');
+        element.attributes['style'] = '''
+          position: absolute;
+          width: 60px;
+          height: 100px;
+          left: 0px;
+          top: 0px;
+          background-color: red;
+          -webkit-transform: translate3d(250px, 100px, 0px);
+          -moz-transform: translate3d(250px, 100px, 0px);
+          ''';
+        document.body!.append(element);
+
+        var elemRect = element.getBoundingClientRect();
+
+        checkPoint(250, 100, new Point(elemRect.left, elemRect.top));
+        checkPoint(310, 200, new Point(elemRect.right, elemRect.bottom));
+      }, expectation);
+    });
+  });
+}
+
+void checkPoint(expectedX, expectedY, Point point) {
+  expect(point.x.round(), equals(expectedX), reason: 'Wrong point.x');
+  expect(point.y.round(), equals(expectedY), reason: 'Wrong point.y');
+}
diff --git a/tests/lib/html/cssstyledeclaration_test.dart b/tests/lib/html/cssstyledeclaration_test.dart
new file mode 100644
index 0000000..aa8a5d4
--- /dev/null
+++ b/tests/lib/html/cssstyledeclaration_test.dart
@@ -0,0 +1,165 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 CssStyleDeclarationTest;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  createTestStyle() {
+    return new CssStyleDeclaration.css("""
+      color: blue;
+      width: 2px !important;
+    """);
+  }
+
+  ;
+
+  test('default constructor is empty', () {
+    var style = new CssStyleDeclaration();
+    expect(style.cssText.isEmpty, isTrue);
+    expect(style.getPropertyPriority('color').isEmpty, isTrue);
+    expect(style.item(0).isEmpty, isTrue);
+    expect(style.length, 0);
+    // These assertions throw a UnimplementedError in dartium:
+    // expect(style.parentRule, isNull);
+    // expect(style.getPropertyCssValue('color'), isNull);
+    // expect(style.getPropertyShorthand('color'), isNull);
+  });
+
+  test('length is wrapped', () {
+    expect(createTestStyle().length, 2);
+  });
+
+  test('getPropertyPriority is wrapped', () {
+    var style = createTestStyle();
+    expect(style.getPropertyPriority("color").isEmpty, isTrue);
+    expect(style.getPropertyPriority("width"), equals("important"));
+  });
+
+  test('removeProperty is wrapped', () {
+    var style = createTestStyle();
+    style.removeProperty("width");
+    expect(style.cssText.trim(), equals("color: blue;"));
+  });
+
+  test('CSS property empty getters and setters', () {
+    var style = createTestStyle();
+    expect(style.border, equals(""));
+
+    style.border = "1px solid blue";
+    style.border = "";
+    expect(style.border, equals(""));
+
+    style.border = "1px solid blue";
+    style.border = null;
+    expect(style.border, equals(""));
+  });
+
+  test('CSS property getters and setters', () {
+    var style = createTestStyle();
+    expect(style.color, equals("blue"));
+    expect(style.width, equals("2px"));
+
+    style.color = "red";
+    style.transform = "translate(10px, 20px)";
+
+    expect(style.color, equals("red"));
+    expect(style.transform, equals("translate(10px, 20px)"));
+  });
+
+  test('Browser prefixes', () {
+    var element = new DivElement();
+    element.style.transform = 'translateX(10px)';
+    document.body!.children.add(element);
+
+    var style = element.getComputedStyle();
+    // Some browsers will normalize this, so it'll be a matrix rather than
+    // the original string. Just check that it's something other than null.
+    expect(style.transform.length, greaterThan(3));
+  });
+
+  // IE9 requires an extra poke for some properties to get applied.
+  test('IE9 Invalidation', () {
+    var element = new DivElement();
+    document.body!.children.add(element);
+
+    // Need to wait one tick after the element has been added to the page.
+    new Timer(const Duration(milliseconds: 10), expectAsync(() {
+      element.style.textDecoration = 'underline';
+      var style = element.getComputedStyle();
+      expect(style.textDecoration.contains('underline'), isTrue);
+    }));
+  });
+
+  test('Invalid values', () {
+    var element = new DivElement();
+    // Should not throw an error.
+    element.style.background = 'some_bad_value';
+  });
+
+  test('css multi get', () {
+    var listElement = new Element.html(
+        '<ul class="foo">'
+        '<li class="bar" style="background-color: red; border-left: 10px;">'
+        '<li class="baz" style="background-color: black;>'
+        '<li class="baz classy" style="background-color: blue; ">'
+        '</ul>',
+        treeSanitizer: new NullTreeSanitizer());
+    document.documentElement!.children.add(listElement);
+
+    var elements = document.querySelectorAll('li');
+    expect(elements.style.backgroundColor, equals('red'));
+    expect(elements.style.borderLeftWidth, equals('10px'));
+    elements = document.querySelectorAll('.baz');
+    expect(elements.style.backgroundColor, equals('black'));
+    expect(elements.style.borderLeftWidth, equals(''));
+    elements = document.querySelectorAll('.bar');
+    expect(elements.style.backgroundColor, equals('red'));
+  });
+
+  test('css multi set', () {
+    var listElement = new Element.html(
+        '<ul class="foo">'
+        '<li class="bar" style="background-color: red; border-left: 10px;">'
+        '<li class="baz" style="background-color: black;>'
+        '<li class="baz" id="wat" style="background-color: blue; ">'
+        '</ul>',
+        treeSanitizer: new NullTreeSanitizer());
+    document.documentElement!.children.add(listElement);
+
+    var elements = document.querySelectorAll('li');
+    elements.style.backgroundColor = 'green';
+    expect(elements.style.backgroundColor, equals('green'));
+    expect(elements.style.borderLeftWidth, equals('10px'));
+
+    elements = document.querySelectorAll('.baz');
+    expect(elements.style.backgroundColor, equals('green'));
+    elements.style.backgroundColor = 'yellow';
+    expect(elements.style.backgroundColor, equals('yellow'));
+    expect(elements.style.borderLeftWidth, equals(''));
+
+    elements = document.querySelectorAll('.bar');
+    expect(elements.style.backgroundColor, equals('green'));
+    elements = document.querySelectorAll('#wat');
+    expect(elements.style.backgroundColor, equals('yellow'));
+
+    elements.style.borderLeftWidth = '18px';
+    expect(elements.style.borderLeftWidth, equals('18px'));
+    elements = document.querySelectorAll('li');
+    expect(elements.style.borderLeftWidth, equals('10px'));
+  });
+
+  test('supports property', () {
+    expect(document.body!.style.supportsProperty('bogus-property'), false);
+    expect(document.body!.style.supportsProperty('background'), true);
+    expect(document.body!.style.supportsProperty('borderBottomWidth'), true);
+    expect(document.body!.style.supportsProperty('animation'), true);
+  });
+}
diff --git a/tests/lib/html/custom/attribute_changed_callback_test.dart b/tests/lib/html/custom/attribute_changed_callback_test.dart
new file mode 100644
index 0000000..6455cc3
--- /dev/null
+++ b/tests/lib/html/custom/attribute_changed_callback_test.dart
@@ -0,0 +1,120 @@
+// 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 attribute_changed_callback_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class A extends HtmlElement {
+  static final tag = 'x-a';
+  factory A() => new Element.tag(tag) as A;
+  A.created() : super.created();
+
+  static var attributeChangedInvocations = 0;
+
+  void attributeChanged(name, oldValue, newValue) {
+    attributeChangedInvocations++;
+  }
+}
+
+class B extends HtmlElement {
+  static final tag = 'x-b';
+  factory B() => new Element.tag(tag) as B;
+  B.created() : super.created() {
+    invocations.add('created');
+  }
+
+  static var invocations = [];
+
+  Completer? completer;
+
+  void attributeChanged(name, oldValue, newValue) {
+    invocations.add('$name: $oldValue => $newValue');
+    if (completer != null) {
+      completer!.complete('value changed to $newValue');
+      completer = null;
+    }
+  }
+}
+
+// Pump custom events polyfill events.
+void customElementsTakeRecords() {
+  if (js.context.hasProperty('CustomElements')) {
+    js.context['CustomElements'].callMethod('takeRecords');
+  }
+}
+
+main() async {
+  // Adapted from Blink's fast/dom/custom/attribute-changed-callback test.
+
+  await customElementsReady;
+  document.registerElement2(A.tag, {'prototype': A});
+  document.registerElement2(B.tag, {'prototype': B});
+
+  group('fully_supported', () {
+    test('transfer attribute changed callback', () {
+      var element = new A();
+
+      element.attributes['a'] = 'b';
+      expect(A.attributeChangedInvocations, 1);
+    });
+
+    test('add, change and remove an attribute', () {
+      var b = new B();
+
+      B.invocations = [];
+      b.attributes['data-s'] = 't';
+      expect(B.invocations, ['data-s: null => t']);
+
+      b.attributes['data-v'] = 'w';
+      B.invocations = [];
+      b.attributes['data-v'] = 'x';
+      expect(B.invocations, ['data-v: w => x']);
+
+      B.invocations = [];
+      b.attributes['data-v'] = 'x';
+      expect(B.invocations, []);
+
+      b.attributes.remove('data-v');
+      expect(B.invocations, ['data-v: x => null']);
+    });
+
+    test('add, change ID', () {
+      B.invocations = [];
+
+      var b = new B();
+      var completer = new Completer();
+      b.completer = completer;
+      b.id = 'x';
+      return completer.future
+          .then((_) => expect(B.invocations, ['created', 'id: null => x']))
+          .then((_) {
+        B.invocations = [];
+        var secondCompleter = new Completer();
+        b.completer = secondCompleter;
+        b.attributes.remove('id');
+        return secondCompleter.future;
+      }).then((_) => expect(B.invocations, ['id: x => null']));
+    });
+  });
+
+  group('unsupported_on_polyfill', () {
+    // If these tests start passing, don't remove the status suppression. Move
+    // the tests to the fullYy_supported group.
+
+    test('add, change classes', () {
+      var b = new B();
+
+      B.invocations = [];
+      b.classes.toggle('u');
+      expect(B.invocations, ['class: null => u']);
+    });
+  });
+}
diff --git a/tests/lib/html/custom/attribute_changed_callback_test.html b/tests/lib/html/custom/attribute_changed_callback_test.html
new file mode 100644
index 0000000..b38ec6e
--- /dev/null
+++ b/tests/lib/html/custom/attribute_changed_callback_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> attribute_changed_callback_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running attribute_changed_callback_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/created_callback_test.dart b/tests/lib/html/custom/created_callback_test.dart
new file mode 100644
index 0000000..5889b06
--- /dev/null
+++ b/tests/lib/html/custom/created_callback_test.dart
@@ -0,0 +1,296 @@
+// 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 created_callback_test;
+
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class A extends HtmlElement {
+  static final tag = 'x-a';
+  factory A() => new Element.tag(tag) as A;
+  A.created() : super.created() {
+    createdInvocations++;
+  }
+
+  static int createdInvocations = 0;
+}
+
+class B extends HtmlElement {
+  static final tag = 'x-b';
+  factory B() => new Element.tag(tag) as B;
+  B.created() : super.created();
+}
+
+class C extends HtmlElement {
+  static final tag = 'x-c';
+  factory C() => new Element.tag(tag) as C;
+  C.created() : super.created() {
+    createdInvocations++;
+
+    if (this.id != 'u') {
+      return;
+    }
+
+    var t = div.querySelector('#t');
+    var v = div.querySelector('#v');
+    var w = div.querySelector('#w');
+
+    expect(querySelector('x-b:not(:unresolved)'), this);
+    expect(querySelectorAll(':unresolved'), [v, w]);
+
+    // As per:
+    // http://www.w3.org/TR/2013/WD-custom-elements-20130514/#serializing-and-parsing
+    // creation order is t, u, v, w (postorder).
+    expect(t is C, isTrue);
+    // Note, this is different from JavaScript where this would be false.
+    expect(v is C, isTrue);
+  }
+
+  static int createdInvocations = 0;
+  static var div;
+}
+
+main() async {
+  // Adapted from Blink's
+  // fast/dom/custom/created-callback test.
+
+  await customElementsReady;
+  document.registerElement2(B.tag, {'prototype': B});
+  document.registerElement2(C.tag, {'prototype': C});
+  ErrorConstructorElement.register();
+
+  test('transfer created callback', () {
+    document.registerElement2(A.tag, {'prototype': A as dynamic});
+    var x = new A();
+    expect(A.createdInvocations, 1);
+  });
+
+  test('unresolved and created callback timing', () {
+    var div = new DivElement();
+    C.div = div;
+    div.setInnerHtml("""
+<x-c id="t"></x-c>
+<x-b id="u"></x-b>
+<x-c id="v"></x-c>
+<x-b id="w"></x-b>
+""", treeSanitizer: NodeTreeSanitizer.trusted);
+
+    upgradeCustomElements(div);
+
+    expect(C.createdInvocations, 2);
+    expect(div.querySelector('#w') is B, isTrue);
+  });
+
+  test('nesting of constructors', NestedElement.test);
+
+  test('access while upgrading gets unupgraded element',
+      AccessWhileUpgradingElement.test);
+
+  test('cannot call created constructor', () {
+    expect(() {
+      new B.created();
+    }, throws);
+  });
+
+  test('cannot register without created', () {
+    expect(() {
+      document.registerElement2(
+          MissingCreatedElement.tag, {'prototype': MissingCreatedElement});
+    }, throws);
+  });
+
+  test('throw on createElement does not upgrade', () {
+    ErrorConstructorElement.callCount = 0;
+
+    var e;
+    expectGlobalError(() {
+      e = new Element.tag(ErrorConstructorElement.tag);
+    });
+    expect(ErrorConstructorElement.callCount, 1);
+    expect(e is HtmlElement, isTrue);
+    expect(e is ErrorConstructorElement, isFalse);
+
+    var dummy = new DivElement();
+    dummy.append(e);
+    e = dummy.firstChild;
+    expect(ErrorConstructorElement.callCount, 1);
+  });
+
+  test('throw on innerHtml does not upgrade', () {
+    ErrorConstructorElement.callCount = 0;
+
+    var dummy = new DivElement();
+    var tag = ErrorConstructorElement.tag;
+    expectGlobalError(() {
+      dummy.setInnerHtml('<$tag></$tag>',
+          treeSanitizer: NodeTreeSanitizer.trusted);
+    });
+
+    expect(ErrorConstructorElement.callCount, 1);
+
+    var e = dummy.firstChild;
+    // Accessing should not re-run the constructor.
+    expect(ErrorConstructorElement.callCount, 1);
+    expect(e is HtmlElement, isTrue);
+    expect(e is ErrorConstructorElement, isFalse);
+  });
+
+  test('cannot register created with params', () {
+    expect(() {
+      document.registerElement2(
+          'x-created-with-params', {'prototype': CreatedWithParametersElement});
+    }, throws);
+  });
+
+  test('created cannot be called from nested constructor',
+      NestedCreatedConstructorElement.test);
+
+  // TODO(vsm): Port additional test from upstream here:
+  // http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dom/custom/created-callback.html?r1=156141&r2=156185
+}
+
+class NestedElement extends HtmlElement {
+  static final tag = 'x-nested';
+
+  final Element b = new B();
+
+  factory NestedElement() => new Element.tag(tag) as NestedElement;
+  NestedElement.created() : super.created();
+
+  static void register() {
+    document.registerElement2(tag, {'prototype': NestedElement});
+  }
+
+  static void test() {
+    register();
+
+    var e = new NestedElement();
+    expect(e.b, isNotNull);
+    expect(e.b is B, isTrue);
+    expect(e is NestedElement, isTrue);
+  }
+}
+
+class AccessWhileUpgradingElement extends HtmlElement {
+  static final tag = 'x-access-while-upgrading';
+
+  static late Element upgradingContext;
+  static late Element upgradingContextChild;
+
+  final foo = runInitializerCode();
+
+  factory AccessWhileUpgradingElement() =>
+      new Element.tag(tag) as AccessWhileUpgradingElement;
+  AccessWhileUpgradingElement.created() : super.created();
+
+  static runInitializerCode() {
+    upgradingContextChild = upgradingContext.firstChild as Element;
+
+    return 666;
+  }
+
+  static void register() {
+    document.registerElement2(tag, {'prototype': AccessWhileUpgradingElement});
+  }
+
+  static void test() {
+    register();
+
+    upgradingContext = new DivElement();
+    upgradingContext.setInnerHtml('<$tag></$tag>',
+        treeSanitizer: new NullTreeSanitizer());
+    dynamic child = upgradingContext.firstChild;
+
+    expect(child.foo, 666);
+    expect(upgradingContextChild is HtmlElement, isFalse);
+    expect(upgradingContextChild is AccessWhileUpgradingElement, isFalse,
+        reason: 'Elements accessed while upgrading should not be upgraded.');
+  }
+}
+
+class MissingCreatedElement extends HtmlElement {
+  static final tag = 'x-missing-created';
+
+  factory MissingCreatedElement() =>
+      new Element.tag(tag) as MissingCreatedElement;
+}
+
+class ErrorConstructorElement extends HtmlElement {
+  static final tag = 'x-throws-in-constructor';
+  static int callCount = 0;
+
+  factory ErrorConstructorElement() =>
+      new Element.tag(tag) as ErrorConstructorElement;
+
+  ErrorConstructorElement.created() : super.created() {
+    ++callCount;
+    throw new Exception('Just messin with ya');
+  }
+
+  static void register() {
+    document.registerElement2(tag, {'prototype': ErrorConstructorElement});
+  }
+}
+
+class NestedCreatedConstructorElement extends HtmlElement {
+  static final tag = 'x-nested-created-constructor';
+
+  // Should not be able to call this here.
+  final B b = constructB();
+  static B? constructedB;
+
+  factory NestedCreatedConstructorElement() =>
+      new Element.tag(tag) as NestedCreatedConstructorElement;
+  NestedCreatedConstructorElement.created() : super.created();
+
+  static void register() {
+    document
+        .registerElement2(tag, {'prototype': NestedCreatedConstructorElement});
+  }
+
+  // Try to run the created constructor, and record the results.
+  static constructB() {
+    // This should throw an exception.
+    constructedB = new B.created();
+    return constructedB;
+  }
+
+  static void test() {
+    register();
+
+    // Exception should have occurred on upgrade.
+    var e;
+    expectGlobalError(() {
+      e = new Element.tag(tag);
+    });
+    expect(e is NestedCreatedConstructorElement, isFalse);
+    expect(e is HtmlElement, isTrue);
+    // Should not have been set.
+    expect(constructedB, isNull);
+  }
+}
+
+class CreatedWithParametersElement extends HtmlElement {
+  CreatedWithParametersElement.created(ignoredParam) : super.created();
+}
+
+void expectGlobalError(Function test) {
+  js.context['testExpectsGlobalError'] = true;
+  try {
+    test();
+  } catch (e) {
+    rethrow;
+  } finally {
+    js.context['testExpectsGlobalError'] = false;
+  }
+  var errors = js.context['testSuppressedGlobalErrors'];
+  expect(errors['length'], 1);
+  // Clear out the errors;
+  js.context['testSuppressedGlobalErrors']['length'] = 0;
+}
diff --git a/tests/lib/html/custom/created_callback_test.html b/tests/lib/html/custom/created_callback_test.html
new file mode 100644
index 0000000..ca6e193
--- /dev/null
+++ b/tests/lib/html/custom/created_callback_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> created_callback_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running created_callback_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/document_register_basic_test.dart b/tests/lib/html/custom/document_register_basic_test.dart
new file mode 100644
index 0000000..7a5db71
--- /dev/null
+++ b/tests/lib/html/custom/document_register_basic_test.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 document_register_basic_test;
+
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class Foo extends HtmlElement {
+  static final tag = 'x-foo';
+  factory Foo() => new Element.tag(tag) as Foo;
+  Foo.created() : super.created();
+
+  get thisIsACustomClass => true;
+}
+
+class Bar extends HtmlElement {
+  static final tag = 'x-bar';
+  factory Bar() => new Element.tag(tag) as Bar;
+  Bar.created() : super.created();
+
+  get thisIsACustomClass => true;
+}
+
+class Baz extends Foo {
+  static final tag = 'x-baz';
+  factory Baz() => new Element.tag(tag) as Baz;
+  Baz.created() : super.created();
+
+  get thisIsAlsoACustomClass => true;
+}
+
+class BadB {}
+
+abstract class BadC extends HtmlElement {
+  BadC.created() : super.created();
+}
+
+main() async {
+  // Adapted from Blink's fast/dom/custom/document-register-basic test.
+
+  await customElementsReady;
+
+  test('Testing document.registerElement2() basic behaviors', () {
+    document.registerElement2(Foo.tag, {'prototype': Foo});
+
+    // Cannot register an existing dart:html type.
+    expect(
+        () => document.registerElement2('x-bad-a', {'prototype': HtmlElement}),
+        throws);
+
+    // Invalid user type.  Doesn't inherit from HtmlElement.
+    expect(() => document.registerElement2('x-bad-b', {'prototype': BadB}),
+        throws);
+
+    // Cannot register abstract class.
+    expect(() => document.registerElement2('x-bad-c', {'prototype': BadC}),
+        throws);
+
+    // Not a type.
+    expect(() => document.registerElement2('x-bad-d', {'prototype': null}),
+        throws);
+
+    // Cannot register system type.
+    expect(() => document.registerElement2('x-bad-e', {'prototype': Object}),
+        throws);
+
+    // Constructor initiated instantiation
+    var createdFoo = new Foo();
+    expect(createdFoo.thisIsACustomClass, isTrue);
+
+    // Dart type correctness
+    expect(createdFoo is HtmlElement, isTrue);
+    expect(createdFoo is Foo, isTrue);
+    expect(createdFoo.runtimeType, Foo);
+
+    // Native getter
+    expect(createdFoo.tagName, "X-FOO");
+
+    // Native setter
+    createdFoo.innerHtml = "Hello";
+    expect(createdFoo.text, "Hello");
+
+    // Native method
+    var childDiv = new DivElement();
+    createdFoo.append(childDiv);
+    expect(createdFoo.lastChild, childDiv);
+
+    // Parser initiated instantiation
+    var container = new DivElement()..id = "container";
+    document.body!.append(container);
+    container.setInnerHtml("<x-foo></x-foo>",
+        treeSanitizer: new NullTreeSanitizer());
+    upgradeCustomElements(container);
+    var parsedFoo = container.firstChild;
+
+    expect(parsedFoo is Foo, isTrue);
+    expect((parsedFoo as Foo).tagName, "X-FOO");
+
+    // Ensuring the wrapper is retained
+    var someProperty = new Expando();
+    someProperty[parsedFoo] = "hello";
+    expect(container.firstChild, parsedFoo);
+    expect(someProperty[container.firstChild!], someProperty[parsedFoo]);
+
+    // Having another constructor
+    document.registerElement2(Bar.tag, {'prototype': Bar});
+    var createdBar = new Bar();
+    expect(createdBar is Bar, isTrue);
+    expect(createdBar is Foo, isFalse);
+    expect(createdBar.tagName, "X-BAR");
+
+    // Having a subclass
+    document.registerElement2(Baz.tag, {'prototype': Baz});
+    var createdBaz = new Baz();
+    expect(createdBaz.tagName, "X-BAZ");
+    expect(createdBaz.thisIsACustomClass, isTrue);
+    expect(createdBaz.thisIsAlsoACustomClass, isTrue);
+
+    // With irregular cases
+    var createdUpperBar = new Element.tag("X-BAR");
+    var createdMixedBar = new Element.tag("X-Bar");
+    expect(createdUpperBar is Bar, isTrue);
+    expect(createdUpperBar.tagName, "X-BAR");
+    expect(createdMixedBar is Bar, isTrue);
+    expect(createdMixedBar.tagName, "X-BAR");
+
+    container.setInnerHtml("<X-BAR></X-BAR><X-Bar></X-Bar>",
+        treeSanitizer: new NullTreeSanitizer());
+    upgradeCustomElements(container);
+    expect(container.firstChild is Bar, isTrue);
+    expect((container.firstChild as Bar).tagName, "X-BAR");
+    expect(container.lastChild is Bar, isTrue);
+    expect((container.lastChild as Bar).tagName, "X-BAR");
+
+    // Constructors shouldn't interfere with each other
+    expect((new Foo()).tagName, "X-FOO");
+    expect((new Bar()).tagName, "X-BAR");
+    expect((new Baz()).tagName, "X-BAZ");
+  });
+}
diff --git a/tests/lib/html/custom/document_register_basic_test.html b/tests/lib/html/custom/document_register_basic_test.html
new file mode 100644
index 0000000..c4042b3
--- /dev/null
+++ b/tests/lib/html/custom/document_register_basic_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> document_register_basic_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running document_register_basic_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/document_register_template_test.dart b/tests/lib/html/custom/document_register_template_test.dart
new file mode 100644
index 0000000..65cffec
--- /dev/null
+++ b/tests/lib/html/custom/document_register_template_test.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.
+
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() async {
+  await customElementsReady;
+
+  test('can register custom template with webcomponents-lite polyfill', () {
+    document.registerElement2(
+        'my-element', {'prototype': MyElement, 'extends': 'template'});
+    dynamic e = new Element.tag('template', 'my-element');
+    document.body!.append(e);
+    expect(e is TemplateElement, isTrue);
+    expect(e.method(), 'value');
+  });
+}
+
+class MyElement extends TemplateElement {
+  MyElement.created() : super.created();
+  method() => 'value';
+}
diff --git a/tests/lib/html/custom/document_register_template_test.html b/tests/lib/html/custom/document_register_template_test.html
new file mode 100644
index 0000000..7c48c6a
--- /dev/null
+++ b/tests/lib/html/custom/document_register_template_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> document_register_basic_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents-lite.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running document_register_basic_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/document_register_type_extensions_test.dart b/tests/lib/html/custom/document_register_type_extensions_test.dart
new file mode 100644
index 0000000..bbeafb5
--- /dev/null
+++ b/tests/lib/html/custom/document_register_type_extensions_test.dart
@@ -0,0 +1,323 @@
+// 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:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class Foo extends HtmlElement {
+  static const tag = 'x-foo';
+  static final List<String> outerHtmlStrings = [
+    '<x-foo></x-foo>',
+    '<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-foo></x-foo>'
+  ];
+  factory Foo() => new Element.tag(tag) as Foo;
+  Foo.created() : super.created();
+}
+
+class Bar extends InputElement {
+  static const tag = 'x-bar';
+  static const outerHtmlString = '<input is="x-bar">';
+  factory Bar() => new Element.tag('input', tag) as Bar;
+  Bar.created() : super.created();
+}
+
+class Baz extends Foo {
+  static const tag = 'x-baz';
+  static final List<String> outerHtmlStrings = [
+    '<x-baz></x-baz>',
+    '<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-baz></x-baz>'
+  ];
+  factory Baz() => new Element.tag(tag) as Baz;
+  Baz.created() : super.created();
+}
+
+class Qux extends Bar {
+  static const tag = 'x-qux';
+  factory Qux() => new Element.tag('input', tag) as Qux;
+  Qux.created() : super.created();
+}
+
+class FooBad extends DivElement {
+  static const tag = 'x-foo';
+  factory FooBad() => new Element.tag('div', tag) as FooBad;
+  FooBad.created() : super.created();
+}
+
+class MyCanvas extends CanvasElement {
+  static const tag = 'my-canvas';
+  factory MyCanvas() => new Element.tag('canvas', tag) as MyCanvas;
+
+  MyCanvas.created() : super.created();
+
+  void fillAsRed() {
+    width = 100;
+    height = 100;
+
+    CanvasRenderingContext2D context =
+        this.getContext('2d') as CanvasRenderingContext2D;
+    context.fillStyle = 'red';
+    context.fillRect(0, 0, width, height);
+    context.fill();
+
+    var data = context.getImageData(0, 0, 1, 1).data;
+    expect(data, [255, 0, 0, 255]);
+  }
+}
+
+class CustomDiv extends DivElement {
+  CustomDiv.created() : super.created();
+}
+
+class CustomCustomDiv extends CustomDiv {
+  static const tag = 'custom-custom';
+  CustomCustomDiv.created() : super.created();
+}
+
+main() async {
+  // Adapted from Blink's fast/dom/custom/document-register-type-extension test.
+
+  var testForm = new FormElement()..id = 'testForm';
+  document.body!.append(testForm);
+
+  var isFormControl = (element) {
+    testForm.append(element);
+    return element.form == testForm;
+  };
+
+  var registeredTypes = false;
+  void registerTypes() {
+    if (registeredTypes) {
+      return;
+    }
+    registeredTypes = true;
+    document.registerElement2(Foo.tag, {'prototype': Foo});
+    document.registerElement2(Bar.tag, {'prototype': Bar, 'extends': 'input'});
+    document.registerElement2(Baz.tag, {'prototype': Baz});
+    document.registerElement2(Qux.tag, {'prototype': Qux, 'extends': 'input'});
+    document.registerElement2(
+        MyCanvas.tag, {'prototype': MyCanvas, 'extends': 'canvas'});
+    document.registerElement2(
+        CustomCustomDiv.tag, {'prototype': CustomCustomDiv, 'extends': 'div'});
+  }
+
+  await customElementsReady;
+
+  group('registration', () {
+    test('cannot register twice', () {
+      registerTypes();
+      expect(
+          () => document.registerElement2(
+              FooBad.tag, {'prototype': Foo, 'extends': 'div'}),
+          throws);
+    });
+
+    test('cannot register for non-matching tag', () {
+      registerTypes();
+      expect(() {
+        document.registerElement2(
+            'x-input-div', {'prototype': Bar, 'extends': 'div'});
+      }, throws);
+    });
+
+    test('cannot register type extension for custom tag', () {
+      registerTypes();
+      expect(() {
+        document
+            .registerElement2('x-custom-tag', {'prototype': CustomCustomDiv});
+      }, throws);
+    });
+  });
+
+  group('construction', () {
+    group('constructors', () {
+      registerTypes();
+      test('custom tag', () {
+        var fooNewed = new Foo();
+        expect(fooNewed.outerHtml, anyOf(Foo.outerHtmlStrings));
+        expect(fooNewed is Foo, isTrue);
+        expect(fooNewed is HtmlElement, isTrue);
+        expect(fooNewed is UnknownElement, isFalse);
+      });
+
+      test('type extension', () {
+        var barNewed = new Bar();
+        expect(barNewed.outerHtml, Bar.outerHtmlString);
+        expect(barNewed is Bar, isTrue);
+        expect(barNewed is InputElement, isTrue);
+        expect(isFormControl(barNewed), isTrue);
+      });
+
+      test('custom tag deriving from custom tag', () {
+        var bazNewed = new Baz();
+        expect(bazNewed.outerHtml, anyOf(Baz.outerHtmlStrings));
+        expect(bazNewed is Baz, isTrue);
+        expect(bazNewed is HtmlElement, isTrue);
+        expect(bazNewed is UnknownElement, isFalse);
+      });
+
+      test('type extension deriving from custom tag', () {
+        var quxNewed = new Qux();
+        var quxOuterHtml = '<input is="x-qux">';
+        expect(quxNewed.outerHtml, quxOuterHtml);
+        expect(quxNewed is Qux, isTrue);
+        expect(quxNewed is InputElement, isTrue);
+        expect(isFormControl(quxNewed), isTrue);
+      });
+    });
+
+    group('single-parameter createElement', () {
+      registerTypes();
+      test('custom tag', () {
+        var fooCreated = new Element.tag('x-foo');
+        expect(fooCreated.outerHtml, anyOf(Foo.outerHtmlStrings));
+        expect(fooCreated is Foo, isTrue);
+      });
+
+      test('does not upgrade type extension', () {
+        var barCreated = new Element.tag('x-bar');
+        expect(barCreated is Bar, isFalse);
+        expect(barCreated.outerHtml, "<x-bar></x-bar>");
+        expect(barCreated is UnknownElement, isFalse);
+        expect(barCreated is HtmlElement, isTrue);
+      });
+
+      test('custom tag deriving from custom tag', () {
+        var bazCreated = new Element.tag('x-baz');
+        expect(bazCreated.outerHtml, anyOf(Baz.outerHtmlStrings));
+        expect(bazCreated is Baz, isTrue);
+        expect(bazCreated is UnknownElement, isFalse);
+      });
+
+      test('type extension deriving from custom tag', () {
+        var quxCreated = new Element.tag('x-qux');
+        expect(quxCreated.outerHtml, "<x-qux></x-qux>");
+        expect(quxCreated is Qux, isFalse);
+        expect(quxCreated is UnknownElement, isFalse);
+        expect(quxCreated is HtmlElement, isTrue);
+      });
+    });
+
+    group('createElement with type extension', () {
+      registerTypes();
+      test('does not upgrade extension of custom tag', () {
+        var divFooCreated = new Element.tag("div", Foo.tag);
+        expect(divFooCreated.outerHtml, '<div is="x-foo"></div>');
+        expect(divFooCreated is Foo, isFalse);
+        expect(divFooCreated is DivElement, isTrue);
+      });
+
+      test('upgrades valid extension', () {
+        var inputBarCreated = new Element.tag("input", Bar.tag);
+        expect(inputBarCreated.outerHtml, Bar.outerHtmlString);
+        expect(inputBarCreated is Bar, isTrue);
+        expect(inputBarCreated is UnknownElement, isFalse);
+        expect(isFormControl(inputBarCreated), isTrue);
+      });
+
+      test('type extension of incorrect tag', () {
+        var divBarCreated = new Element.tag("div", Bar.tag);
+        expect(divBarCreated.outerHtml, '<div is="x-bar"></div>');
+        expect(divBarCreated is Bar, isFalse);
+        expect(divBarCreated is DivElement, isTrue);
+      });
+
+      test('incorrect extension of custom tag', () {
+        var fooBarCreated = new Element.tag(Foo.tag, Bar.tag);
+        expect(
+            fooBarCreated.outerHtml,
+            anyOf([
+              '<x-foo is="x-bar"></x-foo>',
+              '<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" />'
+                  '<x-foo is="x-bar"></x-foo>'
+            ]));
+        expect(fooBarCreated is Foo, isTrue);
+      });
+
+      test('incorrect extension of type extension', () {
+        var barFooCreated = new Element.tag(Bar.tag, Foo.tag);
+        expect(barFooCreated.outerHtml, '<x-bar is="x-foo"></x-bar>');
+        expect(barFooCreated is UnknownElement, isFalse);
+        expect(barFooCreated is HtmlElement, isTrue);
+      });
+
+      test('null type extension', () {
+        var fooCreatedNull = new Element.tag(Foo.tag, null);
+        expect(fooCreatedNull.outerHtml, anyOf(Foo.outerHtmlStrings));
+        expect(fooCreatedNull is Foo, isTrue);
+      });
+
+      test('empty type extension', () {
+        var fooCreatedEmpty = new Element.tag(Foo.tag, "");
+        expect(fooCreatedEmpty.outerHtml, anyOf(Foo.outerHtmlStrings));
+        expect(fooCreatedEmpty is Foo, isTrue);
+      });
+    });
+  });
+
+  group('namespaces', () {
+    test('createElementNS', () {
+      registerTypes();
+      var fooCreatedNS = document.createElementNS(
+          "http://www.w3.org/1999/xhtml", Foo.tag, null);
+      expect(fooCreatedNS.outerHtml, anyOf(Foo.outerHtmlStrings));
+      expect(fooCreatedNS is Foo, isTrue);
+
+      var barCreatedNS = document.createElementNS(
+          "http://www.w3.org/1999/xhtml", "input", Bar.tag);
+      expect(barCreatedNS.outerHtml, Bar.outerHtmlString);
+      expect(barCreatedNS is Bar, isTrue);
+      expect(isFormControl(barCreatedNS), isTrue);
+
+      expect(
+          () => document.createElementNS(
+              'http://example.com/2013/no-such-namespace', 'xml:lang', 'x-bar'),
+          throws);
+    });
+  });
+
+  group('parsing', () {
+    test('parsing', () {
+      registerTypes();
+      createElementFromHtml(html) {
+        var container = new DivElement()
+          ..setInnerHtml(html, treeSanitizer: new NullTreeSanitizer());
+        upgradeCustomElements(container);
+        return container.firstChild;
+      }
+
+      var fooParsed = createElementFromHtml('<x-foo>');
+      expect(fooParsed is Foo, isTrue);
+
+      var barParsed = createElementFromHtml('<input is=x-bar>');
+      expect(barParsed is Bar, isTrue);
+      expect(isFormControl(barParsed), isTrue);
+
+      var divFooParsed = createElementFromHtml('<div is=x-foo>');
+      expect(divFooParsed is Foo, isFalse);
+      expect(divFooParsed is DivElement, isTrue);
+
+      var namedBarParsed = createElementFromHtml('<x-bar>');
+      expect(namedBarParsed is Bar, isFalse);
+      // Polyfill does not convert parsed unregistered custom elements to
+      // HtmlElement.
+      // expect(namedBarParsed is UnknownElement, isFalse);
+      expect(namedBarParsed is HtmlElement, isTrue);
+
+      var divBarParsed = createElementFromHtml('<div is=x-bar>');
+      expect(divBarParsed is Bar, isFalse);
+      expect(divBarParsed is DivElement, isTrue);
+    });
+  });
+
+  group('functional', () {
+    test('canvas', () {
+      registerTypes();
+      var canvas = new MyCanvas();
+      canvas.fillAsRed();
+    });
+  });
+}
diff --git a/tests/lib/html/custom/document_register_type_extensions_test.html b/tests/lib/html/custom/document_register_type_extensions_test.html
new file mode 100644
index 0000000..30c2138
--- /dev/null
+++ b/tests/lib/html/custom/document_register_type_extensions_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> document_register_type_extensions_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running document_register_type_extensions_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/element_upgrade_failure_test.dart b/tests/lib/html/custom/element_upgrade_failure_test.dart
new file mode 100644
index 0000000..947af1c
--- /dev/null
+++ b/tests/lib/html/custom/element_upgrade_failure_test.dart
@@ -0,0 +1,53 @@
+// 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 'dart:js' as js;
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class FooElement extends HtmlElement {
+  static final tag = 'x-foo';
+
+  final int initializedField = 666;
+  late js.JsObject _proxy = new js.JsObject.fromBrowserObject(this);
+
+  factory FooElement() => new Element.tag(tag) as FooElement;
+  FooElement.created() : super.created();
+
+  String doSomething() => _proxy.callMethod('doSomething');
+
+  bool get fooCreated => _proxy['fooCreated'];
+}
+
+main() async {
+  await customElementsReady;
+  var upgrader = document.createElementUpgrader(FooElement);
+  js.context['upgradeListener'] = (e) {
+    upgrader.upgrade(e);
+  };
+
+  test('cannot create upgrader for interfaces', () {
+    expect(() {
+      // TODO(srujzs): Determine if this should be a static error.
+      document.createElementUpgrader(HtmlElementInterface);
+    }, throws);
+  });
+
+  test('cannot upgrade interfaces', () {
+    expect(() {
+      upgrader.upgrade(new HtmlElementInterface());
+      //                   ^^^^^^^^^^^^^^^^^^^^
+      // [analyzer] STATIC_WARNING.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
+    }, throws);
+  });
+}
+
+class HtmlElementInterface implements HtmlElement {
+  //  ^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
+  HtmlElementInterface.created();
+}
diff --git a/tests/lib/html/custom/element_upgrade_test.dart b/tests/lib/html/custom/element_upgrade_test.dart
new file mode 100644
index 0000000..ad574bd
--- /dev/null
+++ b/tests/lib/html/custom/element_upgrade_test.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.
+
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class FooElement extends HtmlElement {
+  static final tag = 'x-foo';
+
+  final int initializedField = 666;
+  late js.JsObject _proxy = new js.JsObject.fromBrowserObject(this);
+
+  factory FooElement() => new Element.tag(tag) as FooElement;
+  FooElement.created() : super.created();
+
+  String doSomething() => _proxy.callMethod('doSomething');
+
+  bool get fooCreated => _proxy['fooCreated'];
+}
+
+main() async {
+  await customElementsReady;
+  var upgrader = document.createElementUpgrader(FooElement);
+  js.context['upgradeListener'] = (e) {
+    upgrader.upgrade(e);
+  };
+
+  document.registerElement2('custom-element', {'prototype': CustomElement});
+
+  test('created gets proxied', () {
+    var element = document.createElement(FooElement.tag);
+    expect(element is FooElement, isTrue);
+    expect((element as FooElement).initializedField, 666);
+    expect(element.text, 'constructed');
+
+    js.context.callMethod('validateIsFoo', [element]);
+
+    expect(element.doSomething(), 'didSomething');
+    expect(element.fooCreated, true);
+  });
+
+  test('dart constructor works', () {
+    var element = new FooElement();
+    expect(element is FooElement, isTrue);
+    expect(element.text, 'constructed');
+
+    js.context.callMethod('validateIsFoo', [element]);
+
+    expect(element.doSomething(), 'didSomething');
+  });
+
+  test('cannot upgrade more than once', () {
+    var fooElement = new FooElement();
+    expect(() {
+      upgrader.upgrade(fooElement);
+    }, throws);
+  });
+
+  test('cannot upgrade non-matching elements', () {
+    expect(() {
+      upgrader.upgrade(new DivElement());
+    }, throws);
+  });
+
+  test('cannot upgrade custom elements', () {
+    var custom = new CustomElement();
+    expect(() {
+      upgrader.upgrade(custom);
+    }, throws);
+  });
+
+  test('can upgrade with extendsTag', () {
+    var upgrader = document.createElementUpgrader(CustomDiv, extendsTag: 'div');
+    var div = new DivElement();
+    var customDiv = upgrader.upgrade(div);
+    expect(customDiv is CustomDiv, isTrue);
+
+    var htmlElement = document.createElement('not-registered');
+    expect(() {
+      upgrader.upgrade(htmlElement);
+    }, throws);
+  });
+
+  test('cannot create upgrader for built-in types', () {
+    expect(() {
+      document.createElementUpgrader(HtmlElement);
+    }, throws);
+  });
+}
+
+class CustomDiv extends DivElement {
+  CustomDiv.created() : super.created();
+}
+
+class CustomElement extends HtmlElement {
+  factory CustomElement() =>
+      document.createElement('custom-element') as CustomElement;
+  CustomElement.created() : super.created();
+}
diff --git a/tests/lib/html/custom/element_upgrade_test.html b/tests/lib/html/custom/element_upgrade_test.html
new file mode 100644
index 0000000..e06cdbc
--- /dev/null
+++ b/tests/lib/html/custom/element_upgrade_test.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta name="dart.unittest" content="full-stack-traces">
+<title> element_upgrade_test </title>
+<style>
+   .unittest-table { font-family:monospace; border:1px; }
+   .unittest-pass { background: #6b3;}
+   .unittest-fail { background: #d55;}
+   .unittest-error { background: #a11;}
+</style>
+<script src="/packages/web_components/webcomponents.js"></script>
+<script src="/packages/web_components/dart_support.js"></script>
+
+<body>
+  <h1> Running element_upgrade_test </h1>
+
+<script>
+var Foo = function() {};
+Foo.prototype = Object.create(HTMLElement.prototype);
+Foo.prototype.createdCallback = function() {
+  this.fooCreated = true;
+  this.textContent = 'constructed';
+
+  // Tell the Dart side that this was created.
+  // For testing purposes, for real code this would use a different mechanism.
+  window.upgradeListener(this);
+};
+
+Foo.prototype.doSomething = function() {
+  this.textContent = 'didSomething';
+  return 'didSomething';
+};
+
+Foo = document.registerElement('x-foo', Foo);
+
+function validateIsFoo(element) {
+  if (!(element instanceof Foo)) {
+    throw Error('Element is not a Foo');
+  }
+
+  if (!element.fooCreated) {
+    throw Error('Expected fooCreated to be set');
+  }
+}
+</script>
+
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
diff --git a/tests/lib/html/custom/entered_left_view/disconnected_subtree_test.dart b/tests/lib/html/custom/entered_left_view/disconnected_subtree_test.dart
new file mode 100644
index 0000000..dba7ed4
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/disconnected_subtree_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.
+
+library entered_left_view_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'entered_left_view_util.dart';
+import 'package:async_helper/async_minitest.dart';
+
+import '../utils.dart';
+
+main() async {
+  await setupFunc();
+  group('disconnected_subtree', () {
+    var div = new DivElement();
+
+    setUp() {
+      invocations = [];
+    }
+
+    test('Enters a disconnected subtree of DOM', () {
+      setUp();
+      div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
+      upgradeCustomElements(div);
+
+      expect(invocations, ['created'],
+          reason: 'the attached callback should not be invoked when inserted '
+              'into a disconnected subtree');
+    });
+
+    test('Leaves a disconnected subtree of DOM', () {
+      setUp();
+      div.innerHtml = '';
+      expect(invocations, [],
+          reason:
+              'the detached callback should not be invoked when removed from a '
+              'disconnected subtree');
+    });
+
+    test('Enters a document with a view as a constituent of a subtree', () {
+      setUp();
+      div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
+      upgradeCustomElements(div);
+      invocations = [];
+      document.body!.append(div);
+      customElementsTakeRecords();
+      expect(invocations, ['attached'],
+          reason:
+              'the attached callback should be invoked when inserted into a '
+              'document with a view as part of a subtree');
+    });
+  });
+}
diff --git a/tests/lib/html/custom/entered_left_view/disconnected_subtree_test.html b/tests/lib/html/custom/entered_left_view/disconnected_subtree_test.html
new file mode 100644
index 0000000..0fd8683
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/disconnected_subtree_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> disconnected_subtree_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running disconnected_subtree_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/entered_left_view/entered_left_view_standard_events_test.dart b/tests/lib/html/custom/entered_left_view/entered_left_view_standard_events_test.dart
new file mode 100644
index 0000000..3d78763
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/entered_left_view_standard_events_test.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.
+
+library entered_left_view_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'entered_left_view_util.dart';
+import 'package:async_helper/async_minitest.dart';
+
+import '../utils.dart';
+
+main() async {
+  await setupFunc();
+  group('standard_events', () {
+    var a;
+    setUp() {
+      invocations = [];
+    }
+
+    test('Created', () {
+      setUp();
+      a = new Element.tag('x-a');
+      expect(invocations, ['created']);
+    });
+
+    test('attached', () {
+      setUp();
+      document.body!.append(a);
+      customElementsTakeRecords();
+      expect(invocations, ['attached']);
+    });
+
+    test('detached', () {
+      setUp();
+      a.remove();
+      customElementsTakeRecords();
+      expect(invocations, ['detached']);
+    });
+
+    var div = new DivElement();
+    test('nesting does not trigger attached', () {
+      setUp();
+      div.append(a);
+      customElementsTakeRecords();
+      expect(invocations, []);
+    });
+
+    test('nested entering triggers attached', () {
+      setUp();
+      document.body!.append(div);
+      customElementsTakeRecords();
+      expect(invocations, ['attached']);
+    });
+
+    test('nested leaving triggers detached', () {
+      setUp();
+      div.remove();
+      customElementsTakeRecords();
+      expect(invocations, ['detached']);
+    });
+  });
+}
diff --git a/tests/lib/html/custom/entered_left_view/entered_left_view_standard_events_test.html b/tests/lib/html/custom/entered_left_view/entered_left_view_standard_events_test.html
new file mode 100644
index 0000000..3688e05
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/entered_left_view_standard_events_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> entered_left_view_standard_events_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running entered_left_view_standard_events_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/entered_left_view/entered_left_view_util.dart b/tests/lib/html/custom/entered_left_view/entered_left_view_util.dart
new file mode 100644
index 0000000..d5f6e7d
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/entered_left_view_util.dart
@@ -0,0 +1,75 @@
+// 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 entered_left_view_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'package:async_helper/async_minitest.dart';
+
+import '../utils.dart';
+
+var invocations = [];
+
+class Foo extends HtmlElement {
+  Foo.created() : super.created() {
+    invocations.add('created');
+  }
+
+  void attached() {
+    invocations.add('attached');
+  }
+
+  void enteredView() {
+    // Deprecated name. Should never be called since we override "attached".
+    invocations.add('enteredView');
+  }
+
+  void detached() {
+    invocations.add('detached');
+  }
+
+  void leftView() {
+    // Deprecated name. Should never be called since we override "detached".
+    invocations.add('leftView');
+  }
+
+  void attributeChanged(String name, String oldValue, String newValue) {
+    invocations.add('attribute changed');
+  }
+}
+
+// Test that the deprecated callbacks still work.
+class FooOldCallbacks extends HtmlElement {
+  FooOldCallbacks.created() : super.created() {
+    invocations.add('created');
+  }
+
+  void enteredView() {
+    invocations.add('enteredView');
+  }
+
+  void leftView() {
+    invocations.add('leftView');
+  }
+
+  void attributeChanged(String name, String oldValue, String newValue) {
+    invocations.add('attribute changed');
+  }
+}
+
+var docA = document;
+var docB = document.implementation.createHtmlDocument('');
+var nullSanitizer = new NullTreeSanitizer();
+
+setupFunc() {
+  // Adapted from Blink's
+  // fast/dom/custom/attached-detached-document.html test.
+  return customElementsReady.then((_) {
+    document.registerElement2('x-a', {'prototype': Foo});
+    document.registerElement2('x-a-old', {'prototype': FooOldCallbacks});
+  });
+}
diff --git a/tests/lib/html/custom/entered_left_view/shadow_dom_test.dart b/tests/lib/html/custom/entered_left_view/shadow_dom_test.dart
new file mode 100644
index 0000000..3da372e
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/shadow_dom_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2020 the Dart project authors.  Please see the AUTHORS file
+// for 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 entered_left_view_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'entered_left_view_util.dart';
+import 'package:async_helper/async_minitest.dart';
+
+import '../utils.dart';
+
+main() async {
+  await setupFunc();
+  group('shadow_dom', () {
+    var div;
+    var s;
+    setUp() {
+      invocations = [];
+      div = new DivElement();
+      s = div.createShadowRoot();
+    }
+
+    tearDown() {
+      customElementsTakeRecords();
+    }
+
+    test('Created in Shadow DOM that is not in a document', () {
+      setUp();
+      s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
+      upgradeCustomElements(s);
+
+      expect(invocations, ['created'],
+          reason: 'the attached callback should not be invoked when entering a '
+              'Shadow DOM subtree not in the document');
+      tearDown();
+    });
+
+    test('Leaves Shadow DOM that is not in a document', () {
+      setUp();
+      s.innerHtml = '';
+      expect(invocations, [],
+          reason: 'the detached callback should not be invoked when leaving a '
+              'Shadow DOM subtree not in the document');
+      tearDown();
+    });
+
+    test('Enters a document with a view as a constituent of Shadow DOM', () {
+      setUp();
+      s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
+      upgradeCustomElements(s);
+
+      document.body!.append(div);
+      customElementsTakeRecords();
+      expect(invocations, ['created', 'attached'],
+          reason: 'the attached callback should be invoked when inserted into '
+              'a document with a view as part of Shadow DOM');
+
+      div.remove();
+      customElementsTakeRecords();
+
+      expect(invocations, ['created', 'attached', 'detached'],
+          reason: 'the detached callback should be invoked when removed from a '
+              'document with a view as part of Shadow DOM');
+      tearDown();
+    });
+  });
+}
diff --git a/tests/lib/html/custom/entered_left_view/shadow_dom_test.html b/tests/lib/html/custom/entered_left_view/shadow_dom_test.html
new file mode 100644
index 0000000..c0967ae
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/shadow_dom_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> shadow_dom_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running shadow_dom_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/entered_left_view/standard_events_old_callback_names_test.dart b/tests/lib/html/custom/entered_left_view/standard_events_old_callback_names_test.dart
new file mode 100644
index 0000000..27bafae
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/standard_events_old_callback_names_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2020 the Dart project authors.  Please see the AUTHORS file
+// for 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 entered_left_view_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'entered_left_view_util.dart';
+import 'package:async_helper/async_minitest.dart';
+
+import '../utils.dart';
+
+main() async {
+  await setupFunc();
+  // TODO(jmesserly): remove after deprecation period.
+  group('standard_events_old_callback_names', () {
+    var a;
+    setUp() {
+      invocations = [];
+    }
+
+    test('Created', () {
+      setUp();
+      a = new Element.tag('x-a-old');
+      expect(invocations, ['created']);
+    });
+
+    test('enteredView', () {
+      setUp();
+      document.body!.append(a);
+      customElementsTakeRecords();
+      expect(invocations, ['enteredView']);
+    });
+
+    test('leftView', () {
+      setUp();
+      a.remove();
+      customElementsTakeRecords();
+      expect(invocations, ['leftView']);
+    });
+
+    var div = new DivElement();
+    test('nesting does not trigger enteredView', () {
+      setUp();
+      div.append(a);
+      customElementsTakeRecords();
+      expect(invocations, []);
+    });
+
+    test('nested entering triggers enteredView', () {
+      setUp();
+      document.body!.append(div);
+      customElementsTakeRecords();
+      expect(invocations, ['enteredView']);
+    });
+
+    test('nested leaving triggers leftView', () {
+      setUp();
+      div.remove();
+      customElementsTakeRecords();
+      expect(invocations, ['leftView']);
+    });
+  });
+}
diff --git a/tests/lib/html/custom/entered_left_view/standard_events_old_callback_names_test.html b/tests/lib/html/custom/entered_left_view/standard_events_old_callback_names_test.html
new file mode 100644
index 0000000..b8d57a1
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/standard_events_old_callback_names_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> standard_events_old_callback_names_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running standard_events_old_callback_names_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/entered_left_view/viewless_document_test.dart b/tests/lib/html/custom/entered_left_view/viewless_document_test.dart
new file mode 100644
index 0000000..33fa4a4
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/viewless_document_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2020 the Dart project authors.  Please see the AUTHORS file
+// for 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 entered_left_view_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'entered_left_view_util.dart';
+import 'package:async_helper/async_minitest.dart';
+
+import '../utils.dart';
+
+main() async {
+  await setupFunc();
+  group('viewless_document', () {
+    var a;
+    setUp() {
+      invocations = [];
+    }
+
+    test('Created, owned by a document without a view', () {
+      setUp();
+      a = docB.createElement('x-a');
+      expect(a.ownerDocument, docB,
+          reason: 'new instance should be owned by the document the definition '
+              'was registered with');
+      expect(invocations, ['created'],
+          reason: 'calling the constructor should invoke the created callback');
+    });
+
+    test('Entered document without a view', () {
+      setUp();
+      docB.body!.append(a);
+      expect(invocations, [],
+          reason: 'attached callback should not be invoked when entering a '
+              'document without a view');
+    });
+
+    test('Attribute changed in document without a view', () {
+      setUp();
+      a.setAttribute('data-foo', 'bar');
+      expect(invocations, ['attribute changed'],
+          reason: 'changing an attribute should invoke the callback, even in a '
+              'document without a view');
+    });
+
+    test('Entered document with a view', () {
+      setUp();
+      document.body!.append(a);
+      customElementsTakeRecords();
+      expect(invocations, ['attached'],
+          reason:
+              'attached callback should be invoked when entering a document '
+              'with a view');
+    });
+
+    test('Left document with a view', () {
+      setUp();
+      a.remove();
+      customElementsTakeRecords();
+      expect(invocations, ['detached'],
+          reason: 'detached callback should be invoked when leaving a document '
+              'with a view');
+    });
+
+    test('Created in a document without a view', () {
+      setUp();
+      docB.body!.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
+      upgradeCustomElements(docB.body!);
+
+      expect(invocations, ['created'],
+          reason: 'only created callback should be invoked when parsing a '
+              'custom element in a document without a view');
+    });
+  });
+}
diff --git a/tests/lib/html/custom/entered_left_view/viewless_document_test.html b/tests/lib/html/custom/entered_left_view/viewless_document_test.html
new file mode 100644
index 0000000..f3b2182
--- /dev/null
+++ b/tests/lib/html/custom/entered_left_view/viewless_document_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> viewless_document_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running viewless_document_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom/regress_194523002_test.dart b/tests/lib/html/custom/regress_194523002_test.dart
new file mode 100644
index 0000000..1d36000
--- /dev/null
+++ b/tests/lib/html/custom/regress_194523002_test.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.
+
+// Regression test for CL 194523002.
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class A extends HtmlElement {
+  static final tag = 'x-a';
+  factory A() => new Element.tag(tag) as A;
+  A.created() : super.created();
+}
+
+main() async {
+  // Adapted from Blink's
+  // fast/dom/custom/constructor-calls-created-synchronously test.
+
+  await customElementsReady;
+  document.registerElement2(A.tag, {'prototype': A});
+}
diff --git a/tests/lib/html/custom/utils.dart b/tests/lib/html/custom/utils.dart
new file mode 100644
index 0000000..5fb73a7f
--- /dev/null
+++ b/tests/lib/html/custom/utils.dart
@@ -0,0 +1,224 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:js' as js;
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+/**
+ * Verifies that [actual] has the same graph structure as [expected].
+ * Detects cycles and DAG structure in Maps and Lists.
+ */
+verifyGraph(expected, actual) {
+  var eItems = [];
+  var aItems = [];
+
+  message(path, reason) => path == ''
+      ? reason
+      : reason == null ? "path: $path" : "path: $path, $reason";
+
+  walk(path, expected, actual) {
+    if (expected is String || expected is num || expected == null) {
+      expect(actual, equals(expected), reason: message(path, 'not equal'));
+      return;
+    }
+
+    // Cycle or DAG?
+    for (int i = 0; i < eItems.length; i++) {
+      if (identical(expected, eItems[i])) {
+        expect(actual, same(aItems[i]),
+            reason: message(path, 'missing back or side edge'));
+        return;
+      }
+    }
+    for (int i = 0; i < aItems.length; i++) {
+      if (identical(actual, aItems[i])) {
+        expect(expected, same(eItems[i]),
+            reason: message(path, 'extra back or side edge'));
+        return;
+      }
+    }
+    eItems.add(expected);
+    aItems.add(actual);
+
+    if (expected is Blob) {
+      expect(actual is Blob, isTrue, reason: '$actual is Blob');
+      expect(expected.type, equals(actual.type),
+          reason: message(path, '.type'));
+      expect(expected.size, equals(actual.size),
+          reason: message(path, '.size'));
+      return;
+    }
+
+    if (expected is ByteBuffer) {
+      expect(actual is ByteBuffer, isTrue, reason: '$actual is ByteBuffer');
+      expect(expected.lengthInBytes, equals(actual.lengthInBytes),
+          reason: message(path, '.lengthInBytes'));
+      // TODO(antonm): one can create a view on top of those
+      // and check if contents identical.  Let's do it later.
+      return;
+    }
+
+    if (expected is DateTime) {
+      expect(actual is DateTime, isTrue, reason: '$actual is DateTime');
+      expect(expected.millisecondsSinceEpoch,
+          equals(actual.millisecondsSinceEpoch),
+          reason: message(path, '.millisecondsSinceEpoch'));
+      return;
+    }
+
+    if (expected is ImageData) {
+      expect(actual is ImageData, isTrue, reason: '$actual is ImageData');
+      expect(expected.width, equals(actual.width),
+          reason: message(path, '.width'));
+      expect(expected.height, equals(actual.height),
+          reason: message(path, '.height'));
+      walk('$path.data', expected.data, actual.data);
+      return;
+    }
+
+    if (expected is TypedData) {
+      expect(actual is TypedData, isTrue, reason: '$actual is TypedData');
+      walk('$path/.buffer', expected.buffer, actual.buffer);
+      expect(expected.offsetInBytes, equals(actual.offsetInBytes),
+          reason: message(path, '.offsetInBytes'));
+      expect(expected.lengthInBytes, equals(actual.lengthInBytes),
+          reason: message(path, '.lengthInBytes'));
+      // And also fallback to elements check below.
+    }
+
+    if (expected is List) {
+      expect(actual, predicate((v) => v is List),
+          reason: message(path, '$actual is List'));
+      expect(actual.length, expected.length,
+          reason: message(path, 'different list lengths'));
+      for (var i = 0; i < expected.length; i++) {
+        walk('$path[$i]', expected[i], actual[i]);
+      }
+      return;
+    }
+
+    if (expected is Map) {
+      expect(actual, predicate((v) => v is Map),
+          reason: message(path, '$actual is Map'));
+      for (var key in expected.keys) {
+        if (!actual.containsKey(key)) {
+          expect(false, isTrue, reason: message(path, 'missing key "$key"'));
+        }
+        walk('$path["$key"]', expected[key], actual[key]);
+      }
+      for (var key in actual.keys) {
+        if (!expected.containsKey(key)) {
+          expect(false, isTrue, reason: message(path, 'extra key "$key"'));
+        }
+      }
+      return;
+    }
+
+    expect(false, isTrue, reason: 'Unhandled type: $expected');
+  }
+
+  walk('', expected, actual);
+}
+
+/**
+ * Sanitizer which does nothing.
+ */
+class NullTreeSanitizer implements NodeTreeSanitizer {
+  void sanitizeTree(Node node) {}
+}
+
+/**
+ * Validate that two DOM trees are equivalent.
+ */
+void validateNodeTree(Node a, Node b, [String path = '']) {
+  path = '${path}${a.runtimeType}';
+  expect(a.nodeType, b.nodeType, reason: '$path nodeTypes differ');
+  expect(a.nodeValue, b.nodeValue, reason: '$path nodeValues differ');
+  expect(a.text, b.text, reason: '$path texts differ');
+  expect(a.nodes.length, b.nodes.length, reason: '$path nodes.lengths differ');
+
+  if (a is Element) {
+    Element bE = b as Element;
+    Element aE = a;
+
+    expect(aE.tagName, bE.tagName, reason: '$path tagNames differ');
+    expect(aE.attributes.length, bE.attributes.length,
+        reason: '$path attributes.lengths differ');
+    for (var key in aE.attributes.keys) {
+      expect(aE.attributes[key], bE.attributes[key],
+          reason: '$path attribute [$key] values differ');
+    }
+  }
+  for (var i = 0; i < a.nodes.length; ++i) {
+    validateNodeTree(a.nodes[i], b.nodes[i], '$path[$i].');
+  }
+}
+
+/**
+ * Upgrade all custom elements in the subtree which have not been upgraded.
+ *
+ * This is needed to cover timing scenarios which the custom element polyfill
+ * does not cover.
+ */
+void upgradeCustomElements(Node node) {
+  if (js.context.hasProperty('CustomElements') &&
+      js.context['CustomElements'].hasProperty('upgradeAll')) {
+    js.context['CustomElements'].callMethod('upgradeAll', [node]);
+  }
+}
+
+/**
+ * A future that completes once all custom elements in the initial HTML page
+ * have been upgraded.
+ *
+ * This is needed because the native implementation can update the elements
+ * while parsing the HTML document, but the custom element polyfill cannot,
+ * so it completes this future once all elements are upgraded.
+ */
+// TODO(jmesserly): rename to webComponentsReady to match the event?
+Future customElementsReady = () {
+  if (_isReady) return new Future.value();
+
+  // Not upgraded. Wait for the polyfill to fire the WebComponentsReady event.
+  // Note: we listen on document (not on document.body) to allow this polyfill
+  // to be loaded in the HEAD element.
+  return document.on['WebComponentsReady'].first;
+}();
+
+// Return true if we are using the polyfill and upgrade is complete, or if we
+// have native document.register and therefore the browser took care of it.
+// Otherwise return false, including the case where we can't find the polyfill.
+bool get _isReady {
+  // If we don't have dart:js, assume things are ready
+  if (js.context == null) return true;
+
+  var customElements = js.context['CustomElements'];
+  if (customElements == null) {
+    // Return true if native document.register, otherwise false.
+    // (Maybe the polyfill isn't loaded yet. Wait for it.)
+    return document.supportsRegisterElement;
+  }
+
+  return customElements['ready'] == true;
+}
+
+/**
+ * *Note* this API is primarily intended for tests. In other code it is better
+ * to write it in a style that works with or without the polyfill, rather than
+ * using this method.
+ *
+ * Synchronously trigger evaluation of pending lifecycle events, which otherwise
+ * need to wait for a [MutationObserver] to signal the changes in the polyfill.
+ * This method can be used to resolve differences in timing between native and
+ * polyfilled custom elements.
+ */
+void customElementsTakeRecords([Node? node]) {
+  var customElements = js.context['CustomElements'];
+  if (customElements == null) return;
+  customElements.callMethod('takeRecords', [node]);
+}
diff --git a/tests/lib/html/custom_element_method_clash_test.dart b/tests/lib/html/custom_element_method_clash_test.dart
new file mode 100644
index 0000000..cd18adb
--- /dev/null
+++ b/tests/lib/html/custom_element_method_clash_test.dart
@@ -0,0 +1,43 @@
+// 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 custom_elements_method_clash;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:async_helper/async_minitest.dart';
+import 'utils.dart';
+
+class CustomElement extends HtmlElement {
+  factory CustomElement() => new Element.tag('x-custom') as CustomElement;
+
+  CustomElement.created() : super.created() {}
+
+  // Try to clash with native 'appendChild' method.
+  void appendChild() {
+    throw 'Gotcha!';
+  }
+}
+
+main() async {
+  await customElementsReady;
+
+  group('test', () {
+    test('test', () {
+      document.registerElement2('x-custom', {'prototype': CustomElement});
+      CustomElement custom = new CustomElement();
+      document.body!.children.add(custom);
+
+      // Will call appendChild in JS.
+      custom.children.add(new DivElement()..text = 'Hello world!');
+
+      try {
+        custom.appendChild(); // Make sure method is not tree shaken.
+        fail('appendChild did not throw');
+      } catch (e) {
+        expect(e, equals('Gotcha!'));
+      }
+    });
+  });
+}
diff --git a/tests/lib/html/custom_element_method_clash_test.html b/tests/lib/html/custom_element_method_clash_test.html
new file mode 100644
index 0000000..1c216a5
--- /dev/null
+++ b/tests/lib/html/custom_element_method_clash_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> custom_element_method_clash_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running custom_element_method_clash_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom_element_name_clash_test.dart b/tests/lib/html/custom_element_name_clash_test.dart
new file mode 100644
index 0000000..098bc93
--- /dev/null
+++ b/tests/lib/html/custom_element_name_clash_test.dart
@@ -0,0 +1,33 @@
+// 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 custom_elements_name_clash;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:async_helper/async_minitest.dart';
+import 'utils.dart';
+
+class CustomElement extends HtmlElement {
+  factory CustomElement() => new Element.tag('x-custom') as CustomElement;
+
+  CustomElement.created() : super.created() {}
+
+  // Try to clash with native 'appendChild' method.
+  var appendChild = 123;
+}
+
+main() async {
+  await customElementsReady;
+
+  group('test', () {
+    test('test', () {
+      document.registerElement2('x-custom', {'prototype': CustomElement});
+      CustomElement custom = new CustomElement();
+      document.body!.children.add(custom);
+      // Will call appendChild in JS.
+      custom.children.add(new DivElement()..text = 'Hello world!');
+    });
+  });
+}
diff --git a/tests/lib/html/custom_element_name_clash_test.html b/tests/lib/html/custom_element_name_clash_test.html
new file mode 100644
index 0000000..289b371
--- /dev/null
+++ b/tests/lib/html/custom_element_name_clash_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> custom_element_name_clash_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running custom_element_name_clash_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom_elements_23127_test.dart b/tests/lib/html/custom_elements_23127_test.dart
new file mode 100644
index 0000000..395de21
--- /dev/null
+++ b/tests/lib/html/custom_elements_23127_test.dart
@@ -0,0 +1,131 @@
+// 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.
+
+// Regression test for http://dartbug.com/23127
+// Tests super calls to a custom element upgrade constructor with various
+// combinations of parameters and type arguments.
+
+library custom_elements_23127_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:async_helper/async_minitest.dart';
+import 'utils.dart';
+
+abstract class B1 extends HtmlElement {
+  void action();
+
+  B1.created() : super.created() {
+    action();
+  }
+}
+
+abstract class B1T<T> extends HtmlElement {
+  void action();
+  var qq = false;
+  B1T.created() : super.created() {
+    action();
+    qq = this is T;
+  }
+}
+
+abstract class B2 extends HtmlElement {
+  void action();
+  var qq;
+  B2.created([a = 1, b = 2, c = 3])
+      : qq = callTwice(() => ++a * ++b), // [a] and [b] are boxed.
+        super.created() {
+    action();
+    qq = [qq, a, b, c];
+  }
+}
+
+abstract class B2T<T> extends HtmlElement {
+  void action();
+  var qq;
+  B2T.created([a = 1, b = 2, c = 3])
+      : qq = callTwice(() => ++a * ++b),
+        super.created() {
+    action();
+    qq = [this is T, qq, a, b, c];
+  }
+}
+
+class C1 extends B1 {
+  int z = 0;
+  C1.created() : super.created();
+  action() {
+    z = 3;
+  }
+}
+
+class C1T extends B1T {
+  int z = 0;
+  C1T.created() : super.created();
+  action() {
+    z = 3;
+  }
+}
+
+class C2 extends B2 {
+  int z = 0;
+  C2.created() : super.created(20);
+  action() {
+    z = 3;
+  }
+}
+
+class C2T extends B2T {
+  int z = 0;
+  C2T.created() : super.created(20);
+  action() {
+    z = 3;
+  }
+}
+
+var callTwice;
+
+main() async {
+  await customElementsReady;
+
+  callTwice = (f) {
+    f();
+    return f();
+  };
+
+  group('baseline', () {
+    test('C1', () {
+      document.register('x-c1', C1);
+      C1 e = document.createElement('x-c1') as C1;
+      expect(e.z, 3);
+    });
+  });
+
+  group('c1t', () {
+    test('C1T', () {
+      document.register('x-c1t', C1T);
+      C1T e = document.createElement('x-c1t') as C1T;
+      expect(e.z, 3);
+      expect(e.qq, true);
+    });
+  });
+
+  group('c2', () {
+    test('C2', () {
+      document.register('x-c2', C2);
+      C2 e = document.createElement('x-c2') as C2;
+      expect(e.z, 3);
+      expect(e.qq, [88, 22, 4, 3]);
+    });
+  });
+
+  group('c2t', () {
+    test('C2T', () {
+      document.register('x-c2t', C2T);
+      C2T e = document.createElement('x-c2t') as C2T;
+      expect(e.z, 3);
+      expect(e.qq, [true, 88, 22, 4, 3]);
+    });
+  });
+}
diff --git a/tests/lib/html/custom_elements_23127_test.html b/tests/lib/html/custom_elements_23127_test.html
new file mode 100644
index 0000000..1384fa0
--- /dev/null
+++ b/tests/lib/html/custom_elements_23127_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> custom_elements_23127_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running custom_elements_23127_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom_elements_test.dart b/tests/lib/html/custom_elements_test.dart
new file mode 100644
index 0000000..30e14a7
--- /dev/null
+++ b/tests/lib/html/custom_elements_test.dart
@@ -0,0 +1,179 @@
+// 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 custom_elements_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:async_helper/async_minitest.dart';
+import 'utils.dart';
+
+class CustomMixin {
+  var mixinMethodCalled;
+
+  void mixinMethod() {
+    mixinMethodCalled = true;
+  }
+}
+
+class CustomType extends HtmlElement with CustomMixin {
+  bool createdCalled = false;
+
+  CustomType.created() : super.created() {
+    createdCalled = true;
+    customCreatedCount++;
+  }
+
+  void invokeMixinMethod() {
+    mixinMethod();
+  }
+}
+
+int customCreatedCount = 0;
+
+int nextTagId = 0;
+String get nextTag => 'x-type${nextTagId++}';
+
+class NotAnElement {}
+
+main() async {
+  await customElementsReady;
+
+  group('register', () {
+    test('register', () {
+      var tag = nextTag;
+      document.registerElement(tag, CustomType);
+
+      var element = new Element.tag(tag) as CustomType;
+      expect(element, isNotNull);
+      expect(element is CustomType, isTrue);
+      expect(element.createdCalled, isTrue);
+    });
+
+    test('register twice', () {
+      var tag = nextTag;
+      document.registerElement(tag, CustomType);
+      expect(() {
+        document.registerElement(tag, CustomType);
+      }, throws, reason: 'Cannot register a tag more than once.');
+
+      var newTag = nextTag;
+      document.registerElement(newTag, CustomType);
+
+      var element = new Element.tag(newTag) as CustomType;
+      expect(element, isNotNull);
+      expect(element is CustomType, isTrue);
+    });
+
+    test('register native', () {
+      expect(() {
+        document.registerElement(nextTag, BodyElement);
+      }, throws, reason: 'Cannot register a native element.');
+    });
+
+    test('register non-element', () {
+      expect(() {
+        document.registerElement(nextTag, NotAnElement);
+      }, throws, reason: 'Cannot register a non-element.');
+    });
+  });
+
+  // TODO(vsm): Modify this test once we agree on the proper semantics.
+  /*
+  group('preregister', () {
+
+    test('pre-registration construction', () {
+      var tag = nextTag;
+      var dom = new Element.html('<div><$tag></$tag></div>');
+
+      var preElement = dom.children[0];
+      expect(preElement, isNotNull);
+      expect(preElement is HtmlElement, isTrue);
+      expect(preElement is CustomType, isFalse);
+      var firedOnPre = false;
+      preElement.onFocus.listen((_) {
+        firedOnPre = true;
+      });
+
+      document.registerElement(tag, CustomType);
+      upgradeCustomElements(dom);
+
+      var postElement = dom.children[0];
+      expect(postElement, isNotNull);
+      expect(postElement is CustomType, isTrue);
+      expect(postElement.createdCalled, isTrue);
+
+      // Element from first query remains an UnknownElement.
+      expect(preElement is HtmlElement, isTrue);
+      expect(preElement.parent, dom);
+      expect(dom.children.length, 1);
+
+      var firedOnPost = false;
+      postElement.onFocus.listen((_) {
+        firedOnPost = true;
+      });
+      // Event handlers persist on old and new element.
+      postElement.dispatchEvent(new Event('focus'));
+      expect(firedOnPre, isTrue);
+      expect(firedOnPost, isTrue);
+    });
+  });*/
+
+  group('innerHtml', () {
+    test('query', () {
+      var tag = nextTag;
+      document.registerElement(tag, CustomType);
+      var element = new DivElement();
+      element.setInnerHtml('<$tag></$tag>',
+          treeSanitizer: new NullTreeSanitizer());
+      upgradeCustomElements(element);
+      document.body!.nodes.add(element);
+      var queried = querySelector(tag) as CustomType;
+
+      expect(queried, isNotNull);
+      expect(queried is CustomType, isTrue);
+      expect(queried.createdCalled, isTrue);
+    });
+
+    test('query id', () {
+      var tag = nextTag;
+      document.registerElement(tag, CustomType);
+      var element = new DivElement();
+      element.setInnerHtml('<$tag id="someid"></$tag>',
+          treeSanitizer: new NullTreeSanitizer());
+      upgradeCustomElements(element);
+      document.body!.nodes.add(element);
+      var queried = querySelector('#someid') as CustomType;
+
+      expect(queried, isNotNull);
+      expect(queried is CustomType, isTrue);
+      expect(queried.id, "someid");
+    });
+  });
+
+  group('lifecycle', () {
+    test('created', () {
+      int oldCount = customCreatedCount;
+      var tag = nextTag;
+      document.registerElement(tag, CustomType);
+      var element = new DivElement();
+      element.setInnerHtml('<$tag></$tag>',
+          treeSanitizer: new NullTreeSanitizer());
+      upgradeCustomElements(element);
+      document.body!.nodes.add(element);
+      expect(customCreatedCount, oldCount + 1);
+    });
+  });
+
+  group('mixins', () {
+    test('can invoke mixin methods', () {
+      var tag = nextTag;
+      document.registerElement(tag, CustomType);
+
+      var element = new Element.tag(tag) as CustomType;
+      element.invokeMixinMethod();
+      expect(element.mixinMethodCalled, isTrue);
+    });
+  });
+}
diff --git a/tests/lib/html/custom_elements_test.html b/tests/lib/html/custom_elements_test.html
new file mode 100644
index 0000000..a5751b8
--- /dev/null
+++ b/tests/lib/html/custom_elements_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> custom_elements_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running custom_elements_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/custom_tags_test.dart b/tests/lib/html/custom_tags_test.dart
new file mode 100644
index 0000000..98b60c2
--- /dev/null
+++ b/tests/lib/html/custom_tags_test.dart
@@ -0,0 +1,47 @@
+// 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:expect/minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  test('create via custom tag', () {
+    var element = new Element.tag('x-basic1')..id = 'basic1';
+    document.body!.nodes.add(element);
+
+    var queryById = querySelector('#basic1');
+    expect(queryById, equals(element));
+
+    var queryByTag = querySelectorAll('x-basic1');
+    expect(queryByTag.length, equals(1));
+    expect(queryByTag[0], equals(element));
+  });
+
+  test('custom inner html', () {
+    var element = new DivElement();
+    element.setInnerHtml("<x-basic2 id='basic2'></x-basic2>",
+        treeSanitizer: new NullTreeSanitizer());
+    document.body!.nodes.add(element);
+
+    var queryById = querySelector('#basic2');
+    expect(queryById is Element, isTrue);
+
+    var queryByTag = querySelectorAll('x-basic2');
+    expect(queryByTag.length, equals(1));
+    expect(queryByTag[0], equals(queryById));
+  });
+
+  test('type extension inner html', () {
+    var element = new DivElement();
+    element.setInnerHtml("<div is='x-basic3' id='basic3'></div>",
+        treeSanitizer: new NullTreeSanitizer());
+    document.body!.nodes.add(element);
+
+    var queryById = querySelector('#basic3');
+    expect(queryById is DivElement, isTrue);
+  });
+}
diff --git a/tests/lib/html/dart_object_local_storage_test.dart b/tests/lib/html/dart_object_local_storage_test.dart
new file mode 100644
index 0000000..3c7130b
--- /dev/null
+++ b/tests/lib/html/dart_object_local_storage_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 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+// TODO(vsm): Rename this to wrapper_caching_test or similar.  It's
+// basically a port of dom/dart_object_local_storage_test.dart.  For
+// wrapping implementation of dart:html (i.e., the dartium one), it is
+// effectively testing dart_object_local_storage in the underlying dom
+// object.
+main() {
+  BodyElement body = document.body!;
+  Storage localStorage = window.localStorage;
+  Storage sessionStorage = window.sessionStorage;
+  var element = new Element.tag('canvas');
+  element.id = 'test';
+  body.append(element);
+
+  test('body', () {
+    expect(body, equals(document.body));
+  });
+  test('localStorage', () {
+    expect(localStorage, equals(window.localStorage));
+  });
+  test('sessionStorage', () {
+    expect(sessionStorage, equals(window.sessionStorage));
+  });
+  test('unknown', () {
+    var test = document.querySelector('#test');
+    expect(element, equals(test));
+  });
+}
diff --git a/tests/lib/html/datalistelement_test.dart b/tests/lib/html/datalistelement_test.dart
new file mode 100644
index 0000000..2a9396d
--- /dev/null
+++ b/tests/lib/html/datalistelement_test.dart
@@ -0,0 +1,71 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isDataListElement =
+      predicate((x) => x is DataListElement, 'is a DataListElement');
+
+  var div;
+
+  setUp(() {
+    div = new DivElement();
+    document.body!.append(div);
+    div.innerHtml = """
+<input id="input" list="browsers" />
+<datalist id="browsers">
+  <option value="Chrome">
+  <option value="Firefox">
+  <option value="Internet Explorer">
+  <option value="Opera">
+  <option value="Safari">
+</datalist>
+""";
+  });
+
+  tearDown(() {
+    document.body!.nodes.removeLast();
+  });
+
+  test('is', () {
+    try {
+      var list = document.querySelector('#browsers');
+      expect(list, isDataListElement);
+    } catch (e) {
+      expect(DataListElement.supported, false);
+    }
+  });
+
+  test('list', () {
+    try {
+      var list = document.querySelector('#browsers') as DataListElement;
+      var input = document.querySelector('#input') as InputElement;
+      expect(input.list, list);
+    } catch (e) {
+      expect(DataListElement.supported, false);
+    }
+  });
+
+  test('options', () {
+    try {
+      var options =
+          (document.querySelector('#browsers') as DataListElement).options;
+      expect(options.length, 5);
+    } catch (e) {
+      expect(DataListElement.supported, false);
+    }
+  });
+
+  test('create', () {
+    try {
+      var list = new DataListElement();
+      expect(list, isDataListElement);
+    } catch (e) {
+      expect(DataListElement.supported, false);
+    }
+  });
+}
diff --git a/tests/lib/html/dispatch_parent_event.js b/tests/lib/html/dispatch_parent_event.js
new file mode 100644
index 0000000..ee204b4
--- /dev/null
+++ b/tests/lib/html/dispatch_parent_event.js
@@ -0,0 +1,5 @@
+// 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.
+//
+window.parent.dispatchEvent(new Event('detect_errors'));
diff --git a/tests/lib/html/document_test.dart b/tests/lib/html/document_test.dart
new file mode 100644
index 0000000..334f67e
--- /dev/null
+++ b/tests/lib/html/document_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+main() {
+  var isElement = predicate((x) => x is Element, 'is an Element');
+  var isDivElement = predicate((x) => x is DivElement, 'is a DivElement');
+  var isAnchorElement =
+      predicate((x) => x is AnchorElement, 'is an AnchorElement');
+  var isUnknownElement =
+      predicate((x) => x is UnknownElement, 'is UnknownElement');
+
+  var inscrutable;
+
+  test('CreateElement', () {
+    // FIXME: nifty way crashes, do it boring way.
+    expect(new Element.tag('span'), isElement);
+    expect(new Element.tag('div'), isDivElement);
+    expect(new Element.tag('a'), isAnchorElement);
+    expect(new Element.tag('bad_name'), isUnknownElement);
+  });
+
+  group('document', () {
+    inscrutable = (x) => x;
+
+    test('Document.query', () {
+      Document doc = new DomParser().parseFromString('''<ResultSet>
+           <Row>A</Row>
+           <Row>B</Row>
+           <Row>C</Row>
+         </ResultSet>''', 'text/xml');
+
+      var rs = doc.querySelector('ResultSet');
+      expect(rs, isNotNull);
+    });
+
+    test('CreateElement', () {
+      // FIXME: nifty way crashes, do it boring way.
+      expect(new Element.tag('span'), isElement);
+      expect(new Element.tag('div'), isDivElement);
+      expect(new Element.tag('a'), isAnchorElement);
+      expect(new Element.tag('bad_name'), isUnknownElement);
+    });
+
+    test('adoptNode', () {
+      var div = new Element.html('<div><div id="foo">bar</div></div>');
+      var doc = document.implementation.createHtmlDocument('');
+      expect(doc.adoptNode(div), div);
+      expect(div.ownerDocument, doc);
+      doc.body!.nodes.add(div);
+      expect(doc.querySelector('#foo')!.text, 'bar');
+    });
+
+    test('importNode', () {
+      var div = new Element.html('<div><div id="foo">bar</div></div>');
+      var doc = document.implementation.createHtmlDocument('');
+      var div2 = doc.importNode(div, true);
+      expect(div2, notEquals(div));
+      expect(div2.ownerDocument, doc);
+      doc.body!.nodes.add(div2);
+      expect(doc.querySelector('#foo')!.text, 'bar');
+    });
+
+    test('typeTest1', () {
+      inscrutable = inscrutable(inscrutable);
+      var doc1 = document;
+      expect(doc1 is HtmlDocument, true);
+      expect(inscrutable(doc1) is HtmlDocument, true);
+      var doc2 = document.implementation.createHtmlDocument('');
+      expect(doc2 is HtmlDocument, true);
+      expect(inscrutable(doc2) is HtmlDocument, true);
+    });
+
+    test('typeTest2', () {
+      inscrutable = inscrutable(inscrutable);
+      // XML document.
+      var doc3 = document.implementation.createDocument(null, 'report', null);
+      expect(doc3 is HtmlDocument, false);
+      expect(inscrutable(doc3) is HtmlDocument, false);
+    });
+  });
+}
diff --git a/tests/lib/html/documentfragment_test.dart b/tests/lib/html/documentfragment_test.dart
new file mode 100644
index 0000000..451427d
--- /dev/null
+++ b/tests/lib/html/documentfragment_test.dart
@@ -0,0 +1,168 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  var isAnchorElement =
+      predicate((x) => x is AnchorElement, 'is an AnchorElement');
+
+  List<String> _nodeStrings(Iterable<Node> input) {
+    List<String> out = [];
+    for (Node n in input) {
+      if (n is Element) {
+        Element e = n;
+        out.add(e.tagName);
+      } else {
+        out.add(n.text!);
+      }
+    }
+    return out;
+  }
+
+  void expectEmptyStyleDeclaration(CssStyleDeclaration style) {
+    expect(style.cssText, equals(''));
+    expect(style.getPropertyPriority('color'), equals(''));
+    expect(style.item(0), equals(''));
+    expect(style.length, equals(0));
+    // TODO(jacobr): these checks throw UnimplementedErrors in dartium.
+    // expect(style.parentRule, isNull);
+    // expect(style.getPropertyCssValue('color'), isNull);
+    // expect(style.getPropertyShorthand('color'), isNull);
+    // expect(style.isPropertyImplicit('color'), isFalse);
+
+    // Ideally these would throw errors, but it's not possible to create a class
+    // that'll intercept these calls without implementing the entire
+    // CssStyleDeclaration interface, so we'll settle for them being no-ops.
+    style.cssText = '* {color: blue}';
+    style.removeProperty('color');
+    style.setProperty('color', 'blue');
+  }
+
+  group('constructors', () {
+    test('0-argument makes an empty fragment', () {
+      final fragment = new DocumentFragment();
+      expect(fragment.children, equals([]));
+    });
+
+    test('.html parses input as HTML', () {
+      final fragment = new DocumentFragment.html('<a>foo</a>');
+      expect(fragment.children[0], isAnchorElement);
+    });
+
+    // test('.svg parses input as SVG', () {
+    //   final fragment = new DocumentFragment.svg('<a>foo</a>');
+    //   expect(fragment.children[0] is SVGAElement, isTrue);
+    // });
+
+    // TODO(nweiz): enable this once XML is ported.
+    // test('.xml parses input as XML', () {
+    //   final fragment = new DocumentFragment.xml('<a>foo</a>');
+    //   expect(fragment.children[0] is XMLElement, isTrue);
+    // });
+  });
+
+  group('children', () {
+    late DocumentFragment fragment;
+    late List<Element> children;
+
+    init() {
+      fragment = new DocumentFragment();
+      children = fragment.children;
+      fragment.nodes.addAll([
+        new Text("1"),
+        new Element.tag("A"),
+        new Element.tag("B"),
+        new Text("2"),
+        new Element.tag("I"),
+        new Text("3"),
+        new Element.tag("U")
+      ]);
+    }
+
+    test('is initially empty', () {
+      children = new DocumentFragment().children;
+      expect(children, equals([]));
+      expect(children.isEmpty, isTrue);
+    });
+
+    test('filters out non-element nodes', () {
+      init();
+      expect(_nodeStrings(fragment.nodes),
+          equals(["1", "A", "B", "2", "I", "3", "U"]));
+      expect(_nodeStrings(children), equals(["A", "B", "I", "U"]));
+    });
+
+    test('only indexes children, not other nodes', () {
+      init();
+      children[1] = new Element.tag("BR");
+      expect(_nodeStrings(fragment.nodes),
+          equals(["1", "A", "BR", "2", "I", "3", "U"]));
+      expect(_nodeStrings(children), equals(["A", "BR", "I", "U"]));
+    });
+
+    test('adds to both children and nodes', () {
+      init();
+      children.add(new Element.tag("UL"));
+      expect(_nodeStrings(fragment.nodes),
+          equals(["1", "A", "B", "2", "I", "3", "U", "UL"]));
+      expect(_nodeStrings(children), equals(["A", "B", "I", "U", "UL"]));
+    });
+
+    test('removes only children, from both children and nodes', () {
+      init();
+      expect(children.removeLast().tagName, equals('U'));
+      expect(
+          _nodeStrings(fragment.nodes), equals(["1", "A", "B", "2", "I", "3"]));
+      expect(_nodeStrings(children), equals(["A", "B", "I"]));
+
+      expect(children.removeLast().tagName, "I");
+      expect(_nodeStrings(fragment.nodes), equals(["1", "A", "B", "2", "3"]));
+      expect(_nodeStrings(children), equals(["A", "B"]));
+    });
+
+    test('accessors are wrapped', () {
+      init();
+      expect(children[0].tagName, "A");
+      expect(_nodeStrings(children.where((e) => e.tagName == "I")), ["I"]);
+      expect(children.every((e) => e is Element), isTrue);
+      expect(children.any((e) => e.tagName == "U"), isTrue);
+      expect(children.isEmpty, isFalse);
+      expect(children.length, 4);
+      expect(children[2].tagName, "I");
+      expect(children.last.tagName, "U");
+    });
+
+    test('setting children overwrites nodes as well', () {
+      init();
+      fragment.children = [new Element.tag("DIV"), new Element.tag("HEAD")];
+      expect(_nodeStrings(fragment.nodes), equals(["DIV", "HEAD"]));
+    });
+  });
+
+  test('setting innerHtml works', () {
+    var fragment = new DocumentFragment();
+    fragment.append(new Text("foo"));
+    fragment.innerHtml = "<a>bar</a>baz";
+    expect(_nodeStrings(fragment.nodes), equals(["A", "baz"]));
+  });
+
+  test('getting innerHtml works', () {
+    var fragment = new DocumentFragment();
+    fragment.nodes.addAll([new Text("foo"), new Element.html("<A>bar</A>")]);
+    expect(fragment.innerHtml, "foo<a>bar</a>");
+  });
+
+  test('query searches the fragment', () {
+    var fragment = new DocumentFragment.html(
+        "<div class='foo'><a>foo</a><b>bar</b></div>");
+    expect(fragment.querySelector(".foo a")!.tagName, "A");
+    expect(_nodeStrings(fragment.querySelectorAll<Element>(".foo *")),
+        equals(["A", "B"]));
+  });
+}
diff --git a/tests/lib/html/dom_constructors_test.dart b/tests/lib/html/dom_constructors_test.dart
new file mode 100644
index 0000000..ff70268
--- /dev/null
+++ b/tests/lib/html/dom_constructors_test.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 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('FileReader', () {
+    FileReader fileReader = new FileReader();
+    expect(fileReader.readyState, equals(FileReader.EMPTY));
+  });
+}
diff --git a/tests/lib/html/dom_isolates_test.dart.child_isolate.dart b/tests/lib/html/dom_isolates_test.dart.child_isolate.dart
new file mode 100644
index 0000000..31e97d2
--- /dev/null
+++ b/tests/lib/html/dom_isolates_test.dart.child_isolate.dart
@@ -0,0 +1,16 @@
+// 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:isolate';
+
+main() {
+  port.receive((msg, replyTo) {
+    if (msg != 'check') {
+      replyTo.send('wrong msg: $msg');
+    }
+    replyTo.send('${window.location}');
+    port.close();
+  });
+}
diff --git a/tests/lib/html/domparser_test.dart b/tests/lib/html/domparser_test.dart
new file mode 100644
index 0000000..b7aa5f3
--- /dev/null
+++ b/tests/lib/html/domparser_test.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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isDomParser = predicate((x) => x is DomParser, 'is a DomParser');
+
+  test('constructorTest', () {
+    var ctx = new DomParser();
+    expect(ctx, isNotNull);
+    expect(ctx, isDomParser);
+  });
+}
diff --git a/tests/lib/html/element_add_test.dart b/tests/lib/html/element_add_test.dart
new file mode 100644
index 0000000..e443659
--- /dev/null
+++ b/tests/lib/html/element_add_test.dart
@@ -0,0 +1,267 @@
+// 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
+// BSD-style license that can be found in the LICENSE file
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  var isSpanElement = predicate((x) => x is SpanElement, 'is a SpanElemt');
+  var isDivElement = predicate((x) => x is DivElement, 'is a DivElement');
+  var isText = predicate((x) => x is Text, 'is a Text');
+
+  void expectNoSuchMethod(void fn()) => expect(fn, throwsNoSuchMethodError);
+
+  group('append', () {
+    test('htmlelement', () {
+      var el = new DivElement();
+      el.append(new SpanElement());
+      expect(el.children.length, equals(1));
+      var span = el.children[0];
+      expect(span, isSpanElement);
+
+      el.append(new DivElement());
+      expect(el.children.length, equals(2));
+      // Validate that the first item is still first.
+      expect(el.children[0], equals(span));
+      expect(el.children[1], isDivElement);
+    });
+
+    test('documentFragment', () {
+      var fragment = new DocumentFragment();
+      fragment.append(new SpanElement());
+      expect(fragment.children.length, equals(1));
+      expect(fragment.children[0], isSpanElement);
+    });
+  });
+
+  group('appendHtml', () {
+    test('htmlelement', () {
+      var el = new DivElement();
+      el.appendHtml('<span></span>');
+      expect(el.children.length, equals(1));
+      var span = el.children[0];
+      expect(span, isSpanElement);
+
+      el.appendHtml('<div></div>');
+      expect(el.children.length, equals(2));
+      // Validate that the first item is still first.
+      expect(el.children[0], equals(span));
+      expect(el.children[1], isDivElement);
+    });
+
+    test('documentFragment', () {
+      var fragment = new DocumentFragment();
+      fragment.appendHtml('<span>something</span>');
+      expect(fragment.children.length, equals(1));
+      expect(fragment.children[0], isSpanElement);
+    });
+
+    test('html interpreted in correct context', () {
+      // appendHtml, in order to sanitize, needs to create a document fragment,
+      // but it needs to be created in the right context. If we try to append
+      // table components then the document fragment needs the table context
+      // or it will fail to create them.
+      var el = new TableElement();
+      el.appendHtml('<tr><td>foo</td></tr>');
+      expect(el.children.length, 1);
+      var section = el.children.first;
+      expect(section is TableSectionElement, isTrue);
+      var row = section.children.first;
+      expect(row is TableRowElement, isTrue);
+      var item = row.children.first;
+      expect(item is TableCellElement, isTrue);
+      expect(item.innerHtml, 'foo');
+    });
+
+    test("use body context for elements that are don't support it", () {
+      // Some elements can't be used as context for createContextualFragment,
+      // often because it doesn't make any sense. So adding children to a
+      // <br> has no real effect on the page, but we can do it. But the
+      // document fragment will have to be created in the body context. Verify
+      // that this doesn't throw and that the children show up.
+      var el = new BRElement();
+      el.appendHtml("<p>Stuff</p>");
+      expect(el.children.length, 1);
+      expect(el.children[0].outerHtml, "<p>Stuff</p>");
+    });
+  });
+
+  group('appendText', () {
+    test('htmlelement', () {
+      var el = new DivElement();
+      el.appendText('foo');
+      // No children were created.
+      expect(el.children.length, equals(0));
+      // One text node was added.
+      expect(el.nodes.length, equals(1));
+    });
+
+    test('htmlelement', () {
+      var el = new DivElement();
+      var twoNewLines = "\n\n";
+      el.appendText(twoNewLines);
+      // No children were created.
+      expect(el.children.length, equals(0));
+      // One text node was added.
+      expect(el.nodes.length, equals(1));
+      expect(el.nodes[0], isText);
+      expect(el.nodes[0].text, equals(twoNewLines));
+      expect(el.text, equals(twoNewLines));
+    });
+
+    test('documentFragment', () {
+      var fragment = new DocumentFragment();
+      fragment.appendText('foo');
+      // No children were created.
+      expect(fragment.children.length, equals(0));
+      // One text node was added.
+      expect(fragment.nodes.length, equals(1));
+    });
+  });
+
+  group('insertAdjacentElement', () {
+    test('beforebegin', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      var newChild = new SpanElement();
+      parent.children.add(child);
+
+      child.insertAdjacentElement('beforebegin', newChild);
+
+      expect(parent.children.length, 2);
+      expect(parent.children[0], isSpanElement);
+    });
+
+    test('afterend', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      var newChild = new SpanElement();
+      parent.children.add(child);
+
+      child.insertAdjacentElement('afterend', newChild);
+
+      expect(parent.children.length, 2);
+      expect(parent.children[1], isSpanElement);
+    });
+
+    test('afterbegin', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      var newChild = new SpanElement();
+      parent.children.add(child);
+
+      parent.insertAdjacentElement('afterbegin', newChild);
+
+      expect(parent.children.length, 2);
+      expect(parent.children[0], isSpanElement);
+    });
+
+    test('beforeend', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      var newChild = new SpanElement();
+      parent.children.add(child);
+
+      parent.insertAdjacentElement('beforeend', newChild);
+
+      expect(parent.children.length, 2);
+      expect(parent.children[1], isSpanElement);
+    });
+  });
+
+  group('insertAdjacentHtml', () {
+    test('beforebegin', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      child.insertAdjacentHtml('beforebegin', '<span></span>');
+
+      expect(parent.children.length, 2);
+      expect(parent.children[0], isSpanElement);
+    });
+
+    test('afterend', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      child.insertAdjacentHtml('afterend', '<span></span>');
+
+      expect(parent.children.length, 2);
+      expect(parent.children[1], isSpanElement);
+    });
+
+    test('afterbegin', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      parent.insertAdjacentHtml('afterbegin', '<span></span>');
+
+      expect(parent.children.length, 2);
+      expect(parent.children[0], isSpanElement);
+    });
+
+    test('beforeend', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      parent.insertAdjacentHtml('beforeend', '<span></span>');
+
+      expect(parent.children.length, 2);
+      expect(parent.children[1], isSpanElement);
+    });
+  });
+
+  group('insertAdjacentText', () {
+    test('beforebegin', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      child.insertAdjacentText('beforebegin', 'test');
+
+      expect(parent.nodes.length, 2);
+      expect(parent.nodes[0], isText);
+    });
+
+    test('afterend', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      child.insertAdjacentText('afterend', 'test');
+
+      expect(parent.nodes.length, 2);
+      expect(parent.nodes[1], isText);
+    });
+
+    test('afterbegin', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      parent.insertAdjacentText('afterbegin', 'test');
+
+      expect(parent.nodes.length, 2);
+      expect(parent.nodes[0], isText);
+    });
+
+    test('beforeend', () {
+      var parent = new DivElement();
+      var child = new DivElement();
+      parent.children.add(child);
+
+      parent.insertAdjacentText('beforeend', 'test');
+
+      expect(parent.nodes.length, 2);
+      expect(parent.nodes[1], isText);
+    });
+  });
+}
diff --git a/tests/lib/html/element_animate_omit_timing_test.dart b/tests/lib/html/element_animate_omit_timing_test.dart
new file mode 100644
index 0000000..933d695
--- /dev/null
+++ b/tests/lib/html/element_animate_omit_timing_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.
+
+library element_animate_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  test('omit timing', () {
+    if (Animation.supported) {
+      var body = document.body!;
+      var player = body.animate([
+        {"transform": "translate(100px, -100%)"},
+        {"transform": "translate(400px, 500px)"}
+      ]);
+      player.on['finish'].listen(expectAsync((_) => 'done'));
+    }
+  });
+}
diff --git a/tests/lib/html/element_animate_simple_timing_test.dart b/tests/lib/html/element_animate_simple_timing_test.dart
new file mode 100644
index 0000000..27f13da
--- /dev/null
+++ b/tests/lib/html/element_animate_simple_timing_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 element_animate_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  test('simple timing', () {
+    if (Animation.supported) {
+      var body = document.body!;
+      var opacity = num.parse(body.getComputedStyle().opacity);
+      body.animate([
+        {"opacity": 100},
+        {"opacity": 0}
+      ], 100);
+      var newOpacity = num.parse(body.getComputedStyle().opacity);
+      expect(newOpacity == opacity, isTrue);
+    }
+  });
+}
diff --git a/tests/lib/html/element_animate_supported_test.dart b/tests/lib/html/element_animate_supported_test.dart
new file mode 100644
index 0000000..7f11c8a
--- /dev/null
+++ b/tests/lib/html/element_animate_supported_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.
+
+library element_animate_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(Animation.supported, isTrue);
+  });
+}
diff --git a/tests/lib/html/element_animate_timing_dict_test.dart b/tests/lib/html/element_animate_timing_dict_test.dart
new file mode 100644
index 0000000..28faf1a
--- /dev/null
+++ b/tests/lib/html/element_animate_timing_dict_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.
+
+library element_animate_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  test('timing dict', () {
+    if (Animation.supported) {
+      var body = document.body!;
+      // Animate different characteristics so the tests can run concurrently.
+      var fontSize = body.getComputedStyle().fontSize;
+      var player = body.animate([
+        {"font-size": "500px"},
+        {"font-size": fontSize}
+      ], {
+        "duration": 100
+      });
+      var newFontSize = body.getComputedStyle().fontSize;
+      // Don't bother to parse to numbers, as long as it's changed that
+      // indicates something is happening.
+      expect(newFontSize == fontSize, isFalse);
+      player.on['finish'].listen(expectAsync((_) => 'done'));
+    }
+  });
+}
diff --git a/tests/lib/html/element_classes_svg_test.dart b/tests/lib/html/element_classes_svg_test.dart
new file mode 100644
index 0000000..cc05a21
--- /dev/null
+++ b/tests/lib/html/element_classes_svg_test.dart
@@ -0,0 +1,229 @@
+// 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:collection';
+import 'dart:html';
+import 'dart:svg' as svg;
+
+import "package:expect/expect.dart";
+import 'package:expect/minitest.dart';
+
+// Test for `querySelectorAll(xxx).classes.op()` where the query returns mixed
+// Html and Svg elements.
+
+Element makeElementsContainer() {
+  var e = new Element.html('<ul class="yes foo">'
+      '<li class="yes quux qux">'
+      '</ul>');
+  final svgContent = r"""
+<svg version="1.1">
+  <circle class="yes qux"></circle>
+  <path class="yes classy"></path>
+</svg>""";
+  final svgElement = new svg.SvgElement.svg(svgContent);
+  e.append(svgElement);
+  return e;
+}
+
+Element? elementsContainer;
+
+/// Test top-level querySelectorAll with generics.
+topLevelQuerySelector() {
+  var noElementsTop = querySelectorAll<svg.PathElement>('.no');
+  expect(noElementsTop.length, 0);
+  expect(noElementsTop is List, true);
+
+  // Expect runtime error all elements in the list are not the proper type.
+  Expect.throwsAssertionError(() => querySelectorAll<svg.CircleElement>('path'),
+      'All elements not of type CircleElement');
+
+  var simpleElems = querySelectorAll('circle');
+  expect(simpleElems.length, 1);
+  expect(simpleElems is List, true);
+  expect(simpleElems is List<dynamic>, true);
+  expect(simpleElems is List<svg.CircleElement>, false);
+  expect(simpleElems[0] is svg.CircleElement, true);
+
+  var varElementsFromTop = querySelectorAll<svg.CircleElement>('circle');
+  expect(varElementsFromTop.length, 1);
+  expect(varElementsFromTop is List, true);
+  expect(varElementsFromTop is List<svg.CircleElement>, true);
+  expect(varElementsFromTop[0] is svg.CircleElement, true);
+  expect(varElementsFromTop is List<svg.PathElement>, false);
+  expect(varElementsFromTop[0] is svg.PathElement, false);
+
+  List<svg.CircleElement> elementsFromTop =
+      querySelectorAll<svg.CircleElement>('circle');
+  expect(elementsFromTop is List, true);
+  expect(elementsFromTop is List<svg.CircleElement>, true);
+  expect(elementsFromTop[0] is svg.CircleElement, true);
+  expect(elementsFromTop.length, 1);
+}
+
+ElementList<Element> elementsSetup() {
+  elementsContainer = makeElementsContainer();
+  document.documentElement!.children.add(elementsContainer!);
+  var elements = document.querySelectorAll('.yes');
+  expect(elements.length, 4);
+
+  topLevelQuerySelector();
+
+  return elements;
+}
+
+void elementsTearDown() {
+  if (elementsContainer != null) {
+    document.documentElement!.children.remove(elementsContainer!);
+    elementsContainer = null;
+  }
+}
+
+/// Returns a canonical string for Set<String> and lists of Element's classes.
+String view(var e) {
+  if (e is Set) return '${e.toList()..sort()}';
+  if (e is Element) return view(e.classes);
+  if (e is Iterable) return '${e.map(view).toList()}';
+  throw new ArgumentError('Cannot make canonical view string for: $e}');
+}
+
+main() {
+  Set<String> extractClasses(Element el) {
+    final match = new RegExp('class="([^"]+)"').firstMatch(el.outerHtml)!;
+    return new LinkedHashSet.from(match[1]!.split(' '));
+  }
+
+  tearDown(elementsTearDown);
+
+  test('list_view', () {
+    // Test that the 'view' helper function is behaving.
+    var elements = elementsSetup();
+    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, yes], [quux, qux, yes], [qux, yes], [classy, yes]]');
+  });
+
+  test('listClasses=', () {
+    var elements = elementsSetup();
+
+    elements.classes = ['foo', 'qux'];
+    expect(view(elements.classes), '[foo, qux]');
+    expect(view(elements), '[[foo, qux], [foo, qux], [foo, qux], [foo, qux]]');
+
+    var elements2 = document.querySelectorAll('.qux');
+    expect(view(elements2.classes), '[foo, qux]');
+    expect(view(elements2), '[[foo, qux], [foo, qux], [foo, qux], [foo, qux]]');
+
+    for (Element e in elements2) {
+      expect(e.classes, equals(['foo', 'qux']));
+      expect(extractClasses(e), equals(['foo', 'qux']));
+    }
+
+    elements.classes = [];
+    expect(view(elements2.classes), '[]');
+    expect(view(elements2), '[[], [], [], []]');
+  });
+
+  test('listMap', () {
+    var elements = elementsSetup();
+    expect(elements.classes.map((c) => c.toUpperCase()).toList(),
+        unorderedEquals(['YES', 'FOO', 'QUX', 'QUUX', 'CLASSY']));
+  });
+
+  test('listContains', () {
+    var elements = elementsSetup();
+    expect(elements.classes.contains('classy'), isTrue);
+    expect(elements.classes.contains('troll'), isFalse);
+  });
+
+  test('listAdd', () {
+    var elements = elementsSetup();
+    var added = elements.classes.add('lassie');
+    expect(added, isFalse);
+
+    expect(view(elements.classes), '[classy, foo, lassie, quux, qux, yes]');
+    expect(
+        view(elements),
+        '[[foo, lassie, yes], [lassie, quux, qux, yes], '
+        '[lassie, qux, yes], [classy, lassie, yes]]');
+  });
+
+  test('listRemove', () {
+    var elements = elementsSetup();
+    expect(elements.classes.remove('lassi'), isFalse);
+    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, yes], [quux, qux, yes], [qux, yes], [classy, yes]]');
+
+    expect(elements.classes.remove('qux'), isTrue);
+    expect(view(elements.classes), '[classy, foo, quux, yes]');
+    expect(view(elements), '[[foo, yes], [quux, yes], [yes], [classy, yes]]');
+  });
+
+  test('listToggle', () {
+    var elements = elementsSetup();
+    elements.classes.toggle('qux');
+    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, qux, yes], [quux, yes], [yes], [classy, qux, yes]]');
+  });
+
+  test('listAddAll', () {
+    var elements = elementsSetup();
+    elements.classes.addAll(['qux', 'lassi', 'sassy']);
+    expect(
+        view(elements.classes), '[classy, foo, lassi, quux, qux, sassy, yes]');
+    expect(
+        view(elements),
+        '[[foo, lassi, qux, sassy, yes], [lassi, quux, qux, sassy, yes], '
+        '[lassi, qux, sassy, yes], [classy, lassi, qux, sassy, yes]]');
+  });
+
+  test('listRemoveAll', () {
+    var elements = elementsSetup();
+    elements.classes.removeAll(['qux', 'classy', 'mumble']);
+    expect(view(elements.classes), '[foo, quux, yes]');
+    expect(view(elements), '[[foo, yes], [quux, yes], [yes], [yes]]');
+
+    elements.classes.removeAll(['foo', 'yes']);
+    expect(view(elements.classes), '[quux]');
+    expect(view(elements), '[[], [quux], [], []]');
+  });
+
+  test('listToggleAll', () {
+    var elements = elementsSetup();
+    elements.classes.toggleAll(['qux', 'mornin']);
+    expect(view(elements.classes), '[classy, foo, mornin, quux, qux, yes]');
+    expect(
+        view(elements),
+        '[[foo, mornin, qux, yes], [mornin, quux, yes], '
+        '[mornin, yes], [classy, mornin, qux, yes]]');
+  });
+
+  test('listRetainAll', () {
+    var elements = elementsSetup();
+    elements.classes.retainAll(['bar', 'baz', 'classy', 'qux']);
+    expect(view(elements.classes), '[classy, qux]');
+    expect(view(elements), '[[], [qux], [qux], [classy]]');
+  });
+
+  test('listRemoveWhere', () {
+    var elements = elementsSetup();
+    elements.classes.removeWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[classy, foo, yes]');
+    expect(view(elements), '[[foo, yes], [yes], [yes], [classy, yes]]');
+  });
+
+  test('listRetainWhere', () {
+    var elements = elementsSetup();
+    elements.classes.retainWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[quux, qux]');
+    expect(view(elements), '[[], [quux, qux], [qux], []]');
+  });
+
+  test('listContainsAll', () {
+    var elements = elementsSetup();
+    expect(elements.classes.containsAll(['qux', 'mornin']), isFalse);
+    expect(elements.classes.containsAll(['qux', 'classy']), isTrue);
+  });
+}
diff --git a/tests/lib/html/element_classes_test.dart b/tests/lib/html/element_classes_test.dart
new file mode 100644
index 0000000..0345692
--- /dev/null
+++ b/tests/lib/html/element_classes_test.dart
@@ -0,0 +1,390 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+Element makeElement() => new Element.tag('div');
+
+Element makeElementWithClasses() =>
+    new Element.html('<div class="foo bar baz"></div>');
+
+CssClassSet makeClassSet() => makeElementWithClasses().classes;
+
+Element makeListElement() => new Element.html('<ul class="foo bar baz">'
+    '<li class="quux qux">'
+    '<li class="meta">'
+    '<li class="classy lassy">'
+    '<li class="qux lassy">'
+    '</ul>');
+
+Element? listElement;
+
+ElementList<Element> listElementSetup() {
+  listElement = makeListElement();
+  document.documentElement!.children.add(listElement!);
+  return document.querySelectorAll('li');
+}
+
+void listElementTearDown() {
+  if (listElement != null) {
+    document.documentElement!.children.remove(listElement!);
+    listElement = null;
+  }
+}
+
+/// Returns a canonical string for Set<String> and lists of Element's classes.
+String view(var e) {
+  if (e is Set) return '${e.toList()..sort()}';
+  if (e is Element) return view(e.classes);
+  if (e is Iterable) return '${e.map(view).toList()}';
+  throw new ArgumentError('Cannot make canonical view string for: $e}');
+}
+
+main() {
+  Set<String> extractClasses(Element el) {
+    final match = new RegExp('class="([^"]+)"').firstMatch(el.outerHtml)!;
+    return new LinkedHashSet.from(match[1]!.split(' '));
+  }
+
+  test('affects the "class" attribute', () {
+    final el = makeElementWithClasses();
+    el.classes.add('qux');
+    expect(extractClasses(el), equals(['foo', 'bar', 'baz', 'qux']));
+  });
+
+  test('is affected by the "class" attribute', () {
+    final el = makeElementWithClasses();
+    el.attributes['class'] = 'foo qux';
+    expect(el.classes, equals(['foo', 'qux']));
+  });
+
+  test('classes=', () {
+    final el = makeElementWithClasses();
+    el.classes = ['foo', 'qux'];
+    expect(el.classes, equals(['foo', 'qux']));
+    expect(extractClasses(el), equals(['foo', 'qux']));
+  });
+
+  test('toString', () {
+    expect(makeClassSet().toString().split(' '), equals(['foo', 'bar', 'baz']));
+    expect(makeElement().classes.toString(), '');
+  });
+
+  test('forEach', () {
+    final classes = <String>[];
+    makeClassSet().forEach(classes.add);
+    expect(classes, equals(['foo', 'bar', 'baz']));
+  });
+
+  test('iterator', () {
+    final classes = <String>[];
+    for (var el in makeClassSet()) {
+      classes.add(el);
+    }
+    expect(classes, equals(['foo', 'bar', 'baz']));
+  });
+
+  test('map', () {
+    expect(makeClassSet().map((c) => c.toUpperCase()).toList(),
+        equals(['FOO', 'BAR', 'BAZ']));
+  });
+
+  test('where', () {
+    expect(makeClassSet().where((c) => c.contains('a')).toList(),
+        equals(['bar', 'baz']));
+  });
+
+  test('every', () {
+    expect(makeClassSet().every((c) => c is String), isTrue);
+    expect(makeClassSet().every((c) => c.contains('a')), isFalse);
+  });
+
+  test('any', () {
+    expect(makeClassSet().any((c) => c.contains('a')), isTrue);
+    expect(makeClassSet().any((c) => c is num), isFalse);
+  });
+
+  test('isEmpty', () {
+    expect(makeClassSet().isEmpty, isFalse);
+    expect(makeElement().classes.isEmpty, isTrue);
+  });
+
+  test('length', () {
+    expect(makeClassSet().length, 3);
+    expect(makeElement().classes.length, 0);
+  });
+
+  test('contains', () {
+    expect(makeClassSet().contains('foo'), isTrue);
+    expect(makeClassSet().contains('qux'), isFalse);
+  });
+
+  test('contains-bad', () {
+    // Non-strings return `false`.
+    // Strings need to be valid tokens.
+    final classes = makeClassSet();
+    expect(classes.contains(1), isFalse);
+    expect(() => classes.contains(''), throws);
+    expect(() => classes.contains('foo bar'), throws);
+  });
+
+  test('add', () {
+    final classes = makeClassSet();
+    var added = classes.add('qux');
+    expect(added, isTrue);
+    expect(classes, equals(['foo', 'bar', 'baz', 'qux']));
+
+    added = classes.add('qux');
+    expect(added, isFalse);
+    final list = new List.from(classes);
+    list.sort((a, b) => a.compareTo(b));
+    expect(list, equals(['bar', 'baz', 'foo', 'qux']),
+        reason: "The class set shouldn't have duplicate elements.");
+  });
+
+  test('add-bad', () {
+    final classes = makeClassSet();
+    expect(() => classes.add(''), throws);
+    expect(() => classes.add('foo bar'), throws);
+  });
+
+  test('remove', () {
+    final classes = makeClassSet();
+    classes.remove('bar');
+    expect(classes, equals(['foo', 'baz']));
+    classes.remove('qux');
+    expect(classes, equals(['foo', 'baz']));
+  });
+
+  test('remove-bad', () {
+    final classes = makeClassSet();
+    expect(() => classes.remove(''), throws);
+    expect(() => classes.remove('foo bar'), throws);
+  });
+
+  test('toggle', () {
+    final classes = makeClassSet();
+    classes.toggle('bar');
+    expect(classes, equals(['foo', 'baz']));
+    classes.toggle('qux');
+    expect(classes, equals(['foo', 'baz', 'qux']));
+
+    classes.toggle('qux', true);
+    expect(classes, equals(['foo', 'baz', 'qux']));
+    classes.toggle('qux', false);
+    expect(classes, equals(['foo', 'baz']));
+    classes.toggle('qux', false);
+    expect(classes, equals(['foo', 'baz']));
+    classes.toggle('qux', true);
+    expect(classes, equals(['foo', 'baz', 'qux']));
+  });
+
+  test('toggle-bad', () {
+    final classes = makeClassSet();
+    expect(() => classes.toggle(''), throws);
+    expect(() => classes.toggle('', true), throws);
+    expect(() => classes.toggle('', false), throws);
+    expect(() => classes.toggle('foo bar'), throws);
+    expect(() => classes.toggle('foo bar', true), throws);
+    expect(() => classes.toggle('foo bar', false), throws);
+  });
+
+  test('addAll', () {
+    final classes = makeClassSet();
+    classes.addAll(['bar', 'qux', 'bip']);
+    expect(classes, equals(['foo', 'bar', 'baz', 'qux', 'bip']));
+  });
+
+  test('removeAll', () {
+    final classes = makeClassSet();
+    classes.removeAll(['bar', 'baz', 'qux']);
+    expect(classes, equals(['foo']));
+  });
+
+  test('toggleAll', () {
+    final classes = makeClassSet();
+    classes.toggleAll(['bar', 'foo']);
+    expect(classes, equals(['baz']));
+    classes.toggleAll(['qux', 'quux']);
+    expect(classes, equals(['baz', 'qux', 'quux']));
+    classes.toggleAll(['bar', 'foo'], true);
+    expect(classes, equals(['baz', 'qux', 'quux', 'bar', 'foo']));
+    classes.toggleAll(['baz', 'quux'], false);
+    expect(classes, equals(['qux', 'bar', 'foo']));
+  });
+
+  test('retainAll', () {
+    final classes = makeClassSet();
+    classes.retainAll(['bar', 'baz', 'qux']);
+    expect(classes, equals(['bar', 'baz']));
+  });
+
+  test('removeWhere', () {
+    final classes = makeClassSet();
+    classes.removeWhere((s) => s.startsWith('b'));
+    expect(classes, equals(['foo']));
+  });
+
+  test('retainWhere', () {
+    final classes = makeClassSet();
+    classes.retainWhere((s) => s.startsWith('b'));
+    expect(classes, equals(['bar', 'baz']));
+  });
+
+  test('containsAll', () {
+    final classes = makeClassSet();
+    expect(classes.containsAll(['foo', 'baz']), isTrue);
+    expect(classes.containsAll(['foo', 'qux']), isFalse);
+    expect(classes.containsAll(['foo', 'baz'].toSet()), isTrue);
+    expect(classes.containsAll(['foo', 'qux'].toSet()), isFalse);
+  });
+
+  test('intersection', () {
+    final classes = makeClassSet();
+    expect(classes.intersection(['foo', 'qux', 'baz'].toSet()),
+        unorderedEquals(['foo', 'baz']));
+  });
+
+  test('clear', () {
+    final classes = makeClassSet();
+    classes.clear();
+    expect(classes, equals([]));
+  });
+
+  test('order', () {
+    var classes = makeClassSet();
+    classes.add('aardvark');
+    expect(classes, equals(['foo', 'bar', 'baz', 'aardvark']));
+    classes.toggle('baz');
+    expect(classes, equals(['foo', 'bar', 'aardvark']));
+    classes.toggle('baz');
+    expect(classes, equals(['foo', 'bar', 'aardvark', 'baz']));
+  });
+
+  tearDown(listElementTearDown);
+
+  test('list_view', () {
+    // Test that the 'view' helper function is behaving.
+    var elements = listElementSetup();
+    expect(view(elements.classes), '[classy, lassy, meta, quux, qux]');
+    expect(
+        view(elements), '[[quux, qux], [meta], [classy, lassy], [lassy, qux]]');
+  });
+
+  test('listClasses=', () {
+    var elements = listElementSetup();
+    elements.classes = ['foo', 'qux'];
+    elements = document.querySelectorAll('li');
+    for (Element e in elements) {
+      expect(e.classes, equals(['foo', 'qux']));
+      expect(extractClasses(e), equals(['foo', 'qux']));
+    }
+
+    elements.classes = [];
+    expect(view(elements.classes), '[]');
+    expect(view(elements), '[[], [], [], []]');
+  });
+
+  test('listMap', () {
+    var elements = listElementSetup();
+    expect(elements.classes.map((c) => c.toUpperCase()).toList(),
+        unorderedEquals(['QUX', 'QUUX', 'META', 'CLASSY', 'LASSY']));
+  });
+
+  test('listContains', () {
+    var elements = listElementSetup();
+    expect(elements.classes.contains('lassy'), isTrue);
+    expect(elements.classes.contains('foo'), isFalse);
+  });
+
+  test('listAdd', () {
+    var elements = listElementSetup();
+    var added = elements.classes.add('lassie');
+    expect(added, isNull);
+
+    expect(view(elements.classes), '[classy, lassie, lassy, meta, quux, qux]');
+    expect(
+        view(elements),
+        '[[lassie, quux, qux], [lassie, meta], [classy, lassie, lassy], '
+        '[lassie, lassy, qux]]');
+  });
+
+  test('listRemove', () {
+    var elements = listElementSetup();
+    expect(elements.classes.remove('lassi'), isFalse);
+    expect(view(elements.classes), '[classy, lassy, meta, quux, qux]');
+    expect(
+        view(elements), '[[quux, qux], [meta], [classy, lassy], [lassy, qux]]');
+
+    expect(elements.classes.remove('qux'), isTrue);
+    expect(view(elements.classes), '[classy, lassy, meta, quux]');
+    expect(view(elements), '[[quux], [meta], [classy, lassy], [lassy]]');
+  });
+
+  test('listToggle', () {
+    var elements = listElementSetup();
+    elements.classes.toggle('qux');
+    expect(view(elements.classes), '[classy, lassy, meta, quux, qux]');
+    expect(
+        view(elements), '[[quux], [meta, qux], [classy, lassy, qux], [lassy]]');
+  });
+
+  test('listAddAll', () {
+    var elements = listElementSetup();
+    elements.classes.addAll(['qux', 'lassi', 'sassy']);
+    expect(view(elements.classes),
+        '[classy, lassi, lassy, meta, quux, qux, sassy]');
+    expect(
+        view(elements),
+        '[[lassi, quux, qux, sassy], [lassi, meta, qux, sassy], '
+        '[classy, lassi, lassy, qux, sassy], [lassi, lassy, qux, sassy]]');
+  });
+
+  test('listRemoveAll', () {
+    var elements = listElementSetup();
+    elements.classes.removeAll(['qux', 'lassy', 'meta']);
+    expect(view(elements.classes), '[classy, quux]');
+    expect(view(elements), '[[quux], [], [classy], []]');
+  });
+
+  test('listToggleAll', () {
+    var elements = listElementSetup();
+    elements.classes.toggleAll(['qux', 'meta', 'mornin']);
+    expect(view(elements.classes), '[classy, lassy, meta, mornin, quux, qux]');
+    expect(
+        view(elements),
+        '[[meta, mornin, quux], [mornin, qux], '
+        '[classy, lassy, meta, mornin, qux], [lassy, meta, mornin]]');
+  });
+
+  test('listRetainAll', () {
+    var elements = listElementSetup();
+    elements.classes.retainAll(['bar', 'baz', 'qux']);
+    expect(view(elements.classes), '[qux]');
+    expect(view(elements), '[[qux], [], [], [qux]]');
+  });
+
+  test('listRemoveWhere', () {
+    var elements = listElementSetup();
+    elements.classes.removeWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[classy, lassy, meta]');
+    expect(view(elements), '[[], [meta], [classy, lassy], [lassy]]');
+  });
+
+  test('listRetainWhere', () {
+    var elements = listElementSetup();
+    elements.classes.retainWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[quux, qux]');
+    expect(view(elements), '[[quux, qux], [], [], [qux]]');
+  });
+
+  test('listContainsAll', () {
+    var elements = listElementSetup();
+    expect(elements.classes.containsAll(['qux', 'meta', 'mornin']), isFalse);
+    expect(elements.classes.containsAll(['qux', 'lassy', 'classy']), isTrue);
+  });
+}
diff --git a/tests/lib/html/element_constructor_1_test.dart b/tests/lib/html/element_constructor_1_test.dart
new file mode 100644
index 0000000..bd265b4
--- /dev/null
+++ b/tests/lib/html/element_constructor_1_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Put universally passing event constructors in this file.
+// Move constructors that fail on some configuration to their own
+// element_constructor_foo_test.dart file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isAnchorElement =
+      predicate((x) => x is AnchorElement, 'is an AnchorElement');
+  var isAreaElement = predicate((x) => x is AreaElement, 'is an AreaElement');
+  var isDivElement = predicate((x) => x is DivElement, 'is a DivElement');
+  var isCanvasElement =
+      predicate((x) => x is CanvasElement, 'is a CanvasElement');
+  var isParagraphElement =
+      predicate((x) => x is ParagraphElement, 'is a ParagraphElement');
+  var isSpanElement = predicate((x) => x is SpanElement, 'is a SpanElement');
+  var isSelectElement =
+      predicate((x) => x is SelectElement, 'is a SelectElement');
+
+  test('anchor1', () {
+    var e = new AnchorElement();
+    expect(e, isAnchorElement);
+  });
+
+  test('anchor2', () {
+    var e = new AnchorElement(href: '#blah');
+    expect(e, isAnchorElement);
+    expect(e.href.endsWith('#blah'), isTrue);
+  });
+
+  test('area', () {
+    var e = new AreaElement();
+    expect(e, isAreaElement);
+  });
+
+  // AudioElement tested in audioelement_test.dart
+
+  test('div', () {
+    var e = new DivElement();
+    expect(e, isDivElement);
+  });
+
+  test('canvas1', () {
+    var e = new CanvasElement();
+    expect(e, isCanvasElement);
+  });
+
+  test('canvas2', () {
+    var e = new CanvasElement(height: 100, width: 200);
+    expect(e, isCanvasElement);
+    expect(e.width, 200);
+    expect(e.height, 100);
+  });
+
+  test('p', () {
+    var e = new ParagraphElement();
+    expect(e, isParagraphElement);
+  });
+
+  test('span', () {
+    var e = new SpanElement();
+    expect(e, isSpanElement);
+  });
+
+  test('select', () {
+    var e = new SelectElement();
+    expect(e, isSelectElement);
+  });
+}
diff --git a/tests/lib/html/element_dimensions_test.dart b/tests/lib/html/element_dimensions_test.dart
new file mode 100644
index 0000000..e45aed4
--- /dev/null
+++ b/tests/lib/html/element_dimensions_test.dart
@@ -0,0 +1,260 @@
+// 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:expect/minitest.dart';
+
+main() {
+  var isElement = predicate((x) => x is Element, 'is an Element');
+  var isCanvasElement =
+      predicate((x) => x is CanvasElement, 'is a CanvasElement');
+  var isDivElement = predicate((x) => x is DivElement, 'is a isDivElement');
+
+  var div = new DivElement();
+  div.id = 'test';
+  document.body!.nodes.add(div);
+
+  void initDiv() {
+    var style = div.style;
+    style
+      ..padding = '4px'
+      ..border = '0px solid #fff'
+      ..margin = '6px'
+      ..height = '10px'
+      ..width = '11px'
+      ..boxSizing = 'content-box'
+      ..overflow = 'visible';
+  }
+
+  div.nodes.addAll([
+    new DivElement(),
+    new CanvasElement(),
+    new DivElement(),
+    new Text('Hello'),
+    new DivElement(),
+    new Text('World'),
+    new CanvasElement()
+  ]);
+
+  group('dimensions', () {
+    setUp(initDiv);
+
+    test('contentEdge.height', () {
+      var all1 = querySelectorAll('#test');
+
+      expect(all1.contentEdge.height, 10);
+      expect(all1[0].getComputedStyle().getPropertyValue('height'), '10px');
+
+      all1.contentEdge.height = new Dimension.px(600);
+      all1.contentEdge.height = 600;
+      expect(all1.contentEdge.height, 600);
+      expect(all1[0].getComputedStyle().getPropertyValue('height'), '600px');
+      all1[0].style.visibility = 'hidden';
+      expect(all1.contentEdge.height, 600);
+      all1[0].style.visibility = 'visible';
+
+      // If user passes in a negative number, set height to 0.
+      all1.contentEdge.height = new Dimension.px(-1);
+      expect(all1.contentEdge.height, 0);
+
+      // Adding padding or border shouldn't affect the height for
+      // non-box-sizing.
+      div.style.padding = '20pc';
+      expect(all1.contentEdge.height, 0);
+      div.style.border = '2px solid #fff';
+      expect(all1.contentEdge.height, 0);
+    });
+
+    test('contentEdge.height with border-box', () {
+      var all1 = document.querySelectorAll('#test');
+      div.style.boxSizing = 'border-box';
+      expect(all1.contentEdge.height, 2);
+      div.style.padding = '20pc';
+      expect(all1.contentEdge.height, 0);
+      div.style.border = '2px solid #fff';
+      expect(all1.contentEdge.height, 0);
+    });
+
+    test('contentEdge.width', () {
+      var all1 = document.querySelectorAll('#test');
+      expect(all1.contentEdge.width, 11);
+      expect(all1[0].getComputedStyle().getPropertyValue('width'), '11px');
+
+      all1.contentEdge.width = new Dimension.px(600);
+      expect(all1.contentEdge.width, 600);
+      expect(all1[0].getComputedStyle().getPropertyValue('width'), '600px');
+      all1[0].style.visibility = 'hidden';
+      expect(all1.contentEdge.width, 600);
+      all1[0].style.visibility = 'visible';
+
+      // If user passes in a negative number, set width to 0.
+      all1.contentEdge.width = new Dimension.px(-1);
+      expect(all1.contentEdge.width, 0);
+
+      // Adding padding or border shouldn't affect the width.
+      div.style.padding = '20pc';
+      expect(all1.contentEdge.width, 0);
+      div.style.border = '2px solid #fff';
+      expect(all1.contentEdge.width, 0);
+    });
+
+    test('contentEdge.width with border-box', () {
+      var all1 = document.querySelectorAll('#test');
+      div.style.boxSizing = 'border-box';
+      expect(all1.contentEdge.width, 3);
+      div.style.padding = '20pc';
+      expect(all1.contentEdge.width, 0);
+      div.style.border = '2px solid #fff';
+      expect(all1.contentEdge.width, 0);
+    });
+
+    test('paddingEdge.height', () {
+      var all1 = document.querySelectorAll('#test');
+      expect(all1.paddingEdge.height, 18);
+      all1[0].style.visibility = 'hidden';
+      expect(all1.paddingEdge.height, 18);
+      all1[0].style.visibility = 'visible';
+
+      // Adding border shouldn't affect the paddingEdge.height.
+      div.style.border = '2px solid #fff';
+      expect(all1.paddingEdge.height, 18);
+      // Adding padding should affect the paddingEdge.height.
+      div.style.padding = '20pc';
+      expect(all1.paddingEdge.height, 650);
+    });
+
+    test('paddingEdge.height with border-box', () {
+      var all1 = document.querySelectorAll('#test');
+      div.style.boxSizing = 'border-box';
+      expect(all1.paddingEdge.height, 10);
+      div.style.padding = '20pc';
+      expect(all1.paddingEdge.height, 640);
+      div.style.border = '2px solid #fff';
+      expect(all1.paddingEdge.height, 640);
+    });
+
+    test('paddingEdge.width', () {
+      var all1 = document.querySelectorAll('#test');
+      expect(all1.paddingEdge.width, 19);
+      all1[0].style.visibility = 'hidden';
+      expect(all1.paddingEdge.width, 19);
+      all1[0].style.visibility = 'visible';
+
+      // Adding border shouldn't affect the width.
+      div.style.border = '2px solid #fff';
+      expect(all1.paddingEdge.width, 19);
+
+      // Adding padding should affect the paddingEdge.width.
+      div.style.padding = '20pc';
+      expect(all1.paddingEdge.width, 651);
+    });
+
+    test('paddingEdge.width with border-box', () {
+      var all1 = document.querySelectorAll('#test');
+      div.style.boxSizing = 'border-box';
+      expect(all1.paddingEdge.width, 11);
+      div.style.padding = '20pc';
+      expect(all1.paddingEdge.width, 640);
+      div.style.border = '2px solid #fff';
+      expect(all1.paddingEdge.width, 640);
+    });
+
+    test('borderEdge.height and marginEdge.height', () {
+      var all1 = document.querySelectorAll('#test');
+      expect(div.borderEdge.height, 18);
+      expect(div.marginEdge.height, 30);
+      expect(all1.borderEdge.height, 18);
+      expect(all1.marginEdge.height, 30);
+      all1[0].style.visibility = 'hidden';
+      expect(all1.borderEdge.height, 18);
+      all1[0].style.visibility = 'visible';
+
+      // Adding border should affect the borderEdge.height.
+      div.style.border = '2px solid #fff';
+      expect(all1.borderEdge.height, 22);
+      // Adding padding should affect the borderEdge.height.
+      div.style.padding = '20pc';
+      expect(all1.borderEdge.height, 654);
+      expect(all1.marginEdge.height, 666);
+    });
+
+    test('borderEdge.height and marginEdge.height with border-box', () {
+      var all1 = document.querySelectorAll('#test');
+      div.style.boxSizing = 'border-box';
+      expect(all1.borderEdge.height, 10);
+      expect(all1.marginEdge.height, 22);
+      div.style.padding = '20pc';
+      expect(all1.borderEdge.height, 640);
+      expect(all1.marginEdge.height, 652);
+      div.style.border = '2px solid #fff';
+      expect(all1.borderEdge.height, 644);
+      expect(all1.marginEdge.height, 656);
+    });
+
+    test('borderEdge.width and marginEdge.width', () {
+      var all1 = document.querySelectorAll('#test');
+      expect(all1.borderEdge.width, 19);
+      expect(all1.marginEdge.width, 31);
+
+      // Adding border should affect the width.
+      div.style.border = '2px solid #fff';
+      expect(all1.borderEdge.width, 23);
+
+      // Adding padding should affect the borderEdge.width.
+      div.style.padding = '20pc';
+      expect(all1.borderEdge.width, 655);
+      expect(all1.marginEdge.width, 667);
+    });
+
+    test('borderEdge.width and marginEdge.width with border-box', () {
+      var all1 = document.querySelectorAll('#test');
+      div.style.boxSizing = 'border-box';
+      expect(all1.borderEdge.width, 11);
+      expect(all1.marginEdge.width, 23);
+      div.style.padding = '20pc';
+      expect(all1.borderEdge.width, 640);
+      expect(all1.marginEdge.width, 652);
+      div.style.border = '2px solid #fff';
+      expect(all1.borderEdge.width, 644);
+      expect(all1.marginEdge.width, 656);
+    });
+
+    test('left and top', () {
+      div.style.border = '1px solid #fff';
+      div.style.margin = '6px 7px';
+      div.style.padding = '4px 5px';
+      var all1 = document.querySelectorAll('#test');
+
+      expect(all1.borderEdge.left, all1[0].getBoundingClientRect().left);
+      expect(all1.borderEdge.top, all1[0].getBoundingClientRect().top);
+
+      expect(
+          all1.contentEdge.left, all1[0].getBoundingClientRect().left + 1 + 5);
+      expect(all1.contentEdge.top, all1[0].getBoundingClientRect().top + 1 + 4);
+
+      expect(all1.marginEdge.left, all1[0].getBoundingClientRect().left - 7);
+      expect(all1.marginEdge.top, all1[0].getBoundingClientRect().top - 6);
+
+      expect(all1.paddingEdge.left, all1[0].getBoundingClientRect().left + 1);
+      expect(all1.paddingEdge.top, all1[0].getBoundingClientRect().top + 1);
+    });
+
+    test('setHeight ElementList', () {
+      div.style.border = '1px solid #fff';
+      div.style.margin = '6px 7px';
+      div.style.padding = '4px 5px';
+      var all1 = document.querySelectorAll('div');
+      all1.contentEdge.height = new Dimension.px(200);
+      all1.contentEdge.height = 200;
+      for (Element elem in all1) {
+        expect(elem.contentEdge.height, 200);
+      }
+      all1.contentEdge.height = new Dimension.px(10);
+      for (Element elem in all1) {
+        expect(elem.contentEdge.height, 10);
+      }
+    });
+  });
+}
diff --git a/tests/lib/html/element_offset_test.dart b/tests/lib/html/element_offset_test.dart
new file mode 100644
index 0000000..21681cf
--- /dev/null
+++ b/tests/lib/html/element_offset_test.dart
@@ -0,0 +1,136 @@
+// 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:expect/minitest.dart';
+
+main() {
+  void initPage() {
+    var level1 = new UListElement()
+      ..classes.add('level-1')
+      ..children.add(new LIElement()..innerHtml = 'I');
+    var itemii = new LIElement()
+      ..classes.add('item-ii')
+      ..style.position = 'relative'
+      ..style.top = '4px'
+      ..innerHtml = 'II';
+    level1.children.add(itemii);
+    var level2 = new UListElement();
+    itemii.children.add(level2);
+    var itema = new LIElement()
+      ..classes.add('item-a')
+      ..innerHtml = 'A';
+    var item1 = new LIElement()
+      ..classes.add('item-1')
+      ..innerHtml = '1';
+    var item2 = new LIElement()
+      ..classes.add('item-2')
+      ..innerHtml = '2';
+    var level3 = new UListElement()..children.addAll([item1, item2]);
+    var itemb = new LIElement()
+      ..classes.add('item-b')
+      ..style.position = 'relative'
+      ..style.top = '20px'
+      ..style.left = '150px'
+      ..innerHtml = 'B'
+      ..children.add(level3);
+    level2.children.addAll([itema, itemb, new LIElement()..innerHtml = 'C']);
+    document.body!.append(level1);
+    document.body!.style.whiteSpace = 'nowrap';
+
+    var bar = new DivElement()..classes.add('bar');
+    var style = bar.style;
+    style
+      ..position = 'absolute'
+      ..top = '8px'
+      ..left = '90px';
+    var baz = new DivElement()..classes.add('baz');
+    style = baz.style;
+    style
+      ..position = 'absolute'
+      ..top = '600px'
+      ..left = '7000px';
+    bar.children.add(baz);
+
+    var quux = new DivElement()..classes.add('quux');
+    var qux = new DivElement()..classes.add('qux')..children.add(quux);
+
+    document.body!.append(bar);
+    document.body!.append(qux);
+  }
+
+  group('offset', () {
+    setUp(initPage);
+
+    test('offsetTo', () {
+      var itema = querySelector('.item-a')!;
+      var itemb = querySelector('.item-b')!;
+      var item1 = querySelector('.item-1')!;
+      var itemii = querySelector('.item-ii')!;
+      var level1 = querySelector('.level-1')!;
+      var baz = querySelector('.baz')!;
+      var bar = querySelector('.bar')!;
+      var qux = querySelector('.qux')!;
+      var quux = querySelector('.quux')!;
+
+      var point = itema.offsetTo(itemii);
+      expect(point.x, 40);
+      expect(point.y, inInclusiveRange(16, 20));
+
+      expect(baz.offsetTo(bar).x, 7000);
+      expect(baz.offsetTo(bar).y, inInclusiveRange(599, 604));
+
+      qux.style.position = 'fixed';
+      expect(quux.offsetTo(qux).x, 0);
+      expect(quux.offsetTo(qux).y, 0);
+
+      point = item1.offsetTo(itemb);
+      expect(point.x, 40);
+      expect(point.y, inInclusiveRange(16, 20));
+      point = itemb.offsetTo(itemii);
+      expect(point.x, 190);
+      expect(point.y, inInclusiveRange(52, 60));
+      point = item1.offsetTo(itemii);
+      expect(point.x, 230);
+      expect(point.y, inInclusiveRange(68, 80));
+    });
+
+    test('documentOffset', () {
+      var bar = querySelector('.bar')!;
+      var baz = querySelector('.baz')!;
+      var qux = querySelector('.qux')!;
+      var quux = querySelector('.quux')!;
+      var itema = querySelector('.item-a')!;
+      var itemb = querySelector('.item-b')!;
+      var item1 = querySelector('.item-1')!;
+      var itemii = querySelector('.item-ii')!;
+
+      expect(itema.documentOffset.x, 88);
+      expect(itema.documentOffset.y, inInclusiveRange(111, 160));
+
+      expect(itemii.documentOffset.x, 48);
+      expect(itemii.documentOffset.y, inInclusiveRange(95, 145));
+
+      expect(itemb.documentOffset.x, 238);
+      expect(itemb.documentOffset.y, inInclusiveRange(147, 205));
+
+      expect(item1.documentOffset.x, 278);
+      expect(item1.documentOffset.y, inInclusiveRange(163, 222));
+
+      expect(bar.documentOffset.x, 90);
+      expect(bar.documentOffset.y, 8);
+
+      expect(baz.documentOffset.x, 7090);
+      expect(baz.documentOffset.y, 608);
+
+      expect(qux.documentOffset.x, 8);
+      expect(qux.documentOffset.y, inInclusiveRange(203, 240));
+
+      expect(quux.documentOffset.x, 8);
+      expect(quux.documentOffset.y, inInclusiveRange(203, 240));
+    });
+  });
+}
diff --git a/tests/lib/html/element_test.dart b/tests/lib/html/element_test.dart
new file mode 100644
index 0000000..cff1fab
--- /dev/null
+++ b/tests/lib/html/element_test.dart
@@ -0,0 +1,998 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 ElementTest;
+
+import 'package:async_helper/async_minitest.dart';
+import 'package:expect/expect.dart';
+import 'dart:async';
+import 'dart:html';
+import 'dart:svg' as svg;
+import 'utils.dart';
+
+expectLargeRect(Rectangle rect) {
+  expect(rect.top, 0);
+  expect(rect.left, 0);
+  expect(rect.width, greaterThan(100));
+  expect(rect.height, greaterThan(100));
+  expect(rect.bottom, rect.top + rect.height);
+  expect(rect.right, rect.left + rect.width);
+}
+
+void testUnsupported(String name, void f()) {
+  test(name, () => Expect.throwsUnsupportedError(f));
+}
+
+main() {
+  var isHRElement = predicate((x) => x is HRElement, 'is a HRElement');
+  var isBRElement = predicate((x) => x is BRElement, 'is a BRElement');
+  var isInputElement =
+      predicate((x) => x is InputElement, 'is an InputElement');
+  var isImageElement =
+      predicate((x) => x is ImageElement, 'is an ImageElement');
+  var isSpanElement = predicate((x) => x is SpanElement, 'is a SpanElement');
+  var isAnchorElement =
+      predicate((x) => x is AnchorElement, 'is an AnchorElement');
+  var isElementList =
+      predicate((x) => x is List<Element>, 'is a List<Element>');
+  var isElementIterable =
+      predicate((x) => x is Iterable<Element>, 'is an Iterable<Element>');
+  var isHeadingElement =
+      predicate((x) => x is HeadingElement, 'is a HeadingElement');
+
+  Element makeElement() => new Element.tag('div');
+
+  Element makeElementWithChildren() =>
+      new Element.html("<div><br/><img/><input/></div>");
+
+  group('position', () {
+    test('computedStyle', () {
+      final element = document.body!;
+      var style = element.getComputedStyle();
+      expect(style.getPropertyValue('left'), 'auto');
+    });
+
+    test('client position synchronous', () {
+      final container = new Element.tag("div");
+      container.style.position = 'absolute';
+      container.style.top = '8px';
+      container.style.left = '9px';
+      final element = new Element.tag("div");
+      element.style.width = '200px';
+      element.style.height = '200px';
+      container.children.add(element);
+      document.body!.children.add(container);
+
+      expect(element.client.width, greaterThan(100));
+      expect(element.client.height, greaterThan(100));
+      expect(element.offset.width, greaterThan(100));
+      expect(element.offset.height, greaterThan(100));
+      expect(element.scrollWidth, greaterThan(100));
+      expect(element.scrollHeight, greaterThan(100));
+      expect(element.getBoundingClientRect().left, 9);
+      expect(element.getBoundingClientRect().top, 8);
+
+      expect(element.documentOffset.x, 9);
+      expect(element.documentOffset.y, 8);
+      container.remove();
+    });
+  });
+
+  group('constructors', () {
+    test('error', () {
+      Expect.throwsStateError(() => new Element.html('<br/><br/>'));
+    });
+
+    test('.html has no parent',
+        () => expect(new Element.html('<br/>').parent, isNull));
+
+    test('.html table', () {
+      // http://developers.whatwg.org/tabular-data.html#tabular-data
+      TableElement node = new Element.html('''
+<table>
+ <caption>Characteristics with positive and negative sides</caption>
+ <thead>
+  <tr>
+   <th id="n"> Negative
+   <th> Characteristic
+   <th> Positive
+ <tbody>
+  <tr>
+   <td headers="n r1"> Sad
+   <th id="r1"> Mood
+   <td> Happy
+  <tr>
+   <td headers="n r2"> Failing
+   <th id="r2"> Grade
+   <td> Passing
+</table>''') as TableElement;
+      expect(node.tagName, 'TABLE');
+      expect(node.parent, isNull);
+      expect(node.caption!.innerHtml,
+          'Characteristics with positive and negative sides');
+      expect(node.tHead!.rows.length, 1);
+      expect(node.tHead!.rows[0].cells.length, 3);
+      expect(node.tBodies.length, 1);
+      expect(node.tBodies[0].rows.length, 2);
+      expect(node.tBodies[0].rows[1].cells.map((c) => c.innerHtml),
+          [' Failing\n   ', ' Grade\n   ', ' Passing\n']);
+    });
+
+    test('.html caption', () {
+      var table = new TableElement();
+      TableCaptionElement node = table
+          .createFragment('<caption><p>Table 1.')
+          .nodes
+          .single as TableCaptionElement;
+      expect(node.tagName, 'CAPTION');
+      expect(node.parent, isNull);
+      expect(node.innerHtml, '<p>Table 1.</p>');
+    });
+
+    test('.html colgroup', () {
+      var table = new TableElement();
+      TableColElement node = table
+          .createFragment('<colgroup> <col> <col> <col>')
+          .nodes
+          .single as TableColElement;
+      expect(node.tagName, 'COLGROUP');
+      expect(node.parent, isNull);
+      expect(node.innerHtml, ' <col> <col> <col>');
+    });
+
+    test('.html tbody', () {
+      var innerHtml = '<tr><td headers="n r1">Sad</td><td>Happy</td></tr>';
+      var table = new TableElement();
+      TableSectionElement node = table
+          .createFragment('<tbody>$innerHtml')
+          .nodes
+          .single as TableSectionElement;
+      expect(node.tagName, 'TBODY');
+      expect(node.parent, isNull);
+      expect(node.rows.length, 1);
+      expect(node.rows[0].cells.length, 2);
+      expect(node.innerHtml, innerHtml);
+    });
+
+    test('.html thead', () {
+      var innerHtml = '<tr><th id="n">Negative</th><th>Positive</th></tr>';
+      var table = new TableElement();
+      TableSectionElement node = table
+          .createFragment('<thead>$innerHtml')
+          .nodes
+          .single as TableSectionElement;
+      expect(node.tagName, 'THEAD');
+      expect(node.parent, isNull);
+      expect(node.rows.length, 1);
+      expect(node.rows[0].cells.length, 2);
+      expect(node.innerHtml, innerHtml);
+    });
+
+    test('.html tfoot', () {
+      var innerHtml = '<tr><th>percentage</th><td>34.3%</td></tr>';
+      var table = new TableElement();
+      TableSectionElement node = table
+          .createFragment('<tfoot>$innerHtml')
+          .nodes
+          .single as TableSectionElement;
+      expect(node.tagName, 'TFOOT');
+      expect(node.parent, isNull);
+      expect(node.rows.length, 1);
+      expect(node.rows[0].cells.length, 2);
+      expect(node.innerHtml, innerHtml);
+    });
+
+    test('.html tr', () {
+      var table = new TableElement();
+      document.body!.append(table);
+      var tBody = table.createTBody();
+      TableRowElement node = tBody
+          .createFragment('<tr><td>foo<td>bar')
+          .nodes
+          .single as TableRowElement;
+      expect(node.tagName, 'TR');
+      expect(node.parent, isNull);
+      expect(node.cells.map((c) => c.innerHtml), ['foo', 'bar']);
+    });
+
+    test('.html td', () {
+      var table = new TableElement();
+      document.body!.append(table);
+      var tBody = table.createTBody();
+      var tRow = tBody.addRow();
+      TableCellElement node =
+          tRow.createFragment('<td>foobar').nodes.single as TableCellElement;
+      expect(node.tagName, 'TD');
+      expect(node.parent, isNull);
+      expect(node.innerHtml, 'foobar');
+    });
+
+    test('.html th', () {
+      var table = new TableElement();
+      document.body!.append(table);
+      var tBody = table.createTBody();
+      var tRow = tBody.addRow();
+      TableCellElement node =
+          tRow.createFragment('<th>foobar').nodes.single as TableCellElement;
+      expect(node.tagName, 'TH');
+      expect(node.parent, isNull);
+      expect(node.innerHtml, 'foobar');
+    });
+
+    test('.html can fire events', () {
+      var e = new Element.html('<button>aha</button>');
+      var gotEvent = false;
+      e.onClick.listen((_) {
+        gotEvent = true;
+      });
+      e.click();
+      expect(gotEvent, isTrue, reason: 'click should have raised click event');
+    });
+  });
+
+  group('eventListening', () {
+    test('streams', () {
+      final target = new TextAreaElement();
+
+      void testEvent(Stream stream, String type, [createEvent(String type)?]) {
+        var firedOnEvent = false;
+        stream.listen((e) {
+          firedOnEvent = true;
+        });
+        expect(firedOnEvent, isFalse);
+        var event = createEvent != null ? createEvent(type) : new Event(type);
+        target.dispatchEvent(event);
+
+        expect(firedOnEvent, isTrue);
+      }
+
+      testEvent(target.onAbort, 'abort');
+      testEvent(target.onBeforeCopy, 'beforecopy');
+      testEvent(target.onBeforeCut, 'beforecut');
+      testEvent(target.onBeforePaste, 'beforepaste');
+      testEvent(target.onBlur, 'blur');
+      testEvent(target.onChange, 'change');
+      testEvent(
+          target.onContextMenu, 'contextmenu', (type) => new MouseEvent(type));
+      // We cannot test dispatching a true ClipboardEvent as the DOM does not
+      // provide a way to create a fake ClipboardEvent.
+      testEvent(target.onCopy, 'copy');
+      testEvent(target.onCut, 'cut');
+      testEvent(target.onPaste, 'paste');
+
+      testEvent(
+          target.onDoubleClick, 'dblclick', (type) => new MouseEvent(type));
+      testEvent(target.onDrag, 'drag', (type) => new MouseEvent(type));
+      testEvent(target.onDragEnd, 'dragend', (type) => new MouseEvent(type));
+      testEvent(
+          target.onDragEnter, 'dragenter', (type) => new MouseEvent(type));
+      testEvent(
+          target.onDragLeave, 'dragleave', (type) => new MouseEvent(type));
+      testEvent(target.onDragOver, 'dragover', (type) => new MouseEvent(type));
+      testEvent(
+          target.onDragStart, 'dragstart', (type) => new MouseEvent(type));
+      testEvent(target.onDrop, 'drop', (type) => new MouseEvent(type));
+      testEvent(target.onError, 'error');
+      testEvent(target.onFocus, 'focus');
+      testEvent(target.onFullscreenChange, 'webkitfullscreenchange');
+      testEvent(target.onInput, 'input');
+      testEvent(target.onInvalid, 'invalid');
+      testEvent(target.onKeyDown, 'keydown', (type) => new KeyboardEvent(type));
+      testEvent(
+          target.onKeyPress, 'keypress', (type) => new KeyboardEvent(type));
+      testEvent(target.onKeyUp, 'keyup', (type) => new KeyboardEvent(type));
+      testEvent(target.onLoad, 'load');
+      testEvent(
+          target.onMouseDown, 'mousedown', (type) => new MouseEvent(type));
+      testEvent(
+          target.onMouseMove, 'mousemove', (type) => new MouseEvent(type));
+      testEvent(target.onMouseOut, 'mouseout', (type) => new MouseEvent(type));
+      testEvent(
+          target.onMouseOver, 'mouseover', (type) => new MouseEvent(type));
+      testEvent(target.onMouseUp, 'mouseup', (type) => new MouseEvent(type));
+      testEvent(target.onReset, 'reset');
+      testEvent(target.onScroll, 'scroll');
+      testEvent(target.onSearch, 'search');
+      testEvent(target.onSelect, 'select');
+      testEvent(target.onSelectStart, 'selectstart');
+      testEvent(target.onSubmit, 'submit');
+      // We would prefer to create new touch events for this test via
+      // new TouchEvent(null, null, null, type)
+      // but that fails on desktop browsers as touch is not enabled.
+      testEvent(target.onTouchCancel, 'touchcancel');
+      testEvent(target.onTouchEnd, 'touchend');
+      testEvent(target.onTouchLeave, 'touchleave');
+      testEvent(target.onTouchMove, 'touchmove');
+      testEvent(target.onTouchStart, 'touchstart');
+    });
+  });
+
+  group('click', () {
+    test('clickEvent', () {
+      var e = new DivElement();
+      var firedEvent = false;
+      e.onClick.listen((event) {
+        firedEvent = true;
+      });
+      expect(firedEvent, false);
+      e.click();
+      expect(firedEvent, true);
+
+      var e2 = new DivElement();
+      var firedEvent2 = false;
+      e2.onClick.matches('.foo').listen((event) {
+        firedEvent2 = true;
+      });
+      e2.click();
+      expect(firedEvent2, false);
+      e2.classes.add('foo');
+      e2.click();
+      expect(firedEvent2, true);
+    });
+  });
+
+  group('attributes', () {
+    test('manipulation', () {
+      final element = new Element.html(
+          '''<div class="foo" style="overflow: hidden" data-foo="bar"
+                   data-foo2="bar2" dir="rtl">
+               </div>''',
+          treeSanitizer: new NullTreeSanitizer());
+      final attributes = element.attributes;
+      expect(attributes['class'], 'foo');
+      startsWith(match) => predicate((x) => x is String && x.startsWith(match));
+      expect(attributes['style'], startsWith('overflow: hidden'));
+      expect(attributes['data-foo'], 'bar');
+      expect(attributes['data-foo2'], 'bar2');
+      expect(attributes.length, 5);
+      expect(element.dataset.length, 2);
+      element.dataset['foo'] = 'baz';
+      expect(element.dataset['foo'], 'baz');
+      expect(attributes['data-foo'], 'baz');
+      attributes['data-foo2'] = 'baz2';
+      expect(attributes['data-foo2'], 'baz2');
+      expect(element.dataset['foo2'], 'baz2');
+      expect(attributes['dir'], 'rtl');
+
+      final dataset = element.dataset;
+      dataset.remove('foo2');
+      expect(attributes.length, 4);
+      expect(dataset.length, 1);
+      attributes.remove('style');
+      expect(attributes.length, 3);
+      dataset['foo3'] = 'baz3';
+      expect(dataset.length, 2);
+      expect(attributes.length, 4);
+      attributes['style'] = 'width: 300px;';
+      expect(attributes.length, 5);
+    });
+
+    test('namespaces', () {
+      var element =
+          new svg.SvgElement.svg('''<svg xmlns="http://www.w3.org/2000/svg"
+                  xmlns:xlink="http://www.w3.org/1999/xlink">
+            <image xlink:href="foo" data-foo="bar"/>
+          </svg>''').children[0];
+
+      var attributes = element.attributes;
+      expect(attributes.length, 1);
+      expect(attributes['data-foo'], 'bar');
+
+      var xlinkAttrs =
+          element.getNamespacedAttributes('http://www.w3.org/1999/xlink');
+      expect(xlinkAttrs.length, 1);
+      expect(xlinkAttrs['href'], 'foo');
+
+      xlinkAttrs.remove('href');
+      expect(xlinkAttrs.length, 0);
+
+      xlinkAttrs['href'] = 'bar';
+      expect(xlinkAttrs['href'], 'bar');
+
+      var randomAttrs = element.getNamespacedAttributes('http://example.com');
+      expect(randomAttrs.length, 0);
+      randomAttrs['href'] = 'bar';
+      expect(randomAttrs.length, 1);
+    });
+  });
+
+  group('children', () {
+    test('is a subset of nodes', () {
+      var el = new Element.html("<div>Foo<br/><img/></div>");
+      expect(el.nodes.length, 3);
+      expect(el.children.length, 2);
+      expect(el.nodes[1], el.children[0]);
+      expect(el.nodes[2], el.children[1]);
+    });
+
+    test('changes when an element is added to nodes', () {
+      var el = new Element.html("<div>Foo<br/><img/></div>");
+      el.nodes.add(new Element.tag('hr'));
+      expect(el.children.length, 3);
+      expect(el.children[2], isHRElement);
+      expect(el.nodes[3], el.children[2]);
+    });
+
+    test('changes nodes when an element is added', () {
+      var el = new Element.html("<div>Foo<br/><img/></div>");
+      el.children.add(new Element.tag('hr'));
+      expect(el.nodes.length, 4);
+      expect(el.nodes[3], isHRElement);
+      expect(el.children[2], el.nodes[3]);
+    });
+
+    test('last', () {
+      var el = makeElementWithChildren();
+      expect(el.children.last, isInputElement);
+    });
+
+    test('forEach', () {
+      var els = [];
+      var el = makeElementWithChildren();
+      el.children.forEach((n) => els.add(n));
+      expect(els[0], isBRElement);
+      expect(els[1], isImageElement);
+      expect(els[2], isInputElement);
+    });
+
+    test('where', () {
+      var filtered =
+          makeElementWithChildren().children.where((n) => n is ImageElement);
+      expect(1, filtered.length);
+      expect(filtered.first, isImageElement);
+      expect(filtered, isElementIterable);
+    });
+
+    test('every', () {
+      var el = makeElementWithChildren();
+      expect(el.children.every((n) => n is Element), isTrue);
+      expect(el.children.every((n) => n is InputElement), isFalse);
+    });
+
+    test('any', () {
+      var el = makeElementWithChildren();
+      expect(el.children.any((n) => n is InputElement), isTrue);
+      expect(el.children.any((n) => n is svg.SvgElement), isFalse);
+    });
+
+    test('isEmpty', () {
+      expect(makeElement().children.isEmpty, isTrue);
+      expect(makeElementWithChildren().children.isEmpty, isFalse);
+    });
+
+    test('length', () {
+      expect(makeElement().children.length, 0);
+      expect(makeElementWithChildren().children.length, 3);
+    });
+
+    test('[]', () {
+      var el = makeElementWithChildren();
+      expect(el.children[0], isBRElement);
+      expect(el.children[1], isImageElement);
+      expect(el.children[2], isInputElement);
+    });
+
+    test('[]=', () {
+      var el = makeElementWithChildren();
+      el.children[1] = new Element.tag('hr');
+      expect(el.children[0], isBRElement);
+      expect(el.children[1], isHRElement);
+      expect(el.children[2], isInputElement);
+    });
+
+    test('add', () {
+      var el = makeElement();
+      el.children.add(new Element.tag('hr'));
+      expect(el.children.last, isHRElement);
+    });
+
+    test('iterator', () {
+      var els = [];
+      var el = makeElementWithChildren();
+      for (var subel in el.children) {
+        els.add(subel);
+      }
+      expect(els[0], isBRElement);
+      expect(els[1], isImageElement);
+      expect(els[2], isInputElement);
+    });
+
+    test('addAll', () {
+      var el = makeElementWithChildren();
+      el.children.addAll([
+        new Element.tag('span'),
+        new Element.tag('a'),
+        new Element.tag('h1')
+      ]);
+      expect(el.children[0], isBRElement);
+      expect(el.children[1], isImageElement);
+      expect(el.children[2], isInputElement);
+      expect(el.children[3], isSpanElement);
+      expect(el.children[4], isAnchorElement);
+      expect(el.children[5], isHeadingElement);
+    });
+
+    test('insert', () {
+      var element = new DivElement();
+      element.children.insert(0, new BRElement());
+      expect(element.children[0], isBRElement);
+      element.children.insert(0, new HRElement());
+      expect(element.children[0], isHRElement);
+      element.children.insert(1, new ImageElement());
+      expect(element.children[1], isImageElement);
+      element.children.insert(element.children.length, new InputElement());
+      expect(element.children.last, isInputElement);
+    });
+
+    test('clear', () {
+      var el = makeElementWithChildren();
+      el.children.clear();
+      expect(el.children, equals([]));
+    });
+
+    test('removeLast', () {
+      var el = makeElementWithChildren();
+      expect(el.children.removeLast(), isInputElement);
+      expect(el.children.length, 2);
+      expect(el.children.removeLast(), isImageElement);
+      expect(el.children.length, 1);
+    });
+
+    test('sublist', () {
+      var el = makeElementWithChildren();
+      expect(el.children.sublist(1, 2), isElementList);
+    });
+
+    test('getRange', () {
+      var el = makeElementWithChildren();
+      expect(el.children.getRange(1, 2).length, 1);
+    });
+
+    test('retainWhere', () {
+      var el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => true);
+      expect(el.children.length, 3);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => false);
+      expect(el.children.length, 0);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => e.localName == 'input');
+      expect(el.children.length, 1);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => e.localName == 'br');
+      expect(el.children.length, 1);
+    });
+
+    test('removeWhere', () {
+      var el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => true);
+      expect(el.children.length, 0);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => false);
+      expect(el.children.length, 3);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => e.localName == 'input');
+      expect(el.children.length, 2);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => e.localName == 'br');
+      expect(el.children.length, 2);
+    });
+
+    testUnsupported('sort', () {
+      var l = makeElementWithChildren().children;
+      l.sort();
+    });
+
+    testUnsupported('setRange', () {
+      var l = makeElementWithChildren().children;
+      l.setRange(0, 0, []);
+    });
+
+    testUnsupported('replaceRange', () {
+      var l = makeElementWithChildren().children;
+      l.replaceRange(0, 0, []);
+    });
+
+    testUnsupported('removeRange', () {
+      var l = makeElementWithChildren().children;
+      l.removeRange(0, 1);
+    });
+
+    testUnsupported('insertAll', () {
+      var l = makeElementWithChildren().children;
+      l.insertAll(0, []);
+    });
+  });
+
+  group('matches', () {
+    test('matches', () {
+      var element = new DivElement();
+      document.body!.append(element);
+      element.classes.add('test');
+
+      expect(element.matches('div'), true);
+      expect(element.matches('span'), false);
+      expect(element.matches('.test'), true);
+    });
+  });
+
+  group('querySelectorAll', () {
+    List<Element> getQuerySelectorAll() {
+      return new Element.html("""
+<div>
+  <hr/>
+  <a class='q' href='http://dartlang.org'>Dart!</a>
+  <p>
+    <span class='q'>Hello</span>,
+    <em>world</em>!
+  </p>
+  <hr class='q'/>
+</div>
+""").querySelectorAll('.q');
+    }
+
+    List<Element> getEmptyQuerySelectorAll() =>
+        new Element.tag('div').querySelectorAll('img');
+
+    test('last', () {
+      expect(getQuerySelectorAll().last, isHRElement);
+    });
+
+    test('forEach', () {
+      var els = [];
+      getQuerySelectorAll().forEach((el) => els.add(el));
+      expect(els[0], isAnchorElement);
+      expect(els[1], isSpanElement);
+      expect(els[2], isHRElement);
+    });
+
+    test('map', () {
+      var texts = getQuerySelectorAll().map((el) => el.text).toList();
+      expect(texts, equals(['Dart!', 'Hello', '']));
+    });
+
+    test('where', () {
+      var filtered =
+          getQuerySelectorAll().where((n) => n is SpanElement).toList();
+      expect(filtered.length, 1);
+      expect(filtered[0], isSpanElement);
+      expect(filtered, isElementList);
+    });
+
+    test('every', () {
+      var el = getQuerySelectorAll();
+      expect(el.every((n) => n is Element), isTrue);
+      expect(el.every((n) => n is SpanElement), isFalse);
+    });
+
+    test('any', () {
+      var el = getQuerySelectorAll();
+      expect(el.any((n) => n is SpanElement), isTrue);
+      expect(el.any((n) => n is svg.SvgElement), isFalse);
+    });
+
+    test('isEmpty', () {
+      expect(getEmptyQuerySelectorAll().isEmpty, isTrue);
+      expect(getQuerySelectorAll().isEmpty, isFalse);
+    });
+
+    test('length', () {
+      expect(getEmptyQuerySelectorAll().length, 0);
+      expect(getQuerySelectorAll().length, 3);
+    });
+
+    test('[]', () {
+      var els = getQuerySelectorAll();
+      expect(els[0], isAnchorElement);
+      expect(els[1], isSpanElement);
+      expect(els[2], isHRElement);
+    });
+
+    test('iterator', () {
+      var els = [];
+      for (var subel in getQuerySelectorAll()) {
+        els.add(subel);
+      }
+      expect(els[0], isAnchorElement);
+      expect(els[1], isSpanElement);
+      expect(els[2], isHRElement);
+    });
+
+    test('sublist', () {
+      expect(getQuerySelectorAll().sublist(1, 2) is List<Element>, isTrue);
+    });
+
+    testUnsupported(
+        '[]=', () => getQuerySelectorAll()[1] = new Element.tag('br'));
+    testUnsupported(
+        'add', () => getQuerySelectorAll().add(new Element.tag('br')));
+
+    testUnsupported('addAll', () {
+      getQuerySelectorAll().addAll([
+        new Element.tag('span'),
+        new Element.tag('a'),
+        new Element.tag('h1')
+      ]);
+    });
+
+    testUnsupported('sort', () => getQuerySelectorAll().sort((a1, a2) => 0));
+
+    testUnsupported('setRange', () {
+      getQuerySelectorAll().setRange(0, 1, [new BRElement()]);
+    });
+
+    testUnsupported(
+        'removeRange', () => getQuerySelectorAll().removeRange(0, 1));
+
+    testUnsupported('clear', () => getQuerySelectorAll().clear());
+
+    testUnsupported('removeLast', () => getQuerySelectorAll().removeLast());
+  });
+
+  group('functional', () {
+    test('toString', () {
+      final elems = makeElementWithChildren().children;
+      expect(elems.toString(), "[br, img, input]");
+      final elem = makeElement().children;
+      expect(elem.toString(), '[]');
+    });
+
+    test('scrollIntoView', () {
+      var child = new DivElement();
+      document.body!.append(child);
+
+      child.scrollIntoView(ScrollAlignment.TOP);
+      child.scrollIntoView(ScrollAlignment.BOTTOM);
+      child.scrollIntoView(ScrollAlignment.CENTER);
+      child.scrollIntoView();
+    });
+  });
+
+  group('_ElementList', () {
+    List<Element> makeElList() => makeElementWithChildren().children;
+
+    test('where', () {
+      var filtered = makeElList().where((n) => n is ImageElement);
+      expect(filtered.length, 1);
+      expect(filtered.first, isImageElement);
+      expect(filtered, isElementIterable);
+    });
+
+    test('sublist', () {
+      var range = makeElList().sublist(1, 3);
+      expect(range, isElementList);
+      expect(range[0], isImageElement);
+      expect(range[1], isInputElement);
+    });
+  });
+
+  group('eventDelegation', () {
+    test('matches', () {
+      Element clickOne = new Element.a();
+      Element selectorOne = new Element.div()
+        ..classes.add('selector')
+        ..children.add(clickOne);
+
+      Element clickTwo = new Element.a();
+      Element selectorTwo = new Element.div()
+        ..classes.add('selector')
+        ..children.add(clickTwo);
+      document.body!.append(selectorOne);
+      document.body!.append(selectorTwo);
+
+      document.body!.onClick
+          .matches('.selector')
+          .listen(expectAsync1((Event event) {
+        expect(event.currentTarget, document.body);
+        expect(event.target, clickOne);
+        expect(event.matchingTarget, selectorOne);
+      }));
+
+      selectorOne.onClick
+          .matches('.selector')
+          .listen(expectAsync1((Event event) {
+        expect(event.currentTarget, selectorOne);
+        expect(event.target, clickOne);
+        expect(event.matchingTarget, selectorOne);
+      }));
+      clickOne.click();
+
+      Element elem = new Element.div()..classes.addAll(['a', 'b']);
+      Element img = new Element.img()
+        ..classes.addAll(['b', 'a', 'd'])
+        ..id = 'cookie';
+      Element input = new InputElement()..classes.addAll(['c', 'd']);
+      var div = new Element.div()
+        ..classes.add('a')
+        ..id = 'wat';
+      document.body!.append(elem);
+      document.body!.append(img);
+      document.body!.append(input);
+      document.body!.append(div);
+
+      Element elem4 = new Element.div()..classes.addAll(['i', 'j']);
+      Element elem5 = new Element.div()
+        ..classes.addAll(['g', 'h'])
+        ..children.add(elem4);
+      Element elem6 = new Element.div()
+        ..classes.addAll(['e', 'f'])
+        ..children.add(elem5);
+      document.body!.append(elem6);
+
+      var firedEvent = false;
+      var elems = querySelectorAll('.a');
+      querySelectorAll('.a').onClick.listen((event) {
+        firedEvent = true;
+      });
+      expect(firedEvent, false);
+      querySelector('.c')!.click();
+      expect(firedEvent, false);
+      querySelector('#wat')!.click();
+      expect(firedEvent, true);
+
+      var firedEvent4 = false;
+      querySelectorAll('.a').onClick.matches('.d').listen((event) {
+        firedEvent4 = true;
+      });
+      expect(firedEvent4, false);
+      querySelector('.c')!.click();
+      expect(firedEvent4, false);
+      querySelector('#wat')!.click();
+      expect(firedEvent4, false);
+      querySelector('#cookie')!.click();
+      expect(firedEvent4, true);
+
+      var firedEvent2 = false;
+      querySelectorAll('.a').onClick.listen((event) {
+        firedEvent2 = true;
+      });
+      Element elem2 = new Element.html('<div class="a"><br/>');
+      document.body!.append(elem2);
+      elem2.click();
+      expect(firedEvent2, false);
+      elem2.classes.add('a');
+      elem2.click();
+      expect(firedEvent2, false);
+
+      var firedEvent3 = false;
+      querySelectorAll(':root').onClick.matches('.a').listen((event) {
+        firedEvent3 = true;
+      });
+      Element elem3 = new Element.html('<div class="d"><br/>');
+      document.body!.append(elem3);
+      elem3.click();
+      expect(firedEvent3, false);
+      elem3.classes.add('a');
+      elem3.click();
+      expect(firedEvent3, true);
+
+      var firedEvent5 = false;
+      querySelectorAll(':root').onClick.matches('.e').listen((event) {
+        firedEvent5 = true;
+      });
+      expect(firedEvent5, false);
+      querySelector('.i')!.click();
+      expect(firedEvent5, true);
+    });
+
+    test('event ordering', () {
+      var a = new DivElement();
+      var b = new DivElement();
+      a.append(b);
+      var c = new DivElement();
+      b.append(c);
+
+      var eventOrder = [];
+
+      ElementStream aEvent = a.on['custom_event'] as ElementStream;
+      aEvent.listen((_) {
+        eventOrder.add('a no-capture');
+      });
+
+      aEvent.capture((_) {
+        eventOrder.add('a capture');
+      });
+
+      ElementStream bEvent = b.on['custom_event'] as ElementStream;
+      bEvent.listen((_) {
+        eventOrder.add('b no-capture');
+      });
+
+      bEvent.capture((_) {
+        eventOrder.add('b capture');
+      });
+
+      document.body!.append(a);
+
+      var event = new Event('custom_event', canBubble: true);
+      c.dispatchEvent(event);
+      expect(eventOrder,
+          ['a capture', 'b capture', 'b no-capture', 'a no-capture']);
+    });
+  });
+
+  group('ElementList', () {
+    // Tests for methods on the DOM class 'NodeList'.
+    //
+    // There are two interesting things that are validated here from the
+    // viewpoint of the dart2js implementation of a 'native' class:
+    //
+    //   1. Some methods are implemented from by 'Object' or 'Interceptor';
+    //      some of these tests validate that a method can be called.
+    //   2. Some methods are implemented by mixins.
+
+    ElementList<Element> makeElementList() =>
+        (new Element.html("<div>Foo<br/><!--baz--><br/><br/></div>"))
+            .querySelectorAll('br');
+
+    test('hashCode', () {
+      var nodes = makeElementList();
+      var hash = nodes.hashCode;
+      final int N = 1000;
+      int matchCount = 0;
+      for (int i = 0; i < N; i++) {
+        if (makeElementList().hashCode == hash) matchCount++;
+      }
+      expect(matchCount, lessThan(N));
+    });
+
+    test('operator==', () {
+      var a = [makeElementList(), makeElementList(), null];
+      for (int i = 0; i < a.length; i++) {
+        for (int j = 0; j < a.length; j++) {
+          expect(i == j, a[i] == a[j]);
+        }
+      }
+    });
+
+    test('runtimeType', () {
+      var nodes1 = makeElementList();
+      var nodes2 = makeElementList();
+      var type1 = nodes1.runtimeType;
+      var type2 = nodes2.runtimeType;
+      expect(type1 == type2, true);
+      String name = '$type1';
+      if (name.length > 3) {
+        expect(name.contains('ElementList'), true);
+      }
+    });
+
+    test('first', () {
+      var nodes = makeElementList();
+      expect(nodes.first, isBRElement);
+    });
+
+    test('last', () {
+      var nodes = makeElementList();
+      expect(nodes.last, isBRElement);
+    });
+
+    test('where', () {
+      var filtered = makeElementList().where((n) => n is BRElement).toList();
+      expect(filtered.length, 3);
+      expect(filtered[0], isBRElement);
+    });
+
+    test('sublist', () {
+      var range = makeElementList().sublist(1, 3);
+      expect(range.length, 2);
+      expect(range[0], isBRElement);
+      expect(range[1], isBRElement);
+    });
+  });
+}
diff --git a/tests/lib/html/element_types_constructors1_test.dart b/tests/lib/html/element_types_constructors1_test.dart
new file mode 100644
index 0000000..9c5575d
--- /dev/null
+++ b/tests/lib/html/element_types_constructors1_test.dart
@@ -0,0 +1,42 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  check(String name, bool fn(), [bool supported = true]) {
+    test(name, () {
+      if (supported) {
+        expect(fn(), isTrue);
+      } else {
+        // Can either throw or return false.
+        expect(() => (fn() || (throw "false")), throws);
+      }
+    });
+  }
+
+  group('constructors', () {
+    check('a', () => new AnchorElement() is AnchorElement);
+    check('area', () => new AreaElement() is AreaElement);
+    check('audio', () => new AudioElement() is AudioElement);
+    check('body', () => new BodyElement() is BodyElement);
+    check('br', () => new BRElement() is BRElement);
+    check('base', () => new BaseElement() is BaseElement);
+    check('button', () => new ButtonElement() is ButtonElement);
+    check('canvas', () => new CanvasElement() is CanvasElement);
+    check('caption', () => new TableCaptionElement() is TableCaptionElement);
+    check('content', () => new ContentElement() is ContentElement,
+        ContentElement.supported);
+    check('details', () => new DetailsElement() is DetailsElement,
+        DetailsElement.supported);
+    check('datalist', () => new DataListElement() is DataListElement,
+        DataListElement.supported);
+    check('dl', () => new DListElement() is DListElement);
+    check('div', () => new DivElement() is DivElement);
+    check('embed', () => new EmbedElement() is EmbedElement,
+        EmbedElement.supported);
+  });
+}
diff --git a/tests/lib/html/element_types_constructors2_test.dart b/tests/lib/html/element_types_constructors2_test.dart
new file mode 100644
index 0000000..d1376b0
--- /dev/null
+++ b/tests/lib/html/element_types_constructors2_test.dart
@@ -0,0 +1,37 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  check(String name, bool fn(), [bool supported = true]) {
+    test(name, () {
+      if (supported) {
+        expect(fn(), supported);
+      } else {
+        // Can either throw or return false.
+        expect(() => (fn() || (throw "false")), throws);
+      }
+    });
+  }
+
+  group('constructors', () {
+    check('fieldset', () => new FieldSetElement() is FieldSetElement);
+    check('form', () => new FormElement() is FormElement);
+    check('head', () => new HeadElement() is HeadElement);
+    check('hr', () => new HRElement() is HRElement);
+    check('html', () => new HtmlHtmlElement() is HtmlHtmlElement);
+    check('h1', () => new HeadingElement.h1() is HeadingElement);
+    check('h2', () => new HeadingElement.h2() is HeadingElement);
+    check('h3', () => new HeadingElement.h3() is HeadingElement);
+    check('h4', () => new HeadingElement.h4() is HeadingElement);
+    check('h5', () => new HeadingElement.h5() is HeadingElement);
+    check('h6', () => new HeadingElement.h6() is HeadingElement);
+    check('iframe', () => new IFrameElement() is IFrameElement);
+    check('img', () => new ImageElement() is ImageElement);
+    check('input', () => new InputElement() is InputElement);
+  });
+}
diff --git a/tests/lib/html/element_types_constructors3_test.dart b/tests/lib/html/element_types_constructors3_test.dart
new file mode 100644
index 0000000..dcd5dbd
--- /dev/null
+++ b/tests/lib/html/element_types_constructors3_test.dart
@@ -0,0 +1,41 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  check(String name, bool fn(), [bool supported = true]) {
+    test(name, () {
+      if (supported) {
+        expect(fn(), isTrue);
+      } else {
+        // Can either throw or return false.
+        expect(() => (fn() || (throw "false")), throws);
+      }
+    });
+  }
+
+  group('constructors', () {
+    check('li', () => new LIElement() is LIElement);
+    check('label', () => new LabelElement() is LabelElement);
+    check('legen', () => new LegendElement() is LegendElement);
+    check('link', () => new LinkElement() is LinkElement);
+    check('map', () => new MapElement() is MapElement);
+    check('menu', () => new MenuElement() is MenuElement);
+    check('meta', () => new MetaElement() is MetaElement);
+    check('meter', () => new MeterElement() is MeterElement,
+        MeterElement.supported);
+    check('del', () => new Element.tag('del') is ModElement);
+    check('ins', () => new Element.tag('ins') is ModElement);
+    check('object', () => new ObjectElement() is ObjectElement,
+        ObjectElement.supported);
+    check('ol', () => new OListElement() is OListElement);
+    check('optgroup', () => new OptGroupElement() is OptGroupElement);
+    check('option', () => new OptionElement() is OptionElement);
+    check('output', () => new OutputElement() is OutputElement,
+        OutputElement.supported);
+  });
+}
diff --git a/tests/lib/html/element_types_constructors4_test.dart b/tests/lib/html/element_types_constructors4_test.dart
new file mode 100644
index 0000000..26e6acb
--- /dev/null
+++ b/tests/lib/html/element_types_constructors4_test.dart
@@ -0,0 +1,36 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  check(String name, bool fn(), [bool supported = true]) {
+    test(name, () {
+      if (supported) {
+        expect(fn(), isTrue);
+      } else {
+        // Can either throw or return false.
+        expect(() => (fn() || (throw "false")), throws);
+      }
+    });
+  }
+
+  group('constructors', () {
+    check('p', () => new ParagraphElement() is ParagraphElement);
+    check('param', () => new ParamElement() is ParamElement);
+    check('pre', () => new PreElement() is PreElement);
+    check('progress', () => new ProgressElement() is ProgressElement,
+        ProgressElement.supported);
+    check('q', () => new QuoteElement() is QuoteElement);
+    check('script', () => new ScriptElement() is ScriptElement);
+    check('select', () => new SelectElement() is SelectElement);
+    check('shadow', () => new ShadowElement() is ShadowElement,
+        ShadowElement.supported);
+    check('source', () => new SourceElement() is SourceElement);
+    check('span', () => new SpanElement() is SpanElement);
+    check('style', () => new StyleElement() is StyleElement);
+  });
+}
diff --git a/tests/lib/html/element_types_constructors5_test.dart b/tests/lib/html/element_types_constructors5_test.dart
new file mode 100644
index 0000000..7039442
--- /dev/null
+++ b/tests/lib/html/element_types_constructors5_test.dart
@@ -0,0 +1,37 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  check(String name, bool fn(), [bool supported = true]) {
+    test(name, () {
+      if (supported) {
+        expect(fn(), isTrue);
+      } else {
+        // Can either throw or return false.
+        expect(() => (fn() || (throw "false")), throws);
+      }
+    });
+  }
+
+  group('constructors', () {
+    check('table', () => new TableElement() is TableElement);
+    check('template', () => new TemplateElement() is TemplateElement,
+        TemplateElement.supported);
+    check('textarea', () => new TextAreaElement() is TextAreaElement);
+    check('title', () => new TitleElement() is TitleElement);
+    check('td', () => new TableCellElement() is TableCellElement);
+    check('col', () => new TableColElement() is TableColElement);
+    check('colgroup', () => new Element.tag('colgroup') is TableColElement);
+    check('tr', () => new TableRowElement() is TableRowElement);
+    check('tbody', () => new Element.tag('tbody') is TableSectionElement);
+    check('tfoot', () => new Element.tag('tfoot') is TableSectionElement);
+    check('thead', () => new Element.tag('thead') is TableSectionElement);
+    check('track', () => new TrackElement() is TrackElement,
+        TrackElement.supported);
+  });
+}
diff --git a/tests/lib/html/element_types_constructors6_test.dart b/tests/lib/html/element_types_constructors6_test.dart
new file mode 100644
index 0000000..50b81c2
--- /dev/null
+++ b/tests/lib/html/element_types_constructors6_test.dart
@@ -0,0 +1,34 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  check(String name, bool fn(), [bool supported = true]) {
+    test(name, () {
+      if (supported) {
+        expect(fn(), isTrue);
+      } else {
+        // Can either throw or return false.
+        expect(() => (fn() || (throw "false")), throws);
+      }
+    });
+  }
+
+  group('ul', () {
+    check('ul', () => new UListElement() is UListElement);
+
+    test('accepts li', () {
+      var ul = new UListElement();
+      var li = new LIElement();
+      ul.append(li);
+    });
+  });
+  group('constructors', () {
+    check('video', () => new VideoElement() is VideoElement);
+    check('unknown', () => new Element.tag('someunknown') is UnknownElement);
+  });
+}
diff --git a/tests/lib/html/element_types_content_test.dart b/tests/lib/html/element_types_content_test.dart
new file mode 100644
index 0000000..2e0109f
--- /dev/null
+++ b/tests/lib/html/element_types_content_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('content_supported', () {
+    expect(ContentElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_datalist_test.dart b/tests/lib/html/element_types_datalist_test.dart
new file mode 100644
index 0000000..a12acc5
--- /dev/null
+++ b/tests/lib/html/element_types_datalist_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('datalist_supported', () {
+    expect(DataListElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_details_test.dart b/tests/lib/html/element_types_details_test.dart
new file mode 100644
index 0000000..b47f998
--- /dev/null
+++ b/tests/lib/html/element_types_details_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('details_supported', () {
+    expect(DetailsElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_embed_test.dart b/tests/lib/html/element_types_embed_test.dart
new file mode 100644
index 0000000..7c23d38
--- /dev/null
+++ b/tests/lib/html/element_types_embed_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('embed_supported', () {
+    expect(EmbedElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_meter_test.dart b/tests/lib/html/element_types_meter_test.dart
new file mode 100644
index 0000000..cdd917e
--- /dev/null
+++ b/tests/lib/html/element_types_meter_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('meter_supported', () {
+    expect(MeterElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_object_test.dart b/tests/lib/html/element_types_object_test.dart
new file mode 100644
index 0000000..03f508c
--- /dev/null
+++ b/tests/lib/html/element_types_object_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('object_supported', () {
+    expect(ObjectElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_output_test.dart b/tests/lib/html/element_types_output_test.dart
new file mode 100644
index 0000000..8781aa3
--- /dev/null
+++ b/tests/lib/html/element_types_output_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('output_supported', () {
+    expect(OutputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_progress_test.dart b/tests/lib/html/element_types_progress_test.dart
new file mode 100644
index 0000000..9dac474
--- /dev/null
+++ b/tests/lib/html/element_types_progress_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('progress_supported', () {
+    expect(ProgressElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_shadow_test.dart b/tests/lib/html/element_types_shadow_test.dart
new file mode 100644
index 0000000..271c49d
--- /dev/null
+++ b/tests/lib/html/element_types_shadow_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('shadow_supported', () {
+    expect(ShadowElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_template_test.dart b/tests/lib/html/element_types_template_test.dart
new file mode 100644
index 0000000..d7939ab
--- /dev/null
+++ b/tests/lib/html/element_types_template_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('template_supported', () {
+    expect(TemplateElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/element_types_track_test.dart b/tests/lib/html/element_types_track_test.dart
new file mode 100644
index 0000000..27c65d1
--- /dev/null
+++ b/tests/lib/html/element_types_track_test.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('track_supported', () {
+    expect(TrackElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/event_callback_test.dart b/tests/lib/html/event_callback_test.dart
new file mode 100644
index 0000000..347e754
--- /dev/null
+++ b/tests/lib/html/event_callback_test.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// Regression test for issue 33627.
+
+import 'dart:html';
+import 'package:expect/expect.dart';
+
+void main() {
+  try {
+    print('InputElement');
+    var i = new InputElement();
+    print('> onKeyPress');
+    i.onKeyPress.listen(onEvent);
+    print('> onClick');
+    i.onClick.listen(onEvent);
+    print('TextAreaElement');
+    var e = new TextAreaElement();
+    print('> onKeyPress');
+    e.onKeyPress.listen(onEvent);
+    print('> onClick');
+    e.onClick.listen(onEvent);
+    print('Done!');
+  } catch (e, s) {
+    print('$e\n$s');
+    Expect.fail("Unexpected exception: $e");
+  }
+}
+
+void onEvent(Event e) {
+  print(e);
+}
diff --git a/tests/lib/html/event_customevent_test.dart b/tests/lib/html/event_customevent_test.dart
new file mode 100644
index 0000000..f109a39
--- /dev/null
+++ b/tests/lib/html/event_customevent_test.dart
@@ -0,0 +1,83 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library EventCustomEventTest;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+import 'dart:js' as js;
+
+class DartPayloadData {
+  final dartValue;
+
+  DartPayloadData(this.dartValue);
+}
+
+main() {
+  test('custom events', () {
+    var provider = new EventStreamProvider<CustomEvent>('foo');
+    var el = new DivElement();
+
+    var fired = false;
+    provider.forTarget(el).listen((ev) {
+      fired = true;
+      expect(ev.detail, {'type': 'detail'});
+    });
+
+    var ev = new CustomEvent('foo',
+        canBubble: false, cancelable: false, detail: {'type': 'detail'});
+    el.dispatchEvent(ev);
+    expect(fired, isTrue);
+  });
+
+  test('custom events from JS', () {
+    var scriptContents = '''
+      var event = document.createEvent("CustomEvent");
+      event.initCustomEvent("js_custom_event", true, true, {type: "detail"});
+      window.dispatchEvent(event);
+    ''';
+
+    var fired = false;
+    window.on['js_custom_event'].listen((ev) {
+      fired = true;
+      expect((ev as CustomEvent).detail, {'type': 'detail'});
+    });
+
+    var script = new ScriptElement();
+    script.text = scriptContents;
+    document.body!.append(script);
+
+    expect(fired, isTrue);
+  });
+
+  test('custom events to JS', () {
+    expect(js.context['gotDartEvent'], isNull);
+    var scriptContents = '''
+      window.addEventListener('dart_custom_event', function(e) {
+        if (e.detail == 'dart_message') {
+          e.preventDefault();
+          window.gotDartEvent = true;
+        }
+        window.console.log('here' + e.detail);
+      }, false);''';
+
+    document.body!.append(new ScriptElement()..text = scriptContents);
+
+    var event = new CustomEvent('dart_custom_event', detail: 'dart_message');
+    window.dispatchEvent(event);
+    expect(js.context['gotDartEvent'], isTrue);
+  });
+
+  test('custom data to Dart', () {
+    var data = new DartPayloadData(666);
+    var event = new CustomEvent('dart_custom_data_event', detail: data);
+
+    var future = window.on['dart_custom_data_event'].first.then((_) {
+      expect(event.detail.dartValue, 666);
+    });
+
+    document.body!.dispatchEvent(event);
+    return future;
+  });
+}
diff --git a/tests/lib/html/event_test.dart b/tests/lib/html/event_test.dart
new file mode 100644
index 0000000..8735137
--- /dev/null
+++ b/tests/lib/html/event_test.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+eventTest(String name, Event eventFn(), void validate(Event),
+    [String type = 'foo']) {
+  test(name, () {
+    final el = new Element.tag('div');
+    var fired = false;
+    el.on[type].listen((ev) {
+      fired = true;
+      validate(ev);
+    });
+    el.dispatchEvent(eventFn());
+    expect(fired, isTrue, reason: 'Expected event to be dispatched.');
+  });
+}
+
+main() {
+  // Issue 1005.
+  // eventTest('AnimationEvent', () => new AnimationEvent('foo', 'color', 0.5),
+  //     (ev) {
+  //   expect(ev.animationName, 'color');
+  //   expect(ev.elapsedTime, 0.5);
+  // });
+
+  // Issue 1005.
+  // eventTest('BeforeLoadEvent',
+  //    () => new BeforeLoadEvent('foo', 'http://example.url'),
+  //    (ev) { expect(ev.url, 'http://example.url'); });
+
+  // Issue 1005.
+  // eventTest('CloseEvent',
+  //     () => new CloseEvent('foo', 5, 'reason', wasClean: true),
+  //     (ev) {
+  //   expect(ev.code, 5);
+  //   expect(ev.reason, 'reason');
+  //   expect(ev.wasClean, isTrue);
+  // });
+
+  eventTest(
+      'CompositionEvent',
+      () =>
+          new CompositionEvent('compositionstart', view: window, data: 'data'),
+      (ev) {
+    expect(ev.data, 'data');
+  }, 'compositionstart');
+
+  // initCustomEvent is not yet implemented
+  // eventTest('CustomEvent',
+  //     () => new CustomEvent('foo', false, false, 'detail'),
+  //     (ev) { expect(ev.detail, 'detail'); });
+
+  // DeviceMotionEvent has no properties to itself, so just test that it doesn't
+  // error out on creation and can be dispatched.
+  // Suppress. DeviceMotion has no constructor, and I don't think it can be
+  // created on a non-mobile device. Issue 23321
+  // eventTest('DeviceMotionEvent', () => new DeviceMotionEvent('foo'), (ev) {});
+
+  // initDeviceOrientationEvent is not yet implemented
+  // eventTest('DeviceOrientationEvent',
+  //     () => new DeviceOrientationEvent('foo', 0.1, 0.2, 0.3),
+  //     (ev) {
+  //   expect(ev.alpha, 0.1);
+  //   expect(ev.beta, 0.2);
+  //   expect(ev.gamma, 0.3);
+  // });
+
+  // Issue 1005.
+  // eventTest('ErrorEvent',
+  //     () => new ErrorEvent('foo', 'message', 'filename', 10),
+  //     (ev) {
+  //   expect('message', ev.message);
+  //   expect('filename', ev.filename);
+  //   expect(ev.lineno, 10);
+  // });
+
+  eventTest(
+      'Event', () => new Event('foo', canBubble: false, cancelable: false),
+      (ev) {
+    expect(ev.type, equals('foo'));
+    expect(ev.bubbles, isFalse);
+    expect(ev.cancelable, isFalse);
+  });
+
+  eventTest(
+      'HashChangeEvent',
+      () => new HashChangeEvent('foo',
+          oldUrl: 'http://old.url', newUrl: 'http://new.url'), (ev) {
+    expect(ev.oldUrl, equals('http://old.url'));
+    expect(ev.newUrl, equals('http://new.url'));
+  });
+
+  // KeyboardEvent has its own test file, and has cross-browser issues.
+
+  eventTest(
+      'MouseEvent',
+      () => new MouseEvent('foo',
+          view: window,
+          detail: 1,
+          screenX: 2,
+          screenY: 3,
+          clientX: 4,
+          clientY: 5,
+          button: 6,
+          ctrlKey: true,
+          altKey: true,
+          shiftKey: true,
+          metaKey: true,
+          relatedTarget: document.body), (ev) {
+    expect(ev.detail, 1);
+    expect(ev.screen.x, 2);
+    expect(ev.screen.y, 3);
+    expect(ev.client.x, 4);
+    expect(ev.client.y, 5);
+    expect(ev.offset.x, 4); // Same as clientX.
+    expect(ev.offset.y, 5); // Same as clientY.
+    expect(ev.button, 6);
+    expect(ev.ctrlKey, isTrue);
+    expect(ev.altKey, isTrue);
+    expect(ev.shiftKey, isTrue);
+    expect(ev.metaKey, isTrue);
+    // TODO(alanknight): The target does not seem to get correctly set.
+    // Issue 23438
+    //  expect(ev.relatedTarget, document.body);
+  });
+
+  // Issue 1005.
+  // eventTest('OverflowEvent',
+  //     () => new OverflowEvent(OverflowEvent.BOTH, true, true),
+  //     (ev) {
+  //   expect(ev.orient, OverflowEvent.BOTH);
+  //   expect(ev.horizontalOverflow, isTrue);
+  //   expect(ev.verticalOverflow, isTrue);
+  // }, type: 'overflowchanged');
+
+  // Issue 1005.
+  // eventTest('PageTransitionEvent',
+  //     () => new PageTransitionEvent('foo', persisted: true),
+  //     (ev) { expect(ev.persisted, isTrue); });
+
+  // initPopStateEvent is not yet implemented
+  // eventTest('PopStateEvent', () => new PopStateEvent('foo', 'state'),
+  //     (ev) { expect(ev.state, 'state'); }
+
+  // Issue 1005.
+  // eventTest('ProgressEvent',
+  //     // canBubble and cancelable are currently required to avoid dartc
+  //     // complaining about the types of the named arguments.
+  //     () => new ProgressEvent('foo', 5, canBubble: true, cancelable: true,
+  //         lengthComputable: true, total: 10),
+  //     (ev) {
+  //   expect(ev.loaded, 5);
+  //   expect(ev.lengthComputable, isTrue);
+  //   expect(ev.total, 10);
+  // });
+
+  eventTest(
+      'StorageEvent',
+      () => new StorageEvent('foo',
+          key: 'key',
+          url: 'http://example.url',
+          storageArea: window.localStorage,
+          canBubble: true,
+          cancelable: true,
+          oldValue: 'old',
+          newValue: 'new'), (ev) {
+    expect(ev.key, 'key');
+    expect(ev.url, 'http://example.url');
+    // Equality isn't preserved for storageArea
+    expect(ev.storageArea, isNotNull);
+    expect(ev.oldValue, 'old');
+    expect(ev.newValue, 'new');
+  });
+
+  // Issue 1005.
+  // eventTest('TransitionEvent', () => new TransitionEvent('foo', 'color', 0.5),
+  //     (ev) {
+  //   expect(ev.propertyName, 'color');
+  //   expect(ev.elapsedTime, 0.5);
+  // });
+
+  eventTest('UIEvent', () => new UIEvent('foo', view: window, detail: 12),
+      (ev) {
+    expect(window, ev.view);
+    expect(12, ev.detail);
+  });
+
+  eventTest(
+      'WheelEvent',
+      // TODO(alanknight): Can't pass window on Dartium. Add view: window
+      // once going through JS.
+      () => new WheelEvent("mousewheel",
+          deltaX: 1,
+          deltaY: 0,
+          detail: 4,
+          screenX: 3,
+          screenY: 4,
+          clientX: 5,
+          clientY: 6,
+          ctrlKey: true,
+          altKey: true,
+          shiftKey: true,
+          metaKey: true), (ev) {
+    expect(ev.deltaX, 1);
+    expect(ev.deltaY, 0);
+    expect(ev.screen.x, 3);
+    expect(ev.screen.y, 4);
+    expect(ev.client.x, 5);
+    expect(ev.client.y, 6);
+    expect(ev.ctrlKey, isTrue);
+    expect(ev.altKey, isTrue);
+    expect(ev.shiftKey, isTrue);
+    expect(ev.metaKey, isTrue);
+  }, 'mousewheel');
+}
diff --git a/tests/lib/html/events_test.dart b/tests/lib/html/events_test.dart
new file mode 100644
index 0000000..c704b2a
--- /dev/null
+++ b/tests/lib/html/events_test.dart
@@ -0,0 +1,117 @@
+// 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 tests.html.events_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:async_helper/async_minitest.dart';
+import 'package:expect/expect.dart';
+
+main() {
+  test('TimeStamp', () {
+    var event = new Event('test');
+
+    var timeStamp = event.timeStamp;
+    expect(timeStamp, greaterThan(0));
+  });
+
+  test('Event canBubble and cancelable', () {
+    // Try every combination of canBubble and cancelable
+    for (var i = 0; i < 4; i++) {
+      var bubble = (i & 1) != 0;
+      var cancel = (i & 2) != 0;
+      var e = new Event('input', canBubble: bubble, cancelable: cancel);
+      expect(e.bubbles, bubble, reason: 'canBubble was set to $bubble');
+      expect(e.cancelable, cancel, reason: 'cancelable was set to $cancel');
+    }
+  });
+
+  // The next test is not asynchronous because [on['test'].dispatch(event)] fires the event
+  // and event listener synchronously.
+  test('EventTarget', () {
+    var element = new Element.tag('test');
+    element.id = 'eventtarget';
+    document.body!.append(element);
+
+    var invocationCounter = 0;
+    void handler(Event e) {
+      expect(e.type, equals('test'));
+      var target = e.target;
+      expect(element, equals(target));
+      invocationCounter++;
+    }
+
+    var event = new Event('test');
+
+    invocationCounter = 0;
+    element.dispatchEvent(event);
+    expect(invocationCounter, 0);
+
+    var provider = new EventStreamProvider<Event>('test');
+
+    var sub = provider.forTarget(element).listen(handler);
+    invocationCounter = 0;
+    element.dispatchEvent(event);
+    expect(invocationCounter, 1);
+
+    sub.cancel();
+    invocationCounter = 0;
+    element.dispatchEvent(event);
+    expect(invocationCounter, 0);
+
+    provider.forTarget(element).listen(handler);
+    invocationCounter = 0;
+    element.dispatchEvent(event);
+    expect(invocationCounter, 1);
+
+    provider.forTarget(element).listen(handler);
+    invocationCounter = 0;
+    element.dispatchEvent(event);
+
+    // NOTE: when run in a custom zone, the handler is wrapped
+    // The logic for html events which ensures identical handlers are added only
+    // once is therefor muted by the wrapped handlers.
+    // Hence, we get different behavior depending on the current zone.
+    if (Zone.current == Zone.root) {
+      expect(invocationCounter, 1);
+    } else {
+      expect(invocationCounter, 2);
+    }
+  });
+
+  test('InitMouseEvent', () {
+    var div = new Element.tag('div');
+    var event = new MouseEvent('zebra', relatedTarget: div);
+  });
+
+  test('DOM event callbacks are associated with the correct zone', () {
+    var callbacks = [];
+
+    var element = new Element.tag('test');
+    element.id = 'eventtarget';
+    document.body!.append(element);
+
+    // runZoned executes the function synchronously, but we don't want to
+    // rely on this. We therefore wrap it into an expectAsync.
+    runZoned(expectAsync0(() {
+      var zone = Zone.current;
+      Expect.notEquals(zone, Zone.root);
+
+      StreamSubscription<Event>? sub;
+
+      void handler(Event e) {
+        expect(Zone.current, equals(zone));
+
+        scheduleMicrotask(expectAsync0(() {
+          expect(Zone.current, equals(zone));
+          sub!.cancel();
+        }));
+      }
+
+      sub = element.on['test'].listen(expectAsync1(handler));
+    }));
+    element.dispatchEvent(new Event('test'));
+  });
+}
diff --git a/tests/lib/html/exceptions_test.dart b/tests/lib/html/exceptions_test.dart
new file mode 100644
index 0000000..7d937ba
--- /dev/null
+++ b/tests/lib/html/exceptions_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 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('EventException', () {
+    final event = new Event('Event');
+    // Intentionally do not initialize it!
+    try {
+      document.dispatchEvent(event);
+    } on DomException catch (e) {
+      expect(e.name, DomException.INVALID_STATE);
+    }
+  });
+}
diff --git a/tests/lib/html/file_sample_test.dart b/tests/lib/html/file_sample_test.dart
new file mode 100644
index 0000000..15d36f4
--- /dev/null
+++ b/tests/lib/html/file_sample_test.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.
+
+library file_sample;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/minitest.dart';
+
+// Expected output from all functions, asynchronous, and event routines.
+const String log_results = 'test-first\n' +
+    'acquire START\n' +
+    'acquire CALLBACK START\n' +
+    'acquire CALLBACK END\n' +
+    'first START\n' +
+    'first END\n' +
+    'test-second\n' +
+    'second START\n' +
+    'second END\n' +
+    'reader onLoadEnd event\n' +
+    'file content = XYZZY Output\n';
+
+// Simple logger to record all output.
+class Logger {
+  StringBuffer _log = new StringBuffer();
+
+  void log(String message) {
+    _log.writeln(message);
+  }
+
+  String get contents => _log.toString();
+}
+
+Logger testLog = new Logger();
+
+Future<FileSystem>? _fileSystem;
+
+late DirectoryEntry _myDirectory;
+
+Future<FileSystem> get fileSystem async {
+  if (_fileSystem != null) return _fileSystem!;
+
+  testLog.log('acquire START');
+  _fileSystem = window.requestFileSystem(100);
+
+  var fs = await _fileSystem!;
+  testLog.log('acquire CALLBACK START');
+  expect(fs.runtimeType, FileSystem);
+  expect(fs.root.runtimeType, DirectoryEntry);
+  testLog.log('acquire CALLBACK END');
+
+  return _fileSystem!;
+}
+
+Future<FileEntry> createFile() async {
+  var fs = await fileSystem;
+
+  _myDirectory =
+      await fs.root.createDirectory('my_directory') as DirectoryEntry;
+
+  FileEntry fileEntry = await _myDirectory.createFile('log.txt') as FileEntry;
+
+  expect(fileEntry.isFile, true);
+  expect(fileEntry.name, 'log.txt');
+  expect(fileEntry.fullPath, '/my_directory/log.txt');
+
+  FileWriter writer = await fileEntry.createWriter();
+
+  Blob blob = new Blob(['XYZZY Output'], 'text/plain');
+
+  writer.write(blob);
+
+  var reader = new FileReader();
+
+  var completer = new Completer<String>();
+
+  reader.onLoadEnd.listen((event) {
+    testLog.log('reader onLoadEnd event');
+    dynamic target = event.currentTarget;
+    testLog.log('file content = ${target.result}');
+    expect(target.result, 'XYZZY Output');
+
+    completer.complete(target.result);
+  });
+
+  Blob readBlob = await fileEntry.file();
+
+  reader.readAsText(readBlob);
+
+  // Wait until onLoadEnd if fired.
+  await completer.future;
+
+  return new Future<FileEntry>.value(fileEntry);
+}
+
+Future<List<Entry>> readEntries(DirectoryEntry directory) async {
+  DirectoryReader reader = directory.createReader();
+  List<Entry> entries = await reader.readEntries();
+  return entries;
+}
+
+Future testFileSystemRequest() async {
+  testLog.log('test-first');
+  var fs = await fileSystem;
+  testLog.log('first START');
+  expect(fs.runtimeType, FileSystem);
+  expect(fs.root.runtimeType, DirectoryEntry);
+  testLog.log('first END');
+}
+
+Future testFileSystemRequestCreateRW() async {
+  testLog.log('test-second');
+  var fs = await fileSystem;
+  testLog.log('second START');
+  expect(fs.runtimeType, FileSystem);
+  expect(fs.root.runtimeType, DirectoryEntry);
+  testLog.log('second END');
+
+  FileEntry fileEntry = await createFile();
+  expect(fileEntry.name, 'log.txt');
+
+  List<Entry> entries = await readEntries(fs.root);
+  expect(entries.length > 0, true);
+  expect(entries[0].isDirectory, true);
+  expect(entries[0].name, 'my_directory');
+
+  List<Entry> myEntries = await readEntries(_myDirectory);
+  expect(myEntries.length, 1);
+  expect(myEntries[0].isFile, true);
+  expect(myEntries[0].name, 'log.txt');
+
+  // Validate every function, async and event mechanism successfully ran.
+  expect(testLog.contents, log_results);
+}
+
+main() {
+  asyncTest(() async {
+    await testFileSystemRequest();
+    await testFileSystemRequestCreateRW();
+  });
+}
diff --git a/tests/lib/html/fileapi_directory_reader_test.dart b/tests/lib/html/fileapi_directory_reader_test.dart
new file mode 100644
index 0000000..7468759
--- /dev/null
+++ b/tests/lib/html/fileapi_directory_reader_test.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.
+
+library fileapi;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+
+class FileAndDir {
+  FileEntry file;
+  DirectoryEntry dir;
+  FileAndDir(this.file, this.dir);
+}
+
+late FileSystem fs;
+
+main() async {
+  getFileSystem() async {
+    fs = await window.requestFileSystem(100);
+  }
+
+  // Do the boilerplate to get several files and directories created to then
+  // test the functions that use those items.
+  Future doDirSetup(String testName) async {
+    await getFileSystem();
+
+    var file = await fs.root.createFile('file_$testName') as FileEntry;
+    var dir = await fs.root.createDirectory('dir_$testName') as DirectoryEntry;
+    return new Future.value(new FileAndDir(file, dir));
+  }
+
+  if (FileSystem.supported) {
+    test('readEntries', () async {
+      var fileAndDir = await doDirSetup('readEntries');
+      var reader = await fileAndDir.dir.createReader();
+      var entries = await reader.readEntries();
+      expect(entries is List, true);
+    });
+  }
+}
diff --git a/tests/lib/html/fileapi_directory_test.dart b/tests/lib/html/fileapi_directory_test.dart
new file mode 100644
index 0000000..b2c7945
--- /dev/null
+++ b/tests/lib/html/fileapi_directory_test.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.
+
+library fileapi;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+
+class FileAndDir {
+  FileEntry file;
+  DirectoryEntry dir;
+  FileAndDir(this.file, this.dir);
+}
+
+late FileSystem fs;
+
+main() async {
+  getFileSystem() async {
+    fs = await window.requestFileSystem(100);
+  }
+
+  if (FileSystem.supported) {
+    await getFileSystem();
+
+    test('directoryDoesntExist', () async {
+      try {
+        await fs.root.getDirectory('directory2');
+      } catch (error) {
+        expect(true, error is DomException);
+        expect(DomException.NOT_FOUND, error.name);
+      }
+    });
+
+    test('directoryCreate', () async {
+      var entry = await fs.root.createDirectory('directory3');
+      expect(entry.name, equals('directory3'));
+    });
+  }
+}
diff --git a/tests/lib/html/fileapi_entry_test.dart b/tests/lib/html/fileapi_entry_test.dart
new file mode 100644
index 0000000..7669fc8
--- /dev/null
+++ b/tests/lib/html/fileapi_entry_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.
+
+library fileapi;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+
+class FileAndDir {
+  FileEntry file;
+  DirectoryEntry dir;
+  FileAndDir(this.file, this.dir);
+}
+
+late FileSystem fs;
+
+main() async {
+  getFileSystem() async {
+    return await window.requestFileSystem(100).then((FileSystem fileSystem) {
+      fs = fileSystem;
+    });
+  }
+
+  // Do the boilerplate to get several files and directories created to then
+  // test the functions that use those items.
+  Future doDirSetup(String testName) async {
+    await getFileSystem();
+
+    var file = await fs.root.createFile('file_$testName') as FileEntry;
+    var dir = await fs.root.createDirectory('dir_$testName') as DirectoryEntry;
+    return new Future.value(new FileAndDir(file, dir));
+  }
+
+  if (FileSystem.supported) {
+    test('copy_move', () async {
+      var fileAndDir = await doDirSetup('copyTo');
+      var entry =
+          await fileAndDir.file.copyTo(fileAndDir.dir, name: 'copiedFile');
+      expect(entry.isFile, true, reason: "Expected File");
+      expect(entry.name, 'copiedFile');
+
+      // getParent
+      fileAndDir = await doDirSetup('getParent');
+      entry = await fileAndDir.file.getParent();
+      expect(entry.name, '');
+      expect(entry.isDirectory, true, reason: "Expected Directory");
+
+      // moveTo
+      fileAndDir = await doDirSetup('moveTo');
+      entry = await fileAndDir.file.moveTo(fileAndDir.dir, name: 'movedFile');
+      expect(entry.name, 'movedFile');
+      expect(entry.fullPath, '/dir_moveTo/movedFile');
+
+      try {
+        entry = await fs.root.getFile('file4');
+        fail("File file4 should not exist.");
+      } catch (error) {
+        expect(error is DomException, true,
+            reason: "Not DomException - not exist");
+        expect(DomException.NOT_FOUND, error.name);
+      }
+
+      // remove
+      fileAndDir = await doDirSetup('remove');
+      expect('file_remove', fileAndDir.file.name);
+      await fileAndDir.file.remove();
+      try {
+        var entry = await fileAndDir.dir.getFile(fileAndDir.file.name);
+        fail("file not removed");
+      } catch (error) {
+        expect(error is DomException, true,
+            reason: "Not DomException - removed");
+        expect(DomException.NOT_FOUND, error.name);
+      }
+    });
+  }
+}
diff --git a/tests/lib/html/fileapi_file_entry_test.dart b/tests/lib/html/fileapi_file_entry_test.dart
new file mode 100644
index 0000000..1789003
--- /dev/null
+++ b/tests/lib/html/fileapi_file_entry_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.
+
+library fileapi;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+
+class FileAndDir {
+  FileEntry file;
+  DirectoryEntry dir;
+  FileAndDir(this.file, this.dir);
+}
+
+late FileSystem fs;
+
+main() async {
+  getFileSystem() async {
+    fs = await window.requestFileSystem(100);
+  }
+
+  // Do the boilerplate to get several files and directories created to then
+  // test the functions that use those items.
+  Future doDirSetup(String testName) async {
+    await getFileSystem();
+
+    var file = await fs.root.createFile('file_$testName') as FileEntry;
+    var dir = await fs.root.createDirectory('dir_$testName') as DirectoryEntry;
+    return new Future.value(new FileAndDir(file, dir));
+  }
+
+  if (FileSystem.supported) {
+    test('createWriter', () async {
+      var fileAndDir = await doDirSetup('createWriter');
+      var writer = await fileAndDir.file.createWriter();
+      expect(writer.position, 0);
+      expect(writer.readyState, FileWriter.INIT);
+      expect(writer.length, 0);
+    });
+
+    test('file', () async {
+      var fileAndDir = await doDirSetup('file');
+      var fileObj = await fileAndDir.file.file();
+      expect(fileObj.name, fileAndDir.file.name);
+      expect(fileObj.relativePath, '');
+      expect(
+          new DateTime.now().difference(fileObj.lastModifiedDate).inMinutes <
+              30,
+          isTrue);
+    });
+  }
+}
diff --git a/tests/lib/html/fileapi_file_test.dart b/tests/lib/html/fileapi_file_test.dart
new file mode 100644
index 0000000..f70bb13
--- /dev/null
+++ b/tests/lib/html/fileapi_file_test.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.
+
+library fileapi;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+
+class FileAndDir {
+  FileEntry file;
+  DirectoryEntry dir;
+  FileAndDir(this.file, this.dir);
+}
+
+late FileSystem fs;
+
+main() async {
+  getFileSystem() async {
+    fs = await window.requestFileSystem(100);
+  }
+
+  if (FileSystem.supported) {
+    await getFileSystem();
+
+    test('fileDoesntExist', () async {
+      try {
+        var fileObj = await fs.root.getFile('file2');
+        fail("file found");
+      } catch (error) {
+        expect(true, error is DomException);
+        expect(DomException.NOT_FOUND, error.name);
+      }
+    });
+
+    test('fileCreate', () async {
+      var fileObj = await fs.root.createFile('file4');
+      expect(fileObj.name, equals('file4'));
+      expect(fileObj.isFile, isTrue);
+
+      var metadata = await fileObj.getMetadata();
+      var changeTime = metadata.modificationTime;
+
+      // Increased Windows buildbots can sometimes be particularly slow.
+      expect(new DateTime.now().difference(changeTime).inMinutes < 4, isTrue);
+      expect(metadata.size, equals(0));
+    });
+  }
+}
diff --git a/tests/lib/html/fileapi_supported_test.dart b/tests/lib/html/fileapi_supported_test.dart
new file mode 100644
index 0000000..75fe3b8
--- /dev/null
+++ b/tests/lib/html/fileapi_supported_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.
+
+library fileapi;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+
+Future<FileSystem>? _fileSystem;
+
+Future<FileSystem> get fileSystem async {
+  if (_fileSystem != null) return _fileSystem!;
+
+  _fileSystem = window.requestFileSystem(100);
+
+  var fs = await _fileSystem!;
+  expect(fs.runtimeType, FileSystem);
+  expect(fs.root.runtimeType, DirectoryEntry);
+
+  return _fileSystem!;
+}
+
+main() {
+  test('supported', () {
+    expect(FileSystem.supported, true);
+  });
+
+  test('requestFileSystem', () async {
+    var expectation = FileSystem.supported ? returnsNormally : throws;
+    expect(() async {
+      var fs = await fileSystem;
+    }, expectation);
+  });
+}
diff --git a/tests/lib/html/fileapi_supported_throws_test.dart b/tests/lib/html/fileapi_supported_throws_test.dart
new file mode 100644
index 0000000..9367451
--- /dev/null
+++ b/tests/lib/html/fileapi_supported_throws_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.
+
+library fileapi;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  test('requestFileSystem', () async {
+    var expectation = FileSystem.supported ? returnsNormally : throws;
+    expect(() async {
+      await window.requestFileSystem(100);
+    }, expectation);
+  });
+}
diff --git a/tests/lib/html/filereader_test.dart b/tests/lib/html/filereader_test.dart
new file mode 100644
index 0000000..6f58706
--- /dev/null
+++ b/tests/lib/html/filereader_test.dart
@@ -0,0 +1,39 @@
+// 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 filereader_test;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+import 'dart:typed_data';
+
+main() {
+  test('readAsText', () {
+    var reader = new FileReader();
+    reader.onLoad.listen(expectAsync((event) {
+      var result = reader.result;
+      expect(result, equals('hello world'));
+    }));
+    reader.readAsText(new Blob(['hello ', 'world']));
+  });
+
+  test('readAsArrayBuffer', () {
+    var reader = new FileReader();
+    reader.onLoad.listen(expectAsync((event) {
+      var result = reader.result;
+      expect(result is Uint8List, isTrue);
+      expect(result, equals([65, 66, 67]));
+    }));
+    reader.readAsArrayBuffer(new Blob(['ABC']));
+  });
+
+  test('readDataUrl', () {
+    var reader = new FileReader();
+    reader.onLoad.listen(expectAsync((event) {
+      String result = reader.result as String;
+      expect(result.startsWith('data:'), isTrue);
+    }));
+    reader.readAsDataUrl(new Blob(['ABC']));
+  });
+}
diff --git a/tests/lib/html/filteredelementlist_test.dart b/tests/lib/html/filteredelementlist_test.dart
new file mode 100644
index 0000000..247c4e8
--- /dev/null
+++ b/tests/lib/html/filteredelementlist_test.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 'dart:html';
+import 'dart:html_common';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var t1 = new Text('T1'),
+      t2 = new Text('T2'),
+      t3 = new Text('T3'),
+      t4 = new Text('T4');
+
+  var d1 = new DivElement(), d2 = new DivElement(), d3 = new DivElement();
+
+  createTestDiv() {
+    var testDiv = new DivElement();
+    testDiv
+      ..append(t1)
+      ..append(d1)
+      ..append(t2)
+      ..append(d2)
+      ..append(t3)
+      ..append(d3)
+      ..append(t4);
+    return testDiv;
+  }
+
+  test('FilteredElementList.insert test', () {
+    var i = new DivElement();
+
+    // Insert before first element
+    var nodeList = createTestDiv();
+    var elementList = new FilteredElementList(nodeList);
+    elementList.insert(0, i);
+    expect(nodeList.childNodes[0], t1);
+    expect(nodeList.childNodes[1], i);
+    expect(nodeList.childNodes[2], d1);
+
+    // Insert in middle
+    nodeList = createTestDiv();
+    elementList = new FilteredElementList(nodeList);
+    elementList.insert(1, i);
+    expect(nodeList.childNodes[2], t2);
+    expect(nodeList.childNodes[3], i);
+    expect(nodeList.childNodes[4], d2);
+
+    // Insert before last element
+    nodeList = createTestDiv();
+    elementList = new FilteredElementList(nodeList);
+    elementList.insert(2, i);
+    expect(nodeList.childNodes[4], t3);
+    expect(nodeList.childNodes[5], i);
+    expect(nodeList.childNodes[6], d3);
+  });
+
+  test('FilteredElementList.insertAll test', () {
+    var i1 = new DivElement(), i2 = new DivElement();
+
+    var it = [i1, i2];
+
+    // Insert before first element
+    var nodeList = createTestDiv();
+    var elementList = new FilteredElementList(nodeList);
+    elementList.insertAll(0, it);
+    expect(nodeList.childNodes[0], t1);
+    expect(nodeList.childNodes[1], i1);
+    expect(nodeList.childNodes[2], i2);
+    expect(nodeList.childNodes[3], d1);
+
+    // Insert in middle
+    nodeList = createTestDiv();
+    elementList = new FilteredElementList(nodeList);
+    elementList.insertAll(1, it);
+    expect(nodeList.childNodes[2], t2);
+    expect(nodeList.childNodes[3], i1);
+    expect(nodeList.childNodes[4], i2);
+    expect(nodeList.childNodes[5], d2);
+
+    // Insert before last element
+    nodeList = createTestDiv();
+    elementList = new FilteredElementList(nodeList);
+    elementList.insertAll(2, it);
+    expect(nodeList.childNodes[4], t3);
+    expect(nodeList.childNodes[5], i1);
+    expect(nodeList.childNodes[6], i2);
+    expect(nodeList.childNodes[7], d3);
+  });
+
+  test('FilteredElementList.insertAndRemove', () {
+    var emptyDiv = new DivElement();
+    var elementList = new FilteredElementList(emptyDiv);
+    expect(() => elementList[0], throwsRangeError);
+    expect(() => elementList.insert(2, new BRElement()), throwsRangeError);
+    var br = new BRElement();
+    elementList.insert(0, br);
+    expect(elementList.removeLast(), br);
+    elementList.add(br);
+    expect(elementList.remove(br), isTrue);
+    var br2 = new BRElement();
+    elementList.add(br);
+    expect(elementList.remove(br2), isFalse);
+    expect(elementList[0], br);
+    expect(() => elementList[1], throwsRangeError);
+  });
+}
diff --git a/tests/lib/html/fontface_loaded_test.dart b/tests/lib/html/fontface_loaded_test.dart
new file mode 100644
index 0000000..ef07061
--- /dev/null
+++ b/tests/lib/html/fontface_loaded_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.
+
+library fontface_loaded_test;
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:html';
+
+class NullTreeSanitizer implements NodeTreeSanitizer {
+  void sanitizeTree(Node node) {}
+}
+
+main() {
+  var style = new Element.html('''
+      <style>
+      @font-face {
+        font-family: 'Ahem';
+        src: url(/root_dart/tests/lib/html/Ahem.ttf);
+        font-style: italic;
+        font-weight: 300;
+        unicode-range: U+0-3FF;
+        font-variant: small-caps;
+        -webkit-font-feature-settings: "dlig" 1;
+        /* font-stretch property is not supported */
+      }
+      </style>
+      ''', treeSanitizer: new NullTreeSanitizer());
+  document.head!.append(style);
+
+  test('document fonts - temporary', () async {
+    var atLeastOneFont = false;
+    var loaded = <Future<FontFace>>[];
+    document.fonts.forEach((FontFace fontFace, _, __) async {
+      atLeastOneFont = true;
+      var f1 = fontFace.loaded;
+      var f2 = fontFace.loaded;
+      loaded.add(fontFace.load());
+      loaded.add(f1);
+      loaded.add(f2);
+    });
+    expect(atLeastOneFont, isTrue);
+    return Future.wait(loaded).then(expectAsync((_) async {
+      document.fonts.forEach((fontFace, _, __) {
+        expect(fontFace.status, 'loaded');
+      });
+      expect(loaded.length, 3);
+      for (var loadedEntry in loaded) {
+        var fontFace = await loadedEntry;
+        expect(fontFace.status, 'loaded');
+        var fontFamily = fontFace.family;
+        if (fontFamily.startsWith('"')) {
+          // FF wraps family in quotes - remove the quotes.
+          fontFamily = fontFamily.substring(1, fontFamily.length - 1);
+        }
+        expect(fontFamily, 'Ahem');
+      }
+    }));
+  });
+}
diff --git a/tests/lib/html/fontface_test.dart b/tests/lib/html/fontface_test.dart
new file mode 100644
index 0000000..a663def
--- /dev/null
+++ b/tests/lib/html/fontface_test.dart
@@ -0,0 +1,16 @@
+// 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 'package:expect/minitest.dart';
+
+main() {
+  test("Creation with parameters", () {
+    var font = new FontFace('Ahem', 'url(Ahem.ttf)', {'variant': 'small-caps'});
+    expect(font is FontFace, isTrue);
+    expect(font.family, 'Ahem');
+    expect(font.variant, 'small-caps');
+  });
+}
diff --git a/tests/lib/html/form_data_test.dart b/tests/lib/html/form_data_test.dart
new file mode 100644
index 0000000..03592e2
--- /dev/null
+++ b/tests/lib/html/form_data_test.dart
@@ -0,0 +1,80 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library FormDataTest;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+
+void main() {
+  // TODO(efortuna): This is a bad test. Revisit when we have tests that can run
+  // both a server and fire up a browser.
+  group('supported', () {
+    test('supported', () {
+      expect(FormData.supported, isTrue);
+    });
+  });
+
+  group('functional', () {
+    test('unsupported throws', () {
+      var expectation = FormData.supported ? returnsNormally : throws;
+      expect(() {
+        new FormData();
+      }, expectation);
+    });
+
+    var isFormData = predicate((x) => x is FormData, 'is a FormData');
+
+    if (FormData.supported) {
+      test('constructorTest1', () {
+        var form = new FormData();
+        expect(form, isNotNull);
+        expect(form, isFormData);
+      });
+
+      test('constructorTest2', () {
+        var form = new FormData(new FormElement());
+        expect(form, isNotNull);
+        expect(form, isFormData);
+      });
+
+      test('appendTest', () {
+        var form = new FormData();
+        form.append('test', '1');
+        form.append('username', 'Elmo');
+        form.append('address', '1 Sesame Street');
+        form.append('password', '123456');
+        expect(form, isNotNull);
+      });
+
+      test('appendBlob', () {
+        var form = new FormData();
+        var blob = new Blob(
+            ['Indescribable... Indestructible! Nothing can stop it!'],
+            'text/plain');
+        form.appendBlob('theBlob', blob, 'theBlob.txt');
+      });
+
+      test('send', () {
+        var form = new FormData();
+        var blobString =
+            'Indescribable... Indestructible! Nothing can stop it!';
+        var blob = new Blob([blobString], 'text/plain');
+        form.appendBlob('theBlob', blob, 'theBlob.txt');
+
+        var xhr = new HttpRequest();
+        xhr.open('POST',
+            '${window.location.protocol}//${window.location.host}/echo');
+
+        xhr.onLoad.listen(expectAsync((e) {
+          expect(xhr.responseText.contains(blobString), isTrue);
+        }));
+        xhr.onError.listen((e) {
+          fail('$e');
+        });
+        xhr.send(form);
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/form_element_test.dart b/tests/lib/html/form_element_test.dart
new file mode 100644
index 0000000..4cc6807f
--- /dev/null
+++ b/tests/lib/html/form_element_test.dart
@@ -0,0 +1,81 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+void main() {
+  var isFormElement = predicate((x) => x is FormElement, 'is a FormElement');
+
+  test('constructorTest1', () {
+    var form = new FormElement();
+    expect(form, isNotNull);
+    expect(form, isFormElement);
+  });
+
+  test('checkValidityTest', () {
+    var form = new FormElement();
+    form.innerHtml = '<label>Google: <input type="search" name="q"></label> '
+        '<input type="submit" value="Search...">';
+    expect(form.checkValidity(), isTrue);
+    // TODO(efortuna): Issue 4832.
+    form.innerHtml = '<input type="email" value="notemail" blaber="test"'
+        ' required>';
+    expect(form.checkValidity(), isFalse);
+  });
+
+  var form = new FormElement();
+  test('acceptCharsetTest', () {
+    var charset = 'abc';
+    form.acceptCharset = charset;
+    expect(form.acceptCharset, charset);
+  });
+
+  test('actionTest', () {
+    var action = 'http://dartlang.org/';
+    form.action = action;
+    expect(form.action, action);
+  });
+
+  test('autocompleteTest', () {
+    var auto = 'on';
+    form.autocomplete = auto;
+    expect(form.autocomplete, auto);
+  });
+
+  test('encodingAndEnctypeTest', () {
+    expect(form.enctype, form.encoding);
+  });
+
+  test('lengthTest', () {
+    expect(form.length, 0);
+    form.innerHtml = '<label>Google: <input type="search" name="q"></label> '
+        '<input type="submit" value="Search...">';
+    expect(form.length, 2);
+  });
+
+  test('methodTest', () {
+    var method = 'post';
+    form.method = method;
+    expect(form.method, method);
+  });
+
+  test('nameTest', () {
+    var name = 'aname';
+    form.name = name;
+    expect(form.name, name);
+  });
+
+  test('noValidateTest', () {
+    form.noValidate = true;
+    expect(form.noValidate, true);
+  });
+
+  test('targetTest', () {
+    var target = 'target';
+    form.target = target;
+    expect(form.target, target);
+  });
+}
diff --git a/tests/lib/html/gamepad_test.dart b/tests/lib/html/gamepad_test.dart
new file mode 100644
index 0000000..35c2764
--- /dev/null
+++ b/tests/lib/html/gamepad_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:expect/minitest.dart';
+import 'dart:html';
+
+main() {
+  var isGamepadList =
+      predicate((x) => x is List<Gamepad?>, 'is a List<Gamepad?>');
+
+  insertTestDiv() {
+    var element = new Element.tag('div');
+    element.innerHtml = r'''
+    A large block of text should go here. Click this
+    block of text multiple times to see each line
+    highlight with every click of the mouse button.
+    ''';
+    document.body!.append(element);
+    return element;
+  }
+
+  test("getGamepads", () {
+    insertTestDiv();
+    var gamepads = window.navigator.getGamepads();
+    expect(gamepads, isGamepadList);
+    for (var gamepad in gamepads) {
+      if (gamepad != null) {
+        expect(gamepad.id, isNotNull);
+      }
+    }
+  });
+}
diff --git a/tests/lib/html/geolocation_test.dart b/tests/lib/html/geolocation_test.dart
new file mode 100644
index 0000000..30d24dc
--- /dev/null
+++ b/tests/lib/html/geolocation_test.dart
@@ -0,0 +1,15 @@
+// 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:expect/minitest.dart';
+
+main() {
+  // Actual tests require browser interaction. This just makes sure the API
+  // is present.
+  test('is not null', () {
+    expect(window.navigator.geolocation, isNotNull);
+  });
+}
diff --git a/tests/lib/html/hidden_dom_1_test.dart b/tests/lib/html/hidden_dom_1_test.dart
new file mode 100644
index 0000000..8c4f892
--- /dev/null
+++ b/tests/lib/html/hidden_dom_1_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:html';
+
+import 'package:expect/minitest.dart';
+
+// Test that the dart:html API does not leak native jsdom methods:
+//   onfocus setter.
+
+main() {
+  test('test1', () {
+    document.body!.children.add(new Element.html(r'''
+<div id='div1'>
+Hello World!
+</div>'''));
+    Element? e = document.querySelector('#div1');
+    expect(e, isNotNull);
+
+    expect(() {
+      confuse(e!).onfocus = null;
+    }, throwsNoSuchMethodError);
+  });
+}
+
+class Decoy {
+  void set onfocus(x) {
+    throw 'dead code';
+  }
+}
+
+confuse(x) => opaqueTrue() ? x : (opaqueTrue() ? new Object() : new Decoy());
+
+/** Returns `true`, but in a way that confuses the compiler. */
+opaqueTrue() => true; // Expand as needed.
diff --git a/tests/lib/html/hidden_dom_2_test.dart b/tests/lib/html/hidden_dom_2_test.dart
new file mode 100644
index 0000000..163de35
--- /dev/null
+++ b/tests/lib/html/hidden_dom_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+// Test that the dart:html API does not leak native jsdom methods:
+//   appendChild operation.
+
+main() {
+  test('test1', () {
+    document.body!.children.add(new Element.html(r'''
+<div id='div1'>
+Hello World!
+</div>'''));
+    Element? e = document.querySelector('#div1');
+    Element e2 = new Element.html(r"<div id='xx'>XX</div>");
+    expect(e, isNotNull);
+
+    expect(() {
+      confuse(e!).appendChild(e2);
+    }, throwsNoSuchMethodError);
+  });
+}
+
+class Decoy {
+  void appendChild(x) {
+    throw 'dead code';
+  }
+}
+
+confuse(x) => opaqueTrue() ? x : (opaqueTrue() ? new Object() : new Decoy());
+
+/** Returns `true`, but in a way that confuses the compiler. */
+opaqueTrue() => true; // Expand as needed.
diff --git a/tests/lib/html/history_hash_change_test.dart b/tests/lib/html/history_hash_change_test.dart
new file mode 100644
index 0000000..d2d2ccb
--- /dev/null
+++ b/tests/lib/html/history_hash_change_test.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.
+
+library HistoryTest;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+import 'dart:async';
+
+main() {
+  test('supported', () {
+    expect(HashChangeEvent.supported, true);
+  });
+}
diff --git a/tests/lib/html/history_supported_test.dart b/tests/lib/html/history_supported_test.dart
new file mode 100644
index 0000000..779e2a3
--- /dev/null
+++ b/tests/lib/html/history_supported_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.
+
+library HistoryTest;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+import 'dart:async';
+
+main() {
+  test('supports_state', () {
+    expect(History.supportsState, true);
+  });
+
+  test('supported_HashChangeEvent', () {
+    expect(HashChangeEvent.supported, true);
+  });
+}
diff --git a/tests/lib/html/history_test.dart b/tests/lib/html/history_test.dart
new file mode 100644
index 0000000..100b220
--- /dev/null
+++ b/tests/lib/html/history_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.
+
+library HistoryTest;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+import 'dart:async';
+
+main() {
+  var expectation = History.supportsState ? returnsNormally : throws;
+
+  test('pushState', () {
+    expect(() {
+      window.history.pushState(null, document.title, '?dummy');
+      var length = window.history.length;
+
+      window.history.pushState(null, document.title, '?foo=bar');
+
+      expect(window.location.href.endsWith('foo=bar'), isTrue);
+    }, expectation);
+  });
+
+  test('pushState with data', () {
+    expect(() {
+      window.history.pushState({'one': 1}, document.title, '?dummy');
+      expect(window.history.state, equals({'one': 1}));
+      window.history.pushState(null, document.title, '?foo=bar');
+
+      expect(window.location.href.endsWith('foo=bar'), isTrue);
+    }, expectation);
+  });
+
+  test('back', () {
+    expect(() {
+      window.history.pushState(null, document.title, '?dummy1');
+      window.history.pushState(null, document.title, '?dummy2');
+      var length = window.history.length;
+
+      expect(window.location.href.endsWith('dummy2'), isTrue);
+
+      // Need to wait a frame or two to let the pushState events occur.
+      new Timer(const Duration(milliseconds: 100), expectAsync(() {
+        window.onPopState.first.then(expectAsync((_) {
+          expect(window.history.length, length);
+          expect(window.location.href.endsWith('dummy1'), isTrue);
+        }));
+
+        window.history.back();
+      }));
+    }, expectation);
+  });
+
+  test('replaceState', () {
+    expect(() {
+      var length = window.history.length;
+
+      window.history.replaceState(null, document.title, '?foo=baz');
+      expect(window.history.length, length);
+      expect(window.location.href.endsWith('foo=baz'), isTrue);
+    }, expectation);
+  });
+
+  test('popstatevent', () {
+    expect(() {
+      var event = new Event.eventType('PopStateEvent', 'popstate');
+      expect(event is PopStateEvent, true);
+    }, expectation);
+  });
+
+  test('hashchangeevent', () {
+    var expectation = HashChangeEvent.supported ? returnsNormally : throws;
+    expect(() {
+      var event = new HashChangeEvent('change', oldUrl: 'old', newUrl: 'new');
+      expect(event is HashChangeEvent, true);
+      expect(event.oldUrl, 'old');
+      expect(event.newUrl, 'new');
+    }, expectation);
+  });
+}
diff --git a/tests/lib/html/html_mock_test.dart b/tests/lib/html/html_mock_test.dart
new file mode 100644
index 0000000..94c016d
--- /dev/null
+++ b/tests/lib/html/html_mock_test.dart
@@ -0,0 +1,94 @@
+// 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:expect/minitest.dart';
+
+class Mock {
+  noSuchMethod(Invocation i) {
+    if (this is Window) return document;
+    if (this is FileList) return new MockFile();
+    return null;
+  }
+}
+
+@proxy
+class MockBodyElement extends Mock implements BodyElement {
+  Node append(Node e) => e;
+}
+
+class _EventListeners {
+  Stream<Event> get onBlur => new Stream.fromIterable([]);
+}
+
+@proxy
+class MockHtmlDocument extends Mock
+    with _EventListeners
+    implements HtmlDocument {
+  BodyElement get body => new MockBodyElement();
+}
+
+@proxy
+class MockWindow extends Mock with _EventListeners implements Window {
+  Stream<Event> get onBeforeUnload => new Stream.fromIterable([]);
+
+  String name = "MOCK_NAME";
+}
+
+@proxy
+class MockLocation extends Mock implements Location {
+  String href = "MOCK_HREF";
+}
+
+@proxy
+class MockFileList extends Mock implements FileList {}
+
+@proxy
+class MockFile extends Mock implements File {}
+
+main() {
+  test('is', () {
+    var win = new MockWindow();
+    expect(win is Window, isTrue);
+  });
+
+  test('getter', () {
+    var win = new MockWindow();
+    expect(win.document, equals(document));
+  });
+
+  test('override', () {
+    Window win = new MockWindow();
+    expect(win.name, equals("MOCK_NAME"));
+  });
+
+  test('override', () {
+    var loc1 = new MockLocation();
+    Location loc2 = loc1;
+    dynamic loc3 = loc1;
+    expect(loc1.href, equals("MOCK_HREF"));
+    loc1.href = "RESET";
+    expect(loc2.href, equals("RESET"));
+    loc2.href = "RESET2";
+    expect(loc3.href, equals("RESET2"));
+  });
+
+  test('method', () {
+    HtmlDocument doc = new MockHtmlDocument();
+  });
+
+  test('mixin', () {
+    Window win = new MockWindow();
+    expect(win.onBlur is Stream, isTrue, reason: 'onBlur should be a stream');
+    HtmlDocument doc = new MockHtmlDocument();
+    expect(doc.onBlur is Stream, isTrue, reason: 'onBlur should be a stream');
+  });
+
+  test('operator', () {
+    var fileList = new MockFileList();
+    expect(fileList[1] is File, isTrue);
+  });
+}
diff --git a/tests/lib/html/htmlcollection_test.dart b/tests/lib/html/htmlcollection_test.dart
new file mode 100644
index 0000000..e0d60e3
--- /dev/null
+++ b/tests/lib/html/htmlcollection_test.dart
@@ -0,0 +1,275 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+bool isChecked(Element e) => (e as CheckboxInputElement).checked;
+bool isUnchecked(Element e) => !(e as CheckboxInputElement).checked;
+
+// Test that List<Element> implements List<T>
+main() {
+  Element insertTestDiv() {
+    Element element = new Element.tag('div');
+    element.innerHtml = r"""
+<div id='allChecked'>
+<input type="checkbox" name="c1" value="1" checked="yes">
+<input type="checkbox" name="c2" value="2" checked="yes">
+<input type="checkbox" name="c3" value="3" checked="yes">
+<input type="checkbox" name="c4" value="4" checked="yes">
+</div>
+<div id='someChecked'>
+<input type="checkbox" name="s1" value="1" checked="yes">
+<input type="checkbox" name="s2" value="2">
+<input type="checkbox" name="s3" value="3" checked="yes">
+<input type="checkbox" name="s4" value="4">
+</div>
+<div id='noneChecked'>
+<input type="checkbox" name="n1" value="1">
+<input type="checkbox" name="n2" value="2">
+<input type="checkbox" name="n3" value="3">
+<input type="checkbox" name="n4" value="4">
+</div>
+<div id='emptyDiv'></div>
+""";
+    document.body!.append(element);
+    return element;
+  }
+
+  test('IsList', () {
+    Element root = insertTestDiv();
+
+    List<Element> eachChecked = document.querySelector('#allChecked')!.children;
+
+    expect(eachChecked is List, isTrue);
+
+    root.remove();
+  });
+  test('Every', () {
+    Element root = insertTestDiv();
+
+    List<Element> eachChecked = document.querySelector('#allChecked')!.children;
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> noneChecked =
+        document.querySelector('#noneChecked')!.children;
+
+    expect(eachChecked.length, 4);
+    expect(someChecked.length, 4);
+    expect(noneChecked.length, 4);
+
+    expect(eachChecked.every(isChecked), isTrue);
+    expect(eachChecked.every(isUnchecked), isFalse);
+    expect(someChecked.every(isChecked), isFalse);
+    expect(someChecked.every(isUnchecked), isFalse);
+    expect(noneChecked.every(isChecked), isFalse);
+    expect(noneChecked.every(isUnchecked), isTrue);
+
+    root.remove();
+  });
+  test('Some', () {
+    Element root = insertTestDiv();
+
+    List<Element> eachChecked = document.querySelector('#allChecked')!.children;
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> noneChecked =
+        document.querySelector('#noneChecked')!.children;
+
+    expect(eachChecked.length, 4);
+    expect(someChecked.length, 4);
+    expect(noneChecked.length, 4);
+
+    expect(eachChecked.any(isChecked), isTrue);
+    expect(eachChecked.any(isUnchecked), isFalse);
+    expect(someChecked.any(isChecked), isTrue);
+    expect(someChecked.any(isUnchecked), isTrue);
+    expect(noneChecked.any(isChecked), isFalse);
+    expect(noneChecked.any(isUnchecked), isTrue);
+
+    root.remove();
+  });
+  test('Filter', () {
+    Element root = insertTestDiv();
+
+    List<Element> eachChecked = document.querySelector('#allChecked')!.children;
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> noneChecked =
+        document.querySelector('#noneChecked')!.children;
+
+    expect(eachChecked.length, 4);
+    expect(someChecked.length, 4);
+    expect(noneChecked.length, 4);
+
+    expect(eachChecked.where(isChecked).length, 4);
+    expect(eachChecked.where(isUnchecked).length, 0);
+    expect(someChecked.where(isChecked).length, 2);
+    expect(someChecked.where(isUnchecked).length, 2);
+    expect(noneChecked.where(isChecked).length, 0);
+    expect(noneChecked.where(isUnchecked).length, 4);
+
+    root.remove();
+  });
+  test('IsEmpty', () {
+    Element root = insertTestDiv();
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> emptyDiv = document.querySelector('#emptyDiv')!.children;
+
+    expect(someChecked.length, 4);
+    expect(emptyDiv.length, 0);
+
+    expect(someChecked.isEmpty, isFalse);
+    expect(emptyDiv.isEmpty, isTrue);
+
+    root.remove();
+  });
+
+  int countWithForEach(collection, predicate) {
+    int count = 0;
+    collection.forEach((element) {
+      if (predicate(element)) count++;
+    });
+    return count;
+  }
+
+  test('ForEach', () {
+    Element root = insertTestDiv();
+
+    List<Element> eachChecked = document.querySelector('#allChecked')!.children;
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> noneChecked =
+        document.querySelector('#noneChecked')!.children;
+
+    expect(eachChecked.length, 4);
+    expect(someChecked.length, 4);
+    expect(noneChecked.length, 4);
+
+    expect(countWithForEach(eachChecked, isChecked), 4);
+    expect(countWithForEach(eachChecked, isUnchecked), 0);
+    expect(countWithForEach(someChecked, isChecked), 2);
+    expect(countWithForEach(someChecked, isUnchecked), 2);
+    expect(countWithForEach(noneChecked, isChecked), 0);
+    expect(countWithForEach(noneChecked, isUnchecked), 4);
+
+    root.remove();
+  });
+
+  int countWithForLoop(collection, predicate) {
+    int count = 0;
+    for (var element in collection) {
+      if (predicate(element)) count++;
+    }
+    return count;
+  }
+
+  test('ForLoop', () {
+    // Uses iterator.
+    Element root = insertTestDiv();
+
+    List<Element> eachChecked = document.querySelector('#allChecked')!.children;
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> noneChecked =
+        document.querySelector('#noneChecked')!.children;
+
+    expect(eachChecked.length, 4);
+    expect(someChecked.length, 4);
+    expect(noneChecked.length, 4);
+
+    expect(countWithForLoop(eachChecked, isChecked), 4);
+    expect(countWithForLoop(eachChecked, isUnchecked), 0);
+    expect(countWithForLoop(someChecked, isChecked), 2);
+    expect(countWithForLoop(someChecked, isUnchecked), 2);
+    expect(countWithForLoop(noneChecked, isChecked), 0);
+    expect(countWithForLoop(noneChecked, isUnchecked), 4);
+
+    root.remove();
+  });
+  test('Last', () {
+    Element root = insertTestDiv();
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    expect(someChecked.length, 4);
+
+    expect(someChecked.last, equals(someChecked[3]));
+
+    root.remove();
+  });
+  test('IndexOf', () {
+    Element root = insertTestDiv();
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> noneChecked =
+        document.querySelector('#noneChecked')!.children;
+
+    expect(someChecked.length, 4);
+    expect(noneChecked.length, 4);
+
+    expect(someChecked.indexOf(someChecked[0], 0), 0);
+    expect(someChecked.indexOf(someChecked[1], 0), 1);
+    expect(someChecked.indexOf(someChecked[2], 0), 2);
+    expect(someChecked.indexOf(someChecked[3], 0), 3);
+
+    expect(someChecked.indexOf(someChecked[0], 1), -1);
+    expect(someChecked.indexOf(someChecked[1], 2), -1);
+    expect(someChecked.indexOf(someChecked[2], 3), -1);
+    expect(someChecked.indexOf(someChecked[3], 4), -1);
+
+    expect(someChecked.indexOf(noneChecked[0], 0), -1);
+    expect(noneChecked.indexOf(someChecked[0], 0), -1);
+    expect(someChecked.indexOf(noneChecked[1], 0), -1);
+    expect(noneChecked.indexOf(someChecked[1], 0), -1);
+
+    root.remove();
+  });
+  test('LastIndexOf', () {
+    Element root = insertTestDiv();
+
+    List<Element> someChecked =
+        document.querySelector('#someChecked')!.children;
+
+    List<Element> noneChecked =
+        document.querySelector('#noneChecked')!.children;
+
+    expect(someChecked.length, 4);
+    expect(noneChecked.length, 4);
+
+    expect(someChecked.lastIndexOf(someChecked[0], 3), 0);
+    expect(someChecked.lastIndexOf(someChecked[1], 3), 1);
+    expect(someChecked.lastIndexOf(someChecked[2], 3), 2);
+    expect(someChecked.lastIndexOf(someChecked[3], 3), 3);
+
+    expect(someChecked.lastIndexOf(someChecked[0], -1), -1);
+    expect(someChecked.lastIndexOf(someChecked[1], 0), -1);
+    expect(someChecked.lastIndexOf(someChecked[2], 1), -1);
+    expect(someChecked.lastIndexOf(someChecked[3], 2), -1);
+
+    expect(someChecked.lastIndexOf(noneChecked[0], 3), -1);
+    expect(noneChecked.lastIndexOf(someChecked[0], 3), -1);
+    expect(someChecked.lastIndexOf(noneChecked[1], 3), -1);
+    expect(noneChecked.lastIndexOf(someChecked[1], 3), -1);
+
+    root.remove();
+  });
+}
diff --git a/tests/lib/html/htmlelement_test.dart b/tests/lib/html/htmlelement_test.dart
new file mode 100644
index 0000000..898ac06
--- /dev/null
+++ b/tests/lib/html/htmlelement_test.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  test('InnerHTML', () {
+    Element element = new Element.tag('div');
+    element.id = 'test';
+    element.innerHtml = 'Hello World';
+    document.body!.append(element);
+
+    element = document.querySelector('#test')!;
+    expect(element.innerHtml, 'Hello World');
+    element.remove();
+  });
+  test('HTMLTable', () {
+    TableElement table = new Element.tag('table') as TableElement;
+
+    TableRowElement row = new Element.tag('tr') as TableRowElement;
+    table.append(row);
+
+    row.append(new Element.tag('td'));
+    row.append(new Element.tag('td'));
+
+    expect(row.cells.length, 2);
+
+    TableRowElement headerRow = table.rows[0];
+    expect(headerRow.cells.length, 2);
+  });
+  test('dataset', () {
+    Element div = new Element.tag('div');
+
+    expect(div.dataset.isEmpty, isTrue);
+    expect(div.dataset['foo'], isNull);
+    expect(div.dataset.isEmpty, isTrue);
+
+    div.dataset['foo'] = 'foo-value';
+    expect(div.dataset['foo'], 'foo-value');
+    expect(div.dataset.isEmpty, isFalse);
+
+    expect(div.dataset.containsValue('foo-value'), isTrue);
+    expect(div.dataset.containsValue('bar-value'), isFalse);
+    expect(div.dataset.containsKey('foo'), isTrue);
+    expect(div.dataset.containsKey('bar'), isFalse);
+
+    bool hasBeenInvoked;
+    String f() {
+      hasBeenInvoked = true;
+      return 'bar-value';
+    }
+
+    hasBeenInvoked = false;
+    expect(div.dataset.putIfAbsent('bar', f), 'bar-value');
+    expect(hasBeenInvoked, isTrue);
+
+    hasBeenInvoked = false;
+    expect(div.dataset.putIfAbsent('bar', f), 'bar-value');
+    expect(hasBeenInvoked, isFalse);
+
+    final keys = <String>[];
+    final values = <String>[];
+    div.dataset.forEach((String key, String value) {
+      keys.add(key);
+      values.add(value);
+    });
+    expect(keys, unorderedEquals(['foo', 'bar']));
+    expect(values, unorderedEquals(['foo-value', 'bar-value']));
+
+    expect(new List<String>.from(div.dataset.keys),
+        unorderedEquals(['foo', 'bar']));
+    expect(new List<String>.from(div.dataset.values),
+        unorderedEquals(['foo-value', 'bar-value']));
+
+    expect(div.dataset.length, 2);
+    expect(div.dataset.isEmpty, isFalse);
+
+    expect(div.dataset.remove('qux'), isNull);
+    expect(div.dataset.length, 2);
+    expect(div.dataset.isEmpty, isFalse);
+
+    expect(div.dataset.remove('foo'), 'foo-value');
+    expect(div.dataset.length, 1);
+    expect(div.dataset.isEmpty, isFalse);
+
+    div.dataset.clear();
+    expect(div.dataset.length, 0);
+    expect(div.dataset.isEmpty, isTrue);
+
+    Element otherDiv = new Element.html(
+        '<div id="dataDiv" data-my-message="Hello World"></div>',
+        treeSanitizer: new NullTreeSanitizer());
+    expect(otherDiv.dataset.containsKey('myMessage'), isTrue);
+
+    Element anotherDiv = new Element.html(
+        '<div id="dataDiv" data-eggs="bacon"></div>',
+        treeSanitizer: new NullTreeSanitizer());
+    expect(anotherDiv.dataset.containsKey('eggs'), isTrue);
+  });
+}
diff --git a/tests/lib/html/htmloptionscollection_test.dart b/tests/lib/html/htmloptionscollection_test.dart
new file mode 100644
index 0000000..583cd88
--- /dev/null
+++ b/tests/lib/html/htmloptionscollection_test.dart
@@ -0,0 +1,38 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('indexedAccessTest', () {
+    // FIXME: we need some massaging to dart:html to enable HTMLOptionsCollection.add
+    // and hence programatic building of collection.
+    SelectElement selectElement = new Element.html('''
+      <select>
+        <option value="0">Option0</option>
+        <option value="1">Option1</option>
+        <option value="2">Option2</option>
+      ''') as SelectElement;
+    final optionsCollection = selectElement.options;
+
+    expect(optionsCollection[0].value, equals('0'));
+    expect(optionsCollection[1].value, equals('1'));
+    expect(optionsCollection[2].value, equals('2'));
+
+    expect(optionsCollection[0].text, equals('Option0'));
+    expect(optionsCollection[1].text, equals('Option1'));
+    expect(optionsCollection[2].text, equals('Option2'));
+
+    expect(() {
+      (optionsCollection as dynamic)[0] = 1;
+    }, throws);
+
+    // OPTIONALS optionsCollection[0] = new OptionElement(value: '42', data: 'Option42');
+    expect(() {
+      optionsCollection[0] = new OptionElement(data: 'Option42', value: '42');
+    }, throws);
+  });
+}
diff --git a/tests/lib/html/http_test.dart b/tests/lib/html/http_test.dart
new file mode 100644
index 0000000..905f4d5
--- /dev/null
+++ b/tests/lib/html/http_test.dart
@@ -0,0 +1,33 @@
+// 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:expect/minitest.dart';
+
+bool testSwitch(int currentValue) {
+  switch (currentValue) {
+    case HttpStatus.continue_:
+      return true;
+    case HttpStatus.ok:
+      return true;
+    case HttpStatus.NETWORK_CONNECT_TIMEOUT_ERROR:
+      return true;
+  }
+
+  return false;
+}
+
+main() {
+  expect(testSwitch(HttpStatus.continue_), isTrue);
+  expect(testSwitch(HttpStatus.CONTINUE), isTrue);
+
+  expect(testSwitch(HttpStatus.ok), isTrue);
+  expect(testSwitch(HttpStatus.OK), isTrue);
+
+  expect(testSwitch(HttpStatus.networkConnectTimeoutError), isTrue);
+  expect(testSwitch(HttpStatus.NETWORK_CONNECT_TIMEOUT_ERROR), isTrue);
+
+  expect(testSwitch(-20100), isFalse);
+}
diff --git a/tests/lib/html/indexeddb_1_test.dart b/tests/lib/html/indexeddb_1_test.dart
new file mode 100644
index 0000000..8dfc0b0
--- /dev/null
+++ b/tests/lib/html/indexeddb_1_test.dart
@@ -0,0 +1,185 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 IndexedDB1Test;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:math' as math;
+import 'dart:indexed_db' as idb;
+
+const String STORE_NAME = 'TEST';
+const int VERSION = 1;
+
+var databaseNameIndex = 0;
+String nextDatabaseName() {
+  return 'Test1_${databaseNameIndex++}';
+}
+
+Future testUpgrade() {
+  var dbName = nextDatabaseName();
+  var upgraded = false;
+
+  // Delete any existing DBs.
+  return html.window.indexedDB!.deleteDatabase(dbName).then((_) {
+    return html.window.indexedDB!
+        .open(dbName, version: 1, onUpgradeNeeded: (e) {});
+  }).then((db) {
+    db.close();
+  }).then((_) {
+    return html.window.indexedDB!.open(dbName, version: 2,
+        onUpgradeNeeded: (e) {
+      expect(e.oldVersion, 1);
+      expect(e.newVersion, 2);
+      upgraded = true;
+    });
+  }).then((_) {
+    expect(upgraded, isTrue);
+  });
+}
+
+testReadWrite(key, value, matcher,
+        [dbName,
+        storeName = STORE_NAME,
+        version = VERSION,
+        stringifyResult = false]) =>
+    () {
+      if (dbName == null) {
+        dbName = nextDatabaseName();
+      }
+      createObjectStore(e) {
+        idb.ObjectStore store = e.target.result.createObjectStore(storeName);
+        expect(store, isNotNull);
+      }
+
+      late idb.Database db;
+      return html.window.indexedDB!.deleteDatabase(dbName).then((_) {
+        return html.window.indexedDB!
+            .open(dbName, version: version, onUpgradeNeeded: createObjectStore);
+      }).then((idb.Database result) {
+        db = result;
+        var transaction = db.transactionList([storeName], 'readwrite');
+        transaction.objectStore(storeName).put(value, key);
+        return transaction.completed;
+      }).then((_) {
+        var transaction = db.transaction(storeName, 'readonly');
+        return transaction.objectStore(storeName).getObject(key);
+      }).then((object) {
+        db.close();
+        if (stringifyResult) {
+          // Stringify the numbers to verify that we're correctly returning ints
+          // as ints vs doubles.
+          expect(object.toString(), matcher);
+        } else {
+          expect(object, matcher);
+        }
+      }).whenComplete(() {
+        return html.window.indexedDB!.deleteDatabase(dbName);
+      });
+    };
+
+testReadWriteTyped(key, value, matcher,
+        [dbName,
+        String storeName = STORE_NAME,
+        version = VERSION,
+        stringifyResult = false]) =>
+    () {
+      if (dbName == null) {
+        dbName = nextDatabaseName();
+      }
+      void createObjectStore(e) {
+        var store = e.target.result.createObjectStore(storeName);
+        expect(store, isNotNull);
+      }
+
+      late idb.Database db;
+      // Delete any existing DBs.
+      return html.window.indexedDB!.deleteDatabase(dbName).then((_) {
+        return html.window.indexedDB!
+            .open(dbName, version: version, onUpgradeNeeded: createObjectStore);
+      }).then((idb.Database result) {
+        db = result;
+        idb.Transaction transaction =
+            db.transactionList([storeName], 'readwrite');
+        transaction.objectStore(storeName).put(value, key);
+
+        return transaction.completed;
+      }).then((idb.Database result) {
+        idb.Transaction transaction = db.transaction(storeName, 'readonly');
+        return transaction.objectStore(storeName).getObject(key);
+      }).then((object) {
+        db.close();
+        if (stringifyResult) {
+          // Stringify the numbers to verify that we're correctly returning ints
+          // as ints vs doubles.
+          expect(object.toString(), matcher);
+        } else {
+          expect(object, matcher);
+        }
+      }).whenComplete(() {
+        return html.window.indexedDB!.deleteDatabase(dbName);
+      });
+    };
+
+void testTypes(testFunction) {
+  test('String', testFunction(123, 'Hoot!', equals('Hoot!')));
+  test('int', testFunction(123, 12345, equals(12345)));
+  test('List', testFunction(123, [1, 2, 3], equals([1, 2, 3])));
+  test('List 2', testFunction(123, [2, 3, 4], equals([2, 3, 4])));
+  test('bool', testFunction(123, [true, false], equals([true, false])));
+  test(
+      'largeInt',
+      testFunction(123, 1371854424211, equals("1371854424211"), null,
+          STORE_NAME, VERSION, true));
+  test(
+      'largeDoubleConvertedToInt',
+      testFunction(123, 1371854424211.0, equals("1371854424211"), null,
+          STORE_NAME, VERSION, true));
+  test(
+      'largeIntInMap',
+      testFunction(123, {'time': 4503599627370492},
+          equals("{time: 4503599627370492}"), null, STORE_NAME, VERSION, true));
+  var now = new DateTime.now();
+  test(
+      'DateTime',
+      testFunction(
+          123,
+          now,
+          predicate((date) =>
+              date.millisecondsSinceEpoch == now.millisecondsSinceEpoch)));
+}
+
+main() {
+  // Test that indexed_db is properly flagged as supported or not.
+  // Note that the rest of the indexed_db tests assume that this has been
+  // checked.
+  group('supported', () {
+    test('supported', () {
+      expect(idb.IdbFactory.supported, true);
+    });
+  });
+
+  group('functional', () {
+    test('throws when unsupported', () {
+      var expectation = idb.IdbFactory.supported ? returnsNormally : throws;
+
+      expect(() {
+        var db = html.window.indexedDB!;
+        db.open('random_db');
+      }, expectation);
+    });
+
+    // Don't bother with these tests if it's unsupported.
+    if (idb.IdbFactory.supported) {
+      test('upgrade', testUpgrade);
+      group('dynamic', () {
+        testTypes(testReadWrite);
+      });
+      group('typed', () {
+        testTypes(testReadWriteTyped);
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/indexeddb_2_test.dart b/tests/lib/html/indexeddb_2_test.dart
new file mode 100644
index 0000000..b13c3cf
--- /dev/null
+++ b/tests/lib/html/indexeddb_2_test.dart
@@ -0,0 +1,133 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 IndexedDB1Test;
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:indexed_db' as idb;
+import 'dart:collection';
+import 'utils.dart';
+
+// Write and re-read Maps: simple Maps; Maps with DAGs; Maps with cycles.
+
+const String DB_NAME = 'Test2';
+const String STORE_NAME = 'TEST';
+const int VERSION = 1;
+
+testReadWrite(key, value, check,
+    [dbName = DB_NAME, storeName = STORE_NAME, version = VERSION]) async {
+  void createObjectStore(e) {
+    idb.ObjectStore store = e.target.result.createObjectStore(storeName);
+    expect(store, isNotNull);
+  }
+
+  idb.Database? db;
+  // Delete any existing DBs.
+  try {
+    await html.window.indexedDB!.deleteDatabase(dbName);
+    db = await html.window.indexedDB!
+        .open(dbName, version: version, onUpgradeNeeded: createObjectStore);
+
+    idb.Transaction transaction = db!.transactionList([storeName], 'readwrite');
+    transaction.objectStore(storeName).put(value, key);
+
+    db = await transaction.completed;
+    transaction = db.transaction(storeName, 'readonly');
+    var object = await transaction.objectStore(storeName).getObject(key);
+
+    db.close();
+    check(value, object);
+  } catch (error) {
+    if (db != null) {
+      db.close();
+    }
+    throw error;
+  }
+}
+
+List<String> get nonNativeListData {
+  List<String> list = [];
+  list.add("data");
+  list.add("clone");
+  list.add("error");
+  list.add("test");
+  return list;
+}
+
+main() {
+  var obj1 = {'a': 100, 'b': 's'};
+  var obj2 = {'x': obj1, 'y': obj1}; // DAG.
+
+  var obj3 = {};
+  obj3['a'] = 100;
+  obj3['b'] = obj3; // Cycle.
+
+  var obj4 = new SplayTreeMap<String, dynamic>(); // Different implementation.
+  obj4['a'] = 100;
+  obj4['b'] = 's';
+
+  var cyclic_list = <Object>[1, 2, 3];
+  cyclic_list[1] = cyclic_list;
+
+  go(name, data) => testReadWrite(123, data, verifyGraph);
+
+  test('test_verifyGraph', () {
+    // Nice to know verifyGraph is working before we rely on it.
+    verifyGraph(obj4, obj4);
+    verifyGraph(obj1, new Map.from(obj1));
+    verifyGraph(obj4, new Map.from(obj4));
+
+    var l1 = [1, 2, 3];
+    var l2 = [
+      const [1, 2, 3],
+      const [1, 2, 3]
+    ];
+    verifyGraph([l1, l1], l2);
+    // Use a try-catch block, since failure can be an expect exception.
+    // package:expect does not allow catching test exceptions.
+    try {
+      verifyGraph([
+        [1, 2, 3],
+        [1, 2, 3]
+      ], l2);
+      fail("Expected failure in verifying the graph.");
+    } catch (_) {
+      // Expected failure. Continue.
+    }
+
+    verifyGraph(cyclic_list, cyclic_list);
+  });
+
+  // Don't bother with these tests if it's unsupported.
+  // Support is tested in indexeddb_1_test
+  if (idb.IdbFactory.supported) {
+    asyncTest(() async {
+      await go('test_simple', obj1);
+      await go('test_DAG', obj2);
+      await go('test_cycle', obj3);
+      await go('test_simple_splay', obj4);
+      await go('const_array_1', const [
+        const [1],
+        const [2]
+      ]);
+      await go('const_array_dag', const [
+        const [1],
+        const [1]
+      ]);
+      await go('array_deferred_copy', [1, 2, 3, obj3, obj3, 6]);
+      await go('array_deferred_copy_2', [
+        1,
+        2,
+        3,
+        [4, 5, obj3],
+        [obj3, 6]
+      ]);
+      await go('cyclic_list', cyclic_list);
+      await go('non-native lists', nonNativeListData);
+    });
+  }
+}
diff --git a/tests/lib/html/indexeddb_3_test.dart b/tests/lib/html/indexeddb_3_test.dart
new file mode 100644
index 0000000..2835aaf
--- /dev/null
+++ b/tests/lib/html/indexeddb_3_test.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.
+
+library IndexedDB3Test;
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:indexed_db';
+
+// Read with cursor.
+
+const String DB_NAME = 'Test3';
+const String STORE_NAME = 'TEST';
+const int VERSION = 1;
+
+Future<Database> createAndOpenDb() {
+  return html.window.indexedDB!.deleteDatabase(DB_NAME).then((_) {
+    return html.window.indexedDB!.open(DB_NAME, version: VERSION,
+        onUpgradeNeeded: (VersionChangeEvent e) {
+      var db = e.target.result;
+      db.createObjectStore(STORE_NAME);
+    });
+  });
+}
+
+Future<Database> writeItems(Database db) {
+  Future<Object> write(index) {
+    var transaction = db.transaction(STORE_NAME, 'readwrite');
+    transaction.objectStore(STORE_NAME).put('Item $index', index);
+    return transaction.completed;
+  }
+
+  var future = write(0);
+  for (var i = 1; i < 100; ++i) {
+    future = future.then((_) => write(i));
+  }
+
+  // Chain on the DB so we return it at the end.
+  return future.then((_) => db);
+}
+
+Future<Database> setupDb() {
+  return createAndOpenDb().then(writeItems);
+}
+
+Future<Database> readAllViaCursor(Database db) {
+  Transaction txn = db.transaction(STORE_NAME, 'readonly');
+  ObjectStore objectStore = txn.objectStore(STORE_NAME);
+  int itemCount = 0;
+  int sumKeys = 0;
+  var lastKey = null;
+
+  var cursors = objectStore.openCursor().asBroadcastStream();
+  cursors.listen((cursor) {
+    ++itemCount;
+    lastKey = cursor.key;
+    sumKeys += cursor.key as int;
+    expect(cursor.value, 'Item ${cursor.key}');
+    cursor.next();
+  });
+  cursors.last.then((cursor) {
+    expect(lastKey, 99);
+    expect(sumKeys, (100 * 99) ~/ 2);
+    expect(itemCount, 100);
+  });
+
+  return cursors.last.then((_) => db);
+}
+
+Future<Database> readAllReversedViaCursor(Database db) {
+  Transaction txn = db.transaction(STORE_NAME, 'readonly');
+  ObjectStore objectStore = txn.objectStore(STORE_NAME);
+  int itemCount = 0;
+  int sumKeys = 0;
+  var lastKey = null;
+
+  var cursors = objectStore.openCursor(direction: 'prev').asBroadcastStream();
+  cursors.listen((cursor) {
+    ++itemCount;
+    lastKey = cursor.key;
+    sumKeys += cursor.key as int;
+    expect(cursor.value, 'Item ${cursor.key}');
+    cursor.next();
+  });
+  cursors.last.then((cursor) {
+    expect(lastKey, 0);
+    expect(sumKeys, (100 * 99) ~/ 2);
+    expect(itemCount, 100);
+  });
+  return cursors.last.then((_) => db);
+}
+
+main() {
+  // Don't bother with these tests if it's unsupported.
+  // Support is tested in indexeddb_1_test
+  if (IdbFactory.supported) {
+    asyncTest(() async {
+      var db = await setupDb();
+      await readAllViaCursor(db);
+      await readAllReversedViaCursor(db);
+    });
+  }
+}
diff --git a/tests/lib/html/indexeddb_4_test.dart b/tests/lib/html/indexeddb_4_test.dart
new file mode 100644
index 0000000..c129225
--- /dev/null
+++ b/tests/lib/html/indexeddb_4_test.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.
+
+library IndexedDB4Test;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:indexed_db';
+
+// Test for KeyRange and Cursor.
+
+const String DB_NAME = 'Test4';
+const String STORE_NAME = 'TEST';
+const int VERSION = 1;
+
+Future<Database> createAndOpenDb() {
+  return html.window.indexedDB!.deleteDatabase(DB_NAME).then((_) {
+    return html.window.indexedDB!.open(DB_NAME, version: VERSION,
+        onUpgradeNeeded: (e) {
+      var db = e.target.result;
+      db.createObjectStore(STORE_NAME);
+    });
+  });
+}
+
+Future<Database> writeItems(Database db) {
+  Future<Object?> write(index) {
+    var transaction = db.transaction(STORE_NAME, 'readwrite');
+    return transaction
+        .objectStore(STORE_NAME)
+        .put({'content': 'Item $index'}, index) as Future<Object?>;
+  }
+
+  var future = write(0);
+  for (var i = 1; i < 100; ++i) {
+    future = future.then((_) => write(i));
+  }
+
+  // Chain on the DB so we return it at the end.
+  return future.then((_) => db);
+}
+
+Future<Database> setupDb() {
+  return createAndOpenDb().then(writeItems);
+}
+
+testRange(db, range, expectedFirst, expectedLast) {
+  Transaction txn = db.transaction(STORE_NAME, 'readonly');
+  ObjectStore objectStore = txn.objectStore(STORE_NAME);
+  var cursors = objectStore
+      .openCursor(range: range, autoAdvance: true)
+      .asBroadcastStream();
+
+  int lastKey = 0;
+  cursors.listen((cursor) {
+    lastKey = cursor.key as int;
+    var value = cursor.value;
+    expect(value['content'], 'Item ${cursor.key}');
+  });
+
+  if (expectedFirst != null) {
+    cursors.first.then((cursor) {
+      expect(cursor.key, expectedFirst);
+    });
+  }
+  if (expectedLast != null) {
+    cursors.last.then((cursor) {
+      expect(lastKey, expectedLast);
+    });
+  }
+
+  return cursors.length.then((length) {
+    if (expectedFirst == null) {
+      expect(length, 0);
+    } else {
+      expect(length, expectedLast - expectedFirst + 1);
+    }
+  });
+}
+
+main() async {
+  // Don't bother with these tests if it's unsupported.
+  // Support is tested in indexeddb_1_test
+  if (IdbFactory.supported) {
+    var db = await setupDb();
+    test('only1', () => testRange(db, new KeyRange.only(55), 55, 55));
+    test('only2', () => testRange(db, new KeyRange.only(100), null, null));
+    test('only3', () => testRange(db, new KeyRange.only(-1), null, null));
+
+    test('lower1', () => testRange(db, new KeyRange.lowerBound(40), 40, 99));
+    // OPTIONALS lower2() => testRange(db, new KeyRange.lowerBound(40, open: true), 41, 99);
+    test('lower2',
+        () => testRange(db, new KeyRange.lowerBound(40, true), 41, 99));
+    // OPTIONALS lower3() => testRange(db, new KeyRange.lowerBound(40, open: false), 40, 99);
+    test('lower3',
+        () => testRange(db, new KeyRange.lowerBound(40, false), 40, 99));
+
+    test('upper1', () => testRange(db, new KeyRange.upperBound(40), 0, 40));
+    // OPTIONALS upper2() => testRange(db, new KeyRange.upperBound(40, open: true), 0, 39);
+    test('upper2',
+        () => testRange(db, new KeyRange.upperBound(40, true), 0, 39));
+    // upper3() => testRange(db, new KeyRange.upperBound(40, open: false), 0, 40);
+    test('upper3',
+        () => testRange(db, new KeyRange.upperBound(40, false), 0, 40));
+
+    test('bound1', () => testRange(db, new KeyRange.bound(20, 30), 20, 30));
+
+    test('bound2', () => testRange(db, new KeyRange.bound(-100, 200), 0, 99));
+
+    bound3() =>
+        // OPTIONALS testRange(db, new KeyRange.bound(20, 30, upperOpen: true),
+        testRange(db, new KeyRange.bound(20, 30, false, true), 20, 29);
+
+    bound4() =>
+        // OPTIONALS testRange(db, new KeyRange.bound(20, 30, lowerOpen: true),
+        testRange(db, new KeyRange.bound(20, 30, true), 21, 30);
+
+    bound5() =>
+        // OPTIONALS testRange(db, new KeyRange.bound(20, 30, lowerOpen: true, upperOpen: true),
+        testRange(db, new KeyRange.bound(20, 30, true, true), 21, 29);
+  }
+}
diff --git a/tests/lib/html/indexeddb_5_test.dart b/tests/lib/html/indexeddb_5_test.dart
new file mode 100644
index 0000000..052a34d
--- /dev/null
+++ b/tests/lib/html/indexeddb_5_test.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 IndexedDB1Test;
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:indexed_db' as idb;
+
+var dbName = 'test_db_5';
+var storeName = 'test_store';
+var indexName = 'name_index';
+var db;
+var value = {'name_index': 'one', 'value': 'add_value'};
+
+Future testInit() async {
+  await html.window.indexedDB!.deleteDatabase(dbName);
+  db = await html.window.indexedDB!.open(dbName, version: 1,
+      onUpgradeNeeded: (idb.VersionChangeEvent e) {
+    var db = e.target.result;
+    var objectStore = db.createObjectStore(storeName, autoIncrement: true);
+    objectStore.createIndex(indexName, 'name_index', unique: false);
+  });
+}
+
+Future testAddDelete() async {
+  var transaction = db.transaction(storeName, 'readwrite');
+  var key = await transaction.objectStore(storeName).add(value);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  var readValue = await transaction.objectStore(storeName).getObject(key);
+  expect(readValue['value'], value['value']);
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readwrite');
+  await transaction.objectStore(storeName).delete(key);
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readonly');
+  var count = await transaction.objectStore(storeName).count();
+  expect(count, 0);
+}
+
+Future testClearCount() async {
+  var transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).add(value);
+
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  var count = await transaction.objectStore(storeName).count();
+  expect(count, 1);
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readwrite');
+  transaction.objectStore(storeName).clear();
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readonly');
+  count = await transaction.objectStore(storeName).count();
+  expect(count, 0);
+}
+
+Future testIndex() async {
+  var transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(value);
+
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readonly');
+  var index = transaction.objectStore(storeName).index(indexName);
+  var count = await index.count();
+  expect(count, 4);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  var cursorsLength = await index.openCursor(autoAdvance: true).length;
+  expect(cursorsLength, 4);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  cursorsLength = await index.openKeyCursor(autoAdvance: true).length;
+  expect(cursorsLength, 4);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  var readValue = await index.get('one');
+  expect(readValue['value'], value['value']);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).clear();
+  return transaction.completed;
+}
+
+Future testCursor() async {
+  var deleteValue = {'name_index': 'two', 'value': 'delete_value'};
+  var updateValue = {'name_index': 'three', 'value': 'update_value'};
+  var updatedValue = {'name_index': 'three', 'value': 'updated_value'};
+  var transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(deleteValue);
+  transaction.objectStore(storeName).add(updateValue);
+
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readwrite');
+  var index = transaction.objectStore(storeName).index(indexName);
+  var cursors = index.openCursor().asBroadcastStream();
+
+  cursors.listen((cursor) {
+    var value = cursor.value;
+    if (value['value'] == 'delete_value') {
+      cursor.delete().then((_) {
+        cursor.next();
+      });
+    } else if (value['value'] == 'update_value') {
+      cursor.update(updatedValue).then((_) {
+        cursor.next();
+      });
+    } else {
+      cursor.next();
+    }
+  });
+  await cursors.last;
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  var readValue = await index.get('three');
+  expect(readValue['value'], 'updated_value');
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  readValue = await index.get('two');
+  expect(readValue, isNull);
+  return transaction.completed;
+}
+
+main() {
+  if (!idb.IdbFactory.supported) {
+    return;
+  }
+  asyncTest(() async {
+    await testInit();
+    await testAddDelete();
+    await testClearCount();
+    await testIndex();
+    await testCursor();
+  });
+}
diff --git a/tests/lib/html/input_element_attributes_test.dart b/tests/lib/html/input_element_attributes_test.dart
new file mode 100644
index 0000000..09730b9
--- /dev/null
+++ b/tests/lib/html/input_element_attributes_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+@pragma('dart2js:noInline')
+returnNothing() {}
+
+// Gets an undefined value from JS.
+dynamic _undefined = returnNothing();
+
+main() {
+  test('valueSetNull', () {
+    final e = new TextInputElement();
+    e.value = null;
+    expect(e.value, '');
+  });
+  test('valueSetNullProxy', () {
+    final e = new TextInputElement();
+    e.value = _undefined;
+    expect(e.value, 'undefined');
+  });
+}
diff --git a/tests/lib/html/input_element_constructor_test.dart b/tests/lib/html/input_element_constructor_test.dart
new file mode 100644
index 0000000..43a6e79
--- /dev/null
+++ b/tests/lib/html/input_element_constructor_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+void check(element, String type, [bool supported = true]) {
+  expect(element is InputElement, true);
+  if (supported) {
+    expect(element.type, type);
+  } else {
+    expect(element.type, 'text');
+  }
+}
+
+main() {
+  test('hidden', () {
+    check(new HiddenInputElement(), 'hidden');
+  });
+
+  test('search', () {
+    check(new SearchInputElement(), 'search', SearchInputElement.supported);
+  });
+
+  test('text', () {
+    check(new TextInputElement(), 'text');
+  });
+
+  test('url', () {
+    check(new UrlInputElement(), 'url', UrlInputElement.supported);
+  });
+
+  test('telephone', () {
+    check(new TelephoneInputElement(), 'tel', TelephoneInputElement.supported);
+  });
+
+  test('email', () {
+    check(new EmailInputElement(), 'email', EmailInputElement.supported);
+  });
+
+  test('password', () {
+    check(new PasswordInputElement(), 'password');
+  });
+
+  test('date', () {
+    check(new DateInputElement(), 'date', DateInputElement.supported);
+  });
+
+  test('month', () {
+    check(new MonthInputElement(), 'month', MonthInputElement.supported);
+  });
+
+  test('week', () {
+    check(new WeekInputElement(), 'week', WeekInputElement.supported);
+  });
+
+  test('time', () {
+    check(new TimeInputElement(), 'time', TimeInputElement.supported);
+    if (TimeInputElement.supported) {
+      var element = new TimeInputElement();
+      var now = new DateTime.now();
+      element.valueAsDate = now;
+      expect(element.valueAsDate is DateTime, isTrue);
+
+      // Bug 8813, setting it is just going to the epoch.
+      //expect(element.valueAsDate, now);
+    }
+  });
+
+  test('datetime-local', () {
+    check(new LocalDateTimeInputElement(), 'datetime-local',
+        LocalDateTimeInputElement.supported);
+  });
+
+  test('number', () {
+    check(new NumberInputElement(), 'number', NumberInputElement.supported);
+  });
+
+  test('range', () {
+    check(new RangeInputElement(), 'range', RangeInputElement.supported);
+  });
+
+  test('checkbox', () {
+    check(new CheckboxInputElement(), 'checkbox');
+  });
+
+  test('radio', () {
+    check(new RadioButtonInputElement(), 'radio');
+  });
+
+  test('file', () {
+    check(new FileUploadInputElement(), 'file');
+  });
+
+  test('submit', () {
+    check(new SubmitButtonInputElement(), 'submit');
+  });
+
+  test('image', () {
+    check(new ImageButtonInputElement(), 'image');
+  });
+
+  test('reset', () {
+    check(new ResetButtonInputElement(), 'reset');
+  });
+
+  test('button', () {
+    check(new ButtonInputElement(), 'button');
+  });
+}
diff --git a/tests/lib/html/input_element_date_test.dart b/tests/lib/html/input_element_date_test.dart
new file mode 100644
index 0000000..6d24371
--- /dev/null
+++ b/tests/lib/html/input_element_date_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(DateInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_datetime_test.dart b/tests/lib/html/input_element_datetime_test.dart
new file mode 100644
index 0000000..ee7acd0
--- /dev/null
+++ b/tests/lib/html/input_element_datetime_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(LocalDateTimeInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_email_test.dart b/tests/lib/html/input_element_email_test.dart
new file mode 100644
index 0000000..2f65bae
--- /dev/null
+++ b/tests/lib/html/input_element_email_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(EmailInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_month_test.dart b/tests/lib/html/input_element_month_test.dart
new file mode 100644
index 0000000..0668d81
--- /dev/null
+++ b/tests/lib/html/input_element_month_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(MonthInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_number_test.dart b/tests/lib/html/input_element_number_test.dart
new file mode 100644
index 0000000..17bd37b
--- /dev/null
+++ b/tests/lib/html/input_element_number_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(NumberInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_range_test.dart b/tests/lib/html/input_element_range_test.dart
new file mode 100644
index 0000000..c6d21cd
--- /dev/null
+++ b/tests/lib/html/input_element_range_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(RangeInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_search_test.dart b/tests/lib/html/input_element_search_test.dart
new file mode 100644
index 0000000..7e57334
--- /dev/null
+++ b/tests/lib/html/input_element_search_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(SearchInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_tel_test.dart b/tests/lib/html/input_element_tel_test.dart
new file mode 100644
index 0000000..de7919c
--- /dev/null
+++ b/tests/lib/html/input_element_tel_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(TelephoneInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_time_test.dart b/tests/lib/html/input_element_time_test.dart
new file mode 100644
index 0000000..c5a8477
--- /dev/null
+++ b/tests/lib/html/input_element_time_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(TimeInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_url_test.dart b/tests/lib/html/input_element_url_test.dart
new file mode 100644
index 0000000..8b14ca0
--- /dev/null
+++ b/tests/lib/html/input_element_url_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(UrlInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/input_element_week_test.dart b/tests/lib/html/input_element_week_test.dart
new file mode 100644
index 0000000..35430cc
--- /dev/null
+++ b/tests/lib/html/input_element_week_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('supported', () {
+    expect(WeekInputElement.supported, true);
+  });
+}
diff --git a/tests/lib/html/instance_of_test.dart b/tests/lib/html/instance_of_test.dart
new file mode 100644
index 0000000..9ee04b3
--- /dev/null
+++ b/tests/lib/html/instance_of_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+main() {
+  var canvas;
+
+  canvas = new Element.tag('canvas');
+  canvas.attributes['width'] = '100';
+  canvas.attributes['height'] = '100';
+  document.body!.append(canvas);
+
+  var isCanvasRenderingContext = predicate(
+      (x) => x is CanvasRenderingContext, 'is a CanvasRenderingContext');
+  var isNotCanvasRenderingContext = predicate(
+      (x) => x is! CanvasRenderingContext, 'is not a CanvasRenderingContext');
+  var isCanvasRenderingContext2D = predicate(
+      (x) => x is CanvasRenderingContext2D, 'is a CanvasRenderingContext2D');
+  var isNotCanvasRenderingContext2D = predicate(
+      (x) => x is! CanvasRenderingContext2D,
+      'is not a CanvasRenderingContext2D');
+  var isElement = predicate((x) => x is Element, 'is an Element');
+  var isNotElement = predicate((x) => x is! Element, 'is not an Element');
+  var isCanvasElement =
+      predicate((x) => x is CanvasElement, 'is a CanvasElement');
+  var isNotCanvasElement =
+      predicate((x) => x is! CanvasElement, 'is not a CanvasElement');
+  var isImageData = predicate((x) => x is ImageData, 'is an ImageData');
+  var isNotImageData = predicate((x) => x is! ImageData, 'is not an ImageData');
+  //var isUint8ClampedArray =
+  //  predicate((x) => x is Uint8ClampedArray, 'is a Uint8ClampedArray');
+  var isIntList = predicate((x) => x is List<int>, 'is a List<int>');
+
+  test('Instanceof', () {
+    expect(canvas, isNotCanvasRenderingContext);
+    expect(canvas, isNotCanvasRenderingContext2D);
+    expect(canvas, isElement);
+    expect(canvas, isCanvasElement);
+    expect(canvas, isNotImageData);
+    // expect(canvas, isNot(isCanvasPixelArray));
+
+    var context = canvas.getContext('2d');
+    expect(context, isCanvasRenderingContext);
+    expect(context, isCanvasRenderingContext2D);
+    expect(context, isNotElement);
+    expect(context, isNotCanvasElement);
+    expect(context, isNotImageData);
+    // expect(context, isNot(isCanvasPixelArray));
+
+    // FIXME(b/5286633): Interface injection type check workaround.
+    var image = (context as CanvasRenderingContext2D)
+        .createImageData(canvas.width as dynamic, canvas.height as dynamic);
+    expect(image, isNotCanvasRenderingContext);
+    expect(image, isNotCanvasRenderingContext2D);
+    expect(image, isNotElement);
+    expect(image, isNotCanvasElement);
+    expect(image, isImageData);
+    // expect(image, isNot(isCanvasPixelArray));
+
+    // Include CanvasPixelArray since constructor and prototype are not
+    // available until one is created.
+    var bytes = image.data;
+    expect(bytes, isNotCanvasRenderingContext);
+    expect(bytes, isNotCanvasRenderingContext2D);
+    expect(bytes, isNotElement);
+    expect(bytes, isNotCanvasElement);
+    expect(bytes, isNotImageData);
+    expect(bytes, isIntList);
+
+    // FIXME: Ensure this is an SpanElement when we next update
+    // WebKit IDL.
+    var span = new Element.tag('span');
+    expect(span, isElement);
+  });
+}
diff --git a/tests/lib/html/interactive_geolocation_test.dart b/tests/lib/html/interactive_geolocation_test.dart
new file mode 100644
index 0000000..1ad3a13
--- /dev/null
+++ b/tests/lib/html/interactive_geolocation_test.dart
@@ -0,0 +1,32 @@
+// 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 interactive_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'utils.dart';
+
+Future testGetCurrentPosition() async {
+  var position = await window.navigator.geolocation.getCurrentPosition();
+  Expect.isNotNull(position.coords.latitude);
+  Expect.isNotNull(position.coords.longitude);
+  Expect.isNotNull(position.coords.accuracy);
+}
+
+Future testWatchPosition() async {
+  var position = await window.navigator.geolocation.watchPosition().first;
+  Expect.isNotNull(position.coords.latitude);
+  Expect.isNotNull(position.coords.longitude);
+  Expect.isNotNull(position.coords.accuracy);
+}
+
+main() {
+  asyncTest(() async {
+    await testGetCurrentPosition();
+    await testWatchPosition();
+  });
+}
diff --git a/tests/lib/html/interactive_media_test.dart b/tests/lib/html/interactive_media_test.dart
new file mode 100644
index 0000000..840e16a
--- /dev/null
+++ b/tests/lib/html/interactive_media_test.dart
@@ -0,0 +1,96 @@
+// 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 interactive_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+import 'package:async_helper/async_helper.dart';
+
+// NOTE: To test enable chrome://flags/#enable-experimental-web-platform-features
+
+main() async {
+  if (MediaStream.supported) {
+    test('getUserMedia audio', () async {
+      try {
+        var mediaStream = await window.navigator.getUserMedia(audio: true);
+        expect(mediaStream, isNotNull);
+        expect(mediaStream is MediaStream, true);
+        var devices = window.navigator.mediaDevices;
+        var enumDevices = await devices.enumerateDevices();
+        expect(enumDevices.length > 1, true);
+        for (var device in enumDevices) {
+          var goodDevLabel = device.label.endsWith('Built-in Output') ||
+              device.label.endsWith('Built-in Microphone');
+          expect(goodDevLabel, true);
+        }
+      } catch (e) {
+        // Could fail if bot machine doesn't support audio or video.
+        expect(e.name == DomException.NOT_FOUND, true);
+      }
+    });
+
+    test('getUserMedia', () {
+      return window.navigator.getUserMedia(video: true).then((stream) {
+        expect(stream, isNotNull);
+
+        var url = Url.createObjectUrlFromStream(stream);
+        expect(url, isNotNull);
+
+        var video = new VideoElement()..autoplay = true;
+
+        var completer = new Completer();
+        video.onError.listen((e) {
+          completer.completeError(e);
+        });
+        video.onPlaying.first.then((e) {
+          completer.complete(video);
+        });
+
+        document.body!.append(video);
+        video.src = url;
+
+        return completer.future;
+      }).catchError((e) {
+        // Could fail if bot machine doesn't support audio or video.
+        expect(e.name == DomException.NOT_FOUND, true);
+      });
+    });
+
+    test('getUserMediaComplexConstructor', () {
+      return window.navigator.getUserMedia(video: {
+        'mandatory': {'minAspectRatio': 1.333, 'maxAspectRatio': 1.334},
+        'optional': [
+          {'minFrameRate': 60},
+          {'maxWidth': 640}
+        ]
+      }).then((stream) {
+        expect(stream, isNotNull);
+
+        var url = Url.createObjectUrlFromStream(stream);
+        expect(url, isNotNull);
+
+        var video = new VideoElement()..autoplay = true;
+
+        var completer = new Completer();
+        video.onError.listen((e) {
+          completer.completeError(e);
+        });
+        video.onPlaying.first.then((e) {
+          completer.complete(video);
+        });
+
+        document.body!.append(video);
+        video.src = url;
+
+        return completer.future;
+      }).catchError((e) {
+        // Could fail if bot machine doesn't support audio or video.
+        expect(e.name == DomException.NOT_FOUND, true);
+      });
+    });
+  }
+}
diff --git a/tests/lib/html/interactive_test.dart b/tests/lib/html/interactive_test.dart
new file mode 100644
index 0000000..86b1e6c
--- /dev/null
+++ b/tests/lib/html/interactive_test.dart
@@ -0,0 +1,55 @@
+// 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 interactive_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:expect/minitest.dart';
+import 'utils.dart';
+
+main() {
+  group('KeyEvent', () {
+    keydownHandlerTest(KeyEvent e) {
+      document.body!.innerHtml =
+          '${document.body!.innerHtml}KeyDOWN: CharCode: ${e.charCode}, '
+          'KeyCode: ${e.keyCode}<br />';
+      expect(e.charCode, 0);
+    }
+
+    keypressHandlerTest(KeyEvent e) {
+      document.body!.innerHtml =
+          '${document.body!.innerHtml}KeyPRESS: CharCode: ${e.charCode}, '
+          'KeyCode: ${e.keyCode}<br />';
+    }
+
+    keyupHandlerTest(KeyEvent e) {
+      document.body!.innerHtml =
+          '${document.body!.innerHtml}KeyUP: CharCode: ${e.charCode}, KeyCode:'
+          ' ${e.keyCode}<br />';
+      expect(e.charCode, 0);
+    }
+
+    keyupHandlerTest2(KeyEvent e) {
+      document.body!.innerHtml =
+          '${document.body!.innerHtml}A second KeyUP handler: CharCode: '
+          '${e.charCode}, KeyCode: ${e.keyCode}<br />';
+      expect(e.charCode, 0);
+    }
+
+    test('keys', () {
+      document.body!.innerHtml =
+          '${document.body!.innerHtml}To test keyboard event values, press '
+          'some keys on your keyboard.<br /><br />The charcode for keydown and '
+          'keyup should be 0, and the keycode should (generally) be populated '
+          'with a value. Keycode and charcode should both have values for the '
+          'keypress event.';
+      KeyboardEventStream.onKeyDown(document.body!).listen(keydownHandlerTest);
+      KeyboardEventStream.onKeyPress(document.body!)
+          .listen(keypressHandlerTest);
+      KeyboardEventStream.onKeyUp(document.body!).listen(keyupHandlerTest);
+      KeyboardEventStream.onKeyUp(document.body!).listen(keyupHandlerTest2);
+    });
+  });
+}
diff --git a/tests/lib/html/isolates_test.dart b/tests/lib/html/isolates_test.dart
new file mode 100644
index 0000000..bec82b3
--- /dev/null
+++ b/tests/lib/html/isolates_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.
+
+library IsolatesTest;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:async';
+import 'dart:html';
+import 'dart:convert';
+import 'dart:isolate' as isolate;
+
+String responseFor(message) => 'response for $message';
+
+void isolateEntry(isolate.SendPort initialReplyTo) {
+  var port = new isolate.ReceivePort();
+  initialReplyTo.send(port.sendPort);
+
+  bool wasThrown = false;
+  try {
+    window.alert('Test');
+  } catch (e) {
+    wasThrown = true;
+  }
+  // If wasn't thrown, do not listen to messages to make test fail.
+  if (!wasThrown) {
+    return;
+  }
+
+  // Check that convert library was loaded to isolate.
+  json.encode([1, 2, 3]);
+
+  port.listen((message) {
+    var data = message[0];
+    var replyTo = message[1];
+    replyTo.send(responseFor(data));
+  });
+}
+
+Future sendReceive(isolate.SendPort port, msg) {
+  var response = new isolate.ReceivePort();
+  port.send([msg, response.sendPort]);
+  return response.first;
+}
+
+main() {
+  test('IsolateSpawn', () {
+    var port = new isolate.ReceivePort();
+    isolate.Isolate.spawn(isolateEntry, port.sendPort);
+    port.close();
+  });
+  test('NonDOMIsolates', () {
+    var callback = expectAsync(() {});
+    var response = new isolate.ReceivePort();
+    var remote = isolate.Isolate.spawn(isolateEntry, response.sendPort);
+    response.first.then((port) {
+      final msg1 = 'foo';
+      final msg2 = 'bar';
+      sendReceive(port, msg1).then((response) {
+        expect(response, equals(responseFor(msg1)));
+        sendReceive(port, msg2).then((response) {
+          expect(response, equals(responseFor(msg2)));
+          callback();
+        });
+      });
+    });
+  });
+}
diff --git a/tests/lib/html/js_array_test.dart b/tests/lib/html/js_array_test.dart
new file mode 100644
index 0000000..1775ed4
--- /dev/null
+++ b/tests/lib/html/js_array_test.dart
@@ -0,0 +1,675 @@
+// 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.
+
+@JS("ArrayTest.Util")
+library js_array_test;
+
+import 'dart:html';
+
+import 'dart:js' as js;
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+import 'json_helper.dart' as json_helper;
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+ArrayTest = {};
+ArrayTest.Util = {
+  callJsMethod: function(jsObj, jsMethodName, args) {
+    return jsObj[jsMethodName].apply(jsObj, args);
+  },
+
+  jsEnumerateIndices: function(obj) {
+    var ret = [];
+    for(var i in obj) {
+      ret.push(i);
+    }
+    return ret;
+  },
+
+  checkIsArray: function(obj) {
+    return Array.isArray(obj);
+  },
+
+  concatValues: function(obj) {
+    return obj.concat("a", "b", ["c", "d"], 42, {foo: 10});
+  },
+
+  concatOntoArray: function(obj) {
+    return [1,2,3].concat(obj, "foo");
+  },
+
+  repeatedConcatOntoArray: function(obj) {
+    return [1,2,3].concat(obj, obj);
+  },
+
+  everyGreaterThanZero: function(obj) {
+    return obj.every(function(currentValue, index, array) {
+      return currentValue > 0;
+    });
+  },
+
+  everyGreaterThanZeroCheckThisArg: function(obj) {
+    var j = 0;
+    return obj.every(function(currentValue, index, array) {
+      if (j != index) {
+        throw "Unxpected index";
+      }
+      j++;
+      if (array !== obj) {
+        throw "Array argument doesn't match obj";
+      }
+      return currentValue > 0;
+    });
+  },
+
+  filterGreater42: function(obj) {
+    return obj.filter(function(currentValue, index, array) {
+      return currentValue > 42;
+    });
+  },
+
+  forEachCollectResult: function(array) {
+    var result = [];
+    array.forEach(function(currentValue) {
+      result.push(currentValue * 2);
+    });
+    return result;
+  },
+
+  someEqual42: function(array) {
+    return array.some(function(currentValue) {
+      return currentValue == 42;
+    });
+  },
+
+  sortNumbersBackwards: function(array) {
+    return array.sort(function(a, b) {
+      return b - a;
+    });
+  },
+
+  spliceDummyItems: function(array) {
+    return array.splice(1, 2, "quick" ,"brown", "fox");
+  },
+
+  spliceTestStringArgs: function(array) {
+    return array.splice("1.2", "2.01", "quick" ,"brown", "fox");
+  },
+
+  splicePastEnd: function(array) {
+    return array.splice(1, 5332, "quick" ,"brown", "fox");
+  },
+
+  callJsToString: function(array) {
+    return array.toString();
+  },
+
+  mapAddIndexToEachElement: function(array) {
+    return array.map(function(currentValue, index) {
+      return currentValue + index;
+    });
+  },
+
+  reduceSumDoubledElements: function(array) {
+    return array.reduce(function(previousValue, currentValue) {
+          return previousValue + currentValue*2;
+        },
+        0);
+  },
+
+  // TODO(jacobr): add a test that distinguishes reduce from reduceRight.
+  reduceRightSumDoubledElements: function(array) {
+    return array.reduceRight(function(previousValue, currentValue) {
+          return previousValue + currentValue*2;
+        },
+        0);
+  },
+
+  getOwnPropertyDescriptor: function(array, property) {
+    return Object.getOwnPropertyDescriptor(array, property);
+  },
+
+  setLength: function(array, len) {
+    return array.length = len;
+  },
+
+  getValue: function(obj, index) {
+    return obj[index];
+  },
+
+  setValue: function(obj, index, value) {
+    return obj[index] = value;
+  },
+
+  // Calling a method from Dart List on an arbitrary target object.
+  callListMethodOnTarget: function(dartArray, target, methodName, args) {
+    return dartArray[methodName].apply(target, args);
+  },
+
+  newArray: function() { return []; },
+
+  newLiteral: function() { return {}; },
+
+};
+""");
+}
+
+@JS()
+class PropertyDescriptor {
+  external get value;
+  external bool get writable;
+  external bool get enumerable;
+  external bool get configurable;
+}
+
+@JS()
+class SimpleJsLiteralClass {
+  external get foo;
+}
+
+class Foo {}
+
+@JS()
+external callJsMethod(List array, String methodName, List args);
+
+callIndexOf(List array, value) => callJsMethod(array, "indexOf", [value]);
+callLastIndexOf(List array, value) =>
+    callJsMethod(array, "lastIndexOf", [value]);
+
+callPop(List array) => callJsMethod(array, "pop", []);
+callPush(List array, element) => callJsMethod(array, "push", [element]);
+callShift(List array) => callJsMethod(array, "shift", []);
+callReverse(List array) => callJsMethod(array, "reverse", []);
+
+callListMethodOnObject(object, String methodName, List args) =>
+    callListMethodOnTarget([], object, methodName, args);
+
+@JS()
+external jsEnumerateIndices(obj);
+@JS()
+external bool checkIsArray(obj);
+@JS()
+external concatValues(obj);
+
+@JS()
+external concatOntoArray(obj);
+
+@JS()
+external repeatedConcatOntoArray(obj);
+@JS()
+external bool everyGreaterThanZero(obj);
+@JS()
+external bool everyGreaterThanZeroCheckThisArg(obj);
+
+@JS()
+external filterGreater42(obj);
+
+@JS()
+external forEachCollectResult(List array);
+@JS()
+external someEqual42(List array);
+@JS()
+external sortNumbersBackwards(List array);
+
+@JS()
+external List spliceDummyItems(List array);
+
+@JS()
+external List spliceTestStringArgs(List array);
+
+@JS()
+external List splicePastEnd(List array);
+
+@JS()
+external String callJsToString(List array);
+
+@JS()
+external mapAddIndexToEachElement(List array);
+@JS()
+external reduceSumDoubledElements(List array);
+
+// TODO(jacobr): add a test that distinguishes reduce from reduceRight.
+@JS()
+external reduceRightSumDoubledElements(List array);
+
+@JS()
+external PropertyDescriptor getOwnPropertyDescriptor(obj, property);
+
+@JS("setLength")
+external callSetLength(List array, length);
+
+@JS()
+external getValue(obj, index);
+
+@JS()
+external setValue(obj, index, value);
+
+@JS()
+external callListMethodOnTarget(
+    List target, object, String methodName, List args);
+
+@JS()
+external newArray();
+
+@JS()
+external newLiteral();
+
+main() {
+  _injectJs();
+
+  group('indexOf', () {
+    var div = new DivElement();
+    var list = [3, 42, "foo", 42, div];
+    test('found', () {
+      expect(callIndexOf(list, 3), equals(0));
+      expect(callIndexOf(list, 42), equals(1));
+      expect(callIndexOf(list, "foo"), equals(2));
+      expect(callIndexOf(list, div), equals(4));
+    });
+
+    test('missing', () {
+      expect(callIndexOf(list, 31), equals(-1));
+      expect(callIndexOf(list, "42"), equals(-1));
+      expect(callIndexOf(list, null), equals(-1));
+    });
+  });
+
+  group('set length', () {
+    test('larger', () {
+      var list = ["a", "b", "c", "d"];
+      expect(callSetLength(list, 10), equals(10));
+      expect(list.length, equals(10));
+      expect(list.last, equals(null));
+      expect(list[3], equals("d"));
+    });
+
+    test('smaller', () {
+      var list = ["a", "b", "c", "d"];
+      expect(callSetLength(list, 2), equals(2));
+      expect(list.first, equals("a"));
+      expect(list.last, equals("b"));
+      expect(list.length, equals(2));
+      expect(callSetLength(list, 0), equals(0));
+      expect(list.length, equals(0));
+      expect(callSetLength(list, 2), equals(2));
+      expect(list.first, equals(null));
+    });
+
+    test('invalid', () {
+      var list = ["a", "b", "c", "d"];
+      expect(() => callSetLength(list, 2.3), throws);
+      expect(list.length, equals(4));
+      expect(() => callSetLength(list, -1), throws);
+      expect(list.length, equals(4));
+      // Make sure we are coercing to a JS number.
+      expect(callSetLength(list, "2"), equals("2"));
+      expect(list.length, equals(2));
+    });
+  });
+
+  group('join', () {
+    var list = [3, 42, "foo"];
+    var listWithDartClasses = [3, new Foo(), 42, "foo", new Object()];
+    test('default', () {
+      expect(callJsMethod(list, "join", []), equals("3,42,foo"));
+      expect(callJsMethod(listWithDartClasses, "join", []),
+          equals("3,${new Foo()},42,foo,${new Object()}"));
+    });
+
+    test('custom separator', () {
+      expect(callJsMethod(list, "join", ["##"]), equals("3##42##foo"));
+    });
+  });
+
+  group('lastIndexOf', () {
+    var list = [3, 42, "foo", 42];
+    test('found', () {
+      expect(callLastIndexOf(list, 3), equals(0));
+      expect(callLastIndexOf(list, 42), equals(3));
+      expect(callLastIndexOf(list, "foo"), equals(2));
+    });
+
+    test('missing', () {
+      expect(callLastIndexOf(list, 31), equals(-1));
+      expect(callLastIndexOf(list, "42"), equals(-1));
+      expect(callLastIndexOf(list, null), equals(-1));
+    });
+  });
+
+  group('pop', () {
+    test('all', () {
+      var foo = new Foo();
+      var div = new DivElement();
+      var list = [3, 42, "foo", foo, div];
+      expect(callPop(list), equals(div));
+      expect(list.length, equals(4));
+      expect(callPop(list), equals(foo));
+      expect(list.length, equals(3));
+      expect(callPop(list), equals("foo"));
+      expect(list.length, equals(2));
+      expect(callPop(list), equals(42));
+      expect(list.length, equals(1));
+      expect(callPop(list), equals(3));
+      expect(list.length, equals(0));
+      expect(callPop(list), equals(null));
+      expect(list.length, equals(0));
+    });
+  });
+
+  group('push', () {
+    test('strings', () {
+      var list = [];
+      var div = new DivElement();
+      expect(callPush(list, "foo"), equals(1));
+      expect(callPush(list, "bar"), equals(2));
+      // Calling push with 0 elements should do nothing.
+      expect(callJsMethod(list, "push", []), equals(2));
+      expect(callPush(list, "baz"), equals(3));
+      expect(callPush(list, div), equals(4));
+      expect(callJsMethod(list, "push", ["a", "b"]), equals(6));
+      expect(list, equals(["foo", "bar", "baz", div, "a", "b"]));
+    });
+  });
+
+  group('shift', () {
+    test('all', () {
+      var foo = new Foo();
+      var div = new DivElement();
+      var list = [3, 42, "foo", foo, div];
+      expect(callShift(list), equals(3));
+      expect(list.length, equals(4));
+      expect(callShift(list), equals(42));
+      expect(list.length, equals(3));
+      expect(callShift(list), equals("foo"));
+      expect(list.length, equals(2));
+      expect(callShift(list), equals(foo));
+      expect(list.length, equals(1));
+      expect(callShift(list), equals(div));
+      expect(list.length, equals(0));
+      expect(callShift(list), equals(null));
+      expect(list.length, equals(0));
+    });
+  });
+
+  group('reverse', () {
+    test('simple', () {
+      var foo = new Foo();
+      var div = new DivElement();
+      var list = [div, 42, foo];
+      callReverse(list);
+      expect(list, equals([foo, 42, div]));
+      list = [3, 42];
+      callReverse(list);
+      expect(list, equals([42, 3]));
+    });
+  });
+
+  group('slice', () {
+    test('copy', () {
+      var foo = new Foo();
+      var div = new DivElement();
+      var list = [3, 42, "foo", foo, div];
+      var copy = callJsMethod(list, "slice", []);
+      expect(identical(list, copy), isFalse);
+      expect(copy.length, equals(list.length));
+      for (var i = 0; i < list.length; i++) {
+        expect(list[i], equals(copy[i]));
+      }
+      expect(identical(list[3], copy[3]), isTrue);
+      expect(identical(list[4], copy[4]), isTrue);
+
+      copy.add("dummy");
+      expect(list.length + 1, equals(copy.length));
+    });
+
+    test('specify start', () {
+      var list = [3, 42, "foo"];
+      var copy = callJsMethod(list, "slice", [1]);
+      expect(copy.first, equals(42));
+    });
+
+    test('specify start and end', () {
+      var list = [3, 42, 92, "foo"];
+      var copy = callJsMethod(list, "slice", [1, 3]);
+      expect(copy.first, equals(42));
+      expect(copy.last, equals(92));
+    });
+
+    test('from end', () {
+      var list = [3, 42, 92, "foo"];
+      expect(callJsMethod(list, "slice", [-2]), equals([92, "foo"]));
+
+      // Past the end of the front of the array.
+      expect(callJsMethod(list, "slice", [-2, 3]), equals([92]));
+
+      // Past the end of the front of the array.
+      expect(callJsMethod(list, "slice", [-10, 2]), equals([3, 42]));
+    });
+  });
+
+  group("js snippet tests", () {
+    test("enumerate indices", () {
+      var list = ["a", "b", "c", "d"];
+      var indices = jsEnumerateIndices(list);
+      expect(indices.length, equals(4));
+      for (int i = 0; i < 4; i++) {
+        expect(indices[i], equals('$i'));
+      }
+    });
+
+    test("set element", () {
+      var list = ["a", "b", "c", "d"];
+      setValue(list, 0, 42);
+      expect(list[0], equals(42));
+      setValue(list, 1, 84);
+      expect(list[1], equals(84));
+      setValue(list, 6, 100); // Off the end of the list.
+      expect(list.length, equals(7));
+      expect(list[4], equals(null));
+      expect(list[6], equals(100));
+
+      // These tests have to be commented out because we don't persist
+      // JS proxies for Dart objects like we could/should.
+      // setValue(list, -1, "foo"); // Not a valid array index
+      // expect(getValue(list, -1), equals("foo"));
+      // expect(getValue(list, "-1"), equals("foo"));
+    });
+
+    test("get element", () {
+      var list = ["a", "b", "c", "d"];
+      expect(getValue(list, 0), equals("a"));
+      expect(getValue(list, 1), equals("b"));
+      expect(getValue(list, 6), equals(null));
+      expect(getValue(list, -1), equals(null));
+
+      expect(getValue(list, "0"), equals("a"));
+      expect(getValue(list, "1"), equals("b"));
+    });
+
+    test("is array", () {
+      var list = ["a", "b"];
+      expect(checkIsArray(list), isTrue);
+    });
+
+    test("property descriptors", () {
+      // This test matters to make behavior consistent with JS native arrays
+      // and to make devtools integration work well.
+      var list = ["a", "b"];
+      var descriptor = getOwnPropertyDescriptor(list, 0);
+
+      expect(descriptor.value, equals("a"));
+      expect(descriptor.writable, isTrue);
+      // TODO(jacobr): commented out until https://github.com/dart-lang/sdk/issues/26128
+      // is fixed.
+      // expect(descriptor.enumerable, isTrue);
+      // expect(descriptor.configurable, isTrue);
+
+      descriptor = getOwnPropertyDescriptor(list, "length");
+      expect(descriptor.value, equals(2));
+      expect(descriptor.writable, isTrue);
+      expect(descriptor.enumerable, isFalse);
+      expect(descriptor.configurable, isFalse);
+    });
+
+    test("concat js arrays", () {
+      var list = ["1", "2"];
+      // Tests that calling the concat method from JS will flatten out JS arrays
+      // We concat the array with "a", "b", ["c", "d"], 42, {foo: 10}
+      // which should generate ["1", "2", "a", "b", ["c", "d"], 42, {foo: 10}]
+      var ret = concatValues(list);
+      expect(list.length, equals(2));
+      expect(ret.length, equals(8));
+      expect(ret[0], equals("1"));
+      expect(ret[3], equals("b"));
+      expect(ret[5], equals("d"));
+      expect(ret[6], equals(42));
+      dynamic item = ret[7];
+      expect(item.foo, equals(10));
+    });
+
+    test("concat onto arrays", () {
+      // This test only passes if we have monkey patched the core Array object
+      // prototype to handle Dart Lists.
+      var list = ["a", "b"];
+      var ret = concatOntoArray(list);
+      expect(list.length, equals(2));
+      expect(ret, equals([1, 2, 3, "a", "b", "foo"]));
+    });
+
+    test("dart arrays on dart arrays", () {
+      // This test only passes if we have monkey patched the core Array object
+      // prototype to handle Dart Lists.
+      var list = ["a", "b"];
+      var ret = callJsMethod(list, "concat", [
+        ["c", "d"],
+        "e",
+        ["f", "g"]
+      ]);
+      expect(list.length, equals(2));
+      expect(ret, equals(["a", "b", "c", "d", "e", "f", "g"]));
+    });
+
+    test("every greater than zero", () {
+      expect(everyGreaterThanZero([1, 5]), isTrue);
+      expect(everyGreaterThanZeroCheckThisArg([1, 5]), isTrue);
+      expect(everyGreaterThanZero([1, 0]), isFalse);
+      expect(everyGreaterThanZero([]), isTrue);
+    });
+
+    test("filter greater than 42", () {
+      expect(filterGreater42([1, 5]), equals([]));
+      expect(filterGreater42([43, 5, 49]), equals([43, 49]));
+      expect(filterGreater42(["43", "5", "49"]), equals(["43", "49"]));
+    });
+
+    test("for each collect result", () {
+      expect(forEachCollectResult([1, 5, 7]), equals([2, 10, 14]));
+    });
+
+    test("some", () {
+      expect(someEqual42([1, 5, 9]), isFalse);
+      expect(someEqual42([1, 42, 9]), isTrue);
+    });
+
+    test("sort backwards", () {
+      var arr = [1, 5, 9];
+      var ret = sortNumbersBackwards(arr);
+      expect(identical(arr, ret), isTrue);
+      expect(ret, equals([9, 5, 1]));
+    });
+
+    test("splice dummy items", () {
+      var list = [1, 2, 3, 4];
+      var removed = spliceDummyItems(list);
+      expect(removed.length, equals(2));
+      expect(removed[0], equals(2));
+      expect(removed[1], equals(3));
+      expect(list.first, equals(1));
+      expect(list[1], equals("quick"));
+      expect(list[2], equals("brown"));
+      expect(list[3], equals("fox"));
+      expect(list.last, equals(4));
+    });
+
+    test("splice string args", () {
+      var list = [1, 2, 3, 4];
+      var removed = spliceTestStringArgs(list);
+      expect(removed.length, equals(2));
+      expect(removed[0], equals(2));
+      expect(removed[1], equals(3));
+      expect(list.first, equals(1));
+      expect(list[1], equals("quick"));
+      expect(list[2], equals("brown"));
+      expect(list[3], equals("fox"));
+      expect(list.last, equals(4));
+    });
+
+    test("splice pastEndOfArray", () {
+      var list = [1, 2, 3, 4];
+      var removed = splicePastEnd(list);
+      expect(removed.length, equals(3));
+      expect(list.first, equals(1));
+      expect(list.length, equals(4));
+      expect(list[1], equals("quick"));
+      expect(list[2], equals("brown"));
+      expect(list[3], equals("fox"));
+    });
+
+    test("splice both bounds past end of array", () {
+      var list = [1];
+      var removed = splicePastEnd(list);
+      expect(removed.length, equals(0));
+      expect(list.first, equals(1));
+      expect(list.length, equals(4));
+      expect(list[1], equals("quick"));
+      expect(list[2], equals("brown"));
+      expect(list[3], equals("fox"));
+    });
+
+    test("call List method on JavaScript object", () {
+      var jsObject = newLiteral();
+      callListMethodOnObject(jsObject, 'push', ["a"]);
+      callListMethodOnObject(jsObject, 'push', ["b"]);
+      callListMethodOnObject(jsObject, 'push', ["c", "d"]);
+      callListMethodOnObject(jsObject, 'push', []);
+
+      expect(json_helper.stringify(jsObject),
+          equals('{"0":"a","1":"b","2":"c","3":"d","length":4}'));
+
+      expect(callListMethodOnObject(jsObject, 'pop', []), equals("d"));
+      expect(callListMethodOnObject(jsObject, 'join', ["#"]), equals("a#b#c"));
+
+      var jsArray = newArray();
+      callListMethodOnObject(jsArray, 'push', ["a"]);
+      callListMethodOnObject(jsArray, 'push', ["b"]);
+      callListMethodOnObject(jsArray, 'push', ["c", "d"]);
+      callListMethodOnObject(jsArray, 'push', []);
+
+      expect(json_helper.stringify(jsArray), equals('["a","b","c","d"]'));
+    });
+  });
+
+  // This test group is disabled until we figure out an efficient way to
+  // distinguish between "array" Dart List types and non-array Dart list types.
+  /*
+  group('Non-array Lists', () {
+    test('opaque proxy', () {
+      // Dartium could easily support making LinkedList and all other classes
+      // implementing List behave like a JavaScript array but that would
+      // be challenging to implement in dart2js until browsers support ES6.
+      var list = ["a", "b", "c", "d"];
+      var listView = new UnmodifiableListView(list.getRange(1,3));
+      expect(listView is List, isTrue);
+      expect(listView.length, equals(2));
+      expect(checkIsArray(listView), isFalse);
+      expect(checkIsArray(listView.toList()), isTrue);
+      expect(getOwnPropertyDescriptor(
+          listView, "length"), equals(null));
+    });
+  });
+  */
+}
diff --git a/tests/lib/html/js_browser_test.dart b/tests/lib/html/js_browser_test.dart
new file mode 100644
index 0000000..8c0714b
--- /dev/null
+++ b/tests/lib/html/js_browser_test.dart
@@ -0,0 +1,32 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('Nodes are proxied', () {
+    var node = new JsObject.fromBrowserObject(new DivElement());
+    context.callMethod('addTestProperty', [node]);
+    expect(node is JsObject, isTrue);
+    // TODO(justinfagnani): make this work in IE9
+    // expect(node.instanceof(context['HTMLDivElement']), isTrue);
+    expect(node['testProperty'], 'test');
+  });
+
+  test('primitives throw ArgumentError', () {
+    for (var v in ['a', 1, 2.0, true]) {
+      expect(() => new JsObject.fromBrowserObject(v), throwsArgumentError);
+    }
+  });
+}
diff --git a/tests/lib/html/js_caching_test.dart b/tests/lib/html/js_caching_test.dart
new file mode 100644
index 0000000..62cfc52
--- /dev/null
+++ b/tests/lib/html/js_caching_test.dart
@@ -0,0 +1,26 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('JS->Dart', () {
+    // Test that we are not pulling cached proxy from the prototype
+    // when asking for a proxy for the object.
+    final proto = context['someProto'];
+    expect(proto['role'], equals('proto'));
+    final obj = context['someObject'];
+    expect(obj['role'], equals('object'));
+  });
+}
diff --git a/tests/lib/html/js_context_test.dart b/tests/lib/html/js_context_test.dart
new file mode 100644
index 0000000..426d121
--- /dev/null
+++ b/tests/lib/html/js_context_test.dart
@@ -0,0 +1,32 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('read global field', () {
+    expect(context['x'], equals(42));
+    expect(context['y'], isNull);
+  });
+
+  test('read global field with underscore', () {
+    expect(context['_x'], equals(123));
+    expect(context['y'], isNull);
+  });
+
+  test('write global field', () {
+    context['y'] = 42;
+    expect(context['y'], equals(42));
+  });
+}
diff --git a/tests/lib/html/js_dart_functions_test.dart b/tests/lib/html/js_dart_functions_test.dart
new file mode 100644
index 0000000..f4d20b1
--- /dev/null
+++ b/tests/lib/html/js_dart_functions_test.dart
@@ -0,0 +1,74 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('invoke Dart callback from JS', () {
+    expect(() => context.callMethod('invokeCallback'), throws);
+
+    context['callback'] = () => 42;
+    expect(context.callMethod('invokeCallback'), equals(42));
+
+    context.deleteProperty('callback');
+  });
+
+  test('pass a Dart function to JS and back', () {
+    var dartFunction = () => 42;
+    context['dartFunction'] = dartFunction;
+    expect(identical(context['dartFunction'], dartFunction), isTrue);
+    context.deleteProperty('dartFunction');
+  });
+
+  test('callback as parameter', () {
+    expect(context.callMethod('getTypeOf', [context['razzle']]),
+        equals("function"));
+  });
+
+  test('invoke Dart callback from JS with this', () {
+    // A JavaScript constructor function implemented in Dart which
+    // uses 'this'
+    final constructor = new JsFunction.withThis(($this, arg1) {
+      var t = $this;
+      $this['a'] = 42;
+    });
+    var o = new JsObject(constructor, ["b"]);
+    expect(o['a'], equals(42));
+  });
+
+  test('invoke Dart callback from JS with 11 parameters', () {
+    context['callbackWith11params'] =
+        (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) =>
+            '$p1$p2$p3$p4$p5$p6$p7$p8$p9$p10$p11';
+    expect(context.callMethod('invokeCallbackWith11params'),
+        equals('1234567891011'));
+  });
+
+  test('return a JS proxy to JavaScript', () {
+    var result = context.callMethod('testJsMap', [
+      () => new JsObject.jsify({'value': 42})
+    ]);
+    expect(result, 42);
+  });
+
+  test('emulated functions should not be callable in JS', () {
+    context['callable'] = new Callable();
+    expect(() => context.callMethod('callable'), throwsNoSuchMethodError);
+
+    Function f = new Callable();
+    context['callable'] = f;
+    expect(context.callMethod('callable'), 'called');
+    context.deleteProperty('callable');
+  });
+}
diff --git a/tests/lib/html/js_dart_js_test.dart b/tests/lib/html/js_dart_js_test.dart
new file mode 100644
index 0000000..2ad2a2e
--- /dev/null
+++ b/tests/lib/html/js_dart_js_test.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 'dart:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('Date', () {
+    context['o'] = new DateTime(1995, 12, 17);
+    var dateType = context['Date'];
+    expect(context.callMethod('isPropertyInstanceOf', ['o', dateType]), isTrue);
+    context.deleteProperty('o');
+  });
+
+  skipIE9_test('window', () {
+    context['o'] = window;
+    var windowType = context['Window'];
+    expect(
+        context.callMethod('isPropertyInstanceOf', ['o', windowType]), isTrue);
+    context.deleteProperty('o');
+  });
+
+  skipIE9_test('document', () {
+    context['o'] = document;
+    var documentType = context['Document'];
+    expect(context.callMethod('isPropertyInstanceOf', ['o', documentType]),
+        isTrue);
+    context.deleteProperty('o');
+  });
+
+  skipIE9_test('Blob', () {
+    var fileParts = ['<a id="a"><b id="b">hey!</b></a>'];
+    context['o'] = new Blob(fileParts, 'text/html');
+    var blobType = context['Blob'];
+    expect(context.callMethod('isPropertyInstanceOf', ['o', blobType]), isTrue);
+    context.deleteProperty('o');
+  });
+
+  test('unattached DivElement', () {
+    context['o'] = new DivElement();
+    var divType = context['HTMLDivElement'];
+    expect(context.callMethod('isPropertyInstanceOf', ['o', divType]), isTrue);
+    context.deleteProperty('o');
+  });
+
+  test('Event', () {
+    context['o'] = new CustomEvent('test');
+    var eventType = context['Event'];
+    expect(
+        context.callMethod('isPropertyInstanceOf', ['o', eventType]), isTrue);
+    context.deleteProperty('o');
+  });
+
+  test('KeyRange', () {
+    if (IdbFactory.supported) {
+      context['o'] = new KeyRange.only(1);
+      var keyRangeType = context['IDBKeyRange'];
+      expect(context.callMethod('isPropertyInstanceOf', ['o', keyRangeType]),
+          isTrue);
+      context.deleteProperty('o');
+    }
+  });
+
+  // this test fails in IE9 for very weird, but unknown, reasons
+  // the expression context['ImageData'] fails if useHtmlConfiguration()
+  // is called, or if the other tests in this file are enabled
+  skipIE9_test('ImageData', () {
+    var canvas = new CanvasElement();
+    var ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
+    context['o'] = ctx.createImageData(1, 1);
+    var imageDataType = context['ImageData'];
+    expect(context.callMethod('isPropertyInstanceOf', ['o', imageDataType]),
+        isTrue);
+    context.deleteProperty('o');
+  });
+
+  test('typed data: Int32List', () {
+    if (Platform.supportsTypedData) {
+      context['o'] = new Int32List.fromList([1, 2, 3, 4]);
+      var listType = context['Int32Array'];
+      // TODO(jacobr): make this test pass. Currently some type information
+      // is lost when typed arrays are passed between JS and Dart.
+      // expect(context.callMethod('isPropertyInstanceOf', ['o', listType]),
+      //    isTrue);
+      context.deleteProperty('o');
+    }
+  });
+}
diff --git a/tests/lib/html/js_dart_to_string_test.dart b/tests/lib/html/js_dart_to_string_test.dart
new file mode 100644
index 0000000..357b08d
--- /dev/null
+++ b/tests/lib/html/js_dart_to_string_test.dart
@@ -0,0 +1,43 @@
+// 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.
+
+@JS()
+library js_dart_to_string_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+
+  function jsToStringViaCoercion(a) {
+    return a + '';
+  };
+""");
+}
+
+@JS()
+external String jsToStringViaCoercion(obj);
+
+class ExampleClassWithCustomToString {
+  var x;
+  ExampleClassWithCustomToString(this.x);
+  String toString() => "#$x#";
+}
+
+main() {
+  _injectJs();
+
+  group('toString', () {
+    test('custom dart', () {
+      var x = new ExampleClassWithCustomToString("fooBar");
+      expect(jsToStringViaCoercion(x), equals("#fooBar#"));
+      expect(jsToStringViaCoercion({'a': 1, 'b': 2}), equals("{a: 1, b: 2}"));
+    });
+  });
+}
diff --git a/tests/lib/html/js_dispatch_property_test.dart b/tests/lib/html/js_dispatch_property_test.dart
new file mode 100644
index 0000000..3fbe2ea
--- /dev/null
+++ b/tests/lib/html/js_dispatch_property_test.dart
@@ -0,0 +1,25 @@
+// 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 for dart2js initialization of dispatchPropertyName.
+
+import 'package:expect/minitest.dart';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+
+import 'js_dispatch_property_test_lib.dart';
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+main() {
+  group('group', () {
+    test('test', () {
+      // Force dynamic interceptor dispatch.
+      var a = confuse(create());
+      expect(a.foo('A'), equals('Foo A'));
+    });
+  });
+}
diff --git a/tests/lib/html/js_dispatch_property_test.html b/tests/lib/html/js_dispatch_property_test.html
new file mode 100644
index 0000000..8b7fc4b
--- /dev/null
+++ b/tests/lib/html/js_dispatch_property_test.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<--
+// 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.
+-->
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> js_type_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running js_type_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tests/lib/html/js_dispatch_property_test_js.js"></script>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/js_dispatch_property_test_js.js b/tests/lib/html/js_dispatch_property_test_js.js
new file mode 100644
index 0000000..0b159d6
--- /dev/null
+++ b/tests/lib/html/js_dispatch_property_test_js.js
@@ -0,0 +1,17 @@
+// 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.
+
+self.create = function() {
+  return {
+    // If the dispatch property name is uninitialized, it will be `undefined` or
+    // `null`, which will match these properties on dispatch record
+    // lookup. These properties map to malformed dispatch records to force an
+    // error.
+
+    'undefined': {p: false},
+    'null': {p: false},
+
+    foo: function(x) { return 'Foo ' + x; },
+  };
+}
\ No newline at end of file
diff --git a/tests/lib/html/js_dispatch_property_test_lib.dart b/tests/lib/html/js_dispatch_property_test_lib.dart
new file mode 100644
index 0000000..80a87a1
--- /dev/null
+++ b/tests/lib/html/js_dispatch_property_test_lib.dart
@@ -0,0 +1,17 @@
+// 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.
+
+@JS()
+library js_dispatch_property_test_lib;
+
+import 'package:js/js.dart';
+
+@JS()
+external A create();
+
+@JS()
+@anonymous
+class A {
+  external String foo(String x);
+}
diff --git a/tests/lib/html/js_extend_class_test.dart b/tests/lib/html/js_extend_class_test.dart
new file mode 100644
index 0000000..546a45a
--- /dev/null
+++ b/tests/lib/html/js_extend_class_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.
+
+@JS()
+library js_extend_class_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+@JS('Date')
+class JSDate {
+  external get jsField;
+  external get jsMethod;
+}
+
+@JS('Date.prototype.jsField')
+external set datePrototypeJSField(v);
+
+@JS('Date.prototype.jsMethod')
+external set datePrototypeJSMethod(v);
+
+// Extending a JS class with a Dart class is only supported by DDC for now.
+// We extend the Date class instead of a user defined JS class to avoid the
+// hassle of ensuring the JS class exists before we use it.
+class DartJsDate extends JSDate {
+  get dartField => 100;
+  int dartMethod(x) {
+    return x * 2;
+  }
+}
+
+main() {
+  // Monkey-patch the JS Date class.
+  datePrototypeJSField = 42;
+  datePrototypeJSMethod = allowInterop((x) => x * 10);
+
+  group('extend js class', () {
+    test('js class members', () {
+      var bar = new DartJsDate();
+      expect(bar.jsField, equals(42));
+      expect(bar.jsMethod(5), equals(50));
+
+      expect(bar.dartField, equals(100));
+      expect(bar.dartMethod(4), equals(8));
+    });
+
+    test('instance checks and casts', () {
+      var bar = new DartJsDate();
+      expect(bar is JSDate, isTrue);
+      expect(bar as JSDate, equals(bar));
+    });
+
+    test('dart subclass members', () {
+      var bar = new DartJsDate();
+      expect(bar.dartField, equals(100));
+      expect(bar.dartMethod(4), equals(8));
+    });
+  });
+}
diff --git a/tests/lib/html/js_function_getter_test.dart b/tests/lib/html/js_function_getter_test.dart
new file mode 100644
index 0000000..d01e29b
--- /dev/null
+++ b/tests/lib/html/js_function_getter_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.
+
+@JS()
+library js_function_getter_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  var bar = { };
+
+  bar.instanceMember = function() {
+    if (this !== bar) {
+      throw 'Unexpected this!';
+    }
+    return arguments.length;
+  };
+
+  bar.staticMember = function() {
+    return arguments.length * 2;
+  };
+
+  bar.dynamicStatic = function() {
+    return arguments.length;
+  };
+
+  bar.add = function(a, b) {
+    return a + b;
+  };
+
+  var foo = { 'bar' : bar };
+""");
+}
+
+typedef int AddFn(int x, int y);
+
+@JS()
+abstract class Bar {
+  external Function get staticMember;
+  external Function get instanceMember;
+  external AddFn get add;
+  external get dynamicStatic;
+  external num get nonFunctionStatic;
+}
+
+@JS()
+abstract class Foo {
+  external Bar get bar;
+}
+
+@JS()
+external Foo get foo;
+
+main() {
+  _injectJs();
+
+  group('call getter as function', () {
+    test('member function', () {
+      expect(foo.bar.instanceMember(), equals(0));
+      expect(foo.bar.instanceMember(0), equals(1));
+      expect(foo.bar.instanceMember(0, 0), equals(2));
+      expect(foo.bar.instanceMember(0, 0, 0, 0, 0, 0), equals(6));
+      var instanceMember = foo.bar.instanceMember;
+      expect(() => instanceMember(), throws);
+      expect(() => instanceMember(0), throws);
+      expect(() => instanceMember(0, 0), throws);
+      expect(() => instanceMember(0, 0, 0, 0, 0, 0), throws);
+    });
+
+    test('static function', () {
+      expect(foo.bar.staticMember(), equals(0));
+      expect(foo.bar.staticMember(0), equals(2));
+      expect(foo.bar.staticMember(0, 0), equals(4));
+      expect(foo.bar.staticMember(0, 0, 0, 0, 0, 0), equals(12));
+      var staticMember = foo.bar.staticMember;
+      expect(staticMember(), equals(0));
+      expect(staticMember(0), equals(2));
+      expect(staticMember(0, 0), equals(4));
+      expect(staticMember(0, 0, 0, 0, 0, 0), equals(12));
+    });
+
+    test('static dynamicStatic', () {
+      expect(foo.bar.dynamicStatic(), equals(0));
+      expect(foo.bar.dynamicStatic(0), equals(1));
+      expect(foo.bar.dynamicStatic(0, 0), equals(2));
+      expect(foo.bar.dynamicStatic(0, 0, 0, 0, 0, 0), equals(6));
+      var dynamicStatic = foo.bar.dynamicStatic;
+      expect(dynamicStatic(), equals(0));
+      expect(dynamicStatic(0), equals(1));
+      expect(dynamicStatic(0, 0), equals(2));
+      expect(dynamicStatic(0, 0, 0, 0, 0, 0), equals(6));
+    });
+
+    test('typedef function', () {
+      expect(foo.bar.add(4, 5), equals(9));
+    });
+  });
+}
diff --git a/tests/lib/html/js_function_getter_trust_types/compile_test.dart b/tests/lib/html/js_function_getter_trust_types/compile_test.dart
new file mode 100644
index 0000000..9cbbe1f
--- /dev/null
+++ b/tests/lib/html/js_function_getter_trust_types/compile_test.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.
+
+// SharedOptions=--trust-type-annotations
+@JS()
+library js_function_getter_trust_types_test;
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+import 'js_function_util.dart';
+
+main() {
+  injectJs();
+
+  foo.bar.nonFunctionStatic();
+//        ^
+// [cfe] Error: 'nonFunctionStatic' isn't a function or method and can't be invoked.
+//^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION_EXPRESSION
+
+  foo.bar.nonFunctionStatic(0);
+//        ^
+// [cfe] Error: 'nonFunctionStatic' isn't a function or method and can't be invoked.
+//^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION_EXPRESSION
+
+  foo.bar.nonFunctionStatic(0, 0);
+//        ^
+// [cfe] Error: 'nonFunctionStatic' isn't a function or method and can't be invoked.
+//^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION_EXPRESSION
+
+  foo.bar.nonFunctionStatic(0, 0, 0, 0, 0, 0);
+//        ^
+// [cfe] Error: 'nonFunctionStatic' isn't a function or method and can't be invoked.
+//^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION_EXPRESSION
+
+  foo.bar.add(4);
+  //         ^
+  // [cfe] Error: Too few positional arguments: 2 required, 1 given.
+  //         ^^^
+  // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
+
+  foo.bar.add(4, 5, 10);
+  //         ^
+  // [cfe] Error: Too many positional arguments: 2 allowed, but 3 found.
+  //         ^^^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+}
diff --git a/tests/lib/html/js_function_getter_trust_types/function_test.dart b/tests/lib/html/js_function_getter_trust_types/function_test.dart
new file mode 100644
index 0000000..5a49f47
--- /dev/null
+++ b/tests/lib/html/js_function_getter_trust_types/function_test.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.
+
+// SharedOptions=--trust-type-annotations
+@JS()
+library js_function_getter_trust_types_test;
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+import 'js_function_util.dart';
+
+main() {
+  injectJs();
+
+  Expect.equals(foo.bar.add(4, 5), 9);
+}
diff --git a/tests/lib/html/js_function_getter_trust_types/js_function_util.dart b/tests/lib/html/js_function_getter_trust_types/js_function_util.dart
new file mode 100644
index 0000000..2f89030
--- /dev/null
+++ b/tests/lib/html/js_function_getter_trust_types/js_function_util.dart
@@ -0,0 +1,48 @@
+// 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=--trust-type-annotations
+@JS()
+library js_function_getter_trust_types_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+
+injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  var bar = { };
+
+  bar.nonFunctionStatic = function() {
+    return arguments.length * 2;
+  };
+
+  bar.add = function(a, b) {
+    return a + b;
+  };
+
+  var foo = { 'bar' : bar };
+""");
+}
+
+typedef int AddFn(int x, int y);
+
+@JS()
+class NotAFn {}
+
+@JS()
+abstract class Bar {
+  external AddFn get add;
+  external NotAFn get nonFunctionStatic;
+}
+
+@JS()
+abstract class Foo {
+  external Bar get bar;
+}
+
+@JS()
+external Foo get foo;
diff --git a/tests/lib/html/js_identity_test.dart b/tests/lib/html/js_identity_test.dart
new file mode 100644
index 0000000..dadf6a9
--- /dev/null
+++ b/tests/lib/html/js_identity_test.dart
@@ -0,0 +1,61 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('context instances should be identical', () {
+    var c1 = context;
+    var c2 = context;
+    expect(identical(c1, c2), isTrue);
+  });
+
+  test('identical JS objects should have identical proxies', () {
+    var o1 = new JsObject(context['Foo'], [1]);
+    context['f1'] = o1;
+    var o2 = context['f1'];
+    expect(identical(o1, o2), isTrue);
+  });
+
+  test('identical Dart functions should have identical proxies', () {
+    var f1 = allowInterop(() => print("I'm a Function!"));
+    expect(context.callMethod('identical', [f1, f1]), isTrue);
+  });
+
+  test('identical JS functions should have identical proxies', () {
+    var f1 = context['Object'];
+    var f2 = context['Object'];
+    expect(identical(f1, f2), isTrue);
+  });
+
+  // TODO(justinfagnani): old tests duplicate checks above, remove
+  // on test next cleanup pass
+  test('test proxy equality', () {
+    var foo1 = new JsObject(context['Foo'], [1]);
+    var foo2 = new JsObject(context['Foo'], [2]);
+    context['foo1'] = foo1;
+    context['foo2'] = foo2;
+    expect(foo1, notEquals(context['foo2']));
+    expect(foo2, equals(context['foo2']));
+    context.deleteProperty('foo1');
+    context.deleteProperty('foo2');
+  });
+
+  test('retrieve same dart Object', () {
+    final obj = new Object();
+    context['obj'] = obj;
+    expect(context['obj'], same(obj));
+    context.deleteProperty('obj');
+  });
+}
diff --git a/tests/lib/html/js_interop_1_test.dart b/tests/lib/html/js_interop_1_test.dart
new file mode 100644
index 0000000..5f57dfb
--- /dev/null
+++ b/tests/lib/html/js_interop_1_test.dart
@@ -0,0 +1,32 @@
+// 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
+// BSD-style license that can be found in the LICENSE file
+
+library JsInterop1Test;
+
+import 'package:async_helper/async_helper.dart';
+import 'dart:async';
+import 'dart:html';
+
+injectSource(code) {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = code;
+  document.body!.append(script);
+}
+
+main() {
+  asyncTest(() async {
+    var subscription;
+    var completer = Completer<void>();
+    subscription = window.onMessage.listen((e) {
+      if (!completer.isCompleted && e.data == 'hello') {
+        completer.complete();
+        subscription.cancel();
+      }
+    });
+    injectSource("window.postMessage('hello', '*');");
+
+    await completer;
+  });
+}
diff --git a/tests/lib/html/js_interop_constructor_name/div_test.dart b/tests/lib/html/js_interop_constructor_name/div_test.dart
new file mode 100644
index 0000000..02a7826
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/div_test.dart
@@ -0,0 +1,42 @@
+// 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 jsTest;
+
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:js';
+import 'package:js/js.dart';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:expect/minitest.dart';
+
+@JS()
+external makeDiv(String text);
+
+@JS()
+class HTMLDivElement {
+  external String bar();
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+main() {
+  test('dom-is-dom', () {
+    var e = confuse(new html.DivElement());
+    expect(e is html.DivElement, isTrue);
+  });
+
+  test('js-is-dom', () {
+    var e = confuse(makeDiv('hello'));
+    expect(e is html.DivElement, isFalse);
+  });
+
+  test('js-is-js', () {
+    var e = confuse(makeDiv('hello'));
+    expect(e is HTMLDivElement, isTrue);
+  });
+}
diff --git a/tests/lib/html/js_interop_constructor_name/div_test.html b/tests/lib/html/js_interop_constructor_name/div_test.html
new file mode 100644
index 0000000..7ef030a
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/div_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> div_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running div_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/js_interop_constructor_name/error1_test.dart b/tests/lib/html/js_interop_constructor_name/error1_test.dart
new file mode 100644
index 0000000..bb27475
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/error1_test.dart
@@ -0,0 +1,35 @@
+// 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 jsTest;
+
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:js';
+import 'package:js/js.dart';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:expect/minitest.dart';
+
+@JS()
+external makeDiv(String text);
+
+@JS()
+class HTMLDivElement {
+  external String bar();
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+main() {
+  test('dom-is-js', () {
+    var e = confuse(new html.DivElement());
+    // Currently, HTML types are not [JavaScriptObject]s. We could change that
+    // by having HTML types extend JavaScriptObject, in which case we would
+    // change this expectation.
+    expect(e is HTMLDivElement, isFalse);
+  });
+}
diff --git a/tests/lib/html/js_interop_constructor_name/error1_test.html b/tests/lib/html/js_interop_constructor_name/error1_test.html
new file mode 100644
index 0000000..7eb4631
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/error1_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> error1_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running error1_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/js_interop_constructor_name/error2_test.dart b/tests/lib/html/js_interop_constructor_name/error2_test.dart
new file mode 100644
index 0000000..9fab532
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/error2_test.dart
@@ -0,0 +1,35 @@
+// 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 jsTest;
+
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:js';
+import 'package:js/js.dart';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:expect/minitest.dart';
+
+@JS()
+external makeDiv(String text);
+
+@JS()
+class HTMLDivElement {
+  external String bar();
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+main() {
+  test('String-is-not-js', () {
+    var e = confuse('kombucha');
+    // A String should not be a JS interop type. The type test flags are added
+    // to Interceptor, but should be added to the class that implements all
+    // the JS-interop methods.
+    expect(e is HTMLDivElement, isFalse);
+  });
+}
diff --git a/tests/lib/html/js_interop_constructor_name/error2_test.html b/tests/lib/html/js_interop_constructor_name/error2_test.html
new file mode 100644
index 0000000..f05cdb4
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/error2_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> error2_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running error2_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/js_interop_constructor_name/method_test.dart b/tests/lib/html/js_interop_constructor_name/method_test.dart
new file mode 100644
index 0000000..e881467
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/method_test.dart
@@ -0,0 +1,47 @@
+// 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 jsTest;
+
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:js';
+import 'package:js/js.dart';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic, Expect;
+import 'package:expect/minitest.dart';
+
+@JS()
+external makeDiv(String text);
+
+@JS()
+class HTMLDivElement {
+  external String bar();
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+main() {
+  test('js-call-js-method', () {
+    var e = confuse(makeDiv('hello'));
+    expect(e.bar(), equals('hello'));
+  });
+
+  test('dom-call-js-method', () {
+    var e = confuse(new html.DivElement());
+    expect(() => e.bar(), throws);
+  });
+
+  test('js-call-dom-method', () {
+    var e = confuse(makeDiv('hello'));
+    expect(() => e.clone(false), throws);
+  });
+
+  test('dom-call-dom-method', () {
+    var e = confuse(new html.DivElement());
+    Expect.type<html.DivElement>(e.clone(false));
+  });
+}
diff --git a/tests/lib/html/js_interop_constructor_name/method_test.html b/tests/lib/html/js_interop_constructor_name/method_test.html
new file mode 100644
index 0000000..a8a0173
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/method_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> method_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running method_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
+  <script type="text/javascript"
+      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/lib/html/js_interop_constructor_name/test_js.js b/tests/lib/html/js_interop_constructor_name/test_js.js
new file mode 100644
index 0000000..828cbc9
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/test_js.js
@@ -0,0 +1,20 @@
+(function() {
+
+  // A constructor function with the same name as a HTML element.
+  function HTMLDivElement(a) {
+    this.a = a;
+  }
+
+  HTMLDivElement.prototype.bar = function() {
+    return this.a;
+  }
+
+  HTMLDivElement.prototype.toString = function() {
+    return "HTMLDivElement(" + this.a + ")";
+  }
+
+  self.makeDiv = function(text) {
+    return new HTMLDivElement(text);
+  };
+
+})();
diff --git a/tests/lib/html/js_javascript_function_test.dart b/tests/lib/html/js_javascript_function_test.dart
new file mode 100644
index 0000000..af9394e
--- /dev/null
+++ b/tests/lib/html/js_javascript_function_test.dart
@@ -0,0 +1,23 @@
+// 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:js';
+
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('is check', () {
+    var fn = (String s) => true;
+    var jsFn = allowInterop(fn);
+    expect(fn is StringToBool, isTrue);
+    expect(jsFn is StringToBool, isTrue);
+    expect(jsFn is Function, isTrue);
+    expect(jsFn is List, isFalse);
+  });
+}
diff --git a/tests/lib/html/js_jsarray_test.dart b/tests/lib/html/js_jsarray_test.dart
new file mode 100644
index 0000000..312e324
--- /dev/null
+++ b/tests/lib/html/js_jsarray_test.dart
@@ -0,0 +1,155 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('new JsArray()', () {
+    var array = new JsArray();
+    var arrayType = context['Array'];
+    expect(array.instanceof(arrayType), true);
+    expect(array, []);
+    // basic check that it behaves like a List
+    array.addAll([1, 2, 3]);
+    expect(array, [1, 2, 3]);
+  });
+
+  test('new JsArray.from()', () {
+    var array = new JsArray.from([1, 2, 3]);
+    var arrayType = context['Array'];
+    expect(array.instanceof(arrayType), true);
+    expect(array, [1, 2, 3]);
+  });
+
+  test('get Array from JS', () {
+    context['a'] = new JsObject(context['Array'], [1, 2, 3]);
+    expect(context.callMethod('isPropertyInstanceOf', ['a', context['Array']]),
+        isTrue);
+    var a = context['a'];
+    expect(a is JsArray, isTrue);
+    expect(a, [1, 2, 3]);
+    context.deleteProperty('a');
+  });
+
+  test('pass Array to JS', () {
+    context['a'] = [1, 2, 3];
+    var a = context['a'];
+    expect(a is List, isTrue);
+    expect(a is JsArray, isFalse);
+    expect(a, [1, 2, 3]);
+    context.deleteProperty('a');
+  });
+
+  test('[]', () {
+    var array = new JsArray.from([1, 2]);
+    expect(array[0], 1);
+    expect(array[1], 2);
+    expect(() => array[-1], throwsRangeError);
+    expect(() => array[2], throwsRangeError);
+  });
+
+  test('[]=', () {
+    var array = new JsArray<Object>.from([1, 2]);
+    array[0] = 'd';
+    array[1] = 'e';
+    expect(array, ['d', 'e']);
+    expect(() => array[-1] = 3, throwsRangeError);
+    expect(() => array[2] = 3, throwsRangeError);
+  });
+
+  test('length', () {
+    var array = new JsArray<int?>.from([1, 2, 3]);
+    expect(array.length, 3);
+    array.add(4);
+    expect(array.length, 4);
+    array.length = 2;
+    expect(array, [1, 2]);
+    array.length = 3;
+    expect(array, [1, 2, null]);
+  });
+
+  test('add', () {
+    var array = new JsArray();
+    array.add('a');
+    expect(array, ['a']);
+    array.add('b');
+    expect(array, ['a', 'b']);
+  });
+
+  test('addAll', () {
+    var array = new JsArray();
+    array.addAll(['a', 'b']);
+    expect(array, ['a', 'b']);
+    // make sure addAll can handle Iterables
+    array.addAll(new Set.from(['c']));
+    expect(array, ['a', 'b', 'c']);
+  });
+
+  test('insert', () {
+    var array = new JsArray.from([]);
+    array.insert(0, 'b');
+    expect(array, ['b']);
+    array.insert(0, 'a');
+    expect(array, ['a', 'b']);
+    array.insert(2, 'c');
+    expect(array, ['a', 'b', 'c']);
+    expect(() => array.insert(4, 'e'), throwsRangeError);
+    expect(() => array.insert(-1, 'e'), throwsRangeError);
+  });
+
+  test('removeAt', () {
+    var array = new JsArray.from(['a', 'b', 'c']);
+    expect(array.removeAt(1), 'b');
+    expect(array, ['a', 'c']);
+    expect(() => array.removeAt(2), throwsRangeError);
+    expect(() => array.removeAt(-1), throwsRangeError);
+  });
+
+  test('removeLast', () {
+    var array = new JsArray.from(['a', 'b', 'c']);
+    expect(array.removeLast(), 'c');
+    expect(array, ['a', 'b']);
+    array.length = 0;
+    expect(() => array.removeLast(), throwsRangeError);
+  });
+
+  test('removeRange', () {
+    var array = new JsArray.from(['a', 'b', 'c', 'd']);
+    array.removeRange(1, 3);
+    expect(array, ['a', 'd']);
+    expect(() => array.removeRange(-1, 2), throwsRangeError);
+    expect(() => array.removeRange(0, 3), throwsRangeError);
+    expect(() => array.removeRange(2, 1), throwsRangeError);
+  });
+
+  test('setRange', () {
+    var array = new JsArray.from(['a', 'b', 'c', 'd']);
+    array.setRange(1, 3, ['e', 'f']);
+    expect(array, ['a', 'e', 'f', 'd']);
+    array.setRange(3, 4, ['g', 'h', 'i'], 1);
+    expect(array, ['a', 'e', 'f', 'h']);
+  });
+
+  test('sort', () {
+    var array = new JsArray.from(['c', 'a', 'b']);
+    array.sort();
+    expect(array, ['a', 'b', 'c']);
+  });
+
+  test('sort with a Comparator', () {
+    var array = new JsArray.from(['c', 'a', 'b']);
+    array.sort((a, b) => -(a.compareTo(b)));
+    expect(array, ['c', 'b', 'a']);
+  });
+}
diff --git a/tests/lib/html/js_jsfunc_callmethod_test.dart b/tests/lib/html/js_jsfunc_callmethod_test.dart
new file mode 100644
index 0000000..374c4ad
--- /dev/null
+++ b/tests/lib/html/js_jsfunc_callmethod_test.dart
@@ -0,0 +1,56 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('new JsObject can return a JsFunction', () {
+    var f = new JsObject(context['Function']);
+    expect(f is JsFunction, isTrue);
+  });
+
+  test('JsFunction.apply on a function defined in JS', () {
+    expect(context['razzle'].apply([]), equals(42));
+  });
+
+  test('JsFunction.apply on a function that uses this', () {
+    var object = new Object();
+    expect(context['returnThis'].apply([], thisArg: object), same(object));
+  });
+
+  test('JsObject.callMethod on a function defined in JS', () {
+    expect(context.callMethod('razzle'), equals(42));
+    expect(() => context.callMethod('dazzle'), throwsNoSuchMethodError);
+  });
+
+  test('callMethod with many arguments', () {
+    expect(context.callMethod('varArgs', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
+        equals(55));
+  });
+
+  test('access a property of a function', () {
+    expect(context.callMethod('Bar'), "ret_value");
+    expect(context['Bar']['foo'], "property_value");
+  });
+/*
+ TODO(jacobr): evaluate whether we should be in the business of throwing
+ ArgumentError outside of checked mode. In unchecked mode this should just
+ return a NoSuchMethodError as the class lacks a method "true".
+
+    test('callMethod throws if name is not a String or num', () {
+      expect(() => context.callMethod(true),
+          throwsArgumentError);
+    });
+*/
+}
diff --git a/tests/lib/html/js_jsify_test.dart b/tests/lib/html/js_jsify_test.dart
new file mode 100644
index 0000000..4a59a1f
--- /dev/null
+++ b/tests/lib/html/js_jsify_test.dart
@@ -0,0 +1,77 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('convert a List', () {
+    final list = [1, 2, 3, 4, 5, 6, 7, 8];
+    var array = new JsObject.jsify(list);
+    expect(context.callMethod('isArray', [array]), isTrue);
+    expect(array['length'], equals(list.length));
+    for (var i = 0; i < list.length; i++) {
+      expect(array[i], equals(list[i]));
+    }
+  });
+
+  test('convert an Iterable', () {
+    final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]);
+    var array = new JsObject.jsify(set);
+    expect(context.callMethod('isArray', [array]), isTrue);
+    expect(array['length'], equals(set.length));
+    for (var i = 0; i < array['length']; i++) {
+      expect(set.contains(array[i]), isTrue);
+    }
+  });
+
+  test('convert a Map', () {
+    var map = {
+      'a': 1,
+      'b': 2,
+      'c': 3,
+      'd': allowInteropCaptureThis((that) => 42)
+    };
+    var jsMap = new JsObject.jsify(map);
+    expect(!context.callMethod('isArray', [jsMap]), isTrue);
+    for (final key in map.keys) {
+      expect(context.callMethod('checkMap', [jsMap, key, map[key]]), isTrue);
+    }
+  });
+
+  test('deep convert a complex object', () {
+    dynamic object = {
+      'a': [
+        1,
+        [2, 3]
+      ],
+      'b': {
+        'c': 3,
+        'd': new JsObject(context['Foo'], [42])
+      },
+      'e': null
+    };
+    var jsObject = new JsObject.jsify(object);
+    expect(jsObject['a'][0], equals(object['a'][0]));
+    expect(jsObject['a'][1][0], equals(object['a'][1][0]));
+    expect(jsObject['a'][1][1], equals(object['a'][1][1]));
+    expect(jsObject['b']['c'], equals(object['b']['c']));
+    expect(jsObject['b']['d'], equals(object['b']['d']));
+    expect(jsObject['b']['d'].callMethod('bar'), equals(42));
+    expect(jsObject['e'], isNull);
+  });
+
+  test('throws if object is not a Map or Iterable', () {
+    expect(() => new JsObject.jsify('a'), throwsArgumentError);
+  });
+}
diff --git a/tests/lib/html/js_jsobject_test.dart b/tests/lib/html/js_jsobject_test.dart
new file mode 100644
index 0000000..a718cb4
--- /dev/null
+++ b/tests/lib/html/js_jsobject_test.dart
@@ -0,0 +1,133 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('new Foo()', () {
+    var foo = new JsObject(context['Foo'], [42]);
+    expect(foo['a'], equals(42));
+    expect(foo.callMethod('bar'), equals(42));
+    expect(() => foo.callMethod('baz'), throwsNoSuchMethodError);
+  });
+
+  test('new container.Foo()', () {
+    final Foo2 = context['container']['Foo'];
+    final foo = new JsObject(Foo2, [42]);
+    expect(foo['a'], 42);
+    expect(Foo2['b'], 38);
+  });
+
+  test('new Array()', () {
+    var a = new JsObject(context['Array']);
+    expect(a is JsArray, isTrue);
+
+    // Test that the object still behaves via the base JsObject interface.
+    // JsArray specific tests are below.
+    expect(a['length'], 0);
+
+    a.callMethod('push', ["value 1"]);
+    expect(a['length'], 1);
+    expect(a[0], "value 1");
+
+    a.callMethod('pop');
+    expect(a['length'], 0);
+  });
+
+  test('new Date()', () {
+    final a = new JsObject(context['Date']);
+    expect(a.callMethod('getTime'), isNotNull);
+  });
+
+  test('new Date(12345678)', () {
+    final a = new JsObject(context['Date'], [12345678]);
+    expect(a.callMethod('getTime'), equals(12345678));
+  });
+
+  test('new Date("December 17, 1995 03:24:00 GMT")', () {
+    final a = new JsObject(context['Date'], ["December 17, 1995 03:24:00 GMT"]);
+    expect(a.callMethod('getTime'), equals(819170640000));
+  });
+
+  test('new Date(1995,11,17)', () {
+    // Note: JS Date counts months from 0 while Dart counts from 1.
+    final a = new JsObject(context['Date'], [1995, 11, 17]);
+    final b = new DateTime(1995, 12, 17);
+    expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
+  });
+
+  test('new Date(1995,11,17,3,24,0)', () {
+    // Note: JS Date counts months from 0 while Dart counts from 1.
+    final a = new JsObject(context['Date'], [1995, 11, 17, 3, 24, 0]);
+    final b = new DateTime(1995, 12, 17, 3, 24, 0);
+    expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
+  });
+
+  test('new Object()', () {
+    final a = new JsObject(context['Object']);
+    expect(a, isNotNull);
+
+    a['attr'] = "value";
+    expect(a['attr'], equals("value"));
+  });
+
+  test(r'new RegExp("^\w+$")', () {
+    final a = new JsObject(context['RegExp'], [r'^\w+$']);
+    expect(a, isNotNull);
+    expect(a.callMethod('test', ['true']), isTrue);
+    expect(a.callMethod('test', [' false']), isFalse);
+  });
+
+  test('js instantiation via map notation : new Array()', () {
+    final a = new JsObject(context['Array']);
+    expect(a, isNotNull);
+    expect(a['length'], equals(0));
+
+    a.callMethod('push', ["value 1"]);
+    expect(a['length'], equals(1));
+    expect(a[0], equals("value 1"));
+
+    a.callMethod('pop');
+    expect(a['length'], equals(0));
+  });
+
+  test('js instantiation via map notation : new Date()', () {
+    final a = new JsObject(context['Date']);
+    expect(a.callMethod('getTime'), isNotNull);
+  });
+
+  test('typed array', () {
+    if (Platform.supportsTypedData) {
+      // Safari's ArrayBuffer is not a Function and so doesn't support bind
+      // which JsObject's constructor relies on.
+      // bug: https://bugs.webkit.org/show_bug.cgi?id=122976
+      if (context['ArrayBuffer']['bind'] != null) {
+        final codeUnits = "test".codeUnits;
+        final buf = new JsObject(context['ArrayBuffer'], [codeUnits.length]);
+        final bufView = new JsObject(context['Uint8Array'], [buf]);
+        for (var i = 0; i < codeUnits.length; i++) {
+          bufView[i] = codeUnits[i];
+        }
+      }
+    }
+  });
+
+  test('>10 parameters', () {
+    final o = new JsObject(context['Baz'], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
+    for (var i = 1; i <= 11; i++) {
+      expect(o["f$i"], i);
+    }
+    expect(o['constructor'], equals(context['Baz']));
+  });
+}
diff --git a/tests/lib/html/js_methods_test.dart b/tests/lib/html/js_methods_test.dart
new file mode 100644
index 0000000..4c226a8
--- /dev/null
+++ b/tests/lib/html/js_methods_test.dart
@@ -0,0 +1,101 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('hashCode and ==', () {
+    final o1 = context['Object'];
+    final o2 = context['Object'];
+    expect(o1 == o2, isTrue);
+    expect(o1.hashCode == o2.hashCode, isTrue);
+    final d = context['document'];
+    expect(o1 == d, isFalse);
+  });
+
+  test('toString', () {
+    var foo = new JsObject(context['Foo'], [42]);
+    expect(foo.toString(), equals("I'm a Foo a=42"));
+    var container = context['container'];
+    expect(container.toString(), equals("[object Object]"));
+  });
+
+  test('toString returns a String even if the JS object does not', () {
+    var foo = new JsObject(context['Liar']);
+    expect(foo.callMethod('toString'), 1);
+    expect(foo.toString(), '1');
+  });
+
+  test('instanceof', () {
+    var foo = new JsObject(context['Foo'], [1]);
+    expect(foo.instanceof(context['Foo']), isTrue);
+    expect(foo.instanceof(context['Object']), isTrue);
+    expect(foo.instanceof(context['String']), isFalse);
+  });
+
+  test('deleteProperty', () {
+    var object = new JsObject.jsify({});
+    object['a'] = 1;
+    expect(context['Object'].callMethod('keys', [object])['length'], 1);
+    expect(context['Object'].callMethod('keys', [object])[0], "a");
+    object.deleteProperty("a");
+    expect(context['Object'].callMethod('keys', [object])['length'], 0);
+  });
+
+/* TODO(jacobr): this is another test that is inconsistent with JS semantics.
+  test('deleteProperty throws if name is not a String or num', () {
+    var object = new JsObject.jsify({});
+    expect(() => object.deleteProperty(true),
+        throwsArgumentError);
+  });
+*/
+
+  test('hasProperty', () {
+    var object = new JsObject.jsify({});
+    object['a'] = 1;
+    expect(object.hasProperty('a'), isTrue);
+    expect(object.hasProperty('b'), isFalse);
+  });
+
+/* TODO(jacobr): is this really the correct unchecked mode behavior?
+  test('hasProperty throws if name is not a String or num', () {
+    var object = new JsObject.jsify({});
+    expect(() => object.hasProperty(true),
+        throwsArgumentError);
+  });
+*/
+
+  test('[] and []=', () {
+    final myArray = context['myArray'];
+    expect(myArray['length'], equals(1));
+    expect(myArray[0], equals("value1"));
+    myArray[0] = "value2";
+    expect(myArray['length'], equals(1));
+    expect(myArray[0], equals("value2"));
+
+    final foo = new JsObject(context['Foo'], [1]);
+    foo["getAge"] = () => 10;
+    expect(foo.callMethod('getAge'), equals(10));
+  });
+
+/* TODO(jacobr): remove as we should only throw this in checked mode.
+  test('[] and []= throw if name is not a String or num', () {
+    var object = new JsObject.jsify({});
+    expect(() => object[true],
+        throwsArgumentError);
+    expect(() => object[true] = 1,
+        throwsArgumentError);
+  });
+*/
+}
diff --git a/tests/lib/html/js_mock_test.dart b/tests/lib/html/js_mock_test.dart
new file mode 100644
index 0000000..310abc9
--- /dev/null
+++ b/tests/lib/html/js_mock_test.dart
@@ -0,0 +1,67 @@
+// 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.
+
+@JS()
+library mock;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS('Node')
+class Node {}
+
+@JS('HTMLDocument')
+class Document extends Node {
+  external Element get body;
+}
+
+@JS()
+external get foo;
+
+@JS()
+external Document get document;
+
+@JS('Element')
+class Element extends Node {
+  external String get tagName;
+}
+
+class MockDocument implements Document {
+  final Element body = new MockElement();
+}
+
+class MockElement implements Element {
+  final tagName = 'MockBody';
+}
+
+void main() {
+  test('js', () {
+    var f = foo;
+    expect(f, isNull);
+
+    var doc = document;
+    expect(doc is Document, isTrue);
+    // Fails in dart2js
+    //expect(doc is! Element, isTrue);
+
+    expect(doc is Node, isTrue);
+
+    expect(doc is! MockDocument, isTrue);
+    expect(doc is! MockElement, isTrue);
+  });
+
+  test('mock', () {
+    var doc = new MockDocument();
+    expect(doc is Document, isTrue);
+    // Fails in dart2js
+    // expect(doc is! Element, isTrue);
+    expect(doc is Node, isTrue);
+
+    var body = doc.body;
+    // Fails in dart2js
+    // expect(body is! Document, isTrue);
+    expect(body is Element, isTrue);
+    expect(body is Node, isTrue);
+  });
+}
diff --git a/tests/lib/html/js_test_util.dart b/tests/lib/html/js_test_util.dart
new file mode 100644
index 0000000..e56887f
--- /dev/null
+++ b/tests/lib/html/js_test_util.dart
@@ -0,0 +1,228 @@
+// 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 TestJsUtils;
+
+import 'dart:html';
+import 'dart:indexed_db' show IdbFactory, KeyRange;
+import 'dart:js';
+
+import 'package:expect/minitest.dart';
+
+injectJs() {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = r"""
+var x = 42;
+
+var _x = 123;
+
+var myArray = ["value1"];
+
+var foreignDoc = (function(){
+  var doc = document.implementation.createDocument("", "root", null);
+  var element = doc.createElement('element');
+  element.setAttribute('id', 'abc');
+  doc.documentElement.appendChild(element);
+  return doc;
+})();
+
+function razzle() {
+  return x;
+}
+
+function returnThis() {
+  return this;
+}
+
+function getTypeOf(o) {
+  return typeof(o);
+}
+
+function varArgs() {
+  var args = arguments;
+  var sum = 0;
+  for (var i = 0; i < args.length; ++i) {
+    sum += args[i];
+  }
+  return sum;
+}
+
+function Foo(a) {
+  this.a = a;
+}
+
+Foo.b = 38;
+
+Foo.prototype.bar = function() {
+  return this.a;
+}
+Foo.prototype.toString = function() {
+  return "I'm a Foo a=" + this.a;
+}
+
+var container = new Object();
+container.Foo = Foo;
+
+function isArray(a) {
+  return a instanceof Array;
+}
+
+function checkMap(m, key, value) {
+  if (m.hasOwnProperty(key))
+    return m[key] == value;
+  else
+    return false;
+}
+
+function invokeCallback() {
+  return callback();
+}
+
+function invokeCallbackWith11params() {
+  return callbackWith11params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+}
+
+function returnElement(element) {
+  return element;
+}
+
+function getElementAttribute(element, attr) {
+  return element.getAttribute(attr);
+}
+
+function addClassAttributes(list) {
+  var result = "";
+  for (var i=0; i < list.length; i++) {
+    result += list[i].getAttribute("class");
+  }
+  return result;
+}
+
+function getNewDate() {
+  return new Date(1995, 11, 17);
+}
+
+function getNewDivElement() {
+  return document.createElement("div");
+}
+
+function getNewEvent() {
+  return new CustomEvent('test');
+}
+
+function getNewBlob() {
+  var fileParts = ['<a id="a"><b id="b">hey!</b></a>'];
+  return new Blob(fileParts, {type : 'text/html'});
+}
+
+function getNewIDBKeyRange() {
+  return IDBKeyRange.only(1);
+}
+
+function getNewImageData() {
+  var canvas = document.createElement('canvas');
+  var context = canvas.getContext('2d');
+  return context.createImageData(1, 1);
+}
+
+function getNewInt32Array() {
+  return new Int32Array([1, 2, 3, 4, 5, 6, 7, 8]);
+}
+
+function getNewArrayBuffer() {
+  return new ArrayBuffer(8);
+}
+
+function isPropertyInstanceOf(property, type) {
+  return window[property] instanceof type;
+}
+
+function testJsMap(callback) {
+  var result = callback();
+  return result['value'];
+}
+
+function addTestProperty(o) {
+  o.testProperty = "test";
+}
+
+function fireClickEvent(w) {
+  var event = w.document.createEvent('Events');
+  event.initEvent('click', true, false);
+  w.document.dispatchEvent(event);
+}
+
+function Bar() {
+  return "ret_value";
+}
+Bar.foo = "property_value";
+
+function Baz(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11) {
+  this.f1 = p1;
+  this.f2 = p2;
+  this.f3 = p3;
+  this.f4 = p4;
+  this.f5 = p5;
+  this.f6 = p6;
+  this.f7 = p7;
+  this.f8 = p8;
+  this.f9 = p9;
+  this.f10 = p10;
+  this.f11 = p11;
+}
+
+function Liar(){}
+
+Liar.prototype.toString = function() {
+  return 1;
+}
+
+function identical(o1, o2) {
+  return o1 === o2;
+}
+
+var someProto = { role: "proto" };
+var someObject = Object.create(someProto);
+someObject.role = "object";
+
+""";
+  document.body!.append(script);
+}
+
+typedef bool StringToBool(String s);
+
+// Some test are either causing other test to fail in IE9, or they are failing
+// for unknown reasons
+// useHtmlConfiguration+ImageData bug: dartbug.com/14355
+skipIE9_test(String description, t()) {
+  if (Platform.supportsTypedData) {
+    test(description, t);
+  }
+}
+
+class Foo {
+  final JsObject _proxy;
+
+  Foo(num a) : this._proxy = new JsObject(context['Foo'], [a]);
+
+  JsObject toJs() => _proxy;
+
+  num get a => _proxy['a'];
+  num bar() => _proxy.callMethod('bar');
+}
+
+class Color {
+  static final RED = new Color._("red");
+  static final BLUE = new Color._("blue");
+  String _value;
+  Color._(this._value);
+  String toJs() => this._value;
+}
+
+class TestDartObject {}
+
+class Callable {
+  call() => 'called';
+}
diff --git a/tests/lib/html/js_transferrables_test.dart b/tests/lib/html/js_transferrables_test.dart
new file mode 100644
index 0000000..46fcdcc
--- /dev/null
+++ b/tests/lib/html/js_transferrables_test.dart
@@ -0,0 +1,118 @@
+// 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:indexed_db' show IdbFactory, KeyRange;
+import 'dart:typed_data' show Int32List;
+import 'dart:js';
+
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+import 'js_test_util.dart';
+
+main() {
+  injectJs();
+
+  test('DateTime', () {
+    var date = context.callMethod('getNewDate');
+    expect(date is DateTime, isTrue);
+  });
+
+  test('window', () {
+    expect(context['window'] is Window, isTrue);
+  });
+
+  test('foreign browser objects should be proxied', () {
+    var iframe = new IFrameElement();
+    document.body!.children.add(iframe);
+    var proxy = new JsObject.fromBrowserObject(iframe);
+
+    // Window
+    var contentWindow = proxy['contentWindow'];
+    expect(contentWindow is! Window, isTrue);
+    expect(contentWindow is JsObject, isTrue);
+
+    // Node
+    var foreignDoc = contentWindow['document'];
+    expect(foreignDoc is! Node, isTrue);
+    expect(foreignDoc is JsObject, isTrue);
+
+    // Event
+    var clicked = false;
+    foreignDoc['onclick'] = (e) {
+      expect(e is! Event, isTrue);
+      expect(e is JsObject, isTrue);
+      clicked = true;
+    };
+
+    context.callMethod('fireClickEvent', [contentWindow]);
+    expect(clicked, isTrue);
+  });
+
+  test('foreign functions pass function is checks', () {
+    var iframe = new IFrameElement();
+    document.body!.children.add(iframe);
+    var proxy = new JsObject.fromBrowserObject(iframe);
+
+    var contentWindow = proxy['contentWindow'];
+    var foreignDoc = contentWindow['document'];
+
+    // Function
+    var foreignFunction = foreignDoc['createElement'];
+    expect(foreignFunction is JsFunction, isTrue);
+
+    // Verify that internal isChecks in callMethod work.
+    foreignDoc.callMethod('createElement', ['div']);
+
+    var typedContentWindow = js_util.getProperty(iframe, 'contentWindow');
+    var typedForeignDoc = js_util.getProperty(typedContentWindow, 'document');
+
+    var typedForeignFunction =
+        js_util.getProperty(typedForeignDoc, 'createElement');
+    expect(typedForeignFunction is Function, isTrue);
+    js_util.callMethod(typedForeignDoc, 'createElement', ['div']);
+  });
+
+  test('document', () {
+    expect(context['document'] is Document, isTrue);
+  });
+
+  skipIE9_test('Blob', () {
+    var blob = context.callMethod('getNewBlob');
+    expect(blob is Blob, isTrue);
+    expect(blob.type, equals('text/html'));
+  });
+
+  test('unattached DivElement', () {
+    var node = context.callMethod('getNewDivElement');
+    expect(node is DivElement, isTrue);
+  });
+
+  test('Event', () {
+    var event = context.callMethod('getNewEvent');
+    expect(event is Event, true);
+  });
+
+  test('KeyRange', () {
+    if (IdbFactory.supported) {
+      var node = context.callMethod('getNewIDBKeyRange');
+      expect(node is KeyRange, isTrue);
+    }
+  });
+
+  test('ImageData', () {
+    var node = context.callMethod('getNewImageData');
+    expect(node is ImageData, isTrue);
+  });
+
+  test('typed data: Int32Array', () {
+    if (Platform.supportsTypedData) {
+      var list = context.callMethod('getNewInt32Array');
+      print(list);
+      expect(list is Int32List, isTrue);
+      expect(list, equals([1, 2, 3, 4, 5, 6, 7, 8]));
+    }
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_anonymous2_exp_test.dart b/tests/lib/html/js_typed_interop_anonymous2_exp_test.dart
new file mode 100644
index 0000000..2c827b8
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_anonymous2_exp_test.dart
@@ -0,0 +1,54 @@
+// 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_anonymous2_test.dart b/tests/lib/html/js_typed_interop_anonymous2_test.dart
new file mode 100644
index 0000000..a5b5302
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_anonymous2_test.dart
@@ -0,0 +1,50 @@
+// 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.
+
+@JS()
+library js_typed_interop_anonymous2_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
new file mode 100644
index 0000000..e160bdd
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_anonymous_exp_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.
+
+// 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_test.dart b/tests/lib/html/js_typed_interop_anonymous_test.dart
new file mode 100644
index 0000000..485f812
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_anonymous_test.dart
@@ -0,0 +1,69 @@
+// 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.
+
+@JS()
+library js_typed_interop_anonymous_test;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS()
+@anonymous
+class Literal {
+  external factory Literal({int? x, String? y, num? z});
+
+  external set x(int? v);
+  external int? get x;
+  external String? get y;
+  external num? get z;
+}
+
+class MockLiteral implements Literal {
+  int? _v = 0;
+  set x(int? v) {
+    _v = v;
+  }
+
+  int? get x => _v;
+  String? get y => "";
+  num? get z => 1;
+}
+
+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);
+  });
+
+  test('mock', () {
+    Literal l = new MockLiteral();
+    expect(l.x, equals(0));
+    l.x = 3;
+    expect(l.x, equals(3));
+    expect(l.y, equals(""));
+    expect(l.z, equals(1));
+  });
+
+  // Test that instance checks behave appropriately.
+  test('Instance checks: implements', () {
+    Object l = new Literal(x: 3, y: "foo");
+    Object m = new MockLiteral();
+    expect(m is Literal, isTrue);
+    expect(m is MockLiteral, isTrue);
+    expect(l is Literal, isTrue);
+    expect(l is MockLiteral, isFalse);
+  });
+
+  // Test that casts behave appropriately.
+  test('Casts: implements', () {
+    Object l = new Literal(x: 3, y: "foo");
+    Object m = new MockLiteral();
+    expect(m as Literal, equals(m));
+    expect(m as MockLiteral, equals(m));
+    expect(l as Literal, equals(l));
+    expect(() => l as MockLiteral, throws);
+  });
+}
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
new file mode 100644
index 0000000..046dcff
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_anonymous_unreachable_exp_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.
+
+// 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_anonymous_unreachable_test.dart b/tests/lib/html/js_typed_interop_anonymous_unreachable_test.dart
new file mode 100644
index 0000000..e0dbaff
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_anonymous_unreachable_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+@JS()
+library js_typed_interop_anonymous_unreachable_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_bind_this_test.dart b/tests/lib/html/js_typed_interop_bind_this_test.dart
new file mode 100644
index 0000000..a444043
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_bind_this_test.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.
+
+@JS()
+library js_typed_interop_bind_this_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+// This is a regression test for https://github.com/dart-lang/sdk/issues/25658
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  "use strict";
+
+  function JsTest() {
+  }
+
+  JsTest.returnThis = function(name, value) {
+    return this;
+  };
+""");
+}
+
+@JS('JsTest.returnThis')
+external returnThis([name, value]);
+
+@JS('JsTest')
+external get jsTestObject;
+
+@JS('window')
+external get jsWindow;
+
+main() {
+  _injectJs();
+
+  group('bind this', () {
+    test('simple', () {
+      expect(identical(returnThis(), jsWindow), isFalse);
+      expect(identical(returnThis(), null), isFalse);
+      expect(identical(returnThis(), jsTestObject), isTrue);
+    });
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_callable_object_test.dart b/tests/lib/html/js_typed_interop_callable_object_test.dart
new file mode 100644
index 0000000..659d2a91
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_callable_object_test.dart
@@ -0,0 +1,68 @@
+// 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.
+
+@JS()
+library js_typed_interop_callable_object_test;
+
+import 'dart:html';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+// This is a regression test for https://github.com/dart-lang/sdk/issues/25658
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  "use strict";
+
+  window.callableObject = function (a, b) { return a + b; };
+  window.callableObject.foo = function() { return "bar"; };
+  window.callableObject.bar = 42;
+
+""");
+}
+
+@JS()
+@anonymous
+class CallableObject {
+  /// If a @JS class implements `call`, the underlying representation must be
+  /// a JavaScript callable (i.e. function).
+  external num call(num a, num b);
+  external int get bar;
+  external String foo();
+}
+
+@JS()
+external CallableObject get callableObject;
+
+main() {
+  _injectJs();
+
+  group('callable object', () {
+    test('simple', () {
+      var obj = callableObject;
+      expect(obj(4, 5), equals(9));
+      expect(obj.bar, equals(42));
+      expect(obj.foo(), equals("bar"));
+
+      expect(callableObject(4, 5), equals(9));
+      expect(callableObject.bar, equals(42));
+      expect(callableObject.foo(), equals("bar"));
+    });
+
+    test('dynamic', () {
+      var obj = confuse(callableObject);
+      expect(obj(4, 5), equals(9));
+      expect(obj.bar, equals(42));
+      expect(obj.foo(), equals("bar"));
+    });
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_default_arg_static_test.dart b/tests/lib/html/js_typed_interop_default_arg_static_test.dart
new file mode 100644
index 0000000..5fbf41b
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_default_arg_static_test.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.
+
+@JS()
+library js_typed_interop_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  var Foo = {
+    get42: function(b) { return arguments.length >= 1 ? b : 42; }
+  };
+""");
+}
+
+@JS()
+class Foo {
+  external static num get42([num? b = 3
+      // TODO(41375): This should be a static error. It's invalid to have a
+      // default value.
+      ]);
+}
+
+main() {
+  _injectJs();
+
+  test('call tearoff from dart with default', () {
+    var f = Foo.get42;
+    // Note: today both SSA and CPS remove the extra argument on static calls,
+    // but they fail to do so on tearoffs.
+    expect(f(), 3);
+    // TODO(41375): Remove this once the above is resolved. This is temporary
+    // to track this test failure.
+    throw ("This test should not execute. It should fail to compile above.");
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_default_arg_test.dart b/tests/lib/html/js_typed_interop_default_arg_test.dart
new file mode 100644
index 0000000..b309af5
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_default_arg_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.
+
+@JS()
+library js_typed_interop_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  var Foo = {
+    get42: function(b) { return arguments.length >= 1 ? b : 42; }
+  };
+""");
+}
+
+@JS()
+class Foo {
+  external static num get42([num? b]);
+}
+
+main() {
+  _injectJs();
+
+  test('call directly from dart', () {
+    expect(Foo.get42(2), 2);
+    expect(Foo.get42(), 42);
+  });
+
+  test('call tearoff from dart with arg', () {
+    var f = Foo.get42;
+    expect(f(2), 2);
+  });
+
+  test('call tearoff from dart with no arg', () {
+    var f = Foo.get42;
+    expect(f(), 42);
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_dynamic_test.dart b/tests/lib/html/js_typed_interop_dynamic_test.dart
new file mode 100644
index 0000000..030c9c2
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_dynamic_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.
+
+@JS()
+library js_typed_interop_anonymous_test;
+
+import 'dart:html';
+import 'dart:js' as js;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+@JS()
+@anonymous
+class Literal {
+  external factory Literal({int? x, String? y, num? z, Function? foo});
+
+  external int? get x;
+  external String? get y;
+  external num? get z;
+  external Function? get foo;
+}
+
+@JS()
+@anonymous
+class FunctionWithExpando {
+  external int call();
+  external String get myExpando;
+}
+
+main() {
+  test('object', () {
+    dynamic l = new Literal(x: 3, y: 'foo', foo: allowInterop((x) => x * 2));
+    expect(l.x, equals(3));
+    expect(l.y, equals('foo'));
+    expect(l.z, isNull);
+    expect(l.foo(4), equals(8));
+  });
+
+  test('function', () {
+    // Get a JS function.
+    dynamic f = js_util.getProperty(window, 'addEventListener');
+    js_util.setProperty(f, 'myExpando', 'foo');
+    expect(f.myExpando, equals('foo'));
+  });
+
+  test('dart object', () {
+    dynamic o = new Object();
+    js_util.setProperty(o, 'x', 3);
+    expect(() => o.x, throwsNoSuchMethodError);
+    expect(() => o.foo(), throwsNoSuchMethodError);
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_lazy_test.dart b/tests/lib/html/js_typed_interop_lazy_test.dart
new file mode 100644
index 0000000..98b26ff
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_lazy_test.dart
@@ -0,0 +1,285 @@
+// 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.
+
+@JS()
+library js_typed_interop_lazy_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+@JS('someProperty')
+external get foo;
+
+@JS('baz.bar')
+external get bar;
+
+@JS('baz.LazyClass')
+class LazyClass {
+  external factory LazyClass(a);
+  external get a;
+}
+
+@JS('baz.foo.NestedLazyClass')
+class NestedLazyClass {
+  external factory NestedLazyClass(a);
+  external get a;
+}
+
+@anonymous
+@JS('some.bogus.ignored.js.path')
+class AnonClass {
+  external factory AnonClass({a});
+  external get a;
+}
+
+@anonymous
+@JS()
+class AnonClass2 {
+  external factory AnonClass2({b});
+  external get b;
+}
+
+abstract class Foo<T> {
+  T get obj;
+}
+
+class Mock1LazyClass implements LazyClass {
+  noSuchMethod(Invocation i) => i.memberName == #a ? 42 : null;
+}
+
+class Mock2LazyClass implements LazyClass {
+  get a => 42;
+}
+
+class Mock1NestedLazyClass implements NestedLazyClass {
+  noSuchMethod(Invocation i) => i.memberName == #a ? 42 : null;
+}
+
+class Mock2NestedLazyClass implements NestedLazyClass {
+  get a => 42;
+}
+
+class Other {
+  noSuchMethod(Invocation i) {}
+}
+
+// Test that the lazy JS classes can be used as a generic type argument.
+class FooImpl extends Foo<LazyClass> {
+  LazyClass get obj => new LazyClass(100);
+}
+
+class NestedFooImpl extends Foo<NestedLazyClass> {
+  NestedLazyClass get obj => new NestedLazyClass(100);
+}
+
+class ExampleGenericClass<T> {
+  String add(T foo) {
+    return foo.toString();
+  }
+}
+
+main() {
+  group('lazy property', () {
+    test('simple', () {
+      expect(foo, isNull);
+      js_util.setProperty(window, 'someProperty', 42);
+      expect(foo, equals(42));
+    });
+
+    test('nested', () {
+      js_util.setProperty(window, 'baz', js_util.newObject());
+      expect(bar, isNull);
+      js_util.setProperty(window, 'baz', js_util.jsify({'bar': 100}));
+      expect(bar, equals(100));
+    });
+  });
+
+  group('lazy class', () {
+    test('type literal', () {
+      // Fine because we can determine the class literals are equal without
+      // having to determine what (non-existant) JS type they correspond to.
+      var x = LazyClass;
+      var y = LazyClass;
+      expect(x == y, isTrue);
+    });
+
+    test('reference in type parameter', () {
+      var o = new FooImpl();
+      expect(o is Foo<LazyClass>, isTrue);
+    });
+
+    test('create instance', () {
+      var anon = new AnonClass(a: 42);
+      // Until LazyClass is defined, fall back to Anon behavior.
+      expect(anon is LazyClass, isTrue); //# 01: ok
+      expect(new Object() is! LazyClass, isTrue);
+
+      document.body!.append(new ScriptElement()
+        ..type = 'text/javascript'
+        ..innerHtml = r"""
+window.baz = {};
+
+baz.LazyClass = function LazyClass(a) {
+  this.a = a;
+};
+""");
+      var l = new LazyClass(42);
+      expect(l.a, equals(42));
+      expect(l is LazyClass, isTrue);
+      expect(l is AnonClass, isTrue);
+      expect((l as AnonClass) == l, isTrue);
+      expect((l as AnonClass2) == l, isTrue);
+      expect(anon is! LazyClass, isTrue); //# 01: ok
+      expect(anon is AnonClass, isTrue);
+      expect(anon is AnonClass2, isTrue);
+
+      // Sanity check that is and as are not broken.
+      expect(new Object() is! LazyClass, isTrue);
+      expect(new Object() is! AnonClass, isTrue);
+      expect(new Object() is! AnonClass2, isTrue);
+
+      expect(<AnonClass>[] is List<AnonClass>, isTrue);
+      // TODO(jacobr): why doesn't this test pass?
+      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<int>[] is! List<AnonClass>, isTrue);
+      expect(<AnonClass>[] is! List<LazyClass>, isTrue); //# 01: ok
+      expect(<int>[] is! List<LazyClass>, isTrue);
+      expect(<LazyClass>[] is List<LazyClass>, isTrue);
+
+      var listLazyClass = <LazyClass?>[];
+      Object instanceLazyObject = l;
+      expect(() => listLazyClass.add(42 as dynamic), throws); //# 01: ok
+      // Regression test for bug where this call failed.
+      listLazyClass.add(instanceLazyObject as LazyClass?);
+      listLazyClass.add(null);
+
+      dynamic listLazyClassDynamic = listLazyClass;
+      expect(() => listLazyClassDynamic.add(42), throws); //# 01: ok
+      // Regression test for bug where this call failed.
+      listLazyClassDynamic.add(instanceLazyObject);
+      listLazyClassDynamic.add(null);
+
+      var genericClass = new ExampleGenericClass<LazyClass?>();
+      genericClass.add(instanceLazyObject as LazyClass?);
+      expect(() => genericClass.add(42 as dynamic), throws); //# 01: ok
+      genericClass.add(null);
+
+      dynamic genericClassDynamic = genericClass;
+      genericClassDynamic.add(instanceLazyObject);
+      expect(() => genericClassDynamic.add(42), throws); //# 01: ok
+      genericClassDynamic.add(null);
+    });
+
+    test('mocks', () {
+      var mock1 = new Mock1LazyClass();
+      expect(mock1 is LazyClass, isTrue);
+      expect((mock1 as dynamic) as LazyClass, equals(mock1));
+      expect(mock1.a, equals(42));
+
+      var mock2 = new Mock2LazyClass();
+      expect(mock2 is LazyClass, isTrue);
+      expect((mock2 as dynamic) as LazyClass, equals(mock2));
+      expect(mock2.a, equals(42));
+
+      Object other = new Other();
+      expect(other is LazyClass, isFalse);
+    });
+  });
+
+  group('nested lazy class', () {
+    test('type literal', () {
+      // Fine because we can determine the class literals are equal without
+      // having to determine what (non-existant) JS type they correspond to.
+      var x = NestedLazyClass;
+      var y = NestedLazyClass;
+      expect(x == y, isTrue);
+    });
+
+    test('reference in type parameter', () {
+      var o = new NestedFooImpl();
+      expect(o is Foo<NestedLazyClass>, isTrue);
+    });
+
+    test('create instance', () {
+      var anon = new AnonClass(a: 42);
+      // Until NestedLazyClass is defined, fall back to Anon behavior.
+      expect(anon is NestedLazyClass, isTrue); //# 01: ok
+      expect(new Object() is! NestedLazyClass, isTrue);
+
+      document.body!.append(new ScriptElement()
+        ..type = 'text/javascript'
+        ..innerHtml = r"""
+window.baz = window.baz || {};
+window.baz.foo = {};
+
+baz.foo.NestedLazyClass = function NestedLazyClass(a) {
+  this.a = a;
+};
+""");
+      var l = new NestedLazyClass(42);
+      expect(l.a, equals(42));
+      expect(l is NestedLazyClass, isTrue);
+      expect(l is AnonClass, isTrue);
+      expect((l as AnonClass) == l, isTrue);
+      expect((l as AnonClass2) == l, isTrue);
+      expect(anon is! NestedLazyClass, isTrue); //# 01: ok
+      expect(anon is AnonClass, isTrue);
+      expect(anon is AnonClass2, isTrue);
+
+      // Sanity check that is and as are not broken.
+      expect(new Object() is! NestedLazyClass, isTrue);
+      expect(new Object() is! AnonClass, isTrue);
+      expect(new Object() is! AnonClass2, isTrue);
+
+      expect(<AnonClass>[] is List<AnonClass>, isTrue);
+      // TODO(jacobr): why doesn't this test pass?
+      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<int>[] is! List<AnonClass>, isTrue);
+      expect(<AnonClass>[] is! List<NestedLazyClass>, isTrue); //# 01: ok
+      expect(<int>[] is! List<NestedLazyClass>, isTrue);
+      expect(<NestedLazyClass>[] is List<NestedLazyClass>, isTrue);
+
+      var listLazyClass = <NestedLazyClass?>[];
+      Object instanceLazyObject = l;
+      expect(() => listLazyClass.add(42 as dynamic), throws); //# 01: ok
+      // Regression test for bug where this call failed.
+      listLazyClass.add(instanceLazyObject as NestedLazyClass?);
+      listLazyClass.add(null);
+
+      dynamic listLazyClassDynamic = listLazyClass;
+      expect(() => listLazyClassDynamic.add(42), throws); //# 01: ok
+      // Regression test for bug where this call failed.
+      listLazyClassDynamic.add(instanceLazyObject);
+      listLazyClassDynamic.add(null);
+
+      var genericClass = new ExampleGenericClass<NestedLazyClass?>();
+      genericClass.add(instanceLazyObject as NestedLazyClass?);
+      expect(() => genericClass.add(42 as dynamic), throws); //# 01: ok
+      genericClass.add(null);
+
+      dynamic genericClassDynamic = genericClass;
+      genericClassDynamic.add(instanceLazyObject);
+      expect(() => genericClassDynamic.add(42), throws); //# 01: ok
+      genericClassDynamic.add(null);
+    });
+
+    test('mocks', () {
+      var mock1 = new Mock1NestedLazyClass();
+      expect(mock1 is NestedLazyClass, isTrue);
+      expect((mock1 as dynamic) as NestedLazyClass, equals(mock1));
+      expect(mock1.a, equals(42));
+
+      var mock2 = new Mock2NestedLazyClass();
+      expect(mock2 is NestedLazyClass, isTrue);
+      expect((mock2 as dynamic) as NestedLazyClass, equals(mock2));
+      expect(mock2.a, equals(42));
+
+      Object other = new Other();
+      expect(other is NestedLazyClass, isFalse);
+    });
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_rename_static_test.dart b/tests/lib/html/js_typed_interop_rename_static_test.dart
new file mode 100644
index 0000000..48d6831
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_rename_static_test.dart
@@ -0,0 +1,95 @@
+// 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.
+
+@JS()
+library js_typed_interop_rename_static_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+@JS('JSTopLevelField')
+external set topLevelFieldOnlySetter(v);
+
+@JS('JSTopLevelField')
+external get topLevelFieldOnlyGetter;
+
+@JS()
+external get topLevelFieldNoRename;
+
+@JS()
+external set topLevelSetterNoRename(v);
+
+@JS()
+external topLevelMethod(v);
+
+@JS('topLevelMethod')
+external renamedTopLevelMethod(v);
+
+@JS('JSFoo')
+class Foo {
+  @JS('JSBar')
+  external static get bar;
+
+  @JS('JSBar')
+  external static set bar(v);
+
+  @JS('JSBar2')
+  external static get bar2;
+
+  @JS('JSBaz')
+  external static set baz(v);
+
+  @JS('JSMethodAddBar')
+  external static addBar(a);
+}
+
+main() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+window.JSFoo = {
+  'JSBar': 42,
+  'JSBar2': 80,
+  'JSMethodAddBar': function(a,b) { return a + this.JSBar; }
+};
+window.JSTopLevelField = 91;
+window.topLevelFieldNoRename = 8;
+window.topLevelMethod = function(a) { return a * 2; };
+""");
+
+  group('rename static', () {
+    test('getter', () {
+      expect(Foo.bar, equals(42));
+      expect(Foo.bar2, equals(80));
+      expect(topLevelFieldOnlyGetter, 91);
+      expect(topLevelFieldNoRename, 8);
+    });
+
+    test('setter', () {
+      Foo.baz = 100;
+      expect(js_util.getProperty(js_util.getProperty(window, 'JSFoo'), 'JSBaz'),
+          equals(100));
+      Foo.bar = 30;
+      expect(Foo.bar, equals(30));
+      expect(js_util.getProperty(js_util.getProperty(window, 'JSFoo'), 'JSBar'),
+          equals(30));
+      topLevelFieldOnlySetter = 83;
+      expect(topLevelFieldOnlyGetter, 83);
+      topLevelSetterNoRename = 10;
+      expect(js_util.getProperty(window, 'topLevelSetterNoRename'), 10);
+    });
+
+    test('method', () {
+      Foo.bar = 100;
+      expect(Foo.addBar(10), equals(110));
+      Foo.bar = 200;
+      expect(Foo.addBar(10), equals(210));
+      expect(topLevelMethod(10), equals(20));
+      expect(renamedTopLevelMethod(10), equals(20));
+    });
+  });
+}
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
new file mode 100644
index 0000000..be112c8
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_side_cast_exp_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.
+
+// 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/html/js_typed_interop_side_cast_test.dart b/tests/lib/html/js_typed_interop_side_cast_test.dart
new file mode 100644
index 0000000..c222073
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_side_cast_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.
+
+@JS()
+library js_typed_interop_anonymous2_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 C {
+  external int get x;
+  external factory C({required int x});
+}
+
+@JS()
+@anonymous
+class B {
+  external int get x;
+  external factory B({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));
+  });
+
+  test('side-casts work for otherwise unreachable types', () {
+    dynamic a = new A(x: 3);
+    expect(a is B, isTrue);
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_test.dart b/tests/lib/html/js_typed_interop_test.dart
new file mode 100644
index 0000000..3ee46e0
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_test.dart
@@ -0,0 +1,459 @@
+// 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.
+
+@JS()
+library js_typed_interop_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  "use strict";
+
+  var Foo = {
+    multiplyDefault2: function(a, b) {
+      if (arguments.length >= 2) return a *b;
+      return a * 2;
+    }
+  };
+
+  var foo = {
+    x: 3,
+    z: 40, // Not specified in typed Dart API so should fail in checked mode.
+    multiplyByX: function(arg) { return arg * this.x; },
+    // This function can be torn off without having to bind this.
+    multiplyBy2: function(arg) { return arg * 2; },
+    multiplyDefault2Function: function(a, b) {
+      if (arguments.length >= 2) return a * b;
+      return a * 2;
+    },
+    callClosureWithArg1: function(closure, arg) {
+      return closure(arg);
+    },
+    callClosureWithArg2: function(closure, arg1, arg2) {
+      return closure(arg1, arg2);
+    },
+    callClosureWithArgAndThis: function(closure, arg) {
+      return closure.apply(this, [arg]);
+    },
+
+    getBar: function() {
+      return bar;
+    }
+  };
+
+  var foob = {
+    x: 8,
+    y: "why",
+    multiplyByX: function(arg) { return arg * this.x; }
+  };
+
+  var bar = {
+    x: "foo",
+    multiplyByX: true,
+    getFoo: function() {
+      return foo;
+    }
+  };
+
+  function ClassWithConstructor(a, b) {
+    this.a = a;
+    this.b = b;
+  };
+
+  ClassWithConstructor.prototype = {
+    getA: function() { return this.a;}
+  };
+
+  var selection = ["a", "b", "c", foo, bar];
+
+  function returnNumArgs() { return arguments.length; };
+  function returnLastArg() { return arguments[arguments.length-1]; };
+
+  function confuse(obj) { return obj; }
+
+  function isUndefined(obj) { return obj === void 0; }
+
+  function StringWrapper(str) {
+    this.str = str;
+  }
+  StringWrapper.prototype = {
+    charCodeAt: function(index) {
+      return this.str.charCodeAt(index);
+    }
+  };
+  function getCanvasContext() {
+    return document.createElement('canvas').getContext('2d');
+  }
+  window.windowProperty = 42;
+  document.documentProperty = 45;
+""");
+}
+
+class RegularClass {
+  factory RegularClass(a) {
+    return new RegularClass.fooConstructor(a);
+  }
+  RegularClass.fooConstructor(this.a);
+  var a;
+}
+
+@JS()
+class ClassWithConstructor {
+  external ClassWithConstructor(aParam, bParam);
+  external getA();
+  external get a;
+  external get b;
+}
+
+@JS('ClassWithConstructor')
+class ClassWithFactory {
+  external factory ClassWithFactory(aParam, bParam);
+  external getA();
+  external get a;
+  external get b;
+}
+
+typedef num MultiplyWithDefault(num a, [num? b]);
+
+@JS()
+@anonymous
+class Foo {
+  external int get x;
+  external set x(int v);
+  external num multiplyByX(num y);
+  external num multiplyBy2(num y);
+  external MultiplyWithDefault get multiplyDefault2Function;
+
+  external callClosureWithArgAndThis(Function closure, arg);
+  external callClosureWithArg1(Function closure, arg1);
+  external callClosureWithArg2(Function closure, arg1, arg2);
+  external Bar getBar();
+
+  external static num multiplyDefault2(num a, [num? b]);
+}
+
+@anonymous
+@JS()
+class ExampleLiteral {
+  external factory ExampleLiteral({int? x, String? y, num? z});
+
+  external int? get x;
+  external String? get y;
+  external num? get z;
+}
+
+@anonymous
+@JS()
+class EmptyLiteral {
+  external factory EmptyLiteral();
+}
+
+@JS('Foob')
+class Foob extends Foo {
+  external String get y;
+}
+
+@JS('Bar')
+class Bar {
+  external String get x;
+  external bool get multiplyByX;
+  external Foo getFoo();
+}
+
+// No @JS is required for these external methods as the library is
+// annotated with Js.
+external Foo get foo;
+external Foob get foob;
+external Bar get bar;
+external Selection get selection;
+
+addWithDefault(a, [b = 100]) => a + b;
+
+external Function get returnNumArgs;
+external Function get returnLastArg;
+
+const STRINGIFY_LOCATION = "JSON.stringify";
+@JS(STRINGIFY_LOCATION)
+external String stringify(obj);
+
+@JS()
+class StringWrapper {
+  external StringWrapper(String str);
+  external int charCodeAt(int i);
+}
+
+// Defeat JS type inference by calling through JavaScript interop.
+@JS()
+external confuse(obj);
+
+@JS()
+external isUndefined(obj);
+
+@JS()
+external CanvasRenderingContext2D getCanvasContext();
+
+@JS('window.window.document.documentProperty')
+external num get propertyOnDocument;
+
+@JS('window.self.window.window.windowProperty')
+external num get propertyOnWindow;
+
+class DartClassWithNullField {
+  int? x;
+}
+
+main() {
+  _injectJs();
+
+  group('object literal', () {
+    test('simple', () {
+      var l = new ExampleLiteral(x: 3, y: "foo");
+      expect(l.x, equals(3));
+      expect(l.y, equals("foo"));
+      expect(l.z, isNull);
+      expect(stringify(l), equals('{"x":3,"y":"foo"}'));
+      var l2 = new ExampleLiteral(y: "foo", x: 3);
+      expect(l2.x, equals(l.x));
+      expect(l2.y, equals(l.y));
+      l = new ExampleLiteral(z: 100);
+      expect(l.x, isNull);
+      expect(l.y, isNull);
+      expect(l.z, equals(100));
+      expect(stringify(l), equals('{"z":100}'));
+    });
+
+    test('empty', () {
+      var l = new EmptyLiteral();
+      expect(stringify(l), equals('{}'));
+    });
+  });
+
+  group('constructor', () {
+    test('simple', () {
+      var o = new ClassWithConstructor("foo", "bar");
+      expect(o.a, equals("foo"));
+      expect(o.b, equals("bar"));
+      expect(o.getA(), equals("foo"));
+    });
+
+    test('external factory', () {
+      var o = new ClassWithFactory("foo", "bar");
+      expect(o.a, equals("foo"));
+      expect(o.b, equals("bar"));
+      expect(o.getA(), equals("foo"));
+    });
+  });
+
+  group('property', () {
+    test('get', () {
+      expect(foo.x, equals(3));
+      expect(foob.x, equals(8));
+      expect(foob.y, equals("why"));
+
+      // Exists in JS but not in API.
+      // TODO(29419): add back this line once the appropriate metadata is
+      // tracked for anonymous JS classes (DARTBUG.
+      // expect(() => (foo as dynamic).zSomeInvalidName, throws);
+      expect(bar.multiplyByX, isTrue);
+    });
+    test('set', () {
+      foo.x = 42;
+      expect(foo.x, equals(42));
+      // Property tagged as read only in typed API.
+      // TODO(29419): add back this line once the appropriate metadata is
+      // tracked for anonymous JS classes.
+      // expect(() => (foob as dynamic).y = "bla", throws);
+      // expect(() => (foo as dynamic).unknownName = 42, throws);
+    });
+  });
+
+  group('method', () {
+    test('call', () {
+      foo.x = 100;
+      expect(foo.multiplyByX(4), equals(400));
+      foob.x = 10;
+      expect(foob.multiplyByX(4), equals(40));
+    });
+
+    test('tearoff', () {
+      foo.x = 10;
+      Function multiplyBy2 = foo.multiplyBy2;
+      expect(multiplyBy2(5), equals(10));
+      foo.x = 73;
+      Function multiplyByX = foo.multiplyByX;
+      // Tearing off a JS closure doesn't bind this.
+      // You will need to use the new method tearoff syntax to bind this.
+      // Invoking will trigger an error throwing because "this is undefined".
+      expect(() => multiplyByX(4), throws);
+
+      MultiplyWithDefault multiplyWithDefault = foo.multiplyDefault2Function;
+      expect(multiplyWithDefault(6, 6), equals(36));
+      expect(multiplyWithDefault(6), equals(12));
+      Function untypedFunction = foo.multiplyDefault2Function;
+      // Calling with extra bogus arguments has no impact for JavaScript
+      // methods.
+      expect(untypedFunction(6, 6, "ignored", "ignored"), equals(36));
+      expect(
+          untypedFunction(6, 6, "ignored", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+          equals(36));
+      // Calling a JavaScript method with too few arguments is also fine and
+      // defaults to JavaScript behavior of setting all unspecified arguments
+      // to undefined resulting in multiplying undefined by 2 == NAN.
+      expect(untypedFunction().toString(), equals(double.nan.toString()));
+    });
+  });
+
+  group('static_method_call', () {
+    test('call directly from dart', () {
+      expect(Foo.multiplyDefault2(6, 7), equals(42));
+      expect(Foo.multiplyDefault2(6), equals(12));
+    });
+  });
+
+  // Note: these extra groups are added to be able to mark each test
+  // individually in status files. This should be split as separate test files.
+  group('static_method_tearoff_1', () {
+    test('call tearoff from dart', () {
+      MultiplyWithDefault tearOffMethod = Foo.multiplyDefault2;
+      expect(tearOffMethod(6, 6), equals(36));
+    });
+  });
+
+  group('static_method_tearoff_2', () {
+    test('call tearoff from dart', () {
+      MultiplyWithDefault tearOffMethod = Foo.multiplyDefault2;
+      expect(tearOffMethod(6), equals(12));
+    });
+  });
+
+  group('closure', () {
+    test('call from js', () {
+      localClosure(x) => x * 10;
+      var wrappedLocalClosure = allowInterop(localClosure);
+      var wrappedLocalClosure2 = allowInterop(localClosure);
+      expect(identical(wrappedLocalClosure2, wrappedLocalClosure), isTrue);
+      expect(foo.callClosureWithArg1(wrappedLocalClosure, 10), equals(100));
+      expect(foo.callClosureWithArg1(wrappedLocalClosure, "a"),
+          equals("aaaaaaaaaa"));
+      expect(foo.callClosureWithArg1(allowInterop(addWithDefault), 10),
+          equals(110));
+      expect(foo.callClosureWithArg2(allowInterop(addWithDefault), 10, 20),
+          equals(30));
+      addThisXAndArg(Foo that, int arg) {
+        return foo.x + arg;
+      }
+
+      dynamic wrappedCaptureThisClosure =
+          allowInteropCaptureThis(addThisXAndArg);
+      expect(wrappedCaptureThisClosure is Function, isTrue);
+      expect(wrappedCaptureThisClosure is Map, isFalse);
+      expect(wrappedCaptureThisClosure is Object, isTrue);
+      foo.x = 20;
+      expect(foo.callClosureWithArgAndThis(wrappedCaptureThisClosure, 10),
+          equals(30));
+      foo.x = 50;
+      expect(foo.callClosureWithArgAndThis(wrappedCaptureThisClosure, 10),
+          equals(60));
+      expect(
+          identical(allowInteropCaptureThis(addThisXAndArg),
+              wrappedCaptureThisClosure),
+          isTrue);
+
+      ExampleLiteral addXValues(that, ExampleLiteral arg) {
+        return new ExampleLiteral(x: that.x + arg.x);
+      }
+
+      // Check to make sure returning a JavaScript value from a Dart closure
+      // works as expected.
+      expect(
+          foo
+              .callClosureWithArg2(allowInterop(addXValues),
+                  new ExampleLiteral(x: 20), new ExampleLiteral(x: 10))
+              .x,
+          equals(30));
+
+      foo.x = 50;
+      expect(
+          foo
+              .callClosureWithArgAndThis(allowInteropCaptureThis(addXValues),
+                  new ExampleLiteral(x: 10))
+              .x,
+          equals(60));
+    });
+
+    test('call from dart', () {
+      var returnNumArgsFn = returnNumArgs;
+      var returnLastArgFn = returnLastArg;
+      expect(returnNumArgsFn(), equals(0));
+      expect(returnNumArgsFn("a", "b", "c"), equals(3));
+      expect(returnNumArgsFn("a", "b", "c", null, null), equals(5));
+      expect(returnNumArgsFn(1, 2, 3, 4, 5, 6, null), equals(7));
+      expect(returnNumArgsFn(1, 2, 3, 4, 5, 6, 7, 8), equals(8));
+      expect(returnLastArgFn(1, 2, "foo"), equals("foo"));
+      expect(returnLastArgFn(1, 2, 3, 4, 5, 6, "foo"), equals("foo"));
+    });
+  });
+
+  group('chain calls', () {
+    test("method calls", () {
+      // In dart2js make sure we still use interceptors when making nested
+      // calls to objects.
+      var bar = foo.getBar().getFoo().getBar().getFoo().getBar();
+      expect(bar.x, equals("foo"));
+    });
+  });
+
+  group('avoid leaks on dart:core', () {
+    test('String', () {
+      var s = confuse('Hello');
+      var stringWrapper = confuse(new StringWrapper('Hello'));
+      // Make sure we don't allow calling JavaScript methods on String.
+      expect(() => s.charCodeAt(0), throws);
+      expect(stringWrapper.charCodeAt(0), equals(72));
+    });
+  });
+
+  group('type check', () {
+    test('js interfaces', () {
+      // Is checks return true for all anonymous JS interfaces.
+      dynamic dartObject = new Object();
+      expect(foo is Foo, isTrue);
+      expect(foo is ExampleLiteral, isTrue);
+
+      expect(dartObject is Foo, isFalse);
+      expect(dartObject is ExampleLiteral, isFalse);
+
+      expect(selection is List, isTrue);
+
+      // We do know at runtime whether something is a JsArray or not.
+      expect(foo is List, isFalse);
+    });
+
+    test('dart interfaces', () {
+      expect(foo is Function, isFalse);
+      expect(selection is List, isTrue);
+    });
+  });
+
+  group('html', () {
+    test('return html type', () {
+      expect(getCanvasContext() is CanvasRenderingContext2D, isTrue);
+    });
+    test('js path contains html types', () {
+      expect(propertyOnWindow, equals(42));
+      expect(propertyOnDocument, equals(45));
+    });
+  });
+
+  test('Dart field is null instead of undefined', () {
+    expect(isUndefined(new DartClassWithNullField().x), false);
+  });
+}
diff --git a/tests/lib/html/js_typed_interop_type1_test.dart b/tests/lib/html/js_typed_interop_type1_test.dart
new file mode 100644
index 0000000..e85bce1
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_type1_test.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.
+
+@JS()
+library js_typed_interop_type1_test;
+
+import 'dart:html';
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+class A {
+  external get foo;
+
+  external A(var foo);
+}
+
+class F {
+  final foo;
+
+  F(this.foo);
+}
+
+@pragma('dart2js:noInline')
+testA(A o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testF(F o) {
+  return o.foo;
+}
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+function A(foo) {
+  this.foo = foo;
+}
+""");
+}
+
+main() {
+  _injectJs();
+
+  var a = new A(1);
+  var f = new F(6);
+
+  Expect.equals(testA(a), 1);
+  Expect.equals(testF(f), 6);
+}
diff --git a/tests/lib/html/js_typed_interop_type2_test.dart b/tests/lib/html/js_typed_interop_type2_test.dart
new file mode 100644
index 0000000..c3c6ca0
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_type2_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@JS()
+library js_typed_interop_type2_test;
+
+import 'dart:html';
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+@anonymous
+class C {
+  external get foo;
+
+  external factory C({required foo});
+}
+
+@JS()
+@anonymous
+class D {
+  external get foo;
+
+  external factory D({required foo});
+}
+
+class F {
+  final foo;
+
+  F(this.foo);
+}
+
+@pragma('dart2js:noInline')
+testC(C o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testF(F o) {
+  return o.foo;
+}
+
+main() {
+  dynamic d = new D(foo: 4);
+  var f = new F(6);
+  Expect.equals(testC(d), 4);
+  Expect.equals(testF(f), 6);
+}
diff --git a/tests/lib/html/js_typed_interop_type3_test.dart b/tests/lib/html/js_typed_interop_type3_test.dart
new file mode 100644
index 0000000..d764182
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_type3_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.
+
+@JS()
+library js_typed_interop_type3_test;
+
+import 'dart:html';
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+class A {
+  external get foo;
+
+  external A(var foo);
+}
+
+@JS()
+@anonymous
+class C {
+  external get foo;
+
+  external factory C({required foo});
+}
+
+@JS()
+@anonymous
+class D {
+  external get foo;
+
+  external factory D({required foo});
+}
+
+class F {
+  final foo;
+
+  F(this.foo);
+}
+
+@pragma('dart2js:noInline')
+testA(A o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testC(C o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testD(D o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testF(F o) {
+  return o.foo;
+}
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+function A(foo) {
+  this.foo = foo;
+}
+""");
+}
+
+main() {
+  _injectJs();
+
+  var a = new A(1);
+  dynamic d = new D(foo: 4);
+
+  Expect.equals(testA(a), 1); //# 01: ok
+  Expect.equals(testA(a), 1); //# 02: ok
+  Expect.equals(testA(d), 4);
+  Expect.equals(testD(d), 4); //# 02: continued
+}
diff --git a/tests/lib/html/js_typed_interop_type_test.dart b/tests/lib/html/js_typed_interop_type_test.dart
new file mode 100644
index 0000000..c3967b5
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_type_test.dart
@@ -0,0 +1,161 @@
+// 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.
+
+@JS()
+library js_typed_interop_type_test;
+
+import 'dart:html';
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+class A {
+  var foo;
+
+  external A(var foo);
+}
+
+@JS()
+class B {
+  var foo;
+
+  external B(var foo);
+}
+
+@JS()
+@anonymous
+class C {
+  late final foo;
+
+  external factory C({foo});
+}
+
+@JS()
+@anonymous
+class D {
+  late final foo;
+
+  external factory D({foo});
+}
+
+class E {
+  final foo;
+
+  E(this.foo);
+}
+
+class F {
+  final foo;
+
+  F(this.foo);
+}
+
+@pragma('dart2js:noInline')
+testA(A o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testB(B o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testC(C o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testD(D o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testE(E o) {
+  return o.foo;
+}
+
+@pragma('dart2js:noInline')
+testF(F o) {
+  return o.foo;
+}
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+function A(foo) {
+  this.foo = foo;
+}
+
+function B(foo) {
+  this.foo = foo;
+}
+""");
+}
+
+void expectValueOrTypeError(f(), value) {
+  try {
+    dynamic i = 0;
+    // TODO(rnystrom): Revisit this now that checked mode is gone in 2.0.
+    String s = i; // Test for checked mode.
+    Expect.equals(f(), value);
+  } on TypeError catch (error) {
+    Expect.throwsTypeError(f);
+  }
+}
+
+main() {
+  _injectJs();
+
+  dynamic a = new A(1);
+  dynamic b = new B(2);
+  dynamic c = new C(foo: 3);
+  dynamic d = new D(foo: 4);
+  dynamic e = new E(5);
+  dynamic f = new F(6);
+
+  Expect.equals(testA(a), 1);
+  Expect.equals(testB(b), 2);
+  Expect.equals(testA(b), 2);
+  Expect.equals(testA(c), 3);
+  Expect.equals(testA(d), 4);
+  expectValueOrTypeError(() => testA(e), 5);
+  expectValueOrTypeError(() => testA(f), 6);
+
+  Expect.equals(testB(a), 1);
+  Expect.equals(testB(b), 2);
+  Expect.equals(testB(c), 3);
+  Expect.equals(testB(d), 4);
+  expectValueOrTypeError(() => testB(e), 5);
+  expectValueOrTypeError(() => testB(f), 6);
+
+  Expect.equals(testC(a), 1);
+  Expect.equals(testC(b), 2);
+  Expect.equals(testC(c), 3);
+  Expect.equals(testC(d), 4);
+  expectValueOrTypeError(() => testC(e), 5);
+  expectValueOrTypeError(() => testC(f), 6);
+
+  Expect.equals(testD(a), 1);
+  Expect.equals(testD(b), 2);
+  Expect.equals(testD(c), 3);
+  Expect.equals(testD(d), 4);
+  expectValueOrTypeError(() => testD(e), 5);
+  expectValueOrTypeError(() => testD(f), 6);
+
+  expectValueOrTypeError(() => testE(a), 1);
+  expectValueOrTypeError(() => testE(b), 2);
+  expectValueOrTypeError(() => testE(c), 3);
+  expectValueOrTypeError(() => testE(d), 4);
+  Expect.equals(testE(e), 5);
+  expectValueOrTypeError(() => testE(f), 6);
+
+  expectValueOrTypeError(() => testF(a), 1);
+  expectValueOrTypeError(() => testF(b), 2);
+  expectValueOrTypeError(() => testF(c), 3);
+  expectValueOrTypeError(() => testF(d), 4);
+  expectValueOrTypeError(() => testF(e), 5);
+  Expect.equals(testF(f), 6);
+}
diff --git a/tests/lib/html/js_typed_interop_window_property_test.dart b/tests/lib/html/js_typed_interop_window_property_test.dart
new file mode 100644
index 0000000..4790b7a
--- /dev/null
+++ b/tests/lib/html/js_typed_interop_window_property_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.
+
+@JS()
+library js_typed_interop_window_property_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+// This is a regression test for https://github.com/dart-lang/sdk/issues/24817
+
+_injectJs() {
+  document.body!.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  "use strict";
+
+  window.foo = [function() { return 42; }];
+""");
+}
+
+@JS("window.foo")
+external List<Function> get foo;
+
+main() {
+  _injectJs();
+
+  Expect.equals(foo[0](), 42);
+}
diff --git a/tests/lib/html/js_util_test.dart b/tests/lib/html/js_util_test.dart
new file mode 100644
index 0000000..ab74e43
--- /dev/null
+++ b/tests/lib/html/js_util_test.dart
@@ -0,0 +1,387 @@
+// 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.
+
+@JS()
+library js_native_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:typed_data' show ByteBuffer, Int32List;
+import 'dart:indexed_db' show IdbFactory, KeyRange;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+import 'package:async_helper/async_helper.dart';
+
+_injectJs() {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = r"""
+var x = 42;
+
+var _x = 123;
+
+var myArray = ["value1"];
+
+function returnThis() {
+  return this;
+}
+
+function getTypeOf(o) {
+  return typeof(o);
+}
+
+function Foo(a) {
+  this.a = a;
+}
+
+Foo.b = 38;
+
+Foo.prototype.bar = function() {
+  return this.a;
+}
+Foo.prototype.toString = function() {
+  return "I'm a Foo a=" + this.a;
+}
+
+var container = new Object();
+container.Foo = Foo;
+
+function checkMap(m, key, value) {
+  if (m.hasOwnProperty(key))
+    return m[key] == value;
+  else
+    return false;
+}
+
+var rejectedPromise = new Promise((resolve, reject) => reject('rejected'));
+var resolvedPromise = new Promise(resolve => resolve('resolved'));
+function getResolvedPromise() {
+  return resolvedPromise;
+}
+
+""";
+  document.body!.append(script);
+}
+
+@JS()
+external bool checkMap(m, String, value);
+
+@JS('JSON.stringify')
+external String stringify(o);
+
+@JS('Node')
+external get JSNodeType;
+
+@JS('Element')
+external get JSElementType;
+
+@JS('Text')
+external get JSTextType;
+
+@JS('HTMLCanvasElement')
+external get JSHtmlCanvasElementType;
+
+@JS()
+class Foo {
+  external Foo(num a);
+
+  external num get a;
+  external num bar();
+}
+
+@JS('Foo')
+external get JSFooType;
+
+@JS()
+@anonymous
+class ExampleTypedLiteral {
+  external factory ExampleTypedLiteral({a, b, JS$_c, JS$class});
+
+  external get a;
+  external get b;
+  external get JS$_c;
+  external set JS$_c(v);
+  // Identical to JS$_c but only accessible within the library.
+  external get _c;
+  external get JS$class;
+  external set JS$class(v);
+}
+
+@JS()
+abstract class Promise<T> {}
+
+@JS()
+external Promise get resolvedPromise;
+
+@JS()
+external Promise get rejectedPromise;
+
+@JS()
+external Promise getResolvedPromise();
+
+@JS("Object.prototype.hasOwnProperty")
+external get _hasOwnProperty;
+
+bool hasOwnProperty(o, String name) {
+  return js_util.callMethod(_hasOwnProperty, 'call', [o, name]);
+}
+
+main() {
+  _injectJs();
+
+  group('js_util.jsify()', () {
+    test('convert a List', () {
+      final list = [1, 2, 3, 4, 5, 6, 7, 8];
+      var array = js_util.jsify(list);
+      expect(array is List, isTrue);
+      expect(identical(array, list), isFalse);
+      expect(array.length, equals(list.length));
+      for (var i = 0; i < list.length; i++) {
+        expect(array[i], equals(list[i]));
+      }
+    });
+
+    test('convert an Iterable', () {
+      final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]);
+      var array = js_util.jsify(set);
+      expect(array is List, isTrue);
+      expect(array.length, equals(set.length));
+      for (var i = 0; i < array.length; i++) {
+        expect(set.contains(array[i]), isTrue);
+      }
+    });
+
+    test('convert a Map', () {
+      var map = {'a': 1, 'b': 2, 'c': 3};
+      var jsMap = js_util.jsify(map);
+      expect(jsMap is! List, isTrue);
+      for (var key in map.keys) {
+        expect(checkMap(jsMap, key, map[key]), isTrue);
+      }
+    });
+
+    test('deep convert a complex object', () {
+      dynamic object = {
+        'a': [
+          1,
+          [2, 3]
+        ],
+        'b': {'c': 3, 'd': new Foo(42)},
+        'e': null
+      };
+      var jsObject = js_util.jsify(object);
+      expect(js_util.getProperty(jsObject, 'a')[0], equals(object['a'][0]));
+      expect(
+          js_util.getProperty(jsObject, 'a')[1][0], equals(object['a'][1][0]));
+      expect(
+          js_util.getProperty(jsObject, 'a')[1][1], equals(object['a'][1][1]));
+      expect(js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'c'),
+          equals(object['b']['c']));
+      expect(js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'd'),
+          equals(object['b']['d']));
+      expect(
+          js_util.callMethod(
+              js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'd'),
+              'bar', []),
+          equals(42));
+      expect(js_util.getProperty(jsObject, 'e'), isNull);
+    });
+
+    test('throws if object is not a Map or Iterable', () {
+      expect(() => js_util.jsify('a'), throwsArgumentError);
+    });
+  });
+
+  group('js_util.newObject', () {
+    test('create', () {
+      expect(identical(js_util.newObject(), js_util.newObject()), isFalse);
+    });
+
+    test('callMethod', () {
+      var o = js_util.newObject();
+      expect(js_util.callMethod(o, 'toString', []), equals('[object Object]'));
+      expect(stringify(o), equals('{}'));
+    });
+
+    test('properties', () {
+      var o = js_util.newObject();
+      expect(js_util.hasProperty(o, 'foo bar'), isFalse);
+      expect(js_util.hasProperty(o, 'toString'), isTrue);
+      expect(hasOwnProperty(o, 'toString'), isFalse);
+      expect(hasOwnProperty(o, 'foo bar'), isFalse);
+      js_util.setProperty(o, 'foo bar', 42);
+      expect(hasOwnProperty(o, 'foo bar'), isTrue);
+      expect(js_util.getProperty(o, 'foo bar'), equals(42));
+      expect(js_util.hasProperty(o, 'foo bar'), isTrue);
+      expect(stringify(o), equals('{"foo bar":42}'));
+    });
+  });
+
+  group('hasProperty', () {
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.hasProperty(f, 'a'), isTrue);
+      expect(js_util.hasProperty(f, 'toString'), isTrue);
+      js_util.setProperty(f, '__proto__', null);
+      expect(js_util.hasProperty(f, 'toString'), isFalse);
+    });
+    test('typed literal', () {
+      var l =
+          new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: null, JS$class: true);
+      expect(js_util.hasProperty(l, 'a'), isTrue);
+      expect(js_util.hasProperty(l, 'b'), isTrue);
+      expect(js_util.hasProperty(l, '_c'), isTrue);
+      expect(l.JS$_c, isNull);
+      expect(js_util.hasProperty(l, 'class'), isTrue);
+      // JS$_c escapes to _c so the property JS$_c will not exist on the object.
+      expect(js_util.hasProperty(l, r'JS$_c'), isFalse);
+      expect(js_util.hasProperty(l, r'JS$class'), isFalse);
+      expect(l.JS$class, isTrue);
+
+      l = new ExampleTypedLiteral(a: null);
+      expect(js_util.hasProperty(l, 'a'), isTrue);
+      expect(js_util.hasProperty(l, 'b'), isFalse);
+      expect(js_util.hasProperty(l, '_c'), isFalse);
+      expect(js_util.hasProperty(l, 'class'), isFalse);
+
+      l = new ExampleTypedLiteral(JS$_c: 74);
+      expect(js_util.hasProperty(l, '_c'), isTrue);
+      expect(l.JS$_c, equals(74));
+    });
+  });
+
+  group('getProperty', () {
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.getProperty(f, 'a'), equals(42));
+      expect(js_util.getProperty(f, 'toString') is Function, isTrue);
+      js_util.setProperty(f, '__proto__', null);
+      expect(js_util.getProperty(f, 'toString'), isNull);
+    });
+
+    test('typed literal', () {
+      var l = new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: 7, JS$class: true);
+      expect(js_util.getProperty(l, 'a'), equals('x'));
+      expect(js_util.getProperty(l, 'b'), equals(42));
+      expect(js_util.getProperty(l, '_c'), equals(7));
+      expect(l.JS$_c, equals(7));
+      expect(js_util.getProperty(l, 'class'), isTrue);
+      expect(js_util.getProperty(l, r'JS$_c'), isNull);
+      expect(js_util.getProperty(l, r'JS$class'), isNull);
+    });
+  });
+
+  group('setProperty', () {
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.getProperty(f, 'a'), equals(42));
+      js_util.setProperty(f, 'a', 100);
+      expect(f.a, equals(100));
+      expect(js_util.getProperty(f, 'a'), equals(100));
+    });
+
+    test('typed literal', () {
+      var l = new ExampleTypedLiteral();
+      js_util.setProperty(l, 'a', 'foo');
+      expect(js_util.getProperty(l, 'a'), equals('foo'));
+      expect(l.a, equals('foo'));
+      js_util.setProperty(l, 'a', l);
+      expect(identical(l.a, l), isTrue);
+      var list = ['arr'];
+      js_util.setProperty(l, 'a', list);
+      expect(identical(l.a, list), isTrue);
+      l.JS$class = 42;
+      expect(l.JS$class, equals(42));
+      js_util.setProperty(l, 'class', 100);
+      expect(l.JS$class, equals(100));
+    });
+  });
+
+  group('callMethod', () {
+    test('html object', () {
+      var canvas = new CanvasElement();
+      expect(
+          identical(canvas.getContext('2d'),
+              js_util.callMethod(canvas, 'getContext', ['2d'])),
+          isTrue);
+    });
+
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.callMethod(f, 'bar', []), equals(42));
+    });
+  });
+
+  group('instanceof', () {
+    test('html object', () {
+      var canvas = new Element.tag('canvas');
+      expect(js_util.instanceof(canvas, JSNodeType), isTrue);
+      expect(js_util.instanceof(canvas, JSTextType), isFalse);
+      expect(js_util.instanceof(canvas, JSElementType), isTrue);
+      expect(js_util.instanceof(canvas, JSHtmlCanvasElementType), isTrue);
+      var div = new Element.tag('div');
+      expect(js_util.instanceof(div, JSNodeType), isTrue);
+      expect(js_util.instanceof(div, JSTextType), isFalse);
+      expect(js_util.instanceof(div, JSElementType), isTrue);
+      expect(js_util.instanceof(div, JSHtmlCanvasElementType), isFalse);
+
+      var text = new Text('foo');
+      expect(js_util.instanceof(text, JSNodeType), isTrue);
+      expect(js_util.instanceof(text, JSTextType), isTrue);
+      expect(js_util.instanceof(text, JSElementType), isFalse);
+    });
+
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.instanceof(f, JSFooType), isTrue);
+      expect(js_util.instanceof(f, JSNodeType), isFalse);
+    });
+
+    test('typed literal', () {
+      var l = new ExampleTypedLiteral();
+      expect(js_util.instanceof(l, JSFooType), isFalse);
+    });
+  });
+
+  group('callConstructor', () {
+    test('html object', () {
+      var textNode = js_util.callConstructor(JSTextType, ['foo']);
+      expect(js_util.instanceof(textNode, JSTextType), isTrue);
+      expect(textNode is Text, isTrue);
+      expect(textNode.text, equals('foo'));
+    });
+
+    test('typed object', () {
+      Foo f = js_util.callConstructor(JSFooType, [42]);
+      expect(f.a, equals(42));
+    });
+  });
+
+  void testResolvedPromise() async {
+    final String result = await js_util.promiseToFuture(resolvedPromise);
+    expect(result, equals('resolved'));
+  }
+
+  void testRejectedPromise() async {
+    try {
+      final String result = await promiseToFuture(rejectedPromise);
+      fail('expected Future to throw an error');
+    } catch (error) {
+      expect(error, equals('rejected'));
+    }
+  }
+
+  void testReturnRejectedPromise() async {
+    final String result = await promiseToFuture(getResolvedPromise());
+    expect(result, equals('resolved'));
+  }
+
+  asyncTest(() async {
+    await testResolvedPromise();
+    await testRejectedPromise();
+    await testReturnRejectedPromise();
+  });
+}
diff --git a/tests/lib/html/json_helper.dart b/tests/lib/html/json_helper.dart
new file mode 100644
index 0000000..7d037ae
--- /dev/null
+++ b/tests/lib/html/json_helper.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.
+
+@JS("JSON")
+library json_helper;
+
+import 'package:js/js.dart';
+
+external String stringify(object);
diff --git a/tests/lib/html/keyboard_event_test.dart b/tests/lib/html/keyboard_event_test.dart
new file mode 100644
index 0000000..74e63d3
--- /dev/null
+++ b/tests/lib/html/keyboard_event_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.
+
+library KeyboardEventTest;
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+// Test that we are correctly determining keyCode and charCode uniformly across
+// browsers.
+
+void testKeyboardEventConstructor() {
+  new KeyboardEvent('keyup');
+}
+
+void keydownHandlerTest(KeyEvent e) {
+  expect(e.charCode, 0);
+}
+
+void testKeys() {
+  var subscription =
+      KeyboardEventStream.onKeyDown(document.body!).listen(keydownHandlerTest);
+  var subscription2 =
+      KeyEvent.keyDownEvent.forTarget(document.body).listen(keydownHandlerTest);
+  var subscription3 =
+      document.body!.onKeyDown.listen((e) => print('regular listener'));
+  subscription.cancel();
+  subscription2.cancel();
+  subscription3.cancel();
+}
+
+void testConstructKeyEvent() {
+  int handlerCallCount = 0;
+  CustomStream<KeyEvent> stream = KeyEvent.keyPressEvent
+      .forTarget(document.body!) as CustomStream<KeyEvent>;
+  var subscription = stream.listen((keyEvent) {
+    expect(keyEvent.charCode, 97);
+    expect(keyEvent.keyCode, 65);
+    handlerCallCount++;
+  });
+  var k = new KeyEvent('keypress', keyCode: 65, charCode: 97);
+  stream.add(k);
+  subscription.cancel();
+  // Capital "A":
+  stream.add(new KeyEvent('keydown', keyCode: 16, charCode: 0));
+
+  subscription = stream.listen((keyEvent) {
+    expect(keyEvent.charCode, 65);
+    expect(keyEvent.keyCode, 65);
+    handlerCallCount++;
+  });
+  stream.add(new KeyEvent('keypress', keyCode: 65, charCode: 65));
+  subscription.cancel();
+
+  expect(handlerCallCount, 2);
+}
+
+void testKeyEventSequence() {
+  int handlerCallCount = 0;
+  // Press "?" by simulating "shift" and then the key that has "/" and "?" on
+  // it.
+  CustomStream<KeyEvent> streamDown =
+      KeyEvent.keyDownEvent.forTarget(document.body!) as CustomStream<KeyEvent>;
+  CustomStream<KeyEvent> streamPress = KeyEvent.keyPressEvent
+      .forTarget(document.body!) as CustomStream<KeyEvent>;
+  CustomStream<KeyEvent> streamUp =
+      KeyEvent.keyUpEvent.forTarget(document.body!) as CustomStream<KeyEvent>;
+
+  var subscription = streamDown.listen((keyEvent) {
+    expect(keyEvent.keyCode, predicate([16, 191].contains));
+    expect(keyEvent.charCode, 0);
+    handlerCallCount++;
+  });
+
+  var subscription2 = streamPress.listen((keyEvent) {
+    expect(keyEvent.keyCode, 23);
+    expect(keyEvent.charCode, 63);
+    handlerCallCount++;
+  });
+
+  var subscription3 = streamUp.listen((keyEvent) {
+    expect(keyEvent.keyCode, predicate([16, 191].contains));
+    expect(keyEvent.charCode, 0);
+    handlerCallCount++;
+  });
+
+  streamDown.add(new KeyEvent('keydown', keyCode: 16, charCode: 0));
+  streamDown.add(new KeyEvent('keydown', keyCode: 191, charCode: 0));
+
+  streamPress.add(new KeyEvent('keypress', keyCode: 23, charCode: 63));
+
+  streamUp.add(new KeyEvent('keyup', keyCode: 191, charCode: 0));
+  streamUp.add(new KeyEvent('keyup', keyCode: 16, charCode: 0));
+  subscription.cancel();
+  subscription2.cancel();
+  subscription3.cancel();
+
+  expect(handlerCallCount, 5);
+}
+
+void testKeyEventKeyboardEvent() {
+  int handlerCallCount = 0;
+  window.onKeyDown.listen((event) {
+    expect(event.keyCode, 16);
+    handlerCallCount++;
+  });
+  CustomStream<KeyEvent> streamDown =
+      KeyEvent.keyDownEvent.forTarget(document.body!) as CustomStream<KeyEvent>;
+  streamDown.add(new KeyEvent('keydown', keyCode: 16, charCode: 0));
+  expect(handlerCallCount, 1);
+}
+
+main() {
+  testKeyboardEventConstructor();
+  testKeys();
+  testConstructKeyEvent();
+  testKeyEventSequence();
+  testKeyEventKeyboardEvent();
+}
diff --git a/tests/lib/html/localstorage_test.dart b/tests/lib/html/localstorage_test.dart
new file mode 100644
index 0000000..57db920
--- /dev/null
+++ b/tests/lib/html/localstorage_test.dart
@@ -0,0 +1,113 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  setUp(() {
+    window.localStorage['key1'] = 'val1';
+    window.localStorage['key2'] = 'val2';
+    window.localStorage['key3'] = 'val3';
+  });
+
+  tearDown(() {
+    window.localStorage.clear();
+  });
+
+  test('containsValue', () {
+    expect(window.localStorage.containsValue('does not exist'), isFalse);
+    expect(window.localStorage.containsValue('key1'), isFalse);
+    expect(window.localStorage.containsValue('val1'), isTrue);
+    expect(window.localStorage.containsValue('val3'), isTrue);
+  });
+
+  test('containsKey', () {
+    expect(window.localStorage.containsKey('does not exist'), isFalse);
+    expect(window.localStorage.containsKey('val1'), isFalse);
+    expect(window.localStorage.containsKey('key1'), isTrue);
+    expect(window.localStorage.containsKey('key3'), isTrue);
+  });
+
+  test('[]', () {
+    expect(window.localStorage['does not exist'], isNull);
+    expect(window.localStorage['key1'], 'val1');
+    expect(window.localStorage['key3'], 'val3');
+  });
+
+  test('[]=', () {
+    expect(window.localStorage['key4'], isNull);
+    window.localStorage['key4'] = 'val4';
+    expect(window.localStorage['key4'], 'val4');
+
+    expect(window.localStorage['key3'], 'val3');
+    window.localStorage['key3'] = 'val3-new';
+    expect(window.localStorage['key3'], 'val3-new');
+  });
+
+  test('putIfAbsent', () {
+    expect(window.localStorage['key4'], isNull);
+    expect(window.localStorage.putIfAbsent('key4', () => 'val4'), 'val4');
+    expect(window.localStorage['key4'], 'val4');
+
+    expect(window.localStorage['key3'], 'val3');
+    expect(
+        window.localStorage.putIfAbsent('key3', () {
+          fail('should not be called');
+          return 'unused';
+        }),
+        'val3');
+    expect(window.localStorage['key3'], 'val3');
+  });
+
+  test('remove', () {
+    expect(window.localStorage.remove('does not exist'), isNull);
+    expect(window.localStorage.remove('key3'), 'val3');
+    expect(window.localStorage, equals({'key1': 'val1', 'key2': 'val2'}));
+  });
+
+  test('clear', () {
+    window.localStorage.clear();
+    expect(window.localStorage, equals({}));
+  });
+
+  test('forEach', () {
+    var results = <String, String>{};
+    window.localStorage.forEach((k, v) {
+      results[k] = v;
+    });
+    expect(results, equals({'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}));
+  });
+
+  test('getKeys', () {
+    expect(window.localStorage.keys.toList(),
+        unorderedEquals(['key1', 'key2', 'key3']));
+  });
+
+  test('getVals', () {
+    expect(window.localStorage.values.toList(),
+        unorderedEquals(['val1', 'val2', 'val3']));
+  });
+
+  test('getEntries', () {
+    var results = <String, String>{};
+    window.localStorage.entries.forEach((e) {
+      results[e.key] = e.value;
+    });
+    expect(results, equals({'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}));
+  });
+
+  test('length', () {
+    expect(window.localStorage.length, 3);
+    window.localStorage.clear();
+    expect(window.localStorage.length, 0);
+  });
+
+  test('isEmpty', () {
+    expect(window.localStorage.isEmpty, isFalse);
+    window.localStorage.clear();
+    expect(window.localStorage.isEmpty, isTrue);
+  });
+}
diff --git a/tests/lib/html/location_test.dart b/tests/lib/html/location_test.dart
new file mode 100644
index 0000000..0b8369c
--- /dev/null
+++ b/tests/lib/html/location_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:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isLocation = predicate((x) => x is Location, 'is a Location');
+
+  test('location hash', () {
+    final location = window.location;
+    expect(location, isLocation);
+
+    // The only navigation we dare try is hash.
+    location.hash = 'hello';
+    var h = location.hash;
+    expect(h, '#hello');
+  });
+
+  test('location.origin', () {
+    var origin = window.location.origin;
+
+    // We build up the origin from Uri, then make sure that it matches.
+    var uri = Uri.parse(window.location.href);
+    var reconstructedOrigin = '${uri.scheme}://${uri.host}';
+    if (uri.port != 0) {
+      reconstructedOrigin = '$reconstructedOrigin:${uri.port}';
+    }
+
+    expect(origin, reconstructedOrigin);
+  });
+}
diff --git a/tests/lib/html/media_stream_test.dart b/tests/lib/html/media_stream_test.dart
new file mode 100644
index 0000000..7dc5bde
--- /dev/null
+++ b/tests/lib/html/media_stream_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+main() {
+  group('supported_media', () {
+    test('supported', () {
+      expect(MediaStream.supported, true);
+    });
+  });
+
+  group('supported_MediaStreamEvent', () {
+    test('supported', () {
+      expect(MediaStreamEvent.supported, true);
+    });
+  });
+
+  group('supported_MediaStreamTrackEvent', () {
+    test('supported', () {
+      expect(MediaStreamTrackEvent.supported, true);
+    });
+  });
+
+  group('constructors', () {
+    test('MediaStreamEvent', () {
+      var expectation = MediaStreamEvent.supported ? returnsNormally : throws;
+      expect(() {
+        var event = new Event.eventType('MediaStreamEvent', 'media');
+        expect(event is MediaStreamEvent, isTrue);
+      }, expectation);
+    });
+
+    test('MediaStreamTrackEvent', () {
+      var expectation =
+          MediaStreamTrackEvent.supported ? returnsNormally : throws;
+      expect(() {
+        var event = new Event.eventType('MediaStreamTrackEvent', 'media');
+        expect(event is MediaStreamTrackEvent, isTrue);
+      }, expectation);
+    });
+  });
+}
diff --git a/tests/lib/html/mediadevices_test.dart b/tests/lib/html/mediadevices_test.dart
new file mode 100644
index 0000000..abc803a
--- /dev/null
+++ b/tests/lib/html/mediadevices_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 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+test() async {
+  var list = await window.navigator.mediaDevices.enumerateDevices();
+  Expect.isTrue(list is List<dynamic>, "Expected list to be List<dynamic>");
+}
+
+void main() {
+  asyncStart();
+  test().then((_) => asyncEnd());
+}
diff --git a/tests/lib/html/mediasource_test.dart b/tests/lib/html/mediasource_test.dart
new file mode 100644
index 0000000..ac6765a
--- /dev/null
+++ b/tests/lib/html/mediasource_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 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isMediaSource = predicate((x) => x is MediaSource, 'is a MediaSource');
+
+  group('supported', () {
+    test('supported', () {
+      expect(MediaSource.supported, true);
+    });
+  });
+
+  // TODO(alanknight): Actually exercise this, right now the tests are trivial.
+  group('functional', () {
+    var source;
+    if (MediaSource.supported) {
+      source = new MediaSource();
+    }
+
+    test('constructorTest', () {
+      if (MediaSource.supported) {
+        expect(source, isNotNull);
+        expect(source, isMediaSource);
+      }
+    });
+
+    test('media types', () {
+      if (MediaSource.supported) {
+        expect(MediaSource.isTypeSupported('text/html'), false);
+        expect(MediaSource.isTypeSupported('video/webm;codecs="vp8,vorbis"'),
+            true);
+      }
+    });
+  });
+}
diff --git a/tests/lib/html/message_channel_test.dart b/tests/lib/html/message_channel_test.dart
new file mode 100644
index 0000000..c6029dd
--- /dev/null
+++ b/tests/lib/html/message_channel_test.dart
@@ -0,0 +1,37 @@
+// 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:expect/minitest.dart';
+
+main() async {
+  var gotOnMessage = false;
+  var gotEventListener = false;
+
+  Completer completer = new Completer();
+
+  var channel = new MessageChannel();
+  channel.port1.postMessage("Tickle me.");
+
+  channel.port2.onMessage.listen((MessageEvent e) {
+    expect(e.data, "Tickle me.");
+    gotOnMessage = true;
+  });
+
+  channel.port2.addEventListener("message", (message) {
+    var msg = message as MessageEvent;
+    expect(msg.data, "Tickle me.");
+    gotEventListener = true;
+    completer.complete();
+  });
+
+  // Wait for the event listener.
+  await completer.future;
+
+  // Make sure both fired.
+  expect(gotOnMessage, true);
+  expect(gotEventListener, true);
+}
diff --git a/tests/lib/html/messageevent_test.dart b/tests/lib/html/messageevent_test.dart
new file mode 100644
index 0000000..83811c9
--- /dev/null
+++ b/tests/lib/html/messageevent_test.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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('new MessageEvent', () {
+    final event = new MessageEvent('type',
+        cancelable: true,
+        data: 'data',
+        origin: 'origin',
+        lastEventId: 'lastEventId');
+
+    expect(event.type, equals('type'));
+    expect(event.bubbles, isFalse);
+    expect(event.cancelable, isTrue);
+    expect(event.data, equals('data'));
+    expect(event.origin, equals('origin'));
+    // IE allows setting this but just ignores it.
+    // expect(event.lastEventId, equals('lastEventId'));
+    expect(event.source, window);
+    // TODO(antonm): accessing ports is not supported yet.
+  });
+}
diff --git a/tests/lib/html/mouse_event_test.dart b/tests/lib/html/mouse_event_test.dart
new file mode 100644
index 0000000..7d7b0d9
--- /dev/null
+++ b/tests/lib/html/mouse_event_test.dart
@@ -0,0 +1,17 @@
+// 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:expect/minitest.dart';
+
+main() {
+  test('relatedTarget', () {
+    var event = new MouseEvent('mouseout');
+    expect(event.relatedTarget, isNull);
+
+    event = new MouseEvent('mouseout', relatedTarget: document.body);
+    expect(event.relatedTarget, document.body);
+  });
+}
diff --git a/tests/lib/html/mutationobserver_test.dart b/tests/lib/html/mutationobserver_test.dart
new file mode 100644
index 0000000..7ee71fe
--- /dev/null
+++ b/tests/lib/html/mutationobserver_test.dart
@@ -0,0 +1,121 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 mutationobserver_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+// Due to https://code.google.com/p/chromium/issues/detail?id=329103
+// mutationObservers sometimes do not fire if the node being observed is GCed
+// so we keep around references to all nodes we have created mutation
+// observers for.
+var keepAlive = [];
+
+void testSupported() {
+  expect(MutationObserver.supported, true);
+}
+
+mutationCallback(Completer done, int count, expectation) {
+  final nodes = [];
+
+  callback(mutations, observer) {
+    for (MutationRecord mutation in mutations) {
+      for (Node node in mutation.addedNodes) {
+        nodes.add(node);
+      }
+    }
+    if (nodes.length >= count) {
+      expect(nodes.length, count);
+      expect(nodes, expectation);
+      done.complete();
+    }
+  }
+
+  // If it's not supported, don't block waiting for it.
+  if (!MutationObserver.supported) {
+    done.complete();
+    return (mutations, observer) {};
+  }
+
+  return callback;
+}
+
+void testEmptyOptionsIsSyntaxError(expectation) {
+  expect(() {
+    var mutationObserver = new MutationObserver((mutations, observer) {
+      expect(false, isTrue, reason: 'Should not be reached');
+    });
+    expect(() {
+      mutationObserver.observe(document);
+    }, throws);
+  }, expectation);
+}
+
+Future<Null> testDirectParallelOptionsNamed(expectation) {
+  final done = new Completer<Null>();
+  expect(() {
+    var container = new DivElement();
+    keepAlive.add(container);
+    var div1 = new DivElement();
+    var div2 = new DivElement();
+    var mutationObserver =
+        new MutationObserver(mutationCallback(done, 2, equals([div1, div2])));
+    mutationObserver.observe(container, childList: true);
+
+    container.append(div1);
+    container.append(div2);
+  }, expectation);
+  return done.future;
+}
+
+Future<Null> testDirectNestedOptionsNamed(expectation) {
+  final done = new Completer<Null>();
+  expect(() {
+    var container = new DivElement();
+    keepAlive.add(container);
+    var div1 = new DivElement();
+    var div2 = new DivElement();
+    var mutationObserver =
+        new MutationObserver(mutationCallback(done, 1, equals([div1])));
+    mutationObserver.observe(container, childList: true);
+
+    container.append(div1);
+    div1.append(div2);
+  }, expectation);
+  return done.future;
+}
+
+Future<Null> testSubtreeOptionsNamed(expectation) {
+  final done = new Completer<Null>();
+  expect(() {
+    var container = new DivElement();
+    keepAlive.add(container);
+    var div1 = new DivElement();
+    var div2 = new DivElement();
+    var mutationObserver =
+        new MutationObserver(mutationCallback(done, 2, equals([div1, div2])));
+    mutationObserver.observe(container, childList: true, subtree: true);
+
+    container.append(div1);
+    div1.append(div2);
+  }, expectation);
+  return done.future;
+}
+
+/**
+ * Test suite for Mutation Observers. This is just a small set of sanity
+ * checks, not a complete test suite.
+ */
+main() async {
+  testSupported();
+
+  final expectation = MutationObserver.supported ? returnsNormally : throws;
+  testEmptyOptionsIsSyntaxError(expectation);
+  await testDirectParallelOptionsNamed(expectation);
+  await testDirectNestedOptionsNamed(expectation);
+  await testSubtreeOptionsNamed(expectation);
+}
diff --git a/tests/lib/html/native_gc_test.dart b/tests/lib/html/native_gc_test.dart
new file mode 100644
index 0000000..42a5a50
--- /dev/null
+++ b/tests/lib/html/native_gc_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.
+
+library NativeGCTest;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+var testEvent = new EventStreamProvider<Event>('test');
+
+void testEventListener() {
+  final int N = 1000000;
+  final int M = 1000;
+
+  var div;
+  for (int i = 0; i < M; ++i) {
+    // This memory should be freed when the listener below is
+    // collected.
+    List<int> l = new List<int>.filled(N, 0);
+
+    // Record the iteration number.
+    l[N - 1] = i;
+
+    div = new Element.tag('div');
+    testEvent.forTarget(div).listen((_) {
+      // Only the final iteration's listener should be invoked.
+      // Note: the reference to l keeps the entire list alive.
+      expect(l[N - 1], M - 1);
+    });
+  }
+
+  final event = new Event('test');
+  div.dispatchEvent(event);
+}
+
+Future<Null> testWindowEventListener() {
+  String message = 'WindowEventListenerTestPingMessage';
+
+  Element testDiv = new DivElement();
+  testDiv.id = '#TestDiv';
+  document.body!.append(testDiv);
+  window.onMessage.listen((e) {
+    if (e.data == message) testDiv.click();
+  });
+
+  for (int i = 0; i < 100; ++i) {
+    triggerMajorGC();
+  }
+
+  final done = new Completer<Null>();
+  testDiv.onClick.listen(((_) {
+    done.complete();
+  }));
+  window.postMessage(message, '*');
+  return done.future;
+}
+
+main() async {
+  testEventListener();
+  await testWindowEventListener();
+}
+
+void triggerMajorGC() {
+  List<int> list = new List<int>.filled(1000000, 0);
+  Element div = new DivElement();
+  div.onClick.listen((e) => print(list[0]));
+}
diff --git a/tests/lib/html/navigator_test.dart b/tests/lib/html/navigator_test.dart
new file mode 100644
index 0000000..02cbafd
--- /dev/null
+++ b/tests/lib/html/navigator_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 'dart:html';
+
+import 'package:expect/expect.dart';
+
+main() {
+  Expect.isNotNull(window.navigator.language);
+}
diff --git a/tests/lib/html/node_test.dart b/tests/lib/html/node_test.dart
new file mode 100644
index 0000000..2e90418
--- /dev/null
+++ b/tests/lib/html/node_test.dart
@@ -0,0 +1,341 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:svg' as svg;
+
+import 'package:expect/minitest.dart';
+
+Node makeNode() => new Element.tag('div');
+Element makeNodeWithChildren() =>
+    new Element.html("<div>Foo<br/><!--baz--></div>");
+
+void testUnsupported(String name, void f()) {
+  test(name, () {
+    expect(f, throwsUnsupportedError);
+  });
+}
+
+main() {
+  var isText = predicate((x) => x is Text, 'is a Text');
+  var isComment = predicate((x) => x is Comment, 'is a Comment');
+  var isBRElement = predicate((x) => x is BRElement, 'is a BRElement');
+  var isHRElement = predicate((x) => x is HRElement, 'is a HRElement');
+  var isNodeList = predicate((x) => x is List<Node>, 'is a List<Node>');
+  var isImageElement =
+      predicate((x) => x is ImageElement, 'is an ImageElement');
+  var isInputElement =
+      predicate((x) => x is InputElement, 'is an InputElement');
+
+  group('functional', () {
+    test('toString', () {
+      final nodes = makeNodeWithChildren();
+      // TODO(efortuna): Update this test when you have actual toString methods
+      // for the items in the node List as well.
+      expect(nodes.nodes.toString(), "[Foo, br, baz]");
+      final node = makeNode();
+      expect(node.nodes.toString(), '[]');
+    });
+
+    test('replaceWith', () {
+      final node = makeNodeWithChildren();
+      final subnode = node.nodes[1];
+      final out = subnode.replaceWith(new Text('Bar'));
+      expect(out, equals(subnode), reason: '#replaceWith should be chainable');
+      expect(node.nodes.length, 3);
+      expect(node.nodes[0], isText);
+      expect(node.nodes[0].text, 'Foo');
+      expect(node.nodes[1], isText);
+      expect(node.nodes[1].text, 'Bar');
+      expect(node.nodes[2], isComment);
+    });
+
+    test('append', () {
+      var node = makeNode();
+      node.append(new Element.tag('hr'));
+      expect(node.nodes.last, isHRElement);
+    });
+
+    test('remove', () {
+      final node = makeNodeWithChildren();
+      final subnode = node.nodes[1];
+      subnode.remove();
+      expect(node.nodes.length, 2);
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isComment);
+    });
+
+    test('contains', () {
+      final Node node =
+          new Element.html("<div>Foo<span><div>Bar<div></span></div>");
+      // IE10 returns false for contains of nodes.
+      //expect(node.contains(node.nodes.first), isTrue);
+      expect(node.contains(node.nodes[1].nodes.first), isTrue);
+      expect(node.contains(new Text('Foo')), isFalse);
+    });
+
+    test('insertAllBefore', () {
+      var node = makeNodeWithChildren();
+      var b = new DivElement();
+      b.nodes.addAll([new HRElement(), new ImageElement(), new InputElement()]);
+      node.insertAllBefore(b.nodes, node.nodes[1]);
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isHRElement);
+      expect(node.nodes[2], isImageElement);
+      expect(node.nodes[3], isInputElement);
+      expect(node.nodes[4], isBRElement);
+      expect(node.nodes[5], isComment);
+
+      var nodes = [new HRElement(), new ImageElement(), new InputElement()];
+      node.insertAllBefore(nodes, node.nodes[5]);
+
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isHRElement);
+      expect(node.nodes[2], isImageElement);
+      expect(node.nodes[3], isInputElement);
+      expect(node.nodes[4], isBRElement);
+      expect(node.nodes[5], isHRElement);
+      expect(node.nodes[6], isImageElement);
+      expect(node.nodes[7], isInputElement);
+      expect(node.nodes[8], isComment);
+    });
+  });
+
+  group('nodes', () {
+    test('is a NodeList', () {
+      expect(makeNodeWithChildren().nodes, isNodeList);
+    });
+
+    test('indexer', () {
+      var node = new DivElement();
+      expect(() {
+        node.nodes[0];
+      }, throwsRangeError);
+
+      expect(() {
+        node.nodes[-1];
+      }, throwsRangeError);
+    });
+
+    test('first', () {
+      var node = makeNodeWithChildren();
+      expect(node.nodes.first, isText);
+
+      node = new DivElement();
+      expect(() {
+        node = node.nodes.first as Element;
+      }, throwsStateError);
+    });
+
+    test('last', () {
+      var node = makeNodeWithChildren();
+      expect(node.nodes.last, isComment);
+    });
+
+    test('forEach', () {
+      var nodes = [];
+      var node = makeNodeWithChildren();
+      node.nodes.forEach((n) => nodes.add(n));
+      expect(nodes[0], isText);
+      expect(nodes[1], isBRElement);
+      expect(nodes[2], isComment);
+    });
+
+    test('where', () {
+      var filtered =
+          makeNodeWithChildren().nodes.where((n) => n is BRElement).toList();
+      expect(filtered.length, 1);
+      expect(filtered[0], isBRElement);
+      expect(filtered, isNodeList);
+    });
+
+    test('every', () {
+      var node = makeNodeWithChildren();
+      expect(node.nodes.every((n) => n is Node), isTrue);
+      expect(node.nodes.every((n) => n is Comment), isFalse);
+    });
+
+    test('any', () {
+      var node = makeNodeWithChildren();
+      expect(node.nodes.any((n) => n is Comment), isTrue);
+      expect(node.nodes.any((n) => n is svg.SvgElement), isFalse);
+    });
+
+    test('isEmpty', () {
+      expect(makeNode().nodes.isEmpty, isTrue);
+      expect(makeNodeWithChildren().nodes.isEmpty, isFalse);
+    });
+
+    test('length', () {
+      expect(makeNode().nodes.length, 0);
+      expect(makeNodeWithChildren().nodes.length, 3);
+    });
+
+    test('[]', () {
+      var node = makeNodeWithChildren();
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isBRElement);
+      expect(node.nodes[2], isComment);
+    });
+
+    test('[]=', () {
+      var node = makeNodeWithChildren();
+      node.nodes[1] = new Element.tag('hr');
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isHRElement);
+      expect(node.nodes[2], isComment);
+    });
+
+    test('add', () {
+      var node = makeNode();
+      node.nodes.add(new Element.tag('hr'));
+      expect(node.nodes.last, isHRElement);
+    });
+
+    test('iterator', () {
+      var nodes = [];
+      var node = makeNodeWithChildren();
+      for (var subnode in node.nodes) {
+        nodes.add(subnode);
+      }
+      expect(nodes[0], isText);
+      expect(nodes[1], isBRElement);
+      expect(nodes[2], isComment);
+    });
+
+    test('addAll', () {
+      var node = makeNodeWithChildren();
+      node.nodes.addAll([
+        new Element.tag('hr'),
+        new Element.tag('img'),
+        new Element.tag('input')
+      ]);
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isBRElement);
+      expect(node.nodes[2], isComment);
+      expect(node.nodes[3], isHRElement);
+      expect(node.nodes[4], isImageElement);
+      expect(node.nodes[5], isInputElement);
+
+      var a = makeNodeWithChildren();
+      var b = makeNodeWithChildren();
+      var childrenLength = a.children.length + b.children.length;
+      var nodesLength = a.nodes.length + b.nodes.length;
+
+      a.children.addAll(b.children);
+      expect(b.children.length, 0);
+      expect(a.children.length, childrenLength);
+
+      b.nodes.addAll(a.children);
+      expect(a.children.length, 0);
+      expect(b.children.length, childrenLength);
+
+      a.nodes.addAll(b.nodes);
+      expect(b.nodes.length, 0);
+      expect(a.nodes.length, nodesLength);
+    });
+
+    test('insert', () {
+      var node = new DivElement();
+      node.nodes.insert(0, new BRElement());
+      expect(node.nodes[0], isBRElement);
+      node.nodes.insert(0, new HRElement());
+      expect(node.nodes[0], isHRElement);
+      node.nodes.insert(1, new ImageElement());
+      expect(node.nodes[1], isImageElement);
+      node.nodes.insert(node.nodes.length, new InputElement());
+      expect(node.nodes.last, isInputElement);
+    });
+
+    test('clear', () {
+      var node = makeNodeWithChildren();
+      node.nodes.clear();
+      expect(node.nodes, []);
+    });
+
+    test('removeLast', () {
+      var node = makeNodeWithChildren();
+      expect(node.nodes.removeLast(), isComment);
+      expect(node.nodes.length, 2);
+      expect(node.nodes.removeLast(), isBRElement);
+      expect(node.nodes.length, 1);
+    });
+
+    test('getRange', () {
+      var items = makeNodeWithChildren().nodes.getRange(0, 1);
+      expect(items.length, 1);
+      expect(items.first, isText);
+    });
+
+    test('sublist', () {
+      var node = makeNodeWithChildren();
+      expect(node.nodes.sublist(1, 3), isNodeList);
+    });
+
+    test('insertAll', () {
+      var node = makeNodeWithChildren();
+      var b = new DivElement();
+      b.nodes.addAll([new HRElement(), new ImageElement(), new InputElement()]);
+      node.nodes.insertAll(1, b.nodes);
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isHRElement);
+      expect(node.nodes[2], isImageElement);
+      expect(node.nodes[3], isInputElement);
+      expect(node.nodes[4], isBRElement);
+      expect(node.nodes[5], isComment);
+
+      var nodes = [new HRElement(), new ImageElement(), new InputElement()];
+      node.nodes.insertAll(5, nodes);
+
+      expect(node.nodes[0], isText);
+      expect(node.nodes[1], isHRElement);
+      expect(node.nodes[2], isImageElement);
+      expect(node.nodes[3], isInputElement);
+      expect(node.nodes[4], isBRElement);
+      expect(node.nodes[5], isHRElement);
+      expect(node.nodes[6], isImageElement);
+      expect(node.nodes[7], isInputElement);
+      expect(node.nodes[8], isComment);
+
+      var d = new DivElement();
+      var ns = d.nodes;
+      // `insertAll` should work when positioned at end.
+      ns.insertAll(ns.length, [new HRElement()]);
+      expect(ns.length, 1);
+      expect(ns[0], isHRElement);
+    });
+
+    testUnsupported('removeRange', () {
+      makeNodeWithChildren().nodes.removeRange(0, 1);
+    });
+
+    testUnsupported('replaceRange', () {
+      makeNodeWithChildren().nodes.replaceRange(0, 1, [new InputElement()]);
+    });
+
+    testUnsupported('fillRange', () {
+      makeNodeWithChildren().nodes.fillRange(0, 1, null);
+    });
+
+    testUnsupported('setAll', () {
+      makeNodeWithChildren().nodes.setAll(0, [new InputElement()]);
+    });
+  });
+
+  group('iterating', () {
+    test('NodeIterator', () {
+      var root = makeNodeWithChildren();
+      var nodeIterator = new NodeIterator(root, NodeFilter.SHOW_COMMENT);
+      expect(nodeIterator.nextNode(), isComment);
+      expect(nodeIterator.nextNode(), isNull);
+    });
+
+    test('TreeWalker', () {
+      var root = makeNodeWithChildren();
+      var treeWalker = new TreeWalker(root, NodeFilter.SHOW_COMMENT);
+      expect(treeWalker.nextNode(), isComment);
+      expect(treeWalker.nextNode(), isNull);
+    });
+  });
+}
diff --git a/tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart b/tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
new file mode 100644
index 0000000..0faaf09
--- /dev/null
+++ b/tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
@@ -0,0 +1,484 @@
+// 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.
+
+/// This tests HTML validation and sanitization, which is very important
+/// for prevent XSS or other attacks. If you suppress this, or parts of it
+/// please make it a critical bug and bring it to the attention of the
+/// dart:html maintainers.
+library node_validator_test;
+
+import 'dart:html';
+import 'dart:svg' as svg;
+
+import 'package:expect/minitest.dart';
+
+import 'utils.dart';
+
+void validateHtml(String html, String reference, NodeValidator validator) {
+  var a = document.body!.createFragment(html, validator: validator);
+  var b = document.body!
+      .createFragment(reference, treeSanitizer: NodeTreeSanitizer.trusted);
+
+  // Prevent a false pass when both the html and the reference both get entirely
+  // deleted, which is technically a match, but unlikely to be what we meant.
+  if (reference != '') {
+    expect(b.childNodes.length > 0, isTrue);
+  }
+  validateNodeTree(a, b);
+}
+
+class RecordingUriValidator implements UriPolicy {
+  final List<String> calls = <String>[];
+
+  bool allowsUri(String uri) {
+    calls.add('$uri');
+    return false;
+  }
+
+  void reset() {
+    calls.clear();
+  }
+}
+
+void testHtml(String name, NodeValidator validator, String html,
+    [String? reference]) {
+  test(name, () {
+    if (reference == null) {
+      reference = html;
+    }
+
+    validateHtml(html, reference!, validator);
+  });
+}
+
+main() {
+  group('DOM_sanitization', () {
+    var validator = new NodeValidatorBuilder.common();
+
+    testHtml('allows simple constructs', validator,
+        '<div class="baz">something</div>');
+
+    testHtml('blocks unknown attributes', validator,
+        '<div foo="baz">something</div>', '<div>something</div>');
+
+    testHtml('blocks custom element', validator,
+        '<x-my-element>something</x-my-element>', '');
+
+    testHtml('blocks custom is element', validator,
+        '<div is="x-my-element">something</div>', '');
+
+    testHtml(
+        'blocks body elements', validator, '<body background="s"></body>', '');
+
+    testHtml(
+        'allows select elements',
+        validator,
+        '<select>'
+            '<option>a</option>'
+            '</select>');
+
+    testHtml('blocks sequential script elements', validator,
+        '<div><script></script><script></script></div>', '<div></div>');
+
+    testHtml('blocks inline styles', validator,
+        '<div style="background: red"></div>', '<div></div>');
+
+    testHtml('blocks namespaced attributes', validator,
+        '<div ns:foo="foo"></div>', '<div></div>');
+
+    testHtml('blocks namespaced common attributes', validator,
+        '<div ns:class="foo"></div>', '<div></div>');
+
+    testHtml('blocks namespaced common elements', validator,
+        '<ns:div></ns:div>', '');
+
+    testHtml('allows CDATA sections', validator,
+        '<span>![CDATA[ some text ]]></span>');
+
+    testHtml('backquotes not removed', validator,
+        '<img src="dice.png" alt="``onload=xss()" />');
+
+    testHtml('0x3000 not removed', validator,
+        '<a href="&#x3000;javascript:alert(1)">CLICKME</a>');
+
+    test('sanitizes template contents', () {
+      if (!TemplateElement.supported) return;
+
+      var html = '<template>'
+          '<div></div>'
+          '<script></script>'
+          '<img src="http://example.com/foo"/>'
+          '</template>';
+
+      var fragment = document.body!.createFragment(html, validator: validator);
+      var template = fragment.nodes.single as TemplateElement;
+
+      var expectedContent = document.body!.createFragment('<div></div>'
+          '<img/>');
+
+      validateNodeTree(template.content, expectedContent);
+    });
+
+    test("appendHtml is sanitized", () {
+      var html = '<body background="s"></body><div></div>';
+      document.body!.appendHtml('<div id="stuff"></div>');
+      var stuff = document.querySelector("#stuff")!;
+      stuff.appendHtml(html);
+      expect(stuff.childNodes.length, 1);
+      stuff.remove();
+    });
+
+    test("documentFragment.appendHtml is sanitized", () {
+      var html = '<div id="things></div>';
+      var fragment = new DocumentFragment.html(html);
+      fragment.appendHtml('<div id="bad"><script></script></div>');
+      expect(fragment.childNodes.length, 1);
+      var child = fragment.childNodes[0] as Element;
+      expect(child.id, "bad");
+      expect(child.childNodes.length, 0);
+    });
+
+    testHtml(
+        "sanitizes embed",
+        validator,
+        "<div><embed src='' type='application/x-shockwave-flash'></embed></div>",
+        "<div></div>");
+  });
+
+  group('URI_sanitization', () {
+    var recorder = new RecordingUriValidator();
+    var validator = new NodeValidatorBuilder()..allowHtml5(uriPolicy: recorder);
+
+    checkUriPolicyCalls(String name, String html, String reference,
+        List<String> expectedCalls) {
+      test(name, () {
+        recorder.reset();
+
+        validateHtml(html, reference, validator);
+        expect(recorder.calls, expectedCalls);
+      });
+    }
+
+    checkUriPolicyCalls('a::href', '<a href="s"></a>', '<a></a>', ['s']);
+
+    checkUriPolicyCalls(
+        'area::href', '<area href="s"></area>', '<area></area>', ['s']);
+
+    checkUriPolicyCalls(
+        'blockquote::cite',
+        '<blockquote cite="s"></blockquote>',
+        '<blockquote></blockquote>',
+        ['s']);
+    checkUriPolicyCalls(
+        'command::icon', '<command icon="s"/>', '<command/>', ['s']);
+    checkUriPolicyCalls('img::src', '<img src="s"/>', '<img/>', ['s']);
+    checkUriPolicyCalls('input::src', '<input src="s"/>', '<input/>', ['s']);
+    checkUriPolicyCalls(
+        'ins::cite', '<ins cite="s"></ins>', '<ins></ins>', ['s']);
+    checkUriPolicyCalls('q::cite', '<q cite="s"></q>', '<q></q>', ['s']);
+    checkUriPolicyCalls(
+        'video::poster', '<video poster="s"/>', '<video/>', ['s']);
+  });
+
+  group('allowNavigation', () {
+    var validator = new NodeValidatorBuilder()..allowNavigation();
+
+    testHtml('allows anchor tags', validator, '<a href="#foo">foo</a>');
+
+    testHtml('allows form elements', validator,
+        '<form method="post" action="/foo"></form>');
+
+    testHtml('disallows script navigation', validator,
+        '<a href="javascript:foo = 1">foo</a>', '<a>foo</a>');
+
+    testHtml('disallows cross-site navigation', validator,
+        '<a href="http://example.com">example.com</a>', '<a>example.com</a>');
+
+    testHtml('blocks other elements', validator,
+        '<a href="#foo"><b>foo</b></a>', '<a href="#foo"></a>');
+
+    testHtml('blocks tag extension', validator, '<a is="x-foo"></a>', '');
+  });
+
+  group('allowImages', () {
+    var validator = new NodeValidatorBuilder()..allowImages();
+
+    testHtml('allows images', validator,
+        '<img src="/foo.jpg" alt="something" width="100" height="100"/>');
+
+    testHtml('blocks onerror', validator,
+        '<img src="/foo.jpg" onerror="something"/>', '<img src="/foo.jpg"/>');
+
+    testHtml('enforces same-origin', validator,
+        '<img src="http://example.com/foo.jpg"/>', '<img/>');
+  });
+
+  group('allowCustomElement', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowCustomElement('x-foo', attributes: ['bar'], uriAttributes: ['baz'])
+      ..allowHtml5();
+
+    testHtml('allows custom elements', validator,
+        '<x-foo bar="something" baz="/foo.jpg"></x-foo>');
+
+    testHtml('validates custom tag URIs', validator,
+        '<x-foo baz="http://example.com/foo.jpg"></x-foo>', '<x-foo></x-foo>');
+
+    testHtml('blocks type extensions', validator, '<div is="x-foo"></div>', '');
+
+    testHtml('blocks tags on non-matching elements', validator,
+        '<div bar="foo"></div>', '<div></div>');
+  });
+
+  group('identify Uri attributes listed as attributes', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowElement('a', attributes: ['href']);
+
+    testHtml(
+        'reject different-origin link',
+        validator,
+        '<a href="http://www.google.com/foo">Google-Foo</a>',
+        '<a>Google-Foo</a>');
+  });
+
+  group('allowTagExtension', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowTagExtension('x-foo', 'div',
+          attributes: ['bar'], uriAttributes: ['baz'])
+      ..allowHtml5();
+
+    testHtml('allows tag extensions', validator,
+        '<div is="x-foo" bar="something" baz="/foo.jpg"></div>');
+
+    testHtml('blocks custom elements', validator, '<x-foo></x-foo>', '');
+
+    testHtml(
+        'validates tag extension URIs',
+        validator,
+        '<div is="x-foo" baz="http://example.com/foo.jpg"></div>',
+        '<div is="x-foo"></div>');
+
+    testHtml('blocks tags on non-matching elements', validator,
+        '<div bar="foo"></div>', '<div></div>');
+
+    testHtml('blocks non-matching tags', validator,
+        '<span is="x-foo">something</span>', '');
+
+    validator = new NodeValidatorBuilder()
+      ..allowTagExtension('x-foo', 'div',
+          attributes: ['bar'], uriAttributes: ['baz'])
+      ..allowTagExtension('x-else', 'div');
+
+    testHtml('blocks tags on non-matching custom elements', validator,
+        '<div bar="foo" is="x-else"></div>', '<div is="x-else"></div>');
+  });
+
+  group('allowTemplating', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowTemplating()
+      ..allowHtml5();
+
+    testHtml(
+        'allows templates', validator, '<template bind="{{a}}"></template>');
+
+    testHtml('allows template attributes', validator,
+        '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo"></template>');
+
+    testHtml('allows template attribute', validator,
+        '<div template repeat="{{}}"></div>');
+
+    testHtml('blocks illegal template attribute', validator,
+        '<div template="foo" repeat="{{}}"></div>', '<div></div>');
+  });
+
+  group('allowSvg', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowSvg()
+      ..allowTextElements();
+
+    testHtml(
+        'allows basic SVG',
+        validator,
+        '<svg xmlns="http://www.w3.org/2000/svg'
+            'xmlns:xlink="http://www.w3.org/1999/xlink">'
+            '<image xlink:href="foo" data-foo="bar"/>'
+            '</svg>');
+
+    testHtml(
+        'blocks script elements',
+        validator,
+        '<svg xmlns="http://www.w3.org/2000/svg>'
+            '<script></script>'
+            '</svg>',
+        '');
+
+    testHtml(
+        'blocks script elements but allows other',
+        validator,
+        '<svg xmlns="http://www.w3.org/2000/svg>'
+            '<script></script><ellipse cx="200" cy="80" rx="100" ry="50"></ellipse>'
+            '</svg>',
+        '<svg xmlns="http://www.w3.org/2000/svg>'
+            '<ellipse cx="200" cy="80" rx="100" ry="50"></ellipse>'
+            '</svg>');
+
+    testHtml(
+        'blocks script handlers',
+        validator,
+        '<svg xmlns="http://www.w3.org/2000/svg'
+            'xmlns:xlink="http://www.w3.org/1999/xlink">'
+            '<image xlink:href="foo" onerror="something"/>'
+            '</svg>',
+        '<svg xmlns="http://www.w3.org/2000/svg'
+            'xmlns:xlink="http://www.w3.org/1999/xlink">'
+            '<image xlink:href="foo"/>'
+            '</svg>');
+
+    testHtml(
+        'blocks foreignObject content',
+        validator,
+        '<svg xmlns="http://www.w3.org/2000/svg">'
+            '<foreignobject width="100" height="150">'
+            '<body xmlns="http://www.w3.org/1999/xhtml">'
+            '<div>Some content</div>'
+            '</body>'
+            '</foreignobject>'
+            '<b>42</b>'
+            '</svg>',
+        '<svg xmlns="http://www.w3.org/2000/svg">'
+            '<b>42</b>'
+            '</svg>');
+  });
+
+  group('allowInlineStyles', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowTextElements()
+      ..allowInlineStyles();
+
+    testHtml('allows inline styles', validator,
+        '<span style="background-color:red">text</span>');
+
+    testHtml('blocks other attributes', validator,
+        '<span class="red-span"></span>', '<span></span>');
+
+    validator = new NodeValidatorBuilder()
+      ..allowTextElements()
+      ..allowInlineStyles(tagName: 'span');
+
+    testHtml('scoped allows inline styles on spans', validator,
+        '<span style="background-color:red">text</span>');
+
+    testHtml('scoped blocks inline styles on LIs', validator,
+        '<li style="background-color:red">text</li>', '<li>text</li>');
+  });
+
+  group('throws', () {
+    var validator = new NodeValidator.throws(new NodeValidatorBuilder.common());
+
+    var validationError = throwsArgumentError;
+
+    test('does not throw on valid syntax', () {
+      expect(() {
+        document.body!.createFragment('<div></div>', validator: validator);
+      }, returnsNormally);
+    });
+
+    test('throws on invalid elements', () {
+      expect(() {
+        document.body!.createFragment('<foo></foo>', validator: validator);
+      }, validationError);
+    });
+
+    test('throws on invalid attributes', () {
+      expect(() {
+        document.body!
+            .createFragment('<div foo="bar"></div>', validator: validator);
+      }, validationError);
+    });
+
+    test('throws on invalid attribute values', () {
+      expect(() {
+        document.body!.createFragment('<img src="http://example.com/foo.jpg"/>',
+            validator: validator);
+      }, validationError);
+    });
+  });
+
+  group('svg', () {
+    test('parsing', () {
+      var svgText = '<svg xmlns="http://www.w3.org/2000/svg'
+          'xmlns:xlink="http://www.w3.org/1999/xlink">'
+          '<image xlink:href="foo" data-foo="bar"/>'
+          '</svg>';
+
+      var fragment = new DocumentFragment.svg(svgText);
+      var element = fragment.nodes.first as Element;
+      expect(element is svg.SvgSvgElement, isTrue);
+      expect(element.children[0] is svg.ImageElement, isTrue);
+    });
+  });
+
+  group('dom_clobbering', () {
+    var validator = new NodeValidatorBuilder.common();
+
+    testHtml(
+        'DOM clobbering of attributes with single node',
+        validator,
+        "<form id='single_node_clobbering' onmouseover='alert(1)'><input name='attributes'>",
+        "");
+
+    testHtml(
+        'DOM clobbering of attributes with multiple nodes',
+        validator,
+        "<form onmouseover='alert(1)'><input name='attributes'>"
+            "<input name='attributes'>",
+        "");
+
+    testHtml('DOM clobbering of lastChild', validator,
+        "<form><input name='lastChild'><input onmouseover='alert(1)'>", "");
+
+    testHtml(
+        'DOM clobbering of both children and lastChild',
+        validator,
+        "<form><input name='lastChild'><input name='children'>"
+            "<input id='children'><input onmouseover='alert(1)'>",
+        "");
+
+    testHtml(
+        'DOM clobbering of both children and lastChild, different order',
+        validator,
+        "<form><input name='children'><input name='children'>"
+            "<input id='children' name='lastChild'>"
+            "<input id='bad' onmouseover='alert(1)'>",
+        "");
+
+    test('tagName makes containing form invalid', () {
+      var fragment = document.body!.createFragment(
+          "<form onmouseover='alert(2)'><input name='tagName'>",
+          validator: validator);
+      var form = fragment.lastChild as FormElement?;
+      // If the tagName was clobbered, the sanitizer should have removed
+      // the whole thing and form is null.
+      // If the tagName was not clobbered, then there will be content,
+      // but the tagName should be the normal value. IE11 has started
+      // doing this.
+      if (form != null) {
+        expect(form.tagName, 'FORM');
+      }
+    });
+
+    test('tagName without mouseover', () {
+      var fragment = document.body!
+          .createFragment("<form><input name='tagName'>", validator: validator);
+      var form = fragment.lastChild as FormElement?;
+      // If the tagName was clobbered, the sanitizer should have removed
+      // the whole thing and form is null.
+      // If the tagName was not clobbered, then there will be content,
+      // but the tagName should be the normal value.
+      if (form != null) {
+        expect(form.tagName, 'FORM');
+      }
+    });
+  });
+}
diff --git a/tests/lib/html/non_instantiated_is_test.dart b/tests/lib/html/non_instantiated_is_test.dart
new file mode 100644
index 0000000..0865b07
--- /dev/null
+++ b/tests/lib/html/non_instantiated_is_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// Regression test for dart2js, that used to emit wrong code on is
+// checks of native classes that are not instantiated.
+
+import 'dart:html';
+
+import 'package:expect/expect.dart';
+
+var a = [new Object()];
+
+main() {
+  Expect.isFalse(a[0] is Node);
+}
diff --git a/tests/lib/html/notification_permission_test.dart b/tests/lib/html/notification_permission_test.dart
new file mode 100644
index 0000000..0edd8ee
--- /dev/null
+++ b/tests/lib/html/notification_permission_test.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.
+
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  test('Notification.requestPermission', () async {
+    String permission = await Notification.requestPermission();
+    expect(permission, isNotNull);
+  });
+}
diff --git a/tests/lib/html/notification_test.dart b/tests/lib/html/notification_test.dart
new file mode 100644
index 0000000..283dc5b
--- /dev/null
+++ b/tests/lib/html/notification_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supported_notification', () {
+    test('supported', () {
+      expect(Notification.supported, true);
+    });
+  });
+
+  group('constructors', () {
+    // Test that we create the notification and that the parameters have
+    // the expected values. Note that these won't actually display, because
+    // we haven't asked for permission, which would have to be done
+    // interactively, so can't run on a bot.
+    test('Notification', () {
+      var expectation = Notification.supported ? returnsNormally : throws;
+      expect(() {
+        var allDefaults = new Notification("Hello world");
+        var allSpecified = new Notification("Deluxe notification",
+            dir: "rtl",
+            body: 'All parameters set',
+            icon: 'icon.png',
+            tag: 'tag',
+            lang: 'en_US');
+        expect(allDefaults is Notification, isTrue);
+        expect(allSpecified is Notification, isTrue);
+        expect(allDefaults.title, "Hello world");
+        expect(allSpecified.title, "Deluxe notification");
+        expect(allSpecified.dir, "rtl");
+        expect(allSpecified.body, "All parameters set");
+        var icon = allSpecified.icon;
+        var tail = Uri.parse(icon).pathSegments.last;
+        expect(tail, "icon.png");
+        expect(allSpecified.tag, "tag");
+        expect(allSpecified.lang, "en_US");
+      }, expectation);
+    });
+  });
+}
diff --git a/tests/lib/html/performance_api_test.dart b/tests/lib/html/performance_api_test.dart
new file mode 100644
index 0000000..2e5643d
--- /dev/null
+++ b/tests/lib/html/performance_api_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:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(Performance.supported, true);
+    });
+  });
+
+  group('performance', () {
+    test('PerformanceApi', () {
+      // Check that code below will not throw exceptions if supported.
+      var expectation = Performance.supported ? returnsNormally : throws;
+      expect(() {
+        var requestStart = window.performance.timing.requestStart;
+        var responseStart = window.performance.timing.responseStart;
+        var responseEnd = window.performance.timing.responseEnd;
+
+        var loading = window.performance.timing.domLoading;
+        var loadedStart = window.performance.timing.domContentLoadedEventStart;
+        var loadedEnd = window.performance.timing.domContentLoadedEventEnd;
+        var complete = window.performance.timing.domComplete;
+
+        var loadEventStart = window.performance.timing.loadEventStart;
+      }, expectation);
+    });
+  });
+}
diff --git a/tests/lib/html/postmessage_anonymous_test.dart b/tests/lib/html/postmessage_anonymous_test.dart
new file mode 100644
index 0000000..1a6562e
--- /dev/null
+++ b/tests/lib/html/postmessage_anonymous_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.
+
+@JS()
+library postmessage_anonymous_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+const String JS_CODE = """
+window.addEventListener('message', handler);
+function handler(e) {
+  var data = e.data;
+  if (typeof data == 'string') return;
+  if (data.recipient != 'JS') return;
+  var response = {recipient: 'DART', msg: data.msg};
+  window.removeEventListener('message', handler);
+  window.postMessage(response, '*');
+}
+""";
+
+const String TEST_MSG = "hello world";
+
+@JS()
+@anonymous
+class Message {
+  external String get recipient;
+  external String get msg;
+  external factory Message({required String recipient, required String msg});
+}
+
+main() {
+  var subscription;
+  subscription = window.onMessage.listen((e) {
+    var data = e.data;
+    if (data is String) return;
+    if (data['recipient'] != 'DART') return;
+    subscription.cancel();
+    Expect.equals(TEST_MSG, data['msg']);
+  });
+  injectSource(JS_CODE);
+  window.postMessage(Message(recipient: 'JS', msg: TEST_MSG), '*');
+}
+
+void injectSource(String code) {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = code;
+  document.body!.append(script);
+}
diff --git a/tests/lib/html/postmessage_structured_test.dart b/tests/lib/html/postmessage_structured_test.dart
new file mode 100644
index 0000000..ace743d
--- /dev/null
+++ b/tests/lib/html/postmessage_structured_test.dart
@@ -0,0 +1,193 @@
+// 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
+// BSD-style license that can be found in the LICENSE file
+
+library postmessage_js_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:collection' show HashMap, SplayTreeMap;
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+import 'utils.dart';
+
+final isMap = predicate((v) => v is Map);
+
+void injectSource(String code) {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = code;
+  document.body!.append(script);
+}
+
+Future go(String name, dynamic value) {
+  // Round-trip graph from Dart to JavaScript and back.
+
+  final JS_CODE = """
+            window.addEventListener('message', handler);
+            function handler(e) {
+              var data = e.data;
+              if (typeof data == 'string') return;
+              if (data.recipient != 'JS') return;
+              window.console.log(data.data);
+              var response = {recipient: 'DART', data: data.data};
+              window.removeEventListener('message', handler);
+              window.postMessage(response, '*');
+            }
+            """;
+  final done = new Completer();
+  var subscription;
+  subscription = window.onMessage.listen((e) {
+    var data = e.data;
+    if (data is String) return; // Messages from unit test protocol.
+    if (data['recipient'] != 'DART') return; // Not for me.
+    try {
+      subscription.cancel();
+      expect(data, isMap);
+      var returnedValue = data['data'];
+      expect(returnedValue, notEquals(value));
+      verifyGraph(value, returnedValue);
+      done.complete();
+    } catch (e) {
+      done.completeError('$name failed: $e');
+    }
+  });
+  injectSource(JS_CODE);
+  window.postMessage({'recipient': 'JS', 'data': value}, '*');
+  return done.future;
+}
+
+Future primitives() async {
+  await testJsToDartPostmessage();
+
+  var obj1 = {'a': 100, 'b': 's'};
+  var obj2 = {'x': obj1, 'y': obj1}; // DAG.
+
+  var obj3 = <String, dynamic>{};
+  obj3['a'] = 100;
+  obj3['b'] = obj3; // Cycle.
+
+  var obj4 = new SplayTreeMap<String, dynamic>(); // Different implementation.
+  obj4['a'] = 100;
+  obj4['b'] = 's';
+
+  var cyclic_list = <dynamic>[1, 2, 3];
+  cyclic_list[1] = cyclic_list;
+
+  await go('test_simple_list', [1, 2, 3]);
+  await go('test_map', obj1);
+  await go('test_DAG', obj2);
+  await go('test_cycle', obj3);
+  await go('test_simple_splay', obj4);
+  await go('const_array_1', const [
+    const [1],
+    const [2]
+  ]);
+  await go('const_array_dag', const [
+    const [1],
+    const [1]
+  ]);
+  await go('array_deferred_copy', [1, 2, 3, obj3, obj3, 6]);
+  await go('array_deferred_copy_2', [
+    1,
+    2,
+    3,
+    [4, 5, obj3],
+    [obj3, 6]
+  ]);
+  await go('cyclic_list', cyclic_list);
+}
+
+Future testJsToDartPostmessage() {
+  // Pass an object literal from JavaScript. It should be seen as a Dart Map.
+  final JS_CODE = """
+        window.postMessage({eggs: 3}, '*');
+        """;
+  final done = new Completer();
+  var subscription = null;
+  subscription = window.onMessage.listen((e) {
+    var data = e.data;
+    if (data is String) return; //    Messages from unit test protocol.
+    try {
+      subscription.cancel();
+      expect(data, isMap);
+      expect(data['eggs'], equals(3));
+      done.complete();
+    } catch (e) {
+      done.completeError(e);
+    }
+  });
+  injectSource(JS_CODE);
+  return done.future;
+}
+
+Future morePrimitives() async {
+  await testJsToDartNullPrototypeEventdata();
+}
+
+Future testJsToDartNullPrototypeEventdata() {
+  // Pass an object with a null prototype from JavaScript.
+  // It should be seen as a Dart Map.
+  final JS_CODE = """
+       // Call anonymous function to create a local scope.
+       (function() {
+          var o = Object.create(null);
+          o.eggs = 3;
+          var foo = new MessageEvent('stuff', {data: o});
+          window.dispatchEvent(foo);
+        })();
+      """;
+  final done = new Completer();
+  var subscription = null;
+  subscription = window.on['stuff'].listen((e) {
+    var data = (e as MessageEvent).data;
+    if (data is String) return; // Messages from unit test protocol.
+    try {
+      subscription.cancel();
+      expect(data, isMap);
+      expect(data['eggs'], equals(3));
+      done.complete();
+    } catch (e) {
+      done.completeError(e);
+    }
+  });
+  injectSource(JS_CODE);
+  return done.future;
+}
+
+Future typedArrays() async {
+  var array_buffer = new Uint8List(16).buffer;
+  var view_a = new Float32List.view(array_buffer, 0, 4);
+  var view_b = new Uint8List.view(array_buffer, 1, 13);
+  var typed_arrays_list = [view_a, array_buffer, view_b];
+
+  // Note that FF is failing this test because in the sent message:
+  // view_a.buffer == array_buffer
+  // But in the response:
+  // view_a.buffer != array_buffer
+  await go('typed_arrays_list', typed_arrays_list);
+}
+
+Future iframe() async {
+  await postMessageClonesData();
+}
+
+Future postMessageClonesData() {
+  var iframe = new IFrameElement();
+  var future = iframe.onLoad.first.then((_) {
+    iframe.contentWindow!.postMessage(new HashMap<String, num>(), '*');
+  });
+  iframe.src = 'about:blank';
+  document.body!.append(iframe);
+
+  return future;
+}
+
+main() async {
+  await primitives();
+  await morePrimitives();
+  await typedArrays();
+  await iframe();
+}
diff --git a/tests/lib/html/private_extension_member_test.dart b/tests/lib/html/private_extension_member_test.dart
new file mode 100644
index 0000000..4512d9e
--- /dev/null
+++ b/tests/lib/html/private_extension_member_test.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.
+
+import 'package:expect/expect.dart';
+
+import 'dart:html';
+
+main() {
+  // Regression test for: https://github.com/dart-lang/dev_compiler/issues/508.
+  // "dart:html" defines some private members on native DOM types and we need
+  // to ensure those can be accessed correctly.
+  //
+  // The createFragment() method sets `_innerHtml` on the element, so we use it
+  // as a test case.
+  Expect.equals("[object DocumentFragment]",
+      new BRElement().createFragment("Hi").toString());
+}
diff --git a/tests/lib/html/query_test.dart b/tests/lib/html/query_test.dart
new file mode 100644
index 0000000..82ffa2f
--- /dev/null
+++ b/tests/lib/html/query_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+main() {
+  final div = new DivElement();
+  final canvas = new CanvasElement(width: 200, height: 200);
+  canvas.id = 'testcanvas';
+  final element = new Element.html("<div><br/><img/><input/><img/></div>");
+  document.body!.nodes.addAll([div, canvas, element]);
+
+  var isCanvasElement =
+      predicate((x) => x is CanvasElement, 'is a CanvasElement');
+  var isImageElement =
+      predicate((x) => x is ImageElement, 'is an ImageElement');
+
+  test('query', () {
+    Element? e = querySelector('#testcanvas');
+    expect(e, isNotNull);
+    expect(e!.id, 'testcanvas');
+    expect(e, isCanvasElement);
+    expect(e, canvas);
+  });
+
+  test('query (None)', () {
+    Element? e = querySelector('#nothere');
+    expect(e, isNull);
+  });
+
+  test('queryAll (One)', () {
+    List l = querySelectorAll('canvas');
+    expect(l.length, 1);
+    expect(l[0], canvas);
+  });
+
+  test('queryAll (Multiple)', () {
+    List l = querySelectorAll('img');
+    expect(l.length, 2);
+    expect(l[0], isImageElement);
+    expect(l[1], isImageElement);
+    expect(l[0] == l[1], isFalse);
+  });
+
+  test('queryAll (None)', () {
+    List l = querySelectorAll('video');
+    expect(l.isEmpty, isTrue);
+  });
+}
diff --git a/tests/lib/html/queryall_test.dart b/tests/lib/html/queryall_test.dart
new file mode 100644
index 0000000..6516a3c
--- /dev/null
+++ b/tests/lib/html/queryall_test.dart
@@ -0,0 +1,87 @@
+// 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
+// BSD-style license that can be found in the LICENSE file
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isElement = predicate((x) => x is Element, 'is an Element');
+  var isCanvasElement =
+      predicate((x) => x is CanvasElement, 'is a CanvasElement');
+  var isDivElement = predicate((x) => x is DivElement, 'is a isDivElement');
+
+  var div = new DivElement();
+  div.id = 'test';
+  document.body!.append(div);
+
+  div.nodes.addAll([
+    new DivElement(),
+    new CanvasElement(),
+    new DivElement(),
+    new Text('Hello'),
+    new DivElement(),
+    new Text('World'),
+    new CanvasElement()
+  ]);
+
+  test('querySelectorAll', () {
+    List<Node> all = querySelectorAll('*');
+    for (var e in all) {
+      expect(e, isElement);
+    }
+  });
+
+  test('document.querySelectorAll', () {
+    List<Element> all1 = querySelectorAll('*');
+    List<Element> all2 = document.querySelectorAll('*');
+    expect(all1.length, equals(all2.length));
+    for (var i = 0; i < all1.length; ++i) {
+      expect(all1[i], equals(all2[i]));
+    }
+  });
+
+  test('querySelectorAll-canvas', () {
+    var all = querySelectorAll('canvas');
+    for (var e in all) {
+      expect(e, isCanvasElement);
+    }
+    expect(all.length, equals(2));
+  });
+
+  test('querySelectorAll-contains', () {
+    List<Element> all = querySelectorAll('*');
+    for (var e in all) {
+      expect(all.contains(e), isTrue);
+    }
+  });
+
+  test('querySelectorAll-where', () {
+    List<Element> all = querySelectorAll('*');
+    var canvases = all.where((e) => e is CanvasElement);
+    for (var e in canvases) {
+      expect(e is CanvasElement, isTrue);
+    }
+    expect(canvases.length, equals(2));
+  });
+
+  test('node.querySelectorAll', () {
+    List<Element> list = div.querySelectorAll('*');
+    expect(list.length, equals(5));
+    expect(list[0], isDivElement);
+    expect(list[1], isCanvasElement);
+    expect(list[2], isDivElement);
+    expect(list[3], isDivElement);
+    expect(list[4], isCanvasElement);
+  });
+
+  test('immutable', () {
+    List<Element> list = div.querySelectorAll('*');
+    int len = list.length;
+    expect(() {
+      list.add(new DivElement());
+    }, throwsUnsupportedError);
+    expect(list.length, equals(len));
+  });
+}
diff --git a/tests/lib/html/range_test.dart b/tests/lib/html/range_test.dart
new file mode 100644
index 0000000..489d1d9
--- /dev/null
+++ b/tests/lib/html/range_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:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supports_createContextualFragment', () {
+      expect(Range.supportsCreateContextualFragment, isTrue);
+    });
+  });
+
+  group('functional', () {
+    test('supported works', () {
+      var range = new Range();
+      range.selectNode(document.body!);
+
+      var expectation =
+          Range.supportsCreateContextualFragment ? returnsNormally : throws;
+
+      expect(() {
+        range.createContextualFragment('<div></div>');
+      }, expectation);
+    });
+  });
+}
diff --git a/tests/lib/html/request_animation_frame_test.dart b/tests/lib/html/request_animation_frame_test.dart
new file mode 100644
index 0000000..d0c0447
--- /dev/null
+++ b/tests/lib/html/request_animation_frame_test.dart
@@ -0,0 +1,61 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library RequestAnimationFrameTest;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+Future testOneShot() async {
+  final done = new Completer();
+  window.requestAnimationFrame(done.complete);
+  await done.future;
+}
+
+Future testTwoShot() async {
+  final done = new Completer();
+  window.requestAnimationFrame((timestamp1) {
+    window.requestAnimationFrame((timestamp2) {
+      // Not monotonic on Safari and IE.
+      // expect(timestamp2, greaterThan(timestamp1),
+      //    reason: 'timestamps ordered');
+      done.complete();
+    });
+  });
+  await done.future;
+}
+
+// How do we test that a callback is never called?  We can't wrap the uncalled
+// callback with 'expectAsync'.  Will request several frames and try
+// cancelling the one that is not the last.
+Future testCancel1() async {
+  final done = new Completer();
+  var frame1 = window.requestAnimationFrame((timestamp1) {
+    fail('Should have been cancelled');
+  });
+  var frame2 = window.requestAnimationFrame(done.complete);
+  window.cancelAnimationFrame(frame1);
+  await done.future;
+}
+
+Future testCancel2() async {
+  final done1 = new Completer();
+  final done2 = new Completer();
+  var frame1 = window.requestAnimationFrame(done1.complete);
+  var frame2 = window.requestAnimationFrame((timestamp2) {
+    fail('Should have been cancelled');
+  });
+  var frame3 = window.requestAnimationFrame(done2.complete);
+  window.cancelAnimationFrame(frame2);
+  await Future.wait([done1.future, done2.future]);
+}
+
+main() async {
+  await testOneShot();
+  await testTwoShot();
+  await testCancel1();
+  await testCancel2();
+}
diff --git a/tests/lib/html/rtc_test.dart b/tests/lib/html/rtc_test.dart
new file mode 100644
index 0000000..6b3c3581
--- /dev/null
+++ b/tests/lib/html/rtc_test.dart
@@ -0,0 +1,46 @@
+// 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:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(RtcPeerConnection.supported, isTrue);
+    });
+  });
+
+  group('functionality', () {
+    // More thorough testing of this API requires the user to
+    // explicitly click "allow this site to access my camera and/or microphone."
+    // or particularly allow that site to always have those permission on each
+    // computer the test is run. For more through tests, see
+    // interactive_test.dart.
+    if (RtcPeerConnection.supported) {
+      test('peer connection', () {
+        var pc = new RtcPeerConnection({
+          'iceServers': [
+            {'url': 'stun:216.93.246.18:3478'}
+          ]
+        });
+        expect(pc is RtcPeerConnection, isTrue);
+        pc.onIceCandidate.listen((candidate) {});
+      });
+
+      test('ice candidate', () {
+        var candidate =
+            new RtcIceCandidate({'sdpMLineIndex': 1, 'candidate': 'hello'});
+        expect(candidate is RtcIceCandidate, isTrue);
+      });
+
+      test('session description', () {
+        var description =
+            new RtcSessionDescription({'sdp': 'foo', 'type': 'offer'});
+        expect(description is RtcSessionDescription, isTrue);
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/selectelement_test.dart b/tests/lib/html/selectelement_test.dart
new file mode 100644
index 0000000..22b19fa
--- /dev/null
+++ b/tests/lib/html/selectelement_test.dart
@@ -0,0 +1,73 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('selectedOptions', () {
+    var element = new SelectElement();
+    element.multiple = false;
+    var options = [
+      new OptionElement(),
+      new DivElement(),
+      new OptionElement(data: 'data', value: 'two', selected: true),
+      new DivElement(),
+      new OptionElement(data: 'data', value: 'two', selected: true),
+      new OptionElement(),
+    ];
+    element.children.addAll(options);
+    expect(element.selectedOptions.length, 1);
+    expect(element.selectedOptions[0], equals(options[4]));
+  });
+
+  test('multiple selectedOptions', () {
+    var element = new SelectElement();
+    element.multiple = true;
+    var options = [
+      new OptionElement(),
+      new DivElement(),
+      new OptionElement(data: 'data', value: 'two', selected: true),
+      new DivElement(),
+      new OptionElement(data: 'data', value: 'two', selected: true),
+      new OptionElement(),
+      new OptionElement(data: 'data', value: 'two', selected: false),
+    ];
+    element.children.addAll(options);
+    expect(element.selectedOptions.length, 2);
+    expect(element.selectedOptions[0], equals(options[2]));
+    expect(element.selectedOptions[1], equals(options[4]));
+  });
+
+  test('options', () {
+    var element = new SelectElement();
+    var options = [
+      new OptionElement(),
+      new OptionElement(data: 'data', value: 'two', selected: true),
+      new OptionElement(data: 'data', value: 'two', selected: true),
+      new OptionElement(),
+    ];
+    element.children.addAll(options);
+    // Use last to make sure that the list was correctly wrapped.
+    expect(element.options.last, equals(options[3]));
+  });
+
+  test('optgroup', () {
+    var element = new Element.html('<select>'
+        '<option>1</option>'
+        '<optgroup>'
+        '<option>2</option>'
+        '</optgroup>'
+        '</select>') as SelectElement;
+
+    expect(element.options.length, 2);
+    element.selectedIndex = 1;
+
+    var optGroup = element.children[1];
+    expect(optGroup is OptGroupElement, isTrue);
+    expect((optGroup.children.single as OptionElement).selected, isTrue);
+    expect(element.selectedOptions, optGroup.children);
+  });
+}
diff --git a/tests/lib/html/serialized_script_value_test.dart b/tests/lib/html/serialized_script_value_test.dart
new file mode 100644
index 0000000..02370b8
--- /dev/null
+++ b/tests/lib/html/serialized_script_value_test.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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+import 'utils.dart';
+
+serializationTest(name, value) {
+  test(name, () {
+    // To check how value is serialized and deserialized, we create a
+    // MessageEvent.
+    final event =
+        new MessageEvent('', data: value, origin: '', lastEventId: '');
+    verifyGraph(value, event.data);
+  });
+}
+
+main() {
+  serializationTest('null', null);
+  serializationTest('int', 1);
+  serializationTest('double', 2.39);
+  serializationTest('string', 'hey!');
+
+  final simpleMap = {'a': 100, 'b': 's'};
+  final dagMap = {'x': simpleMap, 'y': simpleMap};
+  final cyclicMap = {'b': dagMap};
+  cyclicMap['a'] = cyclicMap;
+  serializationTest('simple map', simpleMap);
+  serializationTest('dag map', dagMap);
+  serializationTest('cyclic map', cyclicMap);
+
+  final simpleList = [100, 's'];
+  final dagList = [simpleList, simpleList];
+  final cyclicList = [dagList];
+  cyclicList.add(cyclicList);
+  serializationTest('simple list', simpleList);
+  serializationTest('dag list', dagList);
+  serializationTest('cyclic list', cyclicList);
+
+  serializationTest('datetime', [new DateTime.now()]);
+
+  var blob = new Blob(
+      ['Indescribable... Indestructible! Nothing can stop it!'], 'text/plain');
+  serializationTest('blob', [blob]);
+
+  var canvas = new CanvasElement();
+  canvas.width = 100;
+  canvas.height = 100;
+  var imageData = canvas.context2D.getImageData(0, 0, 1, 1);
+  serializationTest('imagedata', [imageData]);
+}
diff --git a/tests/lib/html/shadow_dom_test.dart b/tests/lib/html/shadow_dom_test.dart
new file mode 100644
index 0000000..3199982
--- /dev/null
+++ b/tests/lib/html/shadow_dom_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(ShadowRoot.supported, true);
+    });
+  });
+
+  group('ShadowDOM_tests', () {
+    var div1, div2, shadowRoot, paragraph1, paragraph2;
+
+    init() {
+      paragraph1 = new ParagraphElement();
+      paragraph2 = new ParagraphElement();
+      [paragraph1, paragraph2].forEach((p) {
+        p.classes.add('foo');
+      });
+      div1 = new DivElement();
+      div2 = new DivElement();
+      div1.classes.add('foo');
+      shadowRoot = div2.createShadowRoot();
+      shadowRoot.append(paragraph1);
+      shadowRoot.append(new ContentElement());
+      div2.append(paragraph2);
+      document.body!.append(div1);
+      document.body!.append(div2);
+    }
+
+    var expectation = ShadowRoot.supported ? returnsNormally : throws;
+
+    test("Shadowed nodes aren't visible to queries from outside ShadowDOM", () {
+      expect(() {
+        init();
+
+        expect(querySelectorAll('.foo'), equals([div1, paragraph2]));
+      }, expectation);
+    });
+
+    test('Parent node of a shadow root must be null.', () {
+      expect(() {
+        init();
+
+        expect(shadowRoot.parent, isNull);
+      }, expectation);
+    });
+
+    // TODO(samhop): test that <content> and <content select="foo"> and
+    // <shadow>
+    // work properly. This is blocked on having a good way to do browser
+    // rendering tests.
+
+    test('Querying in shadowed fragment respects the shadow boundary.', () {
+      expect(() {
+        init();
+
+        expect(shadowRoot.querySelectorAll('.foo'), equals([paragraph1]));
+      }, expectation);
+    });
+
+    if (ShadowRoot.supported) {
+      test('Shadowroot contents are distributed', () {
+        var div = new DivElement();
+
+        var box1 = new DivElement()..classes.add('foo');
+        div.append(box1);
+
+        var box2 = new DivElement();
+        div.append(box2);
+
+        var sRoot = div.createShadowRoot();
+        var content1 = new ContentElement()..select = ".foo";
+        sRoot.append(content1);
+
+        var content2 = new ContentElement();
+        sRoot.append(content2);
+
+        expect(content1.getDistributedNodes(), [box1]);
+        expect(content2.getDistributedNodes(), [box2]);
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/shadowroot_test.dart b/tests/lib/html/shadowroot_test.dart
new file mode 100644
index 0000000..85c4ac1
--- /dev/null
+++ b/tests/lib/html/shadowroot_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isShadowRoot = predicate((x) => x is ShadowRoot, 'is a ShadowRoot');
+
+  test('ShadowRoot supported', () {
+    var isSupported = ShadowRoot.supported;
+
+    // If it's supported, then it should work. Otherwise should fail.
+    if (isSupported) {
+      var div = new DivElement();
+      var shadowRoot = div.createShadowRoot();
+      expect(shadowRoot, isShadowRoot);
+      expect(div.shadowRoot, shadowRoot);
+    } else {
+      expect(() => new DivElement().createShadowRoot(), throws);
+    }
+  });
+}
diff --git a/tests/lib/html/small.mp4 b/tests/lib/html/small.mp4
new file mode 100644
index 0000000..5bb2780
--- /dev/null
+++ b/tests/lib/html/small.mp4
Binary files differ
diff --git a/tests/lib/html/small.webm b/tests/lib/html/small.webm
new file mode 100644
index 0000000..ff01e61
--- /dev/null
+++ b/tests/lib/html/small.webm
Binary files differ
diff --git a/tests/lib/html/speechrecognition_test.dart b/tests/lib/html/speechrecognition_test.dart
new file mode 100644
index 0000000..066faf0
--- /dev/null
+++ b/tests/lib/html/speechrecognition_test.dart
@@ -0,0 +1,41 @@
+// 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:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(SpeechRecognition.supported, true);
+    });
+  });
+
+  group('types', () {
+    var expectation = SpeechRecognition.supported ? returnsNormally : throws;
+
+    test('SpeechRecognition', () {
+      expect(() {
+        var s = new SpeechRecognition();
+        expect(s is SpeechRecognition, true);
+        expect(s.onStart.listen is Function, true);
+      }, expectation);
+    });
+
+    test('SpeechRecognitionEvent', () {
+      expect(() {
+        var e = new SpeechRecognitionEvent('speech');
+        expect(e is SpeechRecognitionEvent, true);
+      }, expectation);
+    });
+
+    test('SpeechRecognitionError', () {
+      expect(() {
+        var e = new SpeechRecognitionError('speech');
+        expect(e is SpeechRecognitionError, true);
+      }, expectation);
+    });
+  });
+}
diff --git a/tests/lib/html/storage_promise_test.dart b/tests/lib/html/storage_promise_test.dart
new file mode 100644
index 0000000..4c8e54d
--- /dev/null
+++ b/tests/lib/html/storage_promise_test.dart
@@ -0,0 +1,41 @@
+// 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 interactive_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+import 'package:async_helper/async_helper.dart';
+
+main() async {
+  bool thenEstimateBefore = false;
+  bool thenEstimateAfter = false;
+  bool thenEstimateDone = false;
+  late Map thenEstimate;
+  test('Basic Promise Test', () async {
+    try {
+      thenEstimateBefore = true;
+      window.navigator.storage.estimate().then((value) {
+        thenEstimate = value!;
+        thenEstimateDone = true;
+      });
+      thenEstimateAfter = true;
+    } catch (msg) {
+      fail("StorageManger failed: $msg");
+    }
+
+    Map estimate = await window.navigator.storage.estimate() as Map;
+
+    expect(thenEstimate['usage'] >= 0, true);
+    expect(thenEstimate['quota'] > 1, true);
+    expect(thenEstimate['usage'], estimate['usage']);
+    expect(thenEstimate['quota'], estimate['quota']);
+
+    expect(thenEstimateBefore, true);
+    expect(thenEstimateAfter, true);
+    expect(thenEstimateDone, true);
+  });
+}
diff --git a/tests/lib/html/storage_test.dart b/tests/lib/html/storage_test.dart
new file mode 100644
index 0000000..21f6e82
--- /dev/null
+++ b/tests/lib/html/storage_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('GetItem', () {
+    final value = window.localStorage['does not exist'];
+    expect(value, isNull);
+  });
+  test('SetItem', () {
+    final key = 'foo';
+    final value = 'bar';
+    window.localStorage[key] = value;
+    final stored = window.localStorage[key];
+    expect(stored, value);
+  });
+
+  test('event', () {
+    // Bug 8076 that not all optional params are optional in Dartium.
+    var event = new StorageEvent('something',
+        oldValue: 'old', newValue: 'new', url: 'url', key: 'key');
+    expect(event is StorageEvent, isTrue);
+    expect(event.oldValue, 'old');
+    expect(event.newValue, 'new');
+  });
+}
diff --git a/tests/lib/html/streams_test.dart b/tests/lib/html/streams_test.dart
new file mode 100644
index 0000000..2d5c210
--- /dev/null
+++ b/tests/lib/html/streams_test.dart
@@ -0,0 +1,278 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+class StreamHelper {
+  var _a;
+  StreamHelper() {
+    _a = new TextInputElement();
+    document.body!.append(_a);
+  }
+
+  Element get element => _a;
+  Stream<Event?> get stream => _a.onFocus;
+
+  // Causes an event on a to be fired.
+  void pulse() {
+    var event = new Event('focus');
+    _a.dispatchEvent(event);
+  }
+}
+
+main() {
+  test('simple', () {
+    var helper = new StreamHelper();
+
+    var callCount = 0;
+    helper.stream.listen((Event? e) {
+      ++callCount;
+    });
+
+    helper.pulse();
+    expect(callCount, 1);
+  });
+
+  test('broadcast', () {
+    var stream = new DivElement().onClick;
+    expect(stream.asBroadcastStream(), stream);
+    expect(stream.isBroadcast, isTrue);
+  });
+
+  // Validates that capturing events fire on parent before child.
+  test('capture', () {
+    var parent = new DivElement();
+    document.body!.append(parent);
+
+    var helper = new StreamHelper();
+    parent.append(helper.element);
+
+    var childCallCount = 0;
+    var parentCallCount = 0;
+    Element.focusEvent.forTarget(parent, useCapture: true).listen((Event e) {
+      ++parentCallCount;
+      expect(childCallCount, 0);
+    });
+
+    Element.focusEvent
+        .forTarget(helper.element, useCapture: true)
+        .listen((Event e) {
+      ++childCallCount;
+      expect(parentCallCount, 1);
+    });
+
+    helper.pulse();
+    expect(childCallCount, 1);
+    expect(parentCallCount, 1);
+  });
+
+  test('cancel', () {
+    var helper = new StreamHelper();
+
+    var callCount = 0;
+    var subscription = helper.stream.listen((_) {
+      ++callCount;
+    });
+
+    helper.pulse();
+    expect(callCount, 1);
+
+    subscription.cancel();
+    helper.pulse();
+    expect(callCount, 1);
+
+    expect(() {
+      subscription.onData((_) {});
+    }, throws);
+
+    // Calling these after a cancel does nothing.
+    subscription.cancel();
+    subscription.pause();
+    subscription.resume();
+  });
+
+  test('pause/resume', () {
+    var helper = new StreamHelper();
+
+    var callCount = 0;
+    var subscription = helper.stream.listen((_) {
+      ++callCount;
+    });
+
+    helper.pulse();
+    expect(callCount, 1);
+
+    subscription.pause();
+    helper.pulse();
+    expect(callCount, 1);
+
+    subscription.resume();
+    helper.pulse();
+    expect(callCount, 2);
+
+    var completer = new Completer<int>.sync();
+    subscription.pause(completer.future);
+    helper.pulse();
+    expect(callCount, 2);
+
+    // Paused, should have no impact.
+    subscription.pause();
+    helper.pulse();
+    subscription.resume();
+    helper.pulse();
+    expect(callCount, 2);
+
+    completer.complete(0);
+    helper.pulse();
+    expect(callCount, 3);
+
+    // Not paused, but resuming once too often is ok.
+    subscription.resume();
+  });
+
+  test('onData', () {
+    var helper = new StreamHelper();
+
+    var callCountOne = 0;
+    var subscription = helper.stream.listen((_) {
+      ++callCountOne;
+    });
+
+    helper.pulse();
+    expect(callCountOne, 1);
+
+    var callCountTwo = 0;
+    subscription.onData((_) {
+      ++callCountTwo;
+    });
+
+    helper.pulse();
+    expect(callCountOne, 1);
+    expect(callCountTwo, 1);
+  });
+
+  test('null onData', () {
+    var helper = new StreamHelper();
+
+    var subscription = helper.stream.listen(null);
+    helper.pulse();
+
+    var callCountOne = 0;
+    subscription.onData((_) {
+      ++callCountOne;
+    });
+    helper.pulse();
+    expect(callCountOne, 1);
+
+    subscription.onData(null);
+    helper.pulse();
+    expect(callCountOne, 1);
+  });
+
+  var stream = new StreamHelper().stream;
+  // Streams have had some type-checking issues, these tests just validate that
+  // those are OK.
+  test('first', () {
+    stream.first.then((_) {});
+  });
+
+  test('asBroadcastStream', () {
+    stream.asBroadcastStream().listen((_) {});
+  });
+
+  test('where', () {
+    stream.where((_) => true).listen((_) {});
+  });
+
+  test('map', () {
+    stream.map((_) => null).listen((_) {});
+  });
+
+  test('reduce', () {
+    stream.reduce((a, b) => null).then((_) {});
+  });
+
+  test('fold', () {
+    stream.fold(null, (a, b) => null).then((_) {});
+  });
+
+  test('contains', () {
+    stream.contains((_) => true).then((_) {});
+  });
+
+  test('every', () {
+    stream.every((_) => true).then((_) {});
+  });
+
+  test('any', () {
+    stream.any((_) => true).then((_) {});
+  });
+
+  test('length', () {
+    stream.length.then((_) {});
+  });
+
+  test('isEmpty', () {
+    stream.isEmpty.then((_) {});
+  });
+
+  test('toList', () {
+    stream.toList().then((_) {});
+  });
+
+  test('toSet', () {
+    stream.toSet().then((_) {});
+  });
+
+  test('take', () {
+    stream.take(1).listen((_) {});
+  });
+
+  test('takeWhile', () {
+    stream.takeWhile((_) => false).listen((_) {});
+  });
+
+  test('skip', () {
+    stream.skip(0).listen((_) {});
+  });
+
+  test('skipWhile', () {
+    stream.skipWhile((_) => false).listen((_) {});
+  });
+
+  test('distinct', () {
+    stream.distinct((a, b) => false).listen((_) {});
+  });
+
+  test('first', () {
+    stream.first.then((_) {});
+  });
+
+  test('last', () {
+    stream.last.then((_) {});
+  });
+
+  test('single', () {
+    stream.single.then((_) {});
+  });
+
+  test('firstWhere', () {
+    stream.firstWhere((_) => true).then((_) {});
+  });
+
+  test('lastWhere', () {
+    stream.lastWhere((_) => true).then((_) {});
+  });
+
+  test('singleWhere', () {
+    stream.singleWhere((_) => true).then((_) {});
+  });
+
+  test('elementAt', () {
+    stream.elementAt(0).then((_) {});
+  });
+}
diff --git a/tests/lib/html/svg_test.dart b/tests/lib/html/svg_test.dart
new file mode 100644
index 0000000..1e9a282
--- /dev/null
+++ b/tests/lib/html/svg_test.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.
+
+import 'dart:html';
+import 'dart:svg' as svg;
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('svgPresence', () {
+    var isSvgElement = predicate((x) => x is svg.SvgElement, 'is a SvgElement');
+
+    test('simpleRect', () {
+      var div = new Element.tag('div');
+      document.body!.append(div);
+      div.setInnerHtml(r'''
+<svg id='svg1' width='200' height='100'>
+<rect id='rect1' x='10' y='20' width='130' height='40' rx='5'fill='blue'></rect>
+</svg>
+''', validator: new NodeValidatorBuilder()..allowSvg());
+
+      var e = document.querySelector('#svg1');
+      expect(e, isNotNull);
+
+      svg.RectElement r = document.querySelector('#rect1') as svg.RectElement;
+      expect(r.x.baseVal.value, 10);
+      expect(r.y.baseVal.value, 20);
+      expect(r.height.baseVal.value, 40);
+      expect(r.width.baseVal.value, 130);
+      expect(r.rx.baseVal.value, 5);
+    });
+
+    test('trailing newline', () {
+      // Ensures that we handle SVG with trailing newlines.
+      var logo = new svg.SvgElement.svg("""
+        <svg xmlns='http://www.w3.org/2000/svg' version='1.1'>
+          <path/>
+        </svg>
+        """);
+
+      expect(logo, isSvgElement);
+    });
+  });
+
+  group('svgInterfaceMatch', () {
+    // Test that SVG elements explicitly implement the IDL interfaces (is-checks
+    // only, see SVGTest3 for behavioural tests).
+    insertTestDiv() {
+      var element = new Element.tag('div');
+      element.setInnerHtml(r'''
+<svg id='svg1' width='200' height='100'>
+<rect id='rect1' x='10' y='20' width='130' height='40' rx='5'fill='blue'></rect>
+</svg>
+''', validator: new NodeValidatorBuilder()..allowSvg());
+      document.body!.append(element);
+      return element;
+    }
+
+    var isElement = predicate((x) => x is Element, 'is an Element');
+    var isSvgElement = predicate((x) => x is svg.SvgElement, 'is a SvgElement');
+    var isSvgSvgElement =
+        predicate((x) => x is svg.SvgSvgElement, 'is a SvgSvgElement');
+    var isNotSvgSvgElement =
+        predicate((x) => x is! svg.SvgSvgElement, 'is not a SvgSvgElement');
+    var isNode = predicate((x) => x is Node, 'is a Node');
+    var isSvgNumber = predicate((x) => x is svg.Number, 'is a svg.Number');
+    var isNotSvgNumber =
+        predicate((x) => x is! svg.Number, 'is not a svg.Number');
+    var isSvgRect = predicate((x) => x is svg.Rect, 'is a svg.Rect');
+    var isNotSvgRect = predicate((x) => x is! svg.Rect, 'is not a svg.Rect');
+
+    test('rect_isChecks', () {
+      var div = insertTestDiv();
+      var r = document.querySelector('#rect1');
+
+      // Direct inheritance chain
+      expect(r, isSvgElement);
+      expect(r, isElement);
+      expect(r, isNode);
+
+      // Interfaces not implemented.
+      expect(r, isNotSvgNumber);
+      expect(r, isNotSvgRect);
+      expect(r, isNotSvgSvgElement);
+
+      div.remove();
+    });
+  });
+
+  insertTestDiv() {
+    var element = new Element.tag('div');
+    element.innerHtml = r'''
+<svg id='svg1' width='200' height='100'>
+<rect id='rect1' x='10' y='20' width='130' height='40' rx='5'fill='blue'></rect>
+</svg>
+''';
+    document.body!.append(element);
+    return element;
+  }
+
+  group('svgBehavioral', () {
+    // Test that SVG elements have the operations advertised through all the IDL
+    // interfaces.  This is a 'duck typing' test, and does not explicitly use
+    // 'is' checks on the expected interfaces (that is in the test group above).
+
+    var isString = predicate((x) => x is String, 'is a String');
+    var isStringList = predicate((x) => x is List<String>, 'is a List<String>');
+    var isSvgMatrix = predicate((x) => x is svg.Matrix, 'is a svg.Matrix');
+    var isSvgAnimatedBoolean =
+        predicate((x) => x is svg.AnimatedBoolean, 'is an svg.AnimatedBoolean');
+    var isSvgAnimatedString =
+        predicate((x) => x is svg.AnimatedString, 'is an svg.AnimatedString');
+    var isSvgRect = predicate((x) => x is svg.Rect, 'is a svg.Rect');
+    var isSvgAnimatedTransformList = predicate(
+        (x) => x is svg.AnimatedTransformList,
+        'is an svg.AnimatedTransformList');
+    var isCssStyleDeclaration =
+        predicate((x) => x is CssStyleDeclaration, 'is a CssStyleDeclaration');
+
+    testRect(name, checker) {
+      test(name, () {
+        var div = insertTestDiv();
+        var r = document.querySelector('#rect1');
+        checker(r);
+        div.remove();
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/svgelement_test.dart b/tests/lib/html/svgelement_test.dart
new file mode 100644
index 0000000..24d7470
--- /dev/null
+++ b/tests/lib/html/svgelement_test.dart
@@ -0,0 +1,478 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:svg' as svg;
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isSvgSvgElement =
+      predicate((x) => x is svg.SvgSvgElement, 'is a SvgSvgElement');
+
+  List<String> _nodeStrings(Iterable<Node> input) {
+    final List<String> out = [];
+    for (Node n in input) {
+      if (n is Element) {
+        Element e = n;
+        out.add(e.tagName);
+      } else {
+        out.add(n.text!);
+      }
+    }
+    return out;
+  }
+
+  testConstructor(String tagName, Function isExpectedClass,
+      [bool expectation = true, allowsInnerHtml = true]) {
+    test(tagName, () {
+      expect(isExpectedClass(new svg.SvgElement.tag(tagName)), expectation);
+      if (allowsInnerHtml) {
+        expect(isExpectedClass(new svg.SvgElement.svg('<$tagName></$tagName>')),
+            expectation && allowsInnerHtml);
+      }
+    });
+  }
+
+  group('additionalConstructors', () {
+    test('valid', () {
+      final svgContent = "<svg version=\"1.1\">\n"
+          "  <circle></circle>\n"
+          "  <path></path>\n"
+          "</svg>";
+      final el = new svg.SvgElement.svg(svgContent);
+      expect(el, isSvgSvgElement);
+      expect(
+          el.innerHtml,
+          anyOf([
+            "<circle></circle><path></path>",
+            '<circle '
+                'xmlns="http://www.w3.org/2000/svg" /><path '
+                'xmlns="http://www.w3.org/2000/svg" />'
+          ]));
+      expect(
+          el.outerHtml,
+          anyOf([
+            svgContent,
+            '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">\n  '
+                '<circle />\n  <path />\n</svg>'
+          ]));
+    });
+
+    test('has no parent',
+        () => expect(new svg.SvgElement.svg('<circle/>').parent, isNull));
+
+    test('empty', () {
+      expect(() => new svg.SvgElement.svg(""), throwsStateError);
+    });
+
+    test('too many elements', () {
+      expect(() => new svg.SvgElement.svg("<circle></circle><path></path>"),
+          throwsStateError);
+    });
+  });
+
+  // Unfortunately, because the filtering mechanism in unittest is a regex done
+  group('supported_animate', () {
+    test('supported', () {
+      expect(svg.AnimateElement.supported, true);
+    });
+  });
+
+  group('supported_animateMotion', () {
+    test('supported', () {
+      expect(svg.AnimateMotionElement.supported, true);
+    });
+  });
+
+  group('supported_animateTransform', () {
+    test('supported', () {
+      expect(svg.AnimateTransformElement.supported, true);
+    });
+  });
+
+  group('supported_feBlend', () {
+    test('supported', () {
+      expect(svg.FEBlendElement.supported, true);
+    });
+  });
+
+  group('supported_feColorMatrix', () {
+    test('supported', () {
+      expect(svg.FEColorMatrixElement.supported, true);
+    });
+  });
+
+  group('supported_feComponentTransfer', () {
+    test('supported', () {
+      expect(svg.FEComponentTransferElement.supported, true);
+    });
+  });
+
+  group('supported_feConvolveMatrix', () {
+    test('supported', () {
+      expect(svg.FEConvolveMatrixElement.supported, true);
+    });
+  });
+
+  group('supported_feDiffuseLighting', () {
+    test('supported', () {
+      expect(svg.FEDiffuseLightingElement.supported, true);
+    });
+  });
+
+  group('supported_feDisplacementMap', () {
+    test('supported', () {
+      expect(svg.FEDisplacementMapElement.supported, true);
+    });
+  });
+
+  group('supported_feDistantLight', () {
+    test('supported', () {
+      expect(svg.FEDistantLightElement.supported, true);
+    });
+  });
+
+  group('supported_feFlood', () {
+    test('supported', () {
+      expect(svg.FEFloodElement.supported, true);
+    });
+  });
+
+  group('supported_feFuncA', () {
+    test('supported', () {
+      expect(svg.FEFuncAElement.supported, true);
+    });
+  });
+
+  group('supported_feFuncB', () {
+    test('supported', () {
+      expect(svg.FEFuncBElement.supported, true);
+    });
+  });
+
+  group('supported_feFuncG', () {
+    test('supported', () {
+      expect(svg.FEFuncGElement.supported, true);
+    });
+  });
+
+  group('supported_feFuncR', () {
+    test('supported', () {
+      expect(svg.FEFuncRElement.supported, true);
+    });
+  });
+
+  group('supported_feGaussianBlur', () {
+    test('supported', () {
+      expect(svg.FEGaussianBlurElement.supported, true);
+    });
+  });
+
+  group('supported_feImage', () {
+    test('supported', () {
+      expect(svg.FEImageElement.supported, true);
+    });
+  });
+
+  group('supported_feMerge', () {
+    test('supported', () {
+      expect(svg.FEMergeElement.supported, true);
+    });
+  });
+
+  group('supported_feMergeNode', () {
+    test('supported', () {
+      expect(svg.FEMergeNodeElement.supported, true);
+    });
+  });
+
+  group('supported_feOffset', () {
+    test('supported', () {
+      expect(svg.FEOffsetElement.supported, true);
+    });
+  });
+
+  group('supported_feComponentTransfer', () {
+    test('supported', () {
+      expect(svg.FEPointLightElement.supported, true);
+    });
+  });
+
+  group('supported_feSpecularLighting', () {
+    test('supported', () {
+      expect(svg.FESpecularLightingElement.supported, true);
+    });
+  });
+
+  group('supported_feComponentTransfer', () {
+    test('supported', () {
+      expect(svg.FESpotLightElement.supported, true);
+    });
+  });
+
+  group('supported_feTile', () {
+    test('supported', () {
+      expect(svg.FETileElement.supported, true);
+    });
+  });
+
+  group('supported_feTurbulence', () {
+    test('supported', () {
+      expect(svg.FETurbulenceElement.supported, true);
+    });
+  });
+
+  group('supported_filter', () {
+    test('supported', () {
+      expect(svg.FilterElement.supported, true);
+    });
+  });
+
+  group('supported_foreignObject', () {
+    test('supported', () {
+      expect(svg.ForeignObjectElement.supported, true);
+    });
+  });
+
+  group('supported_set', () {
+    test('supported', () {
+      expect(svg.SetElement.supported, true);
+    });
+  });
+
+  group('constructors', () {
+    testConstructor('a', (e) => e is svg.AElement);
+    testConstructor('circle', (e) => e is svg.CircleElement);
+    testConstructor('clipPath', (e) => e is svg.ClipPathElement);
+    testConstructor('defs', (e) => e is svg.DefsElement);
+    testConstructor('desc', (e) => e is svg.DescElement);
+    testConstructor('ellipse', (e) => e is svg.EllipseElement);
+    testConstructor('g', (e) => e is svg.GElement);
+    testConstructor('image', (e) => e is svg.ImageElement);
+    testConstructor('line', (e) => e is svg.LineElement);
+    testConstructor('linearGradient', (e) => e is svg.LinearGradientElement);
+    testConstructor('marker', (e) => e is svg.MarkerElement);
+    testConstructor('mask', (e) => e is svg.MaskElement);
+    testConstructor('path', (e) => e is svg.PathElement);
+    testConstructor('pattern', (e) => e is svg.PatternElement);
+    testConstructor('polygon', (e) => e is svg.PolygonElement);
+    testConstructor('polyline', (e) => e is svg.PolylineElement);
+    testConstructor('radialGradient', (e) => e is svg.RadialGradientElement);
+    testConstructor('rect', (e) => e is svg.RectElement);
+    test('script', () {
+      expect(new svg.SvgElement.tag('script') is svg.ScriptElement, isTrue);
+    });
+    testConstructor('stop', (e) => e is svg.StopElement);
+    testConstructor('style', (e) => e is svg.StyleElement);
+    testConstructor('switch', (e) => e is svg.SwitchElement);
+    testConstructor('symbol', (e) => e is svg.SymbolElement);
+    testConstructor('tspan', (e) => e is svg.TSpanElement);
+    testConstructor('text', (e) => e is svg.TextElement);
+    testConstructor('textPath', (e) => e is svg.TextPathElement);
+    testConstructor('title', (e) => e is svg.TitleElement);
+    testConstructor('use', (e) => e is svg.UseElement);
+    testConstructor('view', (e) => e is svg.ViewElement);
+    // TODO(alanknight): Issue 23144
+    testConstructor('animate', (e) => e is svg.AnimateElement,
+        svg.AnimateElement.supported);
+    testConstructor('animateMotion', (e) => e is svg.AnimateMotionElement,
+        svg.AnimateMotionElement.supported);
+    testConstructor('animateTransform', (e) => e is svg.AnimateTransformElement,
+        svg.AnimateTransformElement.supported);
+    testConstructor('feBlend', (e) => e is svg.FEBlendElement,
+        svg.FEBlendElement.supported);
+    testConstructor('feColorMatrix', (e) => e is svg.FEColorMatrixElement,
+        svg.FEColorMatrixElement.supported);
+    testConstructor(
+        'feComponentTransfer',
+        (e) => e is svg.FEComponentTransferElement,
+        svg.FEComponentTransferElement.supported);
+    testConstructor('feConvolveMatrix', (e) => e is svg.FEConvolveMatrixElement,
+        svg.FEConvolveMatrixElement.supported);
+    testConstructor(
+        'feDiffuseLighting',
+        (e) => e is svg.FEDiffuseLightingElement,
+        svg.FEDiffuseLightingElement.supported);
+    testConstructor(
+        'feDisplacementMap',
+        (e) => e is svg.FEDisplacementMapElement,
+        svg.FEDisplacementMapElement.supported);
+    testConstructor('feDistantLight', (e) => e is svg.FEDistantLightElement,
+        svg.FEDistantLightElement.supported);
+    testConstructor('feFlood', (e) => e is svg.FEFloodElement,
+        svg.FEFloodElement.supported);
+    testConstructor('feFuncA', (e) => e is svg.FEFuncAElement,
+        svg.FEFuncAElement.supported);
+    testConstructor('feFuncB', (e) => e is svg.FEFuncBElement,
+        svg.FEFuncBElement.supported);
+    testConstructor('feFuncG', (e) => e is svg.FEFuncGElement,
+        svg.FEFuncGElement.supported);
+    testConstructor('feFuncR', (e) => e is svg.FEFuncRElement,
+        svg.FEFuncRElement.supported);
+    testConstructor('feGaussianBlur', (e) => e is svg.FEGaussianBlurElement,
+        svg.FEGaussianBlurElement.supported);
+    testConstructor('feImage', (e) => e is svg.FEImageElement,
+        svg.FEImageElement.supported);
+    testConstructor('feMerge', (e) => e is svg.FEMergeElement,
+        svg.FEMergeElement.supported);
+    testConstructor('feMergeNode', (e) => e is svg.FEMergeNodeElement,
+        svg.FEMergeNodeElement.supported);
+    testConstructor('feOffset', (e) => e is svg.FEOffsetElement,
+        svg.FEOffsetElement.supported);
+    testConstructor('fePointLight', (e) => e is svg.FEPointLightElement,
+        svg.FEPointLightElement.supported);
+    testConstructor(
+        'feSpecularLighting',
+        (e) => e is svg.FESpecularLightingElement,
+        svg.FESpecularLightingElement.supported);
+    testConstructor('feSpotLight', (e) => e is svg.FESpotLightElement,
+        svg.FESpotLightElement.supported);
+    testConstructor(
+        'feTile', (e) => e is svg.FETileElement, svg.FETileElement.supported);
+    testConstructor('feTurbulence', (e) => e is svg.FETurbulenceElement,
+        svg.FETurbulenceElement.supported);
+    testConstructor(
+        'filter', (e) => e is svg.FilterElement, svg.FilterElement.supported);
+    testConstructor('foreignObject', (e) => e is svg.ForeignObjectElement,
+        svg.ForeignObjectElement.supported, false);
+    testConstructor('metadata', (e) => e is svg.MetadataElement);
+    testConstructor(
+        'set', (e) => e is svg.SetElement, svg.SetElement.supported);
+  });
+
+  group('outerHtml', () {
+    test('outerHtml', () {
+      final el = new svg.SvgSvgElement();
+      el.children.add(new svg.CircleElement());
+      el.children.add(new svg.PathElement());
+      expect(
+          [
+            '<svg version="1.1"><circle></circle><path></path></svg>',
+            '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">'
+                '<circle /><path /></svg>',
+          ].contains(el.outerHtml),
+          true);
+    });
+  });
+
+  group('innerHtml', () {
+    test('get', () {
+      final el = new svg.SvgSvgElement();
+      el.children.add(new svg.CircleElement());
+      el.children.add(new svg.PathElement());
+      // Allow for odd IE serialization.
+      expect(
+          [
+            '<circle></circle><path></path>',
+            '<circle xmlns="http://www.w3.org/2000/svg" />'
+                '<path xmlns="http://www.w3.org/2000/svg" />'
+          ].contains(el.innerHtml),
+          true);
+    });
+
+    test('set', () {
+      final el = new svg.SvgSvgElement();
+      el.children.add(new svg.CircleElement());
+      el.children.add(new svg.PathElement());
+      el.innerHtml = '<rect></rect><a></a>';
+      expect(_nodeStrings(el.children), ["rect", "a"]);
+    });
+  });
+
+  group('elementget', () {
+    test('get', () {
+      final el = new svg.SvgElement.svg("""
+<svg version="1.1">
+  <circle></circle>
+  <path></path>
+  text
+</svg>""");
+      expect(_nodeStrings(el.children), ["circle", "path"]);
+    });
+
+    test('resize', () {
+      var el = new svg.SvgSvgElement();
+      var items = [new svg.CircleElement(), new svg.RectElement()];
+      el.children = items;
+      expect(el.children.length, 2);
+      el.children.length = 1;
+      expect(el.children.length, 1);
+      expect(el.children.contains(items[0]), true);
+      expect(el.children.contains(items[1]), false);
+
+      el.children.length = 0;
+      expect(el.children.contains(items[0]), false);
+    });
+  });
+
+  group('elementset', () {
+    test('set', () {
+      final el = new svg.SvgSvgElement();
+      el.children = [
+        new svg.SvgElement.tag("circle"),
+        new svg.SvgElement.tag("path")
+      ];
+      expect(el.nodes.length, 2);
+      expect(el.nodes[0] is svg.CircleElement, true);
+      expect(el.nodes[1] is svg.PathElement, true);
+    });
+  });
+
+  group('css', () {
+    test('classes', () {
+      var el = new svg.CircleElement();
+      var classes = el.classes;
+      expect(el.classes.length, 0);
+      classes.toggle('foo');
+      expect(el.classes.length, 1);
+      classes.toggle('foo');
+      expect(el.classes.length, 0);
+    });
+
+    test('classes-add-bad', () {
+      var el = new svg.CircleElement();
+      expect(() => el.classes.add(''), throws);
+      expect(() => el.classes.add('foo bar'), throws);
+    });
+    test('classes-remove-bad', () {
+      var el = new svg.CircleElement();
+      expect(() => el.classes.remove(''), throws);
+      expect(() => el.classes.remove('foo bar'), throws);
+    });
+    test('classes-toggle-token', () {
+      var el = new svg.CircleElement();
+      expect(() => el.classes.toggle(''), throws);
+      expect(() => el.classes.toggle('', true), throws);
+      expect(() => el.classes.toggle('', false), throws);
+      expect(() => el.classes.toggle('foo bar'), throws);
+      expect(() => el.classes.toggle('foo bar', true), throws);
+      expect(() => el.classes.toggle('foo bar', false), throws);
+    });
+    test('classes-contains-bad', () {
+      var el = new svg.CircleElement();
+      // Non-strings => false, strings must be valid tokens.
+      expect(el.classes.contains(1), isFalse);
+      expect(() => el.classes.contains(''), throws);
+      expect(() => el.classes.contains('foo bar'), throws);
+    });
+  });
+
+  group('getBoundingClientRect', () {
+    test('is a Rectangle', () {
+      var element = new svg.RectElement();
+      element.attributes['width'] = '100';
+      element.attributes['height'] = '100';
+      var root = new svg.SvgSvgElement();
+      root.append(element);
+
+      document.body!.append(root);
+
+      var rect = element.getBoundingClientRect();
+      expect(rect is Rectangle, isTrue);
+      expect(rect.width, closeTo(100, 1));
+      expect(rect.height, closeTo(100, 1));
+    });
+  });
+}
diff --git a/tests/lib/html/table_test.dart b/tests/lib/html/table_test.dart
new file mode 100644
index 0000000..cb7a4e2
--- /dev/null
+++ b/tests/lib/html/table_test.dart
@@ -0,0 +1,57 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('createTBody', () {
+    var table = new TableElement();
+    var head = table.createTHead();
+    expect(table.tHead, head);
+
+    var headerRow = head.addRow();
+    var headerCell = headerRow.addCell();
+    headerCell.text = 'Header Cell';
+
+    var caption = table.createCaption();
+    expect(table.caption, caption);
+
+    var body = table.createTBody();
+    expect(table.tBodies.length, 1);
+    expect(table.tBodies[0], body);
+
+    var bodyRow = body.addRow();
+    expect(body.rows.length, 1);
+    expect(body.rows[0], bodyRow);
+
+    var bodyCell = bodyRow.addCell();
+    bodyCell.text = 'Body Cell';
+    expect(bodyRow.cells.length, 1);
+    expect(bodyRow.cells[0], bodyCell);
+
+    var foot = table.createTFoot();
+    expect(table.tFoot, foot);
+
+    var footerRow = foot.addRow();
+    expect(foot.rows.length, 1);
+    expect(foot.rows[0], footerRow);
+
+    var footerCell = footerRow.addCell();
+    footerCell.text = 'Footer Cell';
+    expect(footerRow.cells.length, 1);
+    expect(footerRow.cells[0], footerCell);
+
+    var body2 = table.createTBody();
+    var bodyRow2 = body2.addRow();
+    var bodyCell2 = bodyRow2.addCell();
+    bodyCell2.text = 'Body Cell2';
+
+    expect(body2.rows.length, 1);
+
+    expect(table.tBodies.length, 2);
+    expect(table.tBodies[1], body2);
+  });
+}
diff --git a/tests/lib/html/text_event_test.dart b/tests/lib/html/text_event_test.dart
new file mode 100644
index 0000000..26c7a2a
--- /dev/null
+++ b/tests/lib/html/text_event_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/minitest.dart';
+
+import 'event_test.dart';
+
+main() {
+  eventTest('TextEvent', () => new TextEvent('foo', view: window, data: 'data'),
+      (ev) {
+    expect(ev.data, 'data');
+  });
+}
diff --git a/tests/lib/html/touchevent_test.dart b/tests/lib/html/touchevent_test.dart
new file mode 100644
index 0000000..d91abb9
--- /dev/null
+++ b/tests/lib/html/touchevent_test.dart
@@ -0,0 +1,16 @@
+// 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:expect/minitest.dart';
+
+main() {
+  test('Basic TouchEvent', () {
+    if (TouchEvent.supported) {
+      var e = new TouchEvent('touch');
+      expect(e is TouchEvent, isTrue);
+    }
+  });
+}
diff --git a/tests/lib/html/track_element_constructor_test.dart b/tests/lib/html/track_element_constructor_test.dart
new file mode 100644
index 0000000..9fa006b
--- /dev/null
+++ b/tests/lib/html/track_element_constructor_test.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// A regression test for dart2js generating illegal JavaScript code
+// dynamically in non-csp mode.  The name of the field "defaultValue"
+// in JavaScript is "default".  This meant that dart2js would create a
+// constructor function that looked like this:
+//
+// function TrackElement(default) { this.default = default; }
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+void main() {
+  test('', () {
+    if (!TrackElement.supported) return;
+    document.body!.append(new TrackElement()..defaultValue = true);
+    var trackElement = document.querySelector('track') as TrackElement;
+    if (!trackElement.defaultValue) {
+      throw 'Expected default value to be true';
+    }
+    trackElement.defaultValue = false;
+    if (trackElement.defaultValue) {
+      throw 'Expected default value to be false';
+    }
+  });
+}
diff --git a/tests/lib/html/transferables_test.dart b/tests/lib/html/transferables_test.dart
new file mode 100644
index 0000000..1f51643
--- /dev/null
+++ b/tests/lib/html/transferables_test.dart
@@ -0,0 +1,31 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library TransferableTest;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+var isByteBuffer = predicate((x) => x is ByteBuffer, 'is an ByteBuffer');
+
+Future testTransferableTest() {
+  final buffer = (new Float32List(3)).buffer;
+  window.postMessage(
+      {'id': 'transferable data', 'buffer': buffer}, '*', [buffer]);
+
+  return window.onMessage.firstWhere((e) {
+    return e.data is Map && e.data['id'] == 'transferable data';
+  }).then((messageEvent) {
+    expect(messageEvent.data['buffer'], isByteBuffer);
+  });
+}
+
+main() async {
+  if (Platform.supportsTypedData) {
+    await testTransferableTest();
+  }
+}
diff --git a/tests/lib/html/transition_event_test.dart b/tests/lib/html/transition_event_test.dart
new file mode 100644
index 0000000..4376016
--- /dev/null
+++ b/tests/lib/html/transition_event_test.dart
@@ -0,0 +1,41 @@
+// 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 transition_event_test;
+
+import 'dart:html';
+import 'dart:async';
+
+import 'package:expect/minitest.dart';
+
+Future testTransitionEnd() async {
+  var element = new DivElement();
+  document.body!.append(element);
+
+  element.style.opacity = '0';
+  element.style.width = '100px';
+  element.style.height = '100px';
+  element.style.background = 'red';
+  element.style.transition = 'opacity .1s';
+
+  final done = new Completer();
+
+  new Timer(const Duration(milliseconds: 100), () {
+    element.onTransitionEnd.first.then((e) {
+      expect(e is TransitionEvent, isTrue);
+      expect(e.propertyName, 'opacity');
+    }).then(done.complete, onError: done.completeError);
+
+    element.style.opacity = '1';
+  });
+
+  await done.future;
+}
+
+main() async {
+  expect(CssStyleDeclaration.supportsTransitions, isTrue);
+  if (CssStyleDeclaration.supportsTransitions) {
+    await testTransitionEnd();
+  }
+}
diff --git a/tests/lib/html/trusted_html_tree_sanitizer_test.dart b/tests/lib/html/trusted_html_tree_sanitizer_test.dart
new file mode 100644
index 0000000..a0d92ed
--- /dev/null
+++ b/tests/lib/html/trusted_html_tree_sanitizer_test.dart
@@ -0,0 +1,61 @@
+// 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.
+
+/// This tests HTML validation and sanitization, which is very important
+/// for prevent XSS or other attacks. If you suppress this, or parts of it
+/// please make it a critical bug and bring it to the attention of the
+/// dart:html maintainers.
+import 'dart:js' as js;
+import 'dart:html';
+import 'dart:svg' as svg;
+
+import 'package:expect/minitest.dart';
+
+import 'utils.dart';
+
+var oldAdoptNode;
+var jsDocument;
+
+/// We want to verify that with the trusted sanitizer we are not
+/// creating a document fragment. So make DocumentFragment operation
+/// throw.
+makeDocumentFragmentAdoptionThrow() {
+  var document = js.context['document'];
+  jsDocument = new js.JsObject.fromBrowserObject(document);
+  oldAdoptNode = jsDocument['adoptNode'];
+  jsDocument['adoptNode'] = null;
+}
+
+restoreOldAdoptNode() {
+  jsDocument['adoptNode'] = oldAdoptNode;
+}
+
+main() {
+  group('not_create_document_fragment', () {
+    setUp(makeDocumentFragmentAdoptionThrow);
+    tearDown(restoreOldAdoptNode);
+
+    test('setInnerHtml', () {
+      document.body!.setInnerHtml('<div foo="baz">something</div>',
+          treeSanitizer: NodeTreeSanitizer.trusted);
+      expect(document.body!.innerHtml, '<div foo="baz">something</div>');
+    });
+
+    test("appendHtml", () {
+      var oldStuff = document.body!.innerHtml;
+      var newStuff = '<div rumplestiltskin="value">content</div>';
+      document.body!
+          .appendHtml(newStuff, treeSanitizer: NodeTreeSanitizer.trusted);
+      expect(document.body!.innerHtml, oldStuff + newStuff);
+    });
+  });
+
+  group('untrusted', () {
+    setUp(makeDocumentFragmentAdoptionThrow);
+    tearDown(restoreOldAdoptNode);
+    test('untrusted', () {
+      expect(() => document.body!.innerHtml = "<p>anything</p>", throws);
+    });
+  });
+}
diff --git a/tests/lib/html/typed_arrays_1_test.dart b/tests/lib/html/typed_arrays_1_test.dart
new file mode 100644
index 0000000..c624c62
--- /dev/null
+++ b/tests/lib/html/typed_arrays_1_test.dart
@@ -0,0 +1,71 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isList = predicate((x) => x is List, 'is a List');
+  var isNumList = predicate((x) => x is List<num>, 'is a List<num>');
+  var isNotStringList =
+      predicate((x) => x is! List<String>, 'is not a List<String>');
+  var expectation = Platform.supportsTypedData ? returnsNormally : throws;
+
+  group('supported', () {
+    test('supported', () {
+      expect(Platform.supportsTypedData, true);
+    });
+  });
+
+  group('arrays', () {
+    test('createByLengthTest', () {
+      expect(() {
+        var a = new Float32List(10);
+        expect(a.length, 10);
+        expect(a.lengthInBytes, 40);
+        expect(a[4], 0);
+      }, expectation);
+    });
+
+    test('aliasTest', () {
+      expect(() {
+        var a1 = new Uint8List.fromList([0, 0, 1, 0x45]);
+        var a2 = new Float32List.view(a1.buffer);
+
+        expect(a1.lengthInBytes, a2.lengthInBytes);
+
+        expect(a2.length, 1);
+
+        // 0x45010000 = 2048+16
+        expect(a2[0], 2048 + 16);
+
+        a1[2] = 0;
+        // 0x45000000 = 2048
+        expect(a2[0], 2048);
+
+        a1[3]--;
+        a1[2] += 128;
+        // 0x44800000 = 1024
+        expect(a2[0], 1024);
+      }, expectation);
+    });
+
+    // Generic type checking is not available in dart2js, so use this check to
+    // see if we should check for it.
+    var supportsTypeTest = !(new List<String>.empty() is List<int>);
+
+    if (supportsTypeTest) {
+      test('typeTests', () {
+        expect(() {
+          var a = new Float32List(10);
+          expect(a, isList);
+          expect(a, isNumList);
+          expect(a, isNotStringList);
+        }, expectation);
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/typed_arrays_2_test.dart b/tests/lib/html/typed_arrays_2_test.dart
new file mode 100644
index 0000000..51bd8c7
--- /dev/null
+++ b/tests/lib/html/typed_arrays_2_test.dart
@@ -0,0 +1,83 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('viewTest_dynamic', () {
+    var a1 = new Uint8List(1024);
+    for (int i = 0; i < a1.length; i++) {
+      a1[i] = i; // 0,1,2,...,254,255,0,1,2,...
+    }
+
+    var a2 = new Uint32List.view(a1.buffer);
+    expect(1024 ~/ 4, a2.length);
+    expect(a2[0], 0x03020100);
+    expect(a2[1], 0x07060504);
+    expect(a2[2], 0x0B0A0908);
+    expect(a2[50], 0xCBCAC9C8);
+    expect(a2[51], 0xCFCECDCC);
+    expect(a2[64], 0x03020100);
+
+    a2 = new Uint32List.view(a1.buffer, 200);
+    expect(a2.length, (1024 - 200) ~/ 4);
+    expect(a2[0], 0xCBCAC9C8);
+    expect(a2[1], 0xCFCECDCC);
+    expect(a2[14], 0x03020100);
+
+    a2 = new Uint32List.view(a1.buffer, 456, 20);
+    expect(a2.length, 20);
+    expect(a2[0], 0xCBCAC9C8);
+    expect(a2[1], 0xCFCECDCC);
+    expect(a2[14], 0x03020100);
+
+    // OPTIONALS a2 = new Uint32List.view(a1.buffer, length: 30, byteOffset: 456);
+    a2 = new Uint32List.view(a1.buffer, 456, 30);
+    expect(a2.length, 30);
+    expect(a2[0], 0xCBCAC9C8);
+    expect(a2[1], 0xCFCECDCC);
+    expect(a2[14], 0x03020100);
+  });
+
+  test('viewTest_typed', () {
+    Uint8List a1 = new Uint8List(1024);
+    for (int i = 0; i < a1.length; i++) {
+      a1[i] = i;
+    }
+
+    Uint32List a2 = new Uint32List.view(a1.buffer);
+    expect(a2.length, 1024 ~/ 4);
+    expect(a2[0], 0x03020100);
+    expect(a2[50], 0xCBCAC9C8);
+    expect(a2[51], 0xCFCECDCC);
+    expect(a2[64], 0x03020100);
+
+    a2 = new Uint32List.view(a1.buffer, 200);
+    expect(a2.length, (1024 - 200) ~/ 4);
+    expect(a2[0], 0xCBCAC9C8);
+    expect(a2[1], 0xCFCECDCC);
+    expect(a2[14], 0x03020100);
+
+    a2 = new Uint32List.view(a1.buffer, 456, 20);
+    expect(20, a2.length);
+    expect(a2[0], 0xCBCAC9C8);
+    expect(a2[1], 0xCFCECDCC);
+    expect(a2[14], 0x03020100);
+
+    // OPTIONALS a2 = new Uint32List.view(a1.buffer, length: 30, byteOffset: 456);
+    a2 = new Uint32List.view(a1.buffer, 456, 30);
+    expect(a2.length, 30);
+    expect(a2[0], 0xCBCAC9C8);
+    expect(a2[1], 0xCFCECDCC);
+    expect(a2[14], 0x03020100);
+  });
+}
diff --git a/tests/lib/html/typed_arrays_3_test.dart b/tests/lib/html/typed_arrays_3_test.dart
new file mode 100644
index 0000000..7a07f86
--- /dev/null
+++ b/tests/lib/html/typed_arrays_3_test.dart
@@ -0,0 +1,43 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('setElementsTest_dynamic', () {
+    var a1 = new Int8List(1024);
+
+    a1.setRange(4, 7, [0x50, 0x60, 0x70]);
+
+    var a2 = new Uint32List.view(a1.buffer);
+    expect(a2[0], 0x00000000);
+    expect(a2[1], 0x00706050);
+
+    a2.setRange(2, 3, [0x01020304]);
+    expect(a1[8], 0x04);
+    expect(a1[11], 0x01);
+  });
+
+  test('setElementsTest_typed', () {
+    Int8List a1 = new Int8List(1024);
+
+    a1.setRange(4, 7, [0x50, 0x60, 0x70]);
+
+    Uint32List a2 = new Uint32List.view(a1.buffer);
+    expect(a2[0], 0x00000000);
+    expect(a2[1], 0x00706050);
+
+    a2.setRange(2, 3, [0x01020304]);
+    expect(a1[8], 0x04);
+    expect(a1[11], 0x01);
+  });
+}
diff --git a/tests/lib/html/typed_arrays_4_test.dart b/tests/lib/html/typed_arrays_4_test.dart
new file mode 100644
index 0000000..ba8ee16
--- /dev/null
+++ b/tests/lib/html/typed_arrays_4_test.dart
@@ -0,0 +1,45 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('indexOf_dynamic', () {
+    var a1 = new Uint8List(1024);
+    for (int i = 0; i < a1.length; i++) {
+      a1[i] = i;
+    }
+
+    expect(a1.indexOf(50), 50);
+    expect(a1.indexOf(50, 50), 50);
+    expect(a1.indexOf(50, 51), 256 + 50);
+
+    expect(a1.lastIndexOf(50), 768 + 50);
+    expect(a1.lastIndexOf(50, 768 + 50), 768 + 50);
+    expect(a1.lastIndexOf(50, 768 + 50 - 1), 512 + 50);
+  });
+
+  test('indexOf_typed', () {
+    Uint8List a1 = new Uint8List(1024);
+    for (int i = 0; i < a1.length; i++) {
+      a1[i] = i;
+    }
+
+    expect(a1.indexOf(50), 50);
+    expect(a1.indexOf(50, 50), 50);
+    expect(a1.indexOf(50, 51), 256 + 50);
+
+    expect(a1.lastIndexOf(50), 768 + 50);
+    expect(a1.lastIndexOf(50, 768 + 50), 768 + 50);
+    expect(a1.lastIndexOf(50, 768 + 50 - 1), 512 + 50);
+  });
+}
diff --git a/tests/lib/html/typed_arrays_5_test.dart b/tests/lib/html/typed_arrays_5_test.dart
new file mode 100644
index 0000000..e7b1e9b
--- /dev/null
+++ b/tests/lib/html/typed_arrays_5_test.dart
@@ -0,0 +1,47 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('filter_dynamic', () {
+    var a = new Float32List(1024);
+    for (int i = 0; i < a.length; i++) {
+      a[i] = i.toDouble();
+    }
+
+    expect(a.where((x) => x >= 1000).length, equals(24));
+  });
+
+  test('filter_typed', () {
+    Float32List a = new Float32List(1024);
+    for (int i = 0; i < a.length; i++) {
+      a[i] = i.toDouble();
+    }
+
+    expect(a.where((x) => x >= 1000).length, equals(24));
+  });
+
+  test('contains', () {
+    var a = new Int16List(1024);
+    for (int i = 0; i < a.length; i++) {
+      a[i] = i;
+    }
+    expect(a.contains(0), isTrue);
+    expect(a.contains(5), isTrue);
+    expect(a.contains(1023), isTrue);
+
+    expect(a.contains(-5), isFalse);
+    expect(a.contains(-1), isFalse);
+    expect(a.contains(1024), isFalse);
+  });
+}
diff --git a/tests/lib/html/typed_arrays_arraybuffer_test.dart b/tests/lib/html/typed_arrays_arraybuffer_test.dart
new file mode 100644
index 0000000..784a9e2
--- /dev/null
+++ b/tests/lib/html/typed_arrays_arraybuffer_test.dart
@@ -0,0 +1,41 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('constructor', () {
+    var a = new Int8List(100);
+    expect(a.lengthInBytes, 100);
+  });
+
+  test('sublist1', () {
+    var a = new Int8List(100);
+    var s = a.sublist(10, 40);
+    expect(s.length, 30);
+  });
+
+  test('sublist2', () {
+    var a = new Int8List(100);
+    expect(() => a.sublist(10, 400), throwsRangeError);
+  });
+
+  test('sublist3', () {
+    var a = new Int8List(100);
+    expect(() => a.sublist(50, 10), throwsRangeError);
+  });
+
+  test('sublist4', () {
+    var a = new Int8List(100);
+    expect(() => a.sublist(-90, -30), throwsRangeError);
+  });
+}
diff --git a/tests/lib/html/typed_arrays_dataview_test.dart b/tests/lib/html/typed_arrays_dataview_test.dart
new file mode 100644
index 0000000..e774a6d
--- /dev/null
+++ b/tests/lib/html/typed_arrays_dataview_test.dart
@@ -0,0 +1,88 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('create', () {
+    var bd = new ByteData(100);
+    expect(bd.lengthInBytes, 100);
+    expect(bd.offsetInBytes, 0);
+
+    var a1 = new Uint8List.fromList([1, 2, 3, 4, 5, 6, 7, 8]);
+
+    var bd2 = new ByteData.view(a1.buffer);
+    expect(bd2.lengthInBytes, 8);
+    expect(bd2.offsetInBytes, 0);
+
+    var bd3 = new ByteData.view(a1.buffer, 2);
+    expect(bd3.lengthInBytes, 6);
+    expect(bd3.offsetInBytes, 2);
+
+    var bd4 = new ByteData.view(a1.buffer, 3, 4);
+    expect(bd4.lengthInBytes, 4);
+    expect(bd4.offsetInBytes, 3);
+  });
+
+  test('access8', () {
+    var a1 = new Uint8List.fromList([0, 0, 3, 255, 0, 0, 0, 0, 0, 0]);
+
+    var bd = new ByteData.view(a1.buffer, 2, 6);
+
+    expect(bd.getInt8(0), equals(3));
+    expect(bd.getInt8(1), equals(-1));
+    expect(bd.getUint8(0), equals(3));
+    expect(bd.getUint8(1), equals(255));
+
+    bd.setInt8(2, -56);
+    expect(bd.getInt8(2), equals(-56));
+    expect(bd.getUint8(2), equals(200));
+
+    bd.setUint8(3, 200);
+    expect(bd.getInt8(3), equals(-56));
+    expect(bd.getUint8(3), equals(200));
+  });
+
+  test('access16', () {
+    var a1 = new Uint8List.fromList([0, 0, 3, 255, 0, 0, 0, 0, 0, 0]);
+
+    var bd = new ByteData.view(a1.buffer, 2);
+
+    expect(bd.lengthInBytes, equals(10 - 2));
+
+    expect(bd.getInt16(0), equals(1023));
+    expect(bd.getInt16(0, Endian.big), equals(1023));
+    expect(bd.getInt16(0, Endian.little), equals(-253));
+
+    expect(bd.getUint16(0), equals(1023));
+    expect(bd.getUint16(0, Endian.big), equals(1023));
+    expect(bd.getUint16(0, Endian.little), equals(0xFF03));
+
+    bd.setInt16(2, -1);
+    expect(bd.getInt16(2), equals(-1));
+    expect(bd.getUint16(2), equals(0xFFFF));
+  });
+
+  test('access32', () {
+    var a1 = new Uint8List.fromList([0, 0, 3, 255, 0, 0, 0, 0, 0, 0]);
+
+    var bd = new ByteData.view(a1.buffer);
+
+    expect(bd.getInt32(0), equals(1023));
+    expect(bd.getInt32(0, Endian.big), equals(1023));
+    expect(bd.getInt32(0, Endian.little), equals(-0xFD0000));
+
+    expect(bd.getUint32(0), equals(1023));
+    expect(bd.getUint32(0, Endian.big), equals(1023));
+    expect(bd.getUint32(0, Endian.little), equals(0xFF030000));
+  });
+}
diff --git a/tests/lib/html/typed_arrays_range_checks_test.dart b/tests/lib/html/typed_arrays_range_checks_test.dart
new file mode 100644
index 0000000..f6d8dbf
--- /dev/null
+++ b/tests/lib/html/typed_arrays_range_checks_test.dart
@@ -0,0 +1,54 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+const N = 1024;
+
+class _TestList {
+  _TestList(int n);
+
+  operator [](int i) => i;
+  operator []=(int i, v) {}
+}
+
+_obfuscatedList() {
+  var a = new Uint8List(N);
+  var b = new _TestList(N);
+  var k = 0;
+  for (int i = 0; i < 10; ++i) {
+    k += i;
+  }
+  return (k == 45) ? a : b;
+}
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('outOfRangeAccess', () {
+    var a = _obfuscatedList();
+
+    expect(() => a[a.length], throws);
+    expect(() => a[a.length + 1], throws);
+    expect(() => a[a.length + N], throws);
+
+    expect(() => a[-1], throws);
+    expect(() => a[1.5], throws);
+    expect(() => a['length'], throws);
+
+    expect(() => a[a.length] = 0xdeadbeef, throws);
+    expect(() => a[a.length + 1] = 0xdeadbeef, throws);
+    expect(() => a[a.length + N] = 0xdeadbeef, throws);
+
+    expect(() => a[-1] = 0xdeadbeef, throws);
+    expect(() => a[1.5] = 0xdeadbeef, throws);
+    expect(() => a['length'] = 1, throws);
+  });
+}
diff --git a/tests/lib/html/typed_arrays_simd_test.dart b/tests/lib/html/typed_arrays_simd_test.dart
new file mode 100644
index 0000000..3f4919a
--- /dev/null
+++ b/tests/lib/html/typed_arrays_simd_test.dart
@@ -0,0 +1,82 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+const _FLOATING_POINT_ERROR = 0.0000000001;
+floatEquals(value) => closeTo(value, _FLOATING_POINT_ERROR);
+
+class MyFloat32x4 {
+  num x = 0.0;
+  num y = 0.0;
+  num z = 0.0;
+  num w = 0.0;
+}
+
+main() {
+  // Only perform tests if ArrayBuffer is supported.
+  if (!Platform.supportsTypedData) {
+    return;
+  }
+
+  test('test Float32x4', () {
+    if (Platform.supportsSimd) {
+      final val = new Float32x4(1.0, 2.0, 3.0, 4.0);
+      expect(val.x, floatEquals(1.0));
+      expect(val.y, floatEquals(2.0));
+      expect(val.z, floatEquals(3.0));
+      expect(val.w, floatEquals(4.0));
+      final val2 = val + val;
+      expect(val2.x, floatEquals(2.0));
+      expect(val2.y, floatEquals(4.0));
+      expect(val2.z, floatEquals(6.0));
+      expect(val2.w, floatEquals(8.0));
+    }
+  });
+
+  test('test Float32x4List', () {
+    var counter;
+    final list = new Float32List(12);
+    for (int i = 0; i < list.length; ++i) {
+      list[i] = i * 1.0;
+    }
+    if (Platform.supportsSimd) {
+      counter = new Float32x4.zero();
+      final simdlist = new Float32x4List.view(list.buffer);
+      for (int i = 0; i < simdlist.length; ++i) {
+        counter += simdlist[i];
+      }
+    } else {
+      counter = new MyFloat32x4();
+      for (int i = 0; i < list.length; i += 4) {
+        counter.x += list[i];
+        counter.y += list[i + 1];
+        counter.z += list[i + 2];
+        counter.w += list[i + 3];
+      }
+    }
+    expect(counter.x, floatEquals(12.0));
+    expect(counter.y, floatEquals(15.0));
+    expect(counter.z, floatEquals(18.0));
+    expect(counter.w, floatEquals(21.0));
+  });
+
+  test('test Int32x4', () {
+    if (Platform.supportsSimd) {
+      final val = new Int32x4(1, 2, 3, 4);
+      expect(val.x, equals(1));
+      expect(val.y, equals(2));
+      expect(val.z, equals(3));
+      expect(val.w, equals(4));
+      final val2 = val ^ val;
+      expect(val2.x, equals(0));
+      expect(val2.y, equals(0));
+      expect(val2.z, equals(0));
+      expect(val2.w, equals(0));
+    }
+  });
+}
diff --git a/tests/lib/html/typing_test.dart b/tests/lib/html/typing_test.dart
new file mode 100644
index 0000000..9fa3628
--- /dev/null
+++ b/tests/lib/html/typing_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 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isStyleSheetList =
+      predicate((x) => x is List<StyleSheet>, 'is a List<StyleSheet>');
+
+  test('NodeList', () {
+    List<Element> asList = window.document.querySelectorAll('body');
+    // Check it's Iterable
+    int counter = 0;
+    for (Element node in window.document.querySelectorAll('body')) {
+      counter++;
+    }
+    expect(counter, 1);
+    counter = 0;
+    window.document.querySelectorAll('body').forEach((e) {
+      counter++;
+    });
+    expect(counter, 1);
+  });
+
+  test('StyleSheetList', () {
+    var document = window.document as HtmlDocument;
+    List<StyleSheet> asList = document.styleSheets;
+    expect(asList, isStyleSheetList);
+    // Check it's Iterable.
+    int counter = 0;
+    for (StyleSheet styleSheet in document.styleSheets) {
+      counter++;
+    }
+
+    // There is one style sheet from the test framework.
+    expect(counter, 1);
+  });
+}
diff --git a/tests/lib/html/unknownelement_test.dart b/tests/lib/html/unknownelement_test.dart
new file mode 100644
index 0000000..a964bb8
--- /dev/null
+++ b/tests/lib/html/unknownelement_test.dart
@@ -0,0 +1,33 @@
+// 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
+// BSD-style license that can be found in the LICENSE file
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var isUnknownElement =
+      predicate((x) => x is UnknownElement, 'is an UnknownELement');
+
+  dynamic foo = new Element.tag('foo');
+  foo.id = 'foo';
+  var bar = new Element.tag('bar');
+  bar.id = 'bar';
+  document.body!.nodes.addAll(<Node>[foo, bar]);
+
+  test('type-check', () {
+    expect(foo, isUnknownElement);
+    expect(bar, isUnknownElement);
+    expect(querySelector('#foo'), equals(foo));
+    expect(querySelector('#bar'), equals(bar));
+  });
+
+  test('dispatch-fail', () {
+    expect(() => foo.method1(), throwsNoSuchMethodError);
+    expect(() => foo.field1, throwsNoSuchMethodError);
+    expect(() {
+      foo.field1 = 42;
+    }, throwsNoSuchMethodError);
+  });
+}
diff --git a/tests/lib/html/uri_test.dart b/tests/lib/html/uri_test.dart
new file mode 100644
index 0000000..32ec865
--- /dev/null
+++ b/tests/lib/html/uri_test.dart
@@ -0,0 +1,14 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('Uri.base', () {
+    expect(Uri.base.scheme, "http");
+    expect(Uri.base.toString(), window.location.href);
+  });
+}
diff --git a/tests/lib/html/url_test.dart b/tests/lib/html/url_test.dart
new file mode 100644
index 0000000..201f523
--- /dev/null
+++ b/tests/lib/html/url_test.dart
@@ -0,0 +1,75 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library url_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:expect/minitest.dart';
+
+Blob createImageBlob() {
+  var canvas = new CanvasElement();
+  canvas.width = 100;
+  canvas.height = 100;
+
+  var context = canvas.context2D;
+  context.fillStyle = 'red';
+  context.fillRect(0, 0, canvas.width, canvas.height);
+
+  var dataUri = canvas.toDataUrl('image/png');
+  var byteString = window.atob(dataUri.split(',')[1]);
+  var mimeString = dataUri.split(',')[0].split(':')[1].split(';')[0];
+
+  var arrayBuffer = new Uint8List(byteString.length);
+  var dataArray = new Uint8List.view(arrayBuffer.buffer);
+  for (var i = 0; i < byteString.length; i++) {
+    dataArray[i] = byteString.codeUnitAt(i);
+  }
+
+  var blob = new Blob([arrayBuffer], 'image/png');
+  return blob;
+}
+
+Future testCreateObjectUrlFromBlob() async {
+  final done = new Completer();
+  var blob = createImageBlob();
+  var url = Url.createObjectUrlFromBlob(blob);
+  expect(url.length, greaterThan(0));
+  expect(url.startsWith('blob:'), isTrue);
+
+  var img = new ImageElement();
+  img.onLoad.listen((_) {
+    expect(img.complete, true);
+    done.complete();
+  });
+  img.onError.listen((_) {
+    fail('URL failed to load.');
+  });
+  img.src = url;
+  await done.future;
+}
+
+Future testRevokeObjectUrl() async {
+  final done = new Completer();
+  var blob = createImageBlob();
+  var url = Url.createObjectUrlFromBlob(blob);
+  expect(url.startsWith('blob:'), isTrue);
+  Url.revokeObjectUrl(url);
+
+  var img = new ImageElement();
+  // Image should fail to load since the URL was revoked.
+  img.onError.listen(done.complete);
+  img.onLoad.listen((_) {
+    fail('URL should not have loaded.');
+  });
+  img.src = url;
+  await done.future;
+}
+
+main() async {
+  await testCreateObjectUrlFromBlob();
+  await testRevokeObjectUrl();
+}
diff --git a/tests/lib/html/utils.dart b/tests/lib/html/utils.dart
new file mode 100644
index 0000000..8a6304a
--- /dev/null
+++ b/tests/lib/html/utils.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.
+
+/// The test runner for DDC does not handle tests that import files using
+/// relative imports that reach outside of the directory containing the test
+/// (i.e. "../" imports). Since tests both in this directory and in "custom/"
+/// use utils.dart, it needs to be accessible from both places.
+///
+/// We could have every test outside of "custom/" import "custom/utils.dart",
+/// but that feels weird since "utils.dart" doesn't have anything to do with
+/// custom elements.
+///
+/// Instead, it lives there, but is exported from here for the tests in this
+/// directory to import.
+// TODO(rnystrom): If the DDC test runner is fixed to use a different module
+// root that handles "../" imports, move "custom/utils.dart" to here.
+export 'custom/utils.dart';
diff --git a/tests/lib/html/webgl_1_test.dart b/tests/lib/html/webgl_1_test.dart
new file mode 100644
index 0000000..9c3b420
--- /dev/null
+++ b/tests/lib/html/webgl_1_test.dart
@@ -0,0 +1,115 @@
+// 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:typed_data';
+import 'dart:web_gl';
+import 'dart:web_gl' as gl;
+
+import 'package:expect/minitest.dart';
+
+// Test that WebGL is present in dart:web_gl API
+
+final isRenderingContext = predicate((x) => x is RenderingContext);
+final isContextAttributes = predicate((x) => x is Map);
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(RenderingContext.supported, isTrue);
+    });
+  });
+
+  group('functional', () {
+    test('unsupported fails', () {
+      var canvas = new CanvasElement();
+      var context = canvas.getContext3d();
+      if (RenderingContext.supported) {
+        expect(context, isNotNull);
+        expect(context, isRenderingContext);
+      } else {
+        expect(context, isNull);
+      }
+    });
+
+    if (RenderingContext.supported) {
+      test('simple', () {
+        var canvas = new CanvasElement();
+        var context =
+            canvas.getContext('experimental-webgl') as gl.RenderingContext;
+        var shader = context.createShader(gl.WebGL.VERTEX_SHADER);
+        context.shaderSource(shader, 'void main() { }');
+        context.compileShader(shader);
+        var success =
+            context.getShaderParameter(shader, gl.WebGL.COMPILE_STATUS);
+        expect(success, isTrue);
+      });
+
+      test('getContext3d', () {
+        var canvas = new CanvasElement();
+        var context = canvas.getContext3d();
+        expect(context, isNotNull);
+        expect(context, isRenderingContext);
+
+        context = canvas.getContext3d(depth: false);
+        expect(context, isNotNull);
+        expect(context, isRenderingContext);
+      });
+
+      test('texImage2D', () {
+        var canvas = new CanvasElement();
+        gl.RenderingContext context = canvas.getContext3d();
+        var pixels = new Uint8List.fromList([0, 0, 3, 255, 0, 0, 0, 0, 0, 0]);
+        context.texImage2D(1, 1, 1, 1, 10, 10, 1, 1, pixels);
+
+        canvas = new CanvasElement();
+        document.body!.children.add(canvas);
+        CanvasRenderingContext2D context2 =
+            canvas.getContext('2d') as CanvasRenderingContext2D;
+        context.texImage2D(
+            1, 1, 1, 1, 10, context2.getImageData(10, 10, 10, 10));
+
+        context.texImage2D(1, 1, 1, 1, 10, new ImageElement());
+        context.texImage2D(1, 1, 1, 1, 10, new CanvasElement());
+        context.texImage2D(1, 1, 1, 1, 10, new VideoElement());
+      });
+
+      test('texSubImage2D', () {
+        var canvas = new CanvasElement();
+        gl.RenderingContext context = canvas.getContext3d();
+        var pixels = new Uint8List.fromList([0, 0, 3, 255, 0, 0, 0, 0, 0, 0]);
+        context.texSubImage2D(1, 1, 1, 1, 1, 10, 10, 1, pixels);
+
+        canvas = new CanvasElement();
+        document.body!.children.add(canvas);
+        CanvasRenderingContext2D context2 =
+            canvas.getContext('2d') as CanvasRenderingContext2D;
+        context.texSubImage2D(
+            1, 1, 1, 1, 1, 10, context2.getImageData(10, 10, 10, 10));
+
+        context.texSubImage2D(1, 1, 1, 1, 1, 10, new ImageElement());
+        context.texSubImage2D(1, 1, 1, 1, 1, 10, new CanvasElement());
+        context.texSubImage2D(1, 1, 1, 1, 1, 10, new VideoElement());
+      });
+
+      test('getContextAttributes', () {
+        var canvas = new CanvasElement();
+        var context = canvas.getContext3d();
+        var attributes = context.getContextAttributes();
+
+        expect(attributes, isNotNull);
+        expect(attributes, isContextAttributes);
+
+        expect(attributes!['alpha'], isBoolean);
+        expect(attributes['antialias'], isBoolean);
+        expect(attributes['depth'], isBoolean);
+        expect(attributes['premultipliedAlpha'], isBoolean);
+        expect(attributes['preserveDrawingBuffer'], isBoolean);
+        expect(attributes['stencil'], isBoolean);
+      });
+    }
+  });
+}
+
+final isBoolean = predicate((v) => v == true || v == false);
diff --git a/tests/lib/html/webgl_extensions_test.dart b/tests/lib/html/webgl_extensions_test.dart
new file mode 100644
index 0000000..133cc7f
--- /dev/null
+++ b/tests/lib/html/webgl_extensions_test.dart
@@ -0,0 +1,205 @@
+// 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 web_gl_test;
+
+import 'dart:html';
+import 'dart:web_gl';
+
+import 'package:expect/minitest.dart';
+
+final isAngleInstancedArrays = (v) => v is AngleInstancedArrays;
+final isExtBlendMinMax = (v) => v is ExtBlendMinMax;
+final isExtFragDepth = (v) => v is ExtFragDepth;
+final isEXTsRgb = (v) => v is EXTsRgb;
+final isExtShaderTextureLod = (v) => v is ExtShaderTextureLod;
+final isExtTextureFilterAnisotropic = (v) => v is ExtTextureFilterAnisotropic;
+final isOesElementIndexUint = (v) => v is OesElementIndexUint;
+final isOesStandardDerivatives = (v) => v is OesStandardDerivatives;
+final isOesTextureFloat = (v) => v is OesTextureFloat;
+final isOesTextureFloatLinear = (v) => v is OesTextureFloatLinear;
+final isOesTextureHalfFloat = (v) => v is OesTextureHalfFloat;
+final isOesTextureHalfFloatLinear = (v) => v is OesTextureHalfFloatLinear;
+final isOesVertexArrayObject = (v) => v is OesVertexArrayObject;
+final isCompressedTextureAtc = (v) => v is CompressedTextureAtc;
+final isCompressedTextureETC1 = (v) => v is CompressedTextureETC1;
+final isCompressedTexturePvrtc = (v) => v is CompressedTexturePvrtc;
+final isCompressedTextureS3TC = (v) => v is CompressedTextureS3TC;
+final isDebugRendererInfo = (v) => v is DebugRendererInfo;
+final isDebugShaders = (v) => v is DebugShaders;
+final isDepthTexture = (v) => v is DepthTexture;
+final isDrawBuffers = (v) => v is DrawBuffers;
+final isLoseContext = (v) => v is LoseContext;
+
+final isFunction = predicate((v) => v is Function);
+
+// Test that various webgl extensions are available. Only test advertised
+// supported extensions. If the extension has methods, we just test the presence
+// of some methods - we don't test if functionality works.
+
+main() {
+  if (!RenderingContext.supported) return;
+
+  const allExtensions = const [
+    'ANGLE_instanced_arrays',
+    'EXT_blend_minmax',
+    'EXT_color_buffer_float',
+    'EXT_color_buffer_half_float',
+    'EXT_disjoint_timer_query',
+    'EXT_frag_depth',
+    'EXT_sRGB',
+    'EXT_shader_texture_lod',
+    'EXT_texture_filter_anisotropic',
+    'OES_element_index_uint',
+    'OES_standard_derivatives',
+    'OES_texture_float',
+    'OES_texture_float_linear',
+    'OES_texture_half_float',
+    'OES_texture_half_float_linear',
+    'OES_vertex_array_object',
+    'WEBGL_color_buffer_float',
+    'WEBGL_compressed_texture_atc',
+    'WEBGL_compressed_texture_es3',
+    'WEBGL_compressed_texture_etc1',
+    'WEBGL_compressed_texture_pvrtc',
+    'WEBGL_compressed_texture_s3tc',
+    'WEBGL_debug_renderer_info',
+    'WEBGL_debug_shaders',
+    'WEBGL_depth_texture',
+    'WEBGL_draw_buffers',
+    'WEBGL_lose_context',
+  ];
+
+  getExtension(String name) {
+    expect(name, anyOf(allExtensions), reason: 'unknown extension');
+    var canvas = new CanvasElement();
+    var context = canvas.getContext3d();
+    var supportedExtensions = context.getSupportedExtensions()!;
+    if (supportedExtensions.contains(name)) {
+      var extension = context.getExtension(name);
+      expect(extension, isNotNull);
+      return extension;
+    }
+    return null;
+  }
+
+  testType(name, typeMatcher) {
+    test('type', () {
+      var extension = getExtension(name);
+      if (extension == null) return;
+      expect(extension, predicate(typeMatcher));
+      // Ensure that isInstanceOf<X> is not instantiated for an erroneous type
+      // X.  If X is erroneous, there is only a warning at compile time and X is
+      // treated as dynamic, which would make the above line pass.
+      expect(typeMatcher(1), false, reason: 'invalid typeMatcher');
+    });
+  }
+
+  group('ANGLE_instanced_arrays', () {
+    const name = 'ANGLE_instanced_arrays';
+    testType(name, isAngleInstancedArrays);
+    test('vertexAttribDivisorAngle', () {
+      AngleInstancedArrays? extension =
+          getExtension(name) as AngleInstancedArrays?;
+      if (extension == null) return;
+      expect(extension.vertexAttribDivisorAngle, isFunction);
+    });
+  });
+
+  group('EXT_blend_minmax', () {
+    testType('EXT_blend_minmax', isExtBlendMinMax);
+  });
+
+  group('EXT_frag_depth', () {
+    testType('EXT_frag_depth', isExtFragDepth);
+  });
+
+  group('EXT_sRGB', () {
+    testType('EXT_sRGB', isEXTsRgb);
+  });
+
+  group('EXT_shader_texture_lod', () {
+    testType('EXT_shader_texture_lod', isExtShaderTextureLod);
+  });
+
+  group('EXT_texture_filter_anisotropic', () {
+    testType('EXT_texture_filter_anisotropic', isExtTextureFilterAnisotropic);
+  });
+
+  group('OES_element_index_uint', () {
+    testType('OES_element_index_uint', isOesElementIndexUint);
+  });
+
+  group('OES_standard_derivatives', () {
+    testType('OES_standard_derivatives', isOesStandardDerivatives);
+  });
+
+  group('OES_texture_float', () {
+    testType('OES_texture_float', isOesTextureFloat);
+  });
+
+  group('OES_texture_float_linear', () {
+    testType('OES_texture_float_linear', isOesTextureFloatLinear);
+  });
+
+  group('OES_texture_half_float', () {
+    testType('OES_texture_half_float', isOesTextureHalfFloat);
+  });
+
+  group('OES_texture_half_float_linear', () {
+    testType('OES_texture_half_float_linear', isOesTextureHalfFloatLinear);
+  });
+
+  group('OES_vertex_array_object', () {
+    testType('OES_vertex_array_object', isOesVertexArrayObject);
+  });
+
+  group('WEBGL_compressed_texture_atc', () {
+    testType('WEBGL_compressed_texture_atc', isCompressedTextureAtc);
+  });
+
+  group('WEBGL_compressed_texture_etc1', () {
+    testType('WEBGL_compressed_texture_etc1', isCompressedTextureETC1);
+  });
+
+  group('WEBGL_compressed_texture_pvrtc', () {
+    testType('WEBGL_compressed_texture_pvrtc', isCompressedTexturePvrtc);
+  });
+
+  group('WEBGL_compressed_texture_s3tc', () {
+    testType('WEBGL_compressed_texture_s3tc', isCompressedTextureS3TC);
+  });
+
+  group('WEBGL_debug_renderer_info', () {
+    testType('WEBGL_debug_renderer_info', isDebugRendererInfo);
+  });
+
+  group('WEBGL_debug_shaders', () {
+    testType('WEBGL_debug_shaders', isDebugShaders);
+  });
+
+  group('WEBGL_depth_texture', () {
+    testType('WEBGL_depth_texture', isDepthTexture);
+  });
+
+  group('WEBGL_draw_buffers', () {
+    const name = 'WEBGL_draw_buffers';
+    testType(name, isDrawBuffers);
+    test('drawBuffersWebgl', () {
+      DrawBuffers? extension = getExtension(name) as DrawBuffers?;
+      if (extension == null) return;
+      expect(extension.drawBuffersWebgl, isFunction);
+    });
+  });
+
+  group('WEBGL_lose_context', () {
+    const name = 'WEBGL_lose_context';
+    testType(name, isLoseContext);
+    test('loseContext', () {
+      LoseContext? extension = getExtension(name) as LoseContext?;
+      if (extension == null) return;
+      expect(extension.loseContext, isFunction);
+    });
+  });
+}
diff --git a/tests/lib/html/websocket_test.dart b/tests/lib/html/websocket_test.dart
new file mode 100644
index 0000000..a7bd01a
--- /dev/null
+++ b/tests/lib/html/websocket_test.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.
+
+library WebSocketTest;
+
+import 'dart:html';
+
+import 'package:async_helper/async_minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(WebSocket.supported, true);
+    });
+  });
+
+  group('websocket', () {
+    var expectation = WebSocket.supported ? returnsNormally : throws;
+
+    test('constructorTest', () {
+      expect(() {
+        var socket = new WebSocket('ws://localhost/ws', 'chat');
+        expect(socket, isNotNull);
+        expect(socket, isInstanceOf<WebSocket>());
+      }, expectation);
+    });
+
+    if (WebSocket.supported) {
+      test('echo', () {
+        var socket = new WebSocket('ws://${window.location.host}/ws');
+
+        socket.onOpen.first.then((_) {
+          socket.send('hello!');
+        });
+
+        return socket.onMessage.first.then((MessageEvent e) {
+          expect(e.data, 'hello!');
+          socket.close();
+        });
+      });
+
+      test('error handling', () {
+        var socket = new WebSocket('ws://${window.location.host}/ws');
+        socket.onOpen.first.then((_) => socket.send('close-with-error'));
+        return socket.onError.first.then((e) {
+          print('$e was caught, yay!');
+          socket.close();
+        });
+      });
+    }
+  });
+}
diff --git a/tests/lib/html/websql_test.dart b/tests/lib/html/websql_test.dart
new file mode 100644
index 0000000..36daf6c
--- /dev/null
+++ b/tests/lib/html/websql_test.dart
@@ -0,0 +1,122 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 WebDBTest;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:web_sql';
+
+import 'package:async_helper/async_minitest.dart';
+
+Future<SqlResultSet> createTable(
+    SqlTransaction transaction, String tableName, String columnName) async {
+  return transaction.executeSql('CREATE TABLE $tableName ($columnName)', []);
+}
+
+Future<SqlResultSet> insertTable(SqlTransaction transaction, String tableName,
+    String columnName, value) async {
+  final sql = 'INSERT INTO $tableName ($columnName) VALUES (?)';
+  return transaction.executeSql(sql, [value]);
+}
+
+Future<SqlResultSet> queryTable(
+    SqlTransaction transaction, String tableName) async {
+  final sql = 'SELECT * FROM $tableName';
+  return transaction.executeSql(sql, []);
+}
+
+Future<SqlResultSet?> dropTable(SqlTransaction transaction, String tableName,
+    [bool ignoreFailure = false]) async {
+  try {
+    var result = await transaction.executeSql('DROP TABLE $tableName', []);
+    return result;
+  } catch (error) {
+    if (!ignoreFailure) throw error;
+  }
+}
+
+final tableName = 'test_table';
+final columnName = 'test_data';
+
+late SqlDatabase db;
+late SqlTransaction tx;
+
+Future setup() async {
+  if (SqlDatabase.supported) {
+    db = await window.openDatabase('test_db', '1.0', 'test_db', 1024 * 1024);
+    expect(db, isNotNull, reason: 'Unable to open database');
+
+    tx = await db.transaction_future();
+    expect(tx, isNotNull, reason: "Transaction not ready");
+  }
+}
+
+main() async {
+  await setup();
+
+  group('Database', () {
+    test('Open/Transaction', () async {
+      if (!SqlDatabase.supported) return;
+
+      expect(tx, isNotNull, reason: "Transaction not ready");
+
+      // Should not succeed table doesn't exist to be dropped.
+      try {
+        await dropTable(tx, tableName);
+        expect(false, true, reason: "dropTable should fail");
+      } catch (error) {
+        expect(error.message,
+            "could not prepare statement (1 no such table: test_table)");
+      }
+    });
+
+    test('create', () async {
+      if (!SqlDatabase.supported) return;
+
+      expect(tx, isNotNull, reason: "Transaction not ready");
+      try {
+        SqlResultSet createResult =
+            await createTable(tx, tableName, columnName);
+        expect(createResult.insertId, 0);
+      } catch (error) {
+        expect(false, true, reason: "createTable failed - ${error.message}");
+      }
+    });
+
+    test('insert', () async {
+      if (!SqlDatabase.supported) return;
+
+      expect(tx, isNotNull, reason: "Transaction not ready");
+      try {
+        SqlResultSet insertResult =
+            await insertTable(tx, tableName, columnName, 'Some text data');
+        expect(insertResult.insertId, 1);
+        expect(insertResult.rowsAffected, 1);
+      } catch (error) {
+        expect(false, true, reason: "insert failed - ${error.message}");
+      }
+    });
+
+    test('query', () async {
+      if (!SqlDatabase.supported) return;
+
+      expect(tx, isNotNull, reason: "Transaction not ready");
+      try {
+        SqlResultSet queryResult = await queryTable(tx, tableName);
+        expect(queryResult.rows.length, 1);
+        expect(queryResult.rows[0]['test_data'], "Some text data");
+      } catch (error) {
+        expect(false, true, reason: "queryTable failed - ${error.message}");
+      }
+    });
+
+    test('cleanup', () async {
+      if (!SqlDatabase.supported) return;
+
+      expect(tx, isNotNull, reason: "Transaction not ready");
+      await dropTable(tx, tableName, true);
+    });
+  });
+}
diff --git a/tests/lib/html/wheelevent_test.dart b/tests/lib/html/wheelevent_test.dart
new file mode 100644
index 0000000..2614ae0
--- /dev/null
+++ b/tests/lib/html/wheelevent_test.dart
@@ -0,0 +1,82 @@
+// 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 wheel_event_test;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+Future testWheelEvent() async {
+  final done = new Completer();
+  var element = new DivElement();
+  var eventType = Element.mouseWheelEvent.getEventType(element);
+
+  element.onMouseWheel.listen((e) {
+    try {
+      expect(e.screen.x, 100);
+      expect(e.deltaX, 0);
+      expect(e.deltaY.toDouble(), 240.0);
+      expect(e.deltaMode, WheelEvent.DOM_DELTA_PAGE);
+      done.complete();
+    } catch (e) {
+      done.completeError(e);
+    }
+  });
+  var event = new WheelEvent(eventType,
+      deltaX: 0,
+      deltaY: 240,
+      deltaMode: WheelEvent.DOM_DELTA_PAGE,
+      screenX: 100);
+  element.dispatchEvent(event);
+  await done.future;
+}
+
+Future testWheelEventWithDeltaZ() async {
+  final done = new Completer();
+  var element = new DivElement();
+  var eventType = Element.mouseWheelEvent.getEventType(element);
+
+  element.onMouseWheel.listen((e) {
+    try {
+      expect(e.deltaX, 0);
+      expect(e.deltaY, 0);
+      expect(e.screen.x, 0);
+      expect(e.deltaZ.toDouble(), 1.0);
+      done.complete();
+    } catch (e) {
+      done.completeError(e);
+    }
+  });
+  var event = new WheelEvent(eventType, deltaZ: 1.0);
+  element.dispatchEvent(event);
+  await done.future;
+}
+
+Future testWheelEventStream() async {
+  final done = new Completer();
+  var element = new DivElement();
+  var eventType = Element.mouseWheelEvent.getEventType(element);
+
+  element.onMouseWheel.listen((e) {
+    try {
+      expect(e.screen.x, 100);
+      expect(e.deltaX.toDouble(), 240.0);
+      expect(e.deltaY, 0);
+      done.complete();
+    } catch (e) {
+      done.completeError(e);
+    }
+  });
+  var event = new WheelEvent(eventType, deltaX: 240, deltaY: 0, screenX: 100);
+  element.dispatchEvent(event);
+  await done.future;
+}
+
+main() async {
+  await testWheelEvent();
+  await testWheelEventWithDeltaZ();
+  await testWheelEventStream();
+}
diff --git a/tests/lib/html/window_eq_test.dart b/tests/lib/html/window_eq_test.dart
new file mode 100644
index 0000000..03be5ef
--- /dev/null
+++ b/tests/lib/html/window_eq_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 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  var obfuscated = null;
+
+  test('notNull', () {
+    expect(window, isNotNull);
+    expect(window != obfuscated, isTrue);
+  });
+}
diff --git a/tests/lib/html/window_mangling_test.dart b/tests/lib/html/window_mangling_test.dart
new file mode 100644
index 0000000..f427a34
--- /dev/null
+++ b/tests/lib/html/window_mangling_test.dart
@@ -0,0 +1,33 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html' as dom;
+
+import 'package:expect/minitest.dart';
+
+// Defined in dom.Window.
+get navigator => "Dummy";
+
+$eq(x, y) => false;
+$eq$(x, y) => false;
+
+main() {
+  var win = dom.window;
+
+  test('windowMethod', () {
+    final message = navigator;
+    final x = win.navigator;
+    expect(x, notEquals(message));
+  });
+
+  test('windowEquals', () {
+    expect($eq(win, win), isFalse);
+    expect(win == win, isTrue);
+  });
+
+  test('windowEquals', () {
+    expect($eq$(win, win), isFalse);
+    expect(win == win, isTrue);
+  });
+}
diff --git a/tests/lib/html/window_nosuchmethod_test.dart b/tests/lib/html/window_nosuchmethod_test.dart
new file mode 100644
index 0000000..5e3556f
--- /dev/null
+++ b/tests/lib/html/window_nosuchmethod_test.dart
@@ -0,0 +1,38 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html' as dom;
+
+import 'package:expect/minitest.dart';
+
+// Not defined in dom.Window.
+foo(x) => x;
+
+class Unused {
+  foo(x) => 'not $x';
+}
+
+int inscrutable(int x) => x == 0 ? 0 : x | inscrutable(x & (x - 1));
+
+main() {
+  var things = <dynamic>[new Unused(), dom.window];
+
+  test('windowNonMethod', () {
+    var win = things[inscrutable(1)];
+    final message = foo("Hello World");
+    expect(() => win.foo(message), throwsNoSuchMethodError);
+  });
+
+  test('foo', () {
+    var win = things[inscrutable(0)];
+    String x = win.foo('bar');
+    expect(x, 'not bar');
+  });
+
+  // Use dom.window directly in case the compiler does type inference.
+  test('windowNonMethod2', () {
+    final message = foo("Hello World");
+    expect(() => (dom.window as dynamic).foo(message), throwsNoSuchMethodError);
+  });
+}
diff --git a/tests/lib/html/window_test.dart b/tests/lib/html/window_test.dart
new file mode 100644
index 0000000..ab79e66
--- /dev/null
+++ b/tests/lib/html/window_test.dart
@@ -0,0 +1,14 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  test('scrollXY', () {
+    expect(window.scrollX, 0);
+    expect(window.scrollY, 0);
+  });
+}
diff --git a/tests/lib/html/worker_api_test.dart b/tests/lib/html/worker_api_test.dart
new file mode 100644
index 0000000..92a0198
--- /dev/null
+++ b/tests/lib/html/worker_api_test.dart
@@ -0,0 +1,29 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:isolate';
+
+import 'package:async_helper/async_minitest.dart';
+
+worker(message) {
+  var uri = message[0];
+  var replyTo = message[1];
+  try {
+    var url = Url.createObjectUrl(new Blob([''], 'application/javascript'));
+    Url.revokeObjectUrl(url);
+    replyTo.send('Hello from Worker');
+  } catch (e) {
+    replyTo.send('Error: $e');
+  }
+}
+
+main() {
+  test('Use Worker API in Worker', () {
+    var response = new ReceivePort();
+    var remote = Isolate.spawn(worker, ['', response.sendPort]);
+    remote.then((_) => response.first).then(
+        expectAsync((reply) => expect(reply, equals('Hello from Worker'))));
+  });
+}
diff --git a/tests/lib/html/worker_functional_test.dart b/tests/lib/html/worker_functional_test.dart
new file mode 100644
index 0000000..cf3d5ab
--- /dev/null
+++ b/tests/lib/html/worker_functional_test.dart
@@ -0,0 +1,40 @@
+// 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 worker_test;
+
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+
+main() {
+  var workerScript = '''postMessage('WorkerMessage');''';
+
+  test('unsupported', () {
+    if (!Worker.supported) {
+      expect(() => new Worker('worker.js'), throws);
+    } else {
+      new Worker('worker.js').onError.first.then(expectAsync((e) {
+        // This event is expected, "worker.js" doesn't exist.  But the event
+        // *sometimes* propagates to window.onerror in Firefox which causes
+        // this test to fail, so let's stop any further propagation:
+        e.preventDefault();
+        e.stopImmediatePropagation();
+      }));
+    }
+  });
+
+  if (!Worker.supported) return;
+
+  test('works', () {
+    // Use Blob to make a local URL so we don't have to have a separate file.
+    // This does not work on browsers using CSP (Content Security Policy).
+    var blob = new Blob([workerScript], 'text/javascript');
+    var url = Url.createObjectUrl(blob);
+    var worker = new Worker(url);
+    var test = expectAsync((e) {
+      expect(e.data, 'WorkerMessage');
+    });
+    worker.onMessage.first.then(test);
+  });
+}
diff --git a/tests/lib/html/worker_supported_test.dart b/tests/lib/html/worker_supported_test.dart
new file mode 100644
index 0000000..fecb78e
--- /dev/null
+++ b/tests/lib/html/worker_supported_test.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.
+
+library worker_test;
+
+import 'package:expect/minitest.dart';
+import 'dart:html';
+
+main() {
+  test('supported', () {
+    expect(Worker.supported, isTrue);
+  });
+}
diff --git a/tests/lib/html/wrapping_collections_test.dart b/tests/lib/html/wrapping_collections_test.dart
new file mode 100644
index 0000000..d61b84b
--- /dev/null
+++ b/tests/lib/html/wrapping_collections_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 'dart:html';
+import 'dart:html_common';
+import 'dart:js' as js;
+
+import 'package:expect/minitest.dart';
+
+/// Test that if we access objects through JS-interop we get the
+/// appropriate objects, even if dart:html maps them.
+main() {
+  test("Access through JS-interop", () {
+    var performance = js.context['performance'];
+    var entries = performance.callMethod('getEntries', const []);
+    entries.forEach((x) {
+      expect(x is js.JsObject, isTrue);
+    });
+  });
+}
diff --git a/tests/lib/html/xhr_cross_origin_data.txt b/tests/lib/html/xhr_cross_origin_data.txt
new file mode 100644
index 0000000..5872d96
--- /dev/null
+++ b/tests/lib/html/xhr_cross_origin_data.txt
@@ -0,0 +1 @@
+{"version":"1.0","encoding":"UTF-8","feed":{"xmlns":"http://www.w3.org/2005/Atom","xmlns$openSearch":"http://a9.com/-/spec/opensearch/1.1/","xmlns$gd":"http://schemas.google.com/g/2005","xmlns$issues":"http://schemas.google.com/projecthosting/issues/2009","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full"},"updated":{"$t":"2012-10-17T19:55:25.326Z"},"title":{"$t":"Issues - dart"},"subtitle":{"$t":"Issues - dart"},"link":[{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/list"},{"rel":"http://schemas.google.com/g/2005#feed","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full"},{"rel":"http://schemas.google.com/g/2005#post","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full?alt=json&max-results=25"},{"rel":"next","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full?alt=json&start-index=26&max-results=25"}],"generator":{"$t":"ProjectHosting","version":"1.0","uri":"http://code.google.com/feeds/issues"},"openSearch$totalResults":{"$t":6004},"openSearch$startIndex":{"$t":1},"openSearch$itemsPerPage":{"$t":25},"entry":[{"gd$etag":"W/\"CE8DRX47eCl7ImA9WhdaEEw.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/1"},"published":{"$t":"2011-10-06T15:11:23.000Z"},"updated":{"$t":"2011-10-19T08:27:54.000Z"},"title":{"$t":"Process tests sometimes cause timeout on Linux"},"content":{"$t":"Either of the process tests\r\n\r\n  ProcessExitTest.dart\r\n  ProcessSegfaultTest.dart\r\n  ProcessStartExceptionTest.dart\r\n  ProcessStderrTest.dart\r\n  ProcessStdoutTest.dart\r\n\r\ncan hang on Linux. It happens once every ~25 runs.","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/1/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=1"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/1"}],"author":[{"name":{"$t":"sgjesse@google.com"},"uri":{"$t":"/u/sgjesse@google.com/"}}],"issues$cc":[{"issues$uri":{"$t":"/u/100337825224881731112/"},"issues$username":{"$t":"fmal...@google.com"}}],"issues$closedDate":{"$t":"2011-10-19T08:27:54.000Z"},"issues$id":{"$t":1},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$owner":{"issues$uri":{"$t":"/u/sgjesse@google.com/"},"issues$username":{"$t":"sgjesse@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"DUUAQH47eCl7ImA9WhdUGUU.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/2"},"published":{"$t":"2011-10-07T07:53:55.000Z"},"updated":{"$t":"2011-10-07T11:34:01.000Z"},"title":{"$t":"EchoServer tests occasionally crash on Windows"},"content":{"$t":"The EchoServer tests occasionally hits what should be an unreachable path.","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/2/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=2"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/2"}],"author":[{"name":{"$t":"ager@google.com"},"uri":{"$t":"/u/ager@google.com/"}}],"issues$cc":[{"issues$uri":{"$t":"/u/sgjesse@google.com/"},"issues$username":{"$t":"sgjesse@google.com"}}],"issues$closedDate":{"$t":"2011-10-07T11:34:01.000Z"},"issues$id":{"$t":2},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-High"},{"$t":"OpSys-Windows"}],"issues$owner":{"issues$uri":{"$t":"/u/ager@google.com/"},"issues$username":{"$t":"ager@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"DUYMQH47eCl7ImA9WhdbFE8.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/3"},"published":{"$t":"2011-10-10T10:34:32.000Z"},"updated":{"$t":"2011-10-12T13:46:21.000Z"},"title":{"$t":"Dart_Snapshot conflicting uses"},"content":{"$t":"Trying to build Dart after clean checkout from SVN gives me :\r\n\r\nruntime/vm/dart_api_impl.cc: In function ‘void* dart::Dart_CreateIsolate(void*, void*)’:\r\nruntime/vm/dart_api_impl.cc:38:71: error: declaration of ‘void* dart::Dart_CreateIsolate(void*, void*)’ with C language linkage\r\nruntime/include/dart_api.h:185:26: error: conflicts with previous declaration ‘void* Dart_CreateIsolate(const Dart_Snapshot*, void*)’\r\n\r\nI ended up changing the dart_api_impl.cc declaration to use const Dart_Snapshot* and did a cast to (void*) in order to call Dart::CreateIsolate((void*)snapshot, data);","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/3/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=3"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/3"}],"author":[{"name":{"$t":"nelson.s...@gmail.com"},"uri":{"$t":"/u/114313790760784276282/"}}],"issues$closedDate":{"$t":"2011-10-11T15:43:38.000Z"},"issues$id":{"$t":3},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$owner":{"issues$uri":{"$t":"/u/asiva@google.com/"},"issues$username":{"$t":"asiva@google.com"}},"issues$stars":{"$t":13},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"Dk4MRn47eCl7ImA9WhdbEkk.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/4"},"published":{"$t":"2011-10-10T10:44:36.000Z"},"updated":{"$t":"2011-10-10T11:09:47.000Z"},"title":{"$t":"Not-implemented iteration for objects"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n\r\n  main() {\r\n    var obj = {&quot;a&quot;: 1, &quot;b&quot;: 2};\r\n    for (var key in obj) {\r\n      print(key);\r\n    }\r\n  }\r\nhttp://try-dart-lang.appspot.com/s/EmEO\r\n\r\nWhat is the expected output?\r\na\r\nb\r\n\r\nWhat do you see instead?\r\nNoSuchMethodException - receiver: '' function name: 'iterator$named' arguments: []]\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\nOnline dart compiler.\r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\n\r\nIn the specification it says that &quot;for in&quot; construct is desugared into var n0 = e.iterator(); while (n0.hasNext()) { finalVarOrType id = n0.next();\r\nIt is not working because obj.iterator does not exist.","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/4/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=4"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/4"}],"author":[{"name":{"$t":"vjeuxx"},"uri":{"$t":"/u/vjeuxx/"}}],"issues$closedDate":{"$t":"2011-10-10T11:09:47.000Z"},"issues$id":{"$t":4},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Invalid"}},{"gd$etag":"W/\"AkIGQH47eCl7ImA9WhdbEks.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/5"},"published":{"$t":"2011-10-10T11:03:05.000Z"},"updated":{"$t":"2011-10-10T17:42:01.000Z"},"title":{"$t":"Variables in single/double quotes."},"content":{"$t":"Can we use the PHP view that single quotes don't contain variables, but double quotes do... this may help the parser in speed, but more importantly it means the programmer doesn't have to check for and escape variables in single quoted strings.","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/5/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=5"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/5"}],"author":[{"name":{"$t":"cr...@craigfrancis.co.uk"},"uri":{"$t":"/u/105349735893558381122/"}}],"issues$closedDate":{"$t":"2011-10-10T17:42:01.000Z"},"issues$id":{"$t":5},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$stars":{"$t":3},"issues$state":{"$t":"closed"},"issues$status":{"$t":"WontFix"}},{"gd$etag":"W/\"DEIGQX47eCl7ImA9WhRTEUg.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/6"},"published":{"$t":"2011-10-10T11:38:13.000Z"},"updated":{"$t":"2011-11-01T14:08:40.000Z"},"title":{"$t":"Type checking is broken"},"content":{"$t":"Use dartc_test to run:\r\n\r\nbool foo(bool bar()) =&gt; bar();\r\n\r\nbool bar() {}\r\n\r\nmain() {\r\n  foo(bar);\r\n}\r\n\r\nwith --enable_type_checks.\r\n\r\nAn error is thrown because the type of bar is not bool.\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/6/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=6"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/6"}],"author":[{"name":{"$t":"benl@google.com"},"uri":{"$t":"/u/benl@google.com/"}}],"issues$closedDate":{"$t":"2011-11-01T14:08:40.000Z"},"issues$id":{"$t":6},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Area-Compiler"}],"issues$owner":{"issues$uri":{"$t":"/u/jat@google.com/"},"issues$username":{"$t":"jat@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"DEEAQH47eCl7ImA9WhdbFE8.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/7"},"published":{"$t":"2011-10-10T12:32:40.000Z"},"updated":{"$t":"2011-10-12T13:37:21.000Z"},"title":{"$t":"declaredIndentifier typos in Dart Language Specification, Draft Version 0.01, October 10th, 2011"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n1. Open http://www.dartlang.org/docs/spec/dartLangSpec.pdf\r\n2. Search for &quot;indent&quot; (without the quotes)\r\n3. Notice how this should rather read ident instead.\r\n\r\n\u003cb\u003eWhat is the expected output? What do you see instead?\u003c/b\u003e\n\r\nI see what must be a typo.\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\n\r\nDart Programming Language Specification\r\nDraft Version 0.01\r\nThe Dart Team\r\nOctober 10th, 2011\r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\n\r\nHere is a copy/paste from the pdf (with the fi ligature manually reapaired). See my (sic) annotations for where I think the typos are:\r\n\r\n11.9\r\n\r\nTry\r\n\r\nThe try statement supports the definition of exception handling code in a struc-\r\ntured way.\r\n\r\ntryStatement:\r\ntry block (catchPart+ finallyPart? | finallyPart)\r\n;\r\n\r\ncatchPart:\r\ncatch ‘(’ declaredIndentifier (sic) (‘, ’ declaredIndentifier (sic))? ‘)’ block\r\n;\r\n\r\nfinallyPart:\r\nfinally block\r\n;\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/7/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=7"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/7"}],"author":[{"name":{"$t":"adrian.a...@gmail.com"},"uri":{"$t":"/u/114973624116584041537/"}}],"issues$closedDate":{"$t":"2011-10-12T13:37:21.000Z"},"issues$id":{"$t":7},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Component-Docs"}],"issues$owner":{"issues$uri":{"$t":"/u/102708310591662789853/"},"issues$username":{"$t":"gbra...@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Done"}},{"gd$etag":"W/\"D0QNQ347eCl7ImA9WhdbEkg.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/8"},"published":{"$t":"2011-10-10T12:46:09.000Z"},"updated":{"$t":"2011-10-10T14:03:12.000Z"},"title":{"$t":"Build Failure for standalone VM"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n&gt; Follow steps to build VM mentioned at http://code.google.com/p/dart/wiki/Building#Building_the_standalone_VM\r\n\r\n\u003cb\u003eWhat is the expected output? What do you see instead?\u003c/b\u003e\nBuild should be success, but it fails.\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\nLatest version.\r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\n\r\nError output:\r\n~/dart/runtime$ ../tools/build.py --arch=ia32\r\nmake -j 1 BUILDTYPE=Debug_ia32 all\r\n  CXX(target) out/Debug_ia32/obj.target/libdart/runtime/vm/dart_api_impl.o\r\ncc1plus: warnings being treated as errors\r\n../runtime/vm/dart_api_impl.cc: In function ‘void* dart::Dart_CreateIsolate(void*, void*)’:\r\n../runtime/vm/dart_api_impl.cc:38:71: error: declaration of ‘void* dart::Dart_CreateIsolate(void*, void*)’ with C language linkage\r\n../runtime/include/dart_api.h:185:26: error: conflicts with previous declaration ‘void* Dart_CreateIsolate(const Dart_Snapshot*, void*)’\r\nmake: *** [out/Debug_ia32/obj.target/libdart/runtime/vm/dart_api_impl.o] Error 1\r\nBUILD FAILED\r\n\r\n\r\nIs this a known issue? or am I doing something wrong?\r\n\r\nthanks,\r\nswarup","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/8/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=8"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/8"}],"author":[{"name":{"$t":"me.s...@gmail.com"},"uri":{"$t":"/u/112564033093352645938/"}}],"issues$closedDate":{"$t":"2011-10-10T14:03:12.000Z"},"issues$id":{"$t":8},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$mergedInto":{"issues$id":{"$t":3},"issues$project":{"$t":"dart"}},"issues$stars":{"$t":2},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Duplicate"}},{"gd$etag":"W/\"CEMMQH47eCl7ImA9WhdbE0g.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/9"},"published":{"$t":"2011-10-10T13:08:33.000Z"},"updated":{"$t":"2011-10-11T17:01:21.000Z"},"title":{"$t":"\"variable set but not used\" error during build of VM"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n1. &gt; Follow steps to build VM mentioned at http://code.google.com/p/dart/wiki/Building#Building_the_standalone_VM\r\n\r\n\u003cb\u003eWhat is the expected output? What do you see instead?\u003c/b\u003e\nI get some &quot;variable X set but not used&quot;-type warnings, that -Werror escalates to errors, halting the build.\r\nAs a temporary measure, I removed -Werror from all *.mk files, which allows me to build the standalone VM successfully.\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\nRecent svn on arch linux using gcc version 4.6.1 20110819 (prerelease) \r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\nHere is a full list of the warnings (without -Werror and therefor not turned to errors)\r\n\r\n\r\nthird_party/v8/src/ia32/full-codegen-ia32.cc: In member function ‘virtual void v8::internal::FullCodeGenerator::VisitCompareOperation(v8::internal::CompareOperation*)’:\r\nthird_party/v8/src/ia32/full-codegen-ia32.cc:4085:12: warning: variable ‘strict’ set but not used [-Wunused-but-set-variable]\r\n  CXX(host) out/Debug_ia32/obj.host/v8_base/third_party/v8/src/ia32/lithium-gap-resolver-ia32.o\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc: In member function ‘void v8::internal::LCodeGen::DoLoadKeyedFastDoubleElement(v8::internal::LLoadKeyedFastDoubleElement*)’:\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc:2235:12: warning: variable ‘elements’ set but not used [-Wunused-but-set-variable]\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc: In member function ‘void v8::internal::LCodeGen::DoStoreKeyedFastDoubleElement(v8::internal::LStoreKeyedFastDoubleElement*)’:\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc:3100:12: warning: variable ‘elements’ set but not used [-Wunused-but-set-variable]\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc:3101:12: warning: variable ‘key’ set but not used [-Wunused-but-set-variable]\r\n\r\n\r\nthird_party/v8/src/ia32/full-codegen-ia32.cc: In member function ‘virtual void v8::internal::FullCodeGenerator::VisitCompareOperation(v8::internal::CompareOperation*)’:\r\nthird_party/v8/src/ia32/full-codegen-ia32.cc:4085:12: warning: variable ‘strict’ set but not used [-Wunused-but-set-variable]\r\n  CXX(target) out/Debug_ia32/obj.target/v8_base/third_party/v8/src/ia32/lithium-gap-resolver-ia32.o\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc: In member function ‘void v8::internal::LCodeGen::DoLoadKeyedFastDoubleElement(v8::internal::LLoadKeyedFastDoubleElement*)’:\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc:2235:12: warning: variable ‘elements’ set but not used [-Wunused-but-set-variable]\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc: In member function ‘void v8::internal::LCodeGen::DoStoreKeyedFastDoubleElement(v8::internal::LStoreKeyedFastDoubleElement*)’:\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc:3100:12: warning: variable ‘elements’ set but not used [-Wunused-but-set-variable]\r\nthird_party/v8/src/ia32/lithium-codegen-ia32.cc:3101:12: warning: variable ‘key’ set but not used [-Wunused-but-set-variable]\r\n\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/9/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=9"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/9"}],"author":[{"name":{"$t":"waq...@gmail.com"},"uri":{"$t":"/u/110067472520212772478/"}}],"issues$closedDate":{"$t":"2011-10-10T13:20:54.000Z"},"issues$id":{"$t":9},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$mergedInto":{"issues$id":{"$t":43},"issues$project":{"$t":"dart"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Duplicate"}},{"gd$etag":"W/\"DE4GRX47eCl7ImA9WhdbGEo.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/10"},"published":{"$t":"2011-10-10T13:21:56.000Z"},"updated":{"$t":"2011-10-17T18:42:04.000Z"},"title":{"$t":"dartc build failure: private DartNode.setParent()"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n1. build dart compiler\r\n\r\n\u003cb\u003eWhat is the expected output? What do you see instead?\u003c/b\u003e\ndart/compiler/java/com/google/dart/compiler/ast/DartNode.java fails to compile with the following error:\r\n    [javac] /data/down/devel/dart/dart/compiler/java/com/google/dart/compiler/ast/DartNode.java:122: error: setParent(DartNode) has private access in DartNode\r\n    [javac]        child.setParent(this);\r\n    [javac]             ^\r\n\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\ndart svn, javac 1.7.0 on arch linux\r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\nMaking setParent() protected instead of private fixes the issue for me, allowing it to be called from protected method becomeParentOf() of the same class.\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/10/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=10"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/10"}],"author":[{"name":{"$t":"waq...@gmail.com"},"uri":{"$t":"/u/110067472520212772478/"}}],"issues$closedDate":{"$t":"2011-10-17T18:42:04.000Z"},"issues$id":{"$t":10},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Area-Compiler"}],"issues$owner":{"issues$uri":{"$t":"/u/116010686905328984286/"},"issues$username":{"$t":"johnl...@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"D0MCRH47eCl7ImA9WhdbEks.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/11"},"published":{"$t":"2011-10-10T14:07:17.000Z"},"updated":{"$t":"2011-10-10T16:51:05.000Z"},"title":{"$t":"Error in first online tutorial"},"content":{"$t":"\r\n1. Enter any 3 russian symbols instead of &quot;World&quot;\r\n2. Run.\r\n3. Program prints &quot;Hello, хуй!&quot;\r\n\r\nхуй - russian dirty word. Do you have russian programmers? ;)\r\n\r\nI'm using google chrome 14 to try this tutorial.\r\nIn some cases (when number of russian symbols is more then 3) it prints squares instead of letters (it's encoding problems i think ;)\r\n\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/11/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=11"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/11"}],"author":[{"name":{"$t":"podg...@gmail.com"},"uri":{"$t":"/u/105898658743680019064/"}}],"issues$closedDate":{"$t":"2011-10-10T16:51:05.000Z"},"issues$id":{"$t":11},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$owner":{"issues$uri":{"$t":"/u/100337825224881731112/"},"issues$username":{"$t":"fmal...@google.com"}},"issues$stars":{"$t":2},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"A0UBSH47eCl7ImA9WhdbE04.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/12"},"published":{"$t":"2011-10-10T14:28:03.000Z"},"updated":{"$t":"2011-10-11T13:20:59.000Z"},"title":{"$t":"compiler should be be independant of browser code"},"content":{"$t":"Request: Make the Dart-&gt;JS compiler as a seperate file from the browser checking code so that the project can be included in other projects such as Node.JS\r\n\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/12/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=12"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/12"}],"author":[{"name":{"$t":"xdr...@gmail.com"},"uri":{"$t":"/u/117476521218063886204/"}}],"issues$closedDate":{"$t":"2011-10-11T13:20:59.000Z"},"issues$id":{"$t":12},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$stars":{"$t":3},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Invalid"}},{"gd$etag":"W/\"CkEHQ347eCl7ImA9WhJSEkk.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/13"},"published":{"$t":"2011-10-10T14:33:33.000Z"},"updated":{"$t":"2012-07-02T14:50:32.000Z"},"title":{"$t":"Add C#-style extension methods"},"content":{"$t":"Unless I'm reading the spec and examples wrong, it looks as if Dart uses the horrific Java approach of providing utility methods that operate on a interface, by putting them as static methods within some class with a name like 'Arrays' or 'Collections'. This is nonsense, especially when Linq and extension methods in C# have demonstrated a far superior approach, and Dart should provide an equivalent mechanism.\r\n\r\nAn obvious, easy way to add this would be that top level functions can optionally be called on an object using the dot operator, in which case the calling instance is passed as the first function parameter.\r\n\r\nE.g. to write a generic first method that operates over an iterator for a supplied predicate:\r\n\r\nT first&lt;T&gt;(Iterator&lt;T&gt; iterator, bool predicate(T obj)) {\r\n    while (iterator.hasNext()) {\r\n        if (predicate(iterator.next()) {\r\n            return true;\r\n        }\r\n    }\r\n    return false;\r\n}\r\n\r\nThis could be called on an instance of an iterator as follows:\r\n\r\nvar jon = peopleIterator.first((p) =&gt; p.name == 'Jon');\r\n\r\nUsing extension methods that also return iterators, they can then chained together to form fluent expressions:\r\n\r\nvar fiveOldestJons = peopleInterator.where((p) =&gt; p.name == 'Jon').orderBy((p) =&gt; p.age).take(5);\r\n\r\nIt's worrying looking through the language design that you don't seem to looked much beyond JavaScript and Java for your inspiration in Dart. I can't speak for users of other languages, but I strongly doubt C# developers will be particularly impressed by a lot of the Java style anachronisms, and I'd urge you to cast your net a little more widely in general.","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/13/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=13"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/13"}],"author":[{"name":{"$t":"jon.rimmer"},"uri":{"$t":"/u/jon.rimmer/"}}],"issues$closedDate":{"$t":"2011-10-12T13:44:38.000Z"},"issues$id":{"$t":13},"issues$label":[{"$t":"Type-Enhancement"},{"$t":"Priority-Medium"},{"$t":"Area-Language"}],"issues$stars":{"$t":25},"issues$state":{"$t":"closed"},"issues$status":{"$t":"WontFix"}},{"gd$etag":"W/\"Ck4BRn47eCl7ImA9WhRaF04.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/14"},"published":{"$t":"2011-10-10T15:34:16.000Z"},"updated":{"$t":"2012-02-20T09:42:37.000Z"},"title":{"$t":"Add Tau constant to core Math class"},"content":{"$t":"With a new language, we are taking the opportunity to introduce better concepts, right? So please add Tau, the ratio of a circle's circumference to its radius (i.e. 2pi), to the Math class.\r\n\r\nLeave Math.PI as is, but please add Math.TAU\r\n\r\nThis is a safe addition with no side effects and minimal impact to the language and runtime.\r\n\r\nTau manifesto: http://tauday.com/\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/14/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=14"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/14"}],"author":[{"name":{"$t":"peter.ge...@gmail.com"},"uri":{"$t":"/u/116327704440122793403/"}}],"issues$closedDate":{"$t":"2012-02-16T00:26:22.000Z"},"issues$id":{"$t":14},"issues$label":[{"$t":"Type-Enhancement"},{"$t":"Priority-Medium"},{"$t":"Area-Library"}],"issues$owner":{"issues$uri":{"$t":"/u/jjb@google.com/"},"issues$username":{"$t":"jjb@google.com"}},"issues$stars":{"$t":17},"issues$state":{"$t":"closed"},"issues$status":{"$t":"WontFix"}},{"gd$etag":"W/\"DE8BQH47eCl7ImA9WhdaEkw.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/15"},"published":{"$t":"2011-10-10T15:36:24.000Z"},"updated":{"$t":"2011-10-21T17:07:31.000Z"},"title":{"$t":"jQuery integration"},"content":{"$t":"I may be mis-understanding dart, but I would like to put in a request that Google's engineers/someone smarter than me add jQuery as a possible library.\r\n\r\nFor instance, how would I accomplish the following using dart?\r\n\r\n&lt;pre&gt;\r\n$(&quot;p&quot;).click({function(){ alert(&quot;You clicked a paragraph tag!&quot;); });\r\n&lt;/pre&gt;\r\n\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/15/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=15"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/15"}],"author":[{"name":{"$t":"bri...@dearing-group.com"},"uri":{"$t":"/u/108006530617416183710/"}}],"issues$closedDate":{"$t":"2011-10-21T16:26:31.000Z"},"issues$id":{"$t":15},"issues$label":[{"$t":"Type-Enhancement"},{"$t":"Priority-Medium"},{"$t":"Area-UI"}],"issues$stars":{"$t":10},"issues$state":{"$t":"closed"},"issues$status":{"$t":"WontFix"}},{"gd$etag":"W/\"CUQNQ347eCl7ImA9WhdbE0g.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/16"},"published":{"$t":"2011-10-10T16:04:28.000Z"},"updated":{"$t":"2011-10-11T17:16:32.000Z"},"title":{"$t":"Generics disappear on try.dartlang.org"},"content":{"$t":"Go to try.dartlang.org, then insert and execute this code:\r\nclass PointlessValueWrapper {\r\n  PointlessValueWrapper(Type pointlessArgument);\r\n}\r\nmain() {\r\n  new PointlessValueWrapper(5);\r\n  new PointlessValueWrapper(&quot;Hello!&quot;);\r\n}\r\n\r\nAs expected, line 6 raises a warning.\r\n\r\nNow, open the link on the top right in a new tab. You'll see the same code, except the type parameters are missing. Because of this, line 2 now produces an error.\r\n\r\nI expect a tokeniser somewhere is misbehaving.\r\n\r\nUsing Firefox/Nightly (which is at version 10, at the moment).","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/16/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=16"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/16"}],"author":[{"name":{"$t":"pimmhoge...@gmail.com"},"uri":{"$t":"/u/117820825527967972339/"}}],"issues$closedDate":{"$t":"2011-10-11T17:16:32.000Z"},"issues$id":{"$t":16},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Area-Dartboard"}],"issues$owner":{"issues$uri":{"$t":"/u/103267283189406017873/"},"issues$username":{"$t":"knor...@google.com"}},"issues$stars":{"$t":0},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Verified"}},{"gd$etag":"W/\"D0UDRH47eCl7ImA9WhdbEks.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/17"},"published":{"$t":"2011-10-10T16:11:37.000Z"},"updated":{"$t":"2011-10-10T16:47:55.000Z"},"title":{"$t":"Can't build editor"},"content":{"$t":"In editor/build/README.txt:\r\n\r\n---\r\nTo begin, make sure the Dart plugin and feature sources are checked out from\r\nSVN. Edit rcpinit.sh to define the location of the TRUNK directory that was\r\nchecked out. Also checkout the usage profile plugin and feature from perforce.\r\nDefine that directory in rcpinit.sh as GDT_PROF. You only the the usage\r\nprofiler, not all of GPE.\r\n---\r\n\r\nBut google plugin for eclipse is not open-sourced yet:\r\nhttp://code.google.com/eclipse/docs/faq.html#source\r\n\r\nWhere can I find smth like /src/prof-git5/google3/third_party/java/google_plugin_eclipse/opensource/trunk\r\nfor building editor?","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/17/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=17"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/17"}],"author":[{"name":{"$t":"bats...@gmail.com"},"uri":{"$t":"/u/108382165757819799147/"}}],"issues$closedDate":{"$t":"2011-10-10T16:23:46.000Z"},"issues$id":{"$t":17},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Done"}},{"gd$etag":"W/\"CEYMRn47eCl7ImA9WhJbFU0.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/18"},"published":{"$t":"2011-10-10T16:31:10.000Z"},"updated":{"$t":"2012-09-24T15:56:27.000Z"},"title":{"$t":"Building dart on Mac OS X Lion with xcode 4"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n1. checkout source code\r\n2. run tools/build.py\r\n\r\nResult:\r\n=== BUILD NATIVE TARGET v8_base OF PROJECT v8 WITH CONFIGURATION Debug_x64 ===\r\n** BUILD FAILED **\r\n\r\nThe problem is in macosx sdk version. Google Dart needs 10.5 for building, but there are no macosx10.5 sdk in XCode 4 in Lion.\r\n\r\nWorkaround: specify sdk manually in build.py:\r\nIndex: tools/build.py\r\n===================================================================\r\n--- tools/build.py  (revision 296)\r\n+++ tools/build.py  (working copy)\r\n@@ -106,6 +106,8 @@\r\n         if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):\r\n           project_file = 'dart-%s.xcodeproj' % CurrentDirectoryBaseName()\r\n         args = ['xcodebuild',\r\n+                '-sdk',\r\n+                'macosx10.6',\r\n                 '-project',\r\n                 project_file,\r\n                 '-target',\r\n\r\nFull instruction for workaround on Lion:\r\nhttp://batsuev.com/2011/10/building-google-dart-on-os-x-lion-with-xcode-4/\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/18/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=18"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/18"}],"author":[{"name":{"$t":"bats...@gmail.com"},"uri":{"$t":"/u/108382165757819799147/"}}],"issues$cc":[{"issues$uri":{"$t":"/u/efortuna@google.com/"},"issues$username":{"$t":"efortuna@google.com"}},{"issues$uri":{"$t":"/u/dgrove@google.com/"},"issues$username":{"$t":"dgrove@google.com"}}],"issues$id":{"$t":18},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Area-Build"},{"$t":"Milestone-M2"}],"issues$owner":{"issues$uri":{"$t":"/u/iposva@google.com/"},"issues$username":{"$t":"iposva@google.com"}},"issues$stars":{"$t":22},"issues$state":{"$t":"open"},"issues$status":{"$t":"Accepted"}},{"gd$etag":"W/\"D0EBSH47eCl7ImA9WhdbEko.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/19"},"published":{"$t":"2011-10-10T17:36:20.000Z"},"updated":{"$t":"2011-10-10T19:40:59.000Z"},"title":{"$t":"Integration with Eclipse"},"content":{"$t":"There should be a good integration towards common IDE's like Eclipse. ","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/19/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=19"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/19"}],"author":[{"name":{"$t":"ad...@trollweb.no"},"uri":{"$t":"/u/108751899022404107859/"}}],"issues$closedDate":{"$t":"2011-10-10T19:40:59.000Z"},"issues$id":{"$t":19},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$stars":{"$t":0},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Invalid"}},{"gd$etag":"W/\"DE4BRX47eCl7ImA9WhdbE0k.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/20"},"published":{"$t":"2011-10-10T17:48:37.000Z"},"updated":{"$t":"2011-10-11T15:29:14.000Z"},"title":{"$t":"typo in initial example on try-dart-lang.appspot.com"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n1. Visit http://try-dart-lang.appspot.com/\r\n\r\n\u003cb\u003eWhat is the expected output? What do you see instead?\u003c/b\u003e\n\r\nI expected to see coherent wording. Instead, I see &quot;When you run the code … it it submitted to AppEngine&quot;. I believe the intended wording was &quot;When you run the code, it is submitted to AppEngine&quot;.\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\n\r\nThe live version on Chrome and Fedora.\r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\n\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/20/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=20"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/20"}],"author":[{"name":{"$t":"mich...@ficarra.me"},"uri":{"$t":"/u/111990041337538184628/"}}],"issues$closedDate":{"$t":"2011-10-11T14:01:40.000Z"},"issues$id":{"$t":20},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Component-Docs"}],"issues$owner":{"issues$uri":{"$t":"/u/pdr@google.com/"},"issues$username":{"$t":"pdr@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"Ck8AQH47eCl7ImA9WhdbE0k.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/21"},"published":{"$t":"2011-10-10T17:55:20.000Z"},"updated":{"$t":"2011-10-11T13:47:21.000Z"},"title":{"$t":"Include Open Sans Bold web font in dartlang.org pages"},"content":{"$t":"The pages on dartlang.org use this tag to load Open Sans:\r\n\r\n&lt;link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'&gt;\r\n\r\nThis doesn't load the boldface file, while some parts like .intro &gt; dl &gt; dt are set in boldface. Currently this means that the regular font is made bold programmatically at these places, which looks very bad.\r\n\r\nInstead, please use this tag:\r\n\r\n&lt;link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'&gt;","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/21/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=21"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/21"}],"author":[{"name":{"$t":"sander.d...@gmail.com"},"uri":{"$t":"/u/117653750014788020856/"}}],"issues$closedDate":{"$t":"2011-10-11T13:47:21.000Z"},"issues$id":{"$t":21},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Component-Docs"}],"issues$owner":{"issues$uri":{"$t":"/u/drfibonacci@google.com/"},"issues$username":{"$t":"drfibonacci@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}},{"gd$etag":"W/\"CE4DR347eCl7ImA9WhJaEko.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/22"},"published":{"$t":"2011-10-10T18:47:48.000Z"},"updated":{"$t":"2012-10-03T14:02:56.000Z"},"title":{"$t":"Support non-nullable types."},"content":{"$t":"Short version: Null pointers are a really good way to mess up a program at runtime, and I'd like the Dart team to reevaluate whether they're absolutely required.\r\n\r\nSlightly longer version: I would say the #1 cause of issues in my programs (excluding logical errors/requirements errors) are NPEs. Having a language support NPE removal, be it via some clever compiler warning or simply removing null altogether, would be wonderful. I'm personally partial to Scala's method of null removal, but I'm sure PL gurus like yourselves have seen many others.\r\n\r\nDart has a stated goal of avoiding the creation of programs that &quot;are difficult to debug or maintain.&quot; NPEs are a huge pain point in this regard. I'd be really happy if the Dart team reevaluated whether they are absolutely required to achieve the other aims.","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/22/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=22"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/22"}],"author":[{"name":{"$t":"cfle...@gmail.com"},"uri":{"$t":"/u/117457048271408990845/"}}],"issues$id":{"$t":22},"issues$label":[{"$t":"Type-Enhancement"},{"$t":"Priority-Medium"},{"$t":"Area-Language"},{"$t":"Milestone-Later"}],"issues$owner":{"issues$uri":{"$t":"/u/102708310591662789853/"},"issues$username":{"$t":"gbra...@google.com"}},"issues$stars":{"$t":110},"issues$state":{"$t":"open"},"issues$status":{"$t":"Triaged"}},{"gd$etag":"W/\"A0YNSH47eCl7ImA9WhdbE04.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/23"},"published":{"$t":"2011-10-10T19:00:32.000Z"},"updated":{"$t":"2011-10-11T13:19:59.000Z"},"title":{"$t":"The example Fibonacci is not responsive most of the times"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n1. At dartland.org, choose the example Fibonacci.\r\n2. Instead of 20, as a parameter for the function Fib, use 50.\r\n\r\n\u003cb\u003eWhat is the expected output? What do you see instead?\u003c/b\u003e\nI was expecting a numeric output generated by the function. Instead, the page freezes or crashes.\r\n\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\nn/a. Google Chrome on Windows 7\r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\n\r\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/23/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=23"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/23"}],"author":[{"name":{"$t":"guilherm...@gmail.com"},"uri":{"$t":"/u/117803371227799387793/"}}],"issues$closedDate":{"$t":"2011-10-11T13:19:59.000Z"},"issues$id":{"$t":23},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$stars":{"$t":0},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Invalid"}},{"gd$etag":"W/\"CU8BSH47eCl7ImA9WhdbEko.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/24"},"published":{"$t":"2011-10-10T19:01:19.000Z"},"updated":{"$t":"2011-10-10T19:10:59.000Z"},"title":{"$t":"Allowing null pointers is undesirable"},"content":{"$t":"Short version: Null pointers are a really good way to mess up a program at runtime, and I'd like the Dart team to reevaluate whether they're absolutely required.\r\n\r\nSlightly longer version: I would say the #1 cause of issues in my programs (excluding logical errors/requirements errors) are NPEs. Having a language support NPE removal, be it via some clever compiler warning or simply removing null altogether, would be wonderful. I'm personally partial to Scala's method of null removal, but I'm sure PL gurus like yourselves have seen many others.\r\n\r\nDart has a stated goal of avoiding the creation of programs that &quot;are difficult to debug or maintain.&quot; NPEs are a huge pain point in this regard. I'd be really happy if the Dart team reevaluated whether they are absolutely required to achieve the other aims.","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/24/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=24"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/24"}],"author":[{"name":{"$t":"cfle...@gmail.com"},"uri":{"$t":"/u/117457048271408990845/"}}],"issues$closedDate":{"$t":"2011-10-10T19:10:59.000Z"},"issues$id":{"$t":24},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"}],"issues$mergedInto":{"issues$id":{"$t":22},"issues$project":{"$t":"dart"}},"issues$stars":{"$t":2},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Duplicate"}},{"gd$etag":"W/\"C0EBRX47eCl7ImA9WhdbE0k.\"","id":{"$t":"http://code.google.com/feeds/issues/p/dart/issues/full/25"},"published":{"$t":"2011-10-10T19:50:14.000Z"},"updated":{"$t":"2011-10-11T14:00:54.000Z"},"title":{"$t":"Another typo in http://try-dart-lang.appspot.com/ code comments"},"content":{"$t":"\u003cb\u003eWhat steps will reproduce the problem?\u003c/b\u003e\n1. Visit http://try-dart-lang.appspot.com/\r\n\r\n\u003cb\u003eWhat is the expected output? What do you see instead?\u003c/b\u003e\n\r\nIn addition to issue20, I spotted another typo, marked with (sic) below.\r\n\r\nThe first or second &quot;of&quot; can be deleted, whichever you prefer :-)\r\n\r\n&quot;// Here you can try out the Dart Language from the comfort of of (sic) your own&quot;\r\n\r\n\u003cb\u003eWhat version of the product are you using? On what operating system?\u003c/b\u003e\n\r\nAbove URL at the time of this issue submission.\r\n\r\n\u003cb\u003ePlease provide any additional information below.\u003c/b\u003e\n","type":"html"},"link":[{"rel":"replies","type":"application/atom+xml","href":"http://code.google.com/feeds/issues/p/dart/issues/25/comments/full"},{"rel":"alternate","type":"text/html","href":"http://code.google.com/p/dart/issues/detail?id=25"},{"rel":"self","type":"application/atom+xml","href":"https://code.google.com/feeds/issues/p/dart/issues/full/25"}],"author":[{"name":{"$t":"adrian.a...@gmail.com"},"uri":{"$t":"/u/114973624116584041537/"}}],"issues$closedDate":{"$t":"2011-10-11T14:00:54.000Z"},"issues$id":{"$t":25},"issues$label":[{"$t":"Type-Defect"},{"$t":"Priority-Medium"},{"$t":"Component-Docs"}],"issues$owner":{"issues$uri":{"$t":"/u/pdr@google.com/"},"issues$username":{"$t":"pdr@google.com"}},"issues$stars":{"$t":1},"issues$state":{"$t":"closed"},"issues$status":{"$t":"Fixed"}}]}}
diff --git a/tests/lib/html/xhr_cross_origin_test.dart b/tests/lib/html/xhr_cross_origin_test.dart
new file mode 100644
index 0000000..7bc0a20
--- /dev/null
+++ b/tests/lib/html/xhr_cross_origin_test.dart
@@ -0,0 +1,105 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library XHRCrossOriginTest;
+
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
+import 'dart:html';
+import "dart:convert";
+
+/**
+ * Examine the value of "crossOriginPort" as passed in from the url from
+ * [window.location] to determine what the cross-origin port is for
+ * this test.
+ */
+// TODO(efortuna): If we need to use this function frequently, make a
+// url_analyzer library that is part of test.dart that these tests can import.
+int get crossOriginPort {
+  var searchUrl = window.location.search;
+  var crossOriginStr = 'crossOriginPort=';
+  var index = searchUrl.indexOf(crossOriginStr);
+  var nextArg = searchUrl.indexOf('&', index);
+  return int.parse(searchUrl.substring(index + crossOriginStr.length,
+      nextArg == -1 ? searchUrl.length : nextArg));
+}
+
+var port = crossOriginPort;
+var host = '${window.location.protocol}//${window.location.hostname}:$port';
+
+Future testGetCrossDomain() async {
+  var gotError = false;
+  var url = '$host/root_dart/tests/lib/html/xhr_cross_origin_data.txt';
+  try {
+    var xhr = await HttpRequest.request(url);
+    var data = json.decode(xhr.response);
+    expect(data.containsKey('feed'), isTrue);
+    expect(data['feed'].containsKey('entry'), isTrue);
+    expect(data, isMap);
+  } catch (e) {
+    // Consume errors when not supporting cross origin.
+    gotError = true;
+  }
+  // Expect that we got an error when cross origin is not supported.
+  expect(gotError, !HttpRequest.supportsCrossOrigin);
+}
+
+Future testRequestCrossOrigin() async {
+  var url = '$host/root_dart/tests/lib/html/xhr_cross_origin_data.txt';
+  var response = await HttpRequest.requestCrossOrigin(url);
+  expect(response.contains('feed'), isTrue);
+}
+
+Future testRequestCrossOriginErrors() async {
+  try {
+    var response = await HttpRequest.requestCrossOrigin('does_not_exist');
+    fail('404s should fail request.');
+  } catch (_) {
+    // Expected failure.
+  }
+}
+
+void testCrossDomain() {
+  var url = '$host/root_dart/tests/lib/html/xhr_cross_origin_data.txt';
+  var xhr = new HttpRequest();
+  xhr.open('GET', url, async: true);
+  var validate = expectAsync((data) {
+    expect(data.containsKey('feed'), isTrue);
+    expect(data['feed'].containsKey('entry'), isTrue);
+    expect(data, isMap);
+  });
+  xhr.onReadyStateChange.listen((e) {
+    if (xhr.readyState == HttpRequest.DONE) {
+      validate(json.decode(xhr.response));
+    }
+  });
+  xhr.send();
+}
+
+Future testGetWithCredentialsCrossDomain() async {
+  var url = '$host/root_dart/tests/lib/html/xhr_cross_origin_data.txt';
+  var xhr = await HttpRequest.request(url, withCredentials: true);
+  var data = json.decode(xhr.response);
+  expect(data.containsKey('feed'), isTrue);
+  expect(data['feed'].containsKey('entry'), isTrue);
+  expect(data, isMap);
+}
+
+main() {
+  test('supported', () {
+    expect(HttpRequest.supportsCrossOrigin, isTrue);
+  });
+
+  asyncTest(() async {
+    await testGetCrossDomain();
+    await testRequestCrossOrigin();
+    await testRequestCrossOriginErrors();
+    // Skip the rest if not supported.
+    if (!HttpRequest.supportsCrossOrigin) {
+      return;
+    }
+    testCrossDomain();
+    await testGetWithCredentialsCrossDomain();
+  });
+}
diff --git a/tests/lib/html/xhr_test.dart b/tests/lib/html/xhr_test.dart
new file mode 100644
index 0000000..c885248
--- /dev/null
+++ b/tests/lib/html/xhr_test.dart
@@ -0,0 +1,265 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library XHRTest;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:async_helper/async_minitest.dart';
+import 'package:async_helper/async_helper.dart';
+
+// Cache blocker is a workaround for:
+// https://code.google.com/p/dart/issues/detail?id=11834
+var cacheBlocker = new DateTime.now().millisecondsSinceEpoch;
+var url = '/root_dart/tests/lib/html/xhr_cross_origin_data.txt?'
+    'cacheBlock=$cacheBlocker';
+
+void validate200Response(xhr) {
+  expect(xhr.status, 200);
+  var data = json.decode(xhr.responseText);
+  expect(data.containsKey('feed'), isTrue);
+  expect(data['feed'].containsKey('entry'), isTrue);
+  expect(data, isMap);
+}
+
+void validate404(xhr) {
+  expect(xhr.status, 404);
+  // We cannot say much about xhr.responseText, most HTTP servers will
+  // include an HTML page explaining the error to a human.
+  String responseText = xhr.responseText;
+  expect(responseText, isNotNull);
+}
+
+Future testXhrNoFile() async {
+  HttpRequest xhr = new HttpRequest();
+  xhr.open("GET", "NonExistingFile", async: true);
+  var completer = new Completer<void>();
+  xhr.onReadyStateChange.listen((event) {
+    if (!completer.isCompleted && xhr.readyState == HttpRequest.DONE) {
+      completer.complete();
+      validate404(xhr);
+    }
+  });
+  xhr.send();
+  await completer;
+}
+
+Future testXhrFile() async {
+  var loadEndCalled = false;
+
+  var xhr = new HttpRequest();
+  xhr.open('GET', url, async: true);
+  var completer = new Completer<void>();
+  xhr.onReadyStateChange.listen((e) {
+    if (!completer.isCompleted && xhr.readyState == HttpRequest.DONE) {
+      completer.complete();
+      validate200Response(xhr);
+
+      Timer.run(expectAsync(() {
+        expect(loadEndCalled, HttpRequest.supportsLoadEndEvent);
+      }));
+    }
+  });
+
+  xhr.onLoadEnd.listen((ProgressEvent e) {
+    loadEndCalled = true;
+  });
+  xhr.send();
+  await completer;
+}
+
+Future testRequestNoFile() async {
+  try {
+    await HttpRequest.request('NonExistingFile');
+    fail('Request should not have succeeded.');
+  } catch (error) {
+    HttpRequest xhr = error.target;
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate404(xhr);
+  }
+}
+
+Future testRequestFile() async {
+  var xhr = await HttpRequest.request(url);
+  expect(xhr.readyState, HttpRequest.DONE);
+  validate200Response(xhr);
+}
+
+Future testRequestOnProgress() async {
+  var progressCalled = false;
+  var xhr = await HttpRequest.request(url, onProgress: (_) {
+    progressCalled = true;
+  });
+  expect(xhr.readyState, HttpRequest.DONE);
+  expect(progressCalled, HttpRequest.supportsProgressEvent);
+  validate200Response(xhr);
+}
+
+Future testRequestWithCredentialsNoFile() async {
+  try {
+    await HttpRequest.request('NonExistingFile', withCredentials: true);
+    fail('Request should not have succeeded.');
+  } catch (error) {
+    HttpRequest xhr = error.target;
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate404(xhr);
+  }
+}
+
+Future testRequestWithCredentialsFile() async {
+  try {
+    HttpRequest xhr = await HttpRequest.request(url, withCredentials: true);
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate200Response(xhr);
+  } catch (_) {
+    fail('Request should succeed.');
+  }
+}
+
+Future testGetStringFile() => HttpRequest.getString(url);
+
+Future testGetStringNoFile() async {
+  try {
+    await HttpRequest.getString('NonExistingFile');
+    fail('Succeeded for non-existing file.');
+  } catch (error) {
+    HttpRequest xhr = error.target;
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate404(xhr);
+  }
+}
+
+Future testRequestResponseTypeArrayBuffer() async {
+  if (Platform.supportsTypedData) {
+    var xhr = await HttpRequest.request(url,
+        responseType: 'arraybuffer',
+        requestHeaders: {'Content-Type': 'text/xml'});
+    expect(xhr.status, 200);
+    var byteBuffer = xhr.response;
+    expect(byteBuffer, isInstanceOf<ByteBuffer>());
+    expect(byteBuffer, isNotNull);
+  }
+}
+
+Future testOverrideMimeType() async {
+  bool gotError = false;
+  try {
+    await HttpRequest.request(url, mimeType: 'application/binary');
+  } catch (_) {
+    gotError = true;
+  }
+  expect(gotError, !HttpRequest.supportsOverrideMimeType);
+}
+
+Future testXhrUpload() async {
+  if (Platform.supportsTypedData) {
+    var xhr = new HttpRequest();
+    var progressCalled = false;
+    xhr.upload.onProgress.listen((e) {
+      progressCalled = true;
+    });
+
+    xhr.open(
+        'POST', '${window.location.protocol}//${window.location.host}/echo');
+
+    // 10MB of payload data w/ a bit of data to make sure it
+    // doesn't get compressed to nil.
+    var data = new Uint8List(1 * 1024 * 1024);
+    for (var i = 0; i < data.length; ++i) {
+      data[i] = i & 0xFF;
+    }
+    xhr.send(new Uint8List.view(data.buffer));
+
+    await xhr.onLoad.first;
+    expect(progressCalled, isTrue, reason: 'onProgress should be fired');
+  }
+}
+
+Future testXhrPostFormData() async {
+  var data = {'name': 'John', 'time': '2 pm'};
+
+  var parts = [];
+  for (var key in data.keys) {
+    parts.add('${Uri.encodeQueryComponent(key)}='
+        '${Uri.encodeQueryComponent(data[key]!)}');
+  }
+  var encodedData = parts.join('&');
+
+  var xhr = await HttpRequest.postFormData(
+      '${window.location.protocol}//${window.location.host}/echo', data);
+  expect(xhr.responseText, encodedData);
+}
+
+Future testRequestResponseTypeBlob() async {
+  if (Platform.supportsTypedData) {
+    var xhr = await HttpRequest.request(url, responseType: 'blob');
+    expect(xhr.status, 200);
+    var blob = xhr.response;
+    expect(blob is Blob, isTrue);
+    expect(blob, isNotNull);
+  }
+}
+
+Future testResponseTypeJson() async {
+  var url = '${window.location.protocol}//${window.location.host}/echo';
+  var data = {
+    'key': 'value',
+    'a': 'b',
+    'one': 2,
+  };
+
+  var xhr = await HttpRequest.request(url,
+      method: 'POST', sendData: json.encode(data), responseType: 'json');
+  expect(xhr.status, 200);
+  var jsonResponse = xhr.response;
+  expect(jsonResponse, data);
+}
+
+Future testResponseHeaders() async {
+  var xhr = await HttpRequest.request(url);
+  var contentTypeHeader = xhr.responseHeaders['content-type'];
+  expect(contentTypeHeader, isNotNull);
+  // Should be like: 'text/plain; charset=utf-8'
+  expect(contentTypeHeader!.contains('text/plain'), isTrue);
+  expect(contentTypeHeader.contains('charset=utf-8'), isTrue);
+}
+
+main() {
+  test('supportsProgressEvent', () {
+    expect(HttpRequest.supportsProgressEvent, isTrue);
+  });
+
+  test('supportsOnLoadEnd', () {
+    expect(HttpRequest.supportsLoadEndEvent, isTrue);
+  });
+
+  test('supportsOverrideMimeType', () {
+    expect(HttpRequest.supportsOverrideMimeType, isTrue);
+  });
+
+  asyncTest(() async {
+    await testXhrNoFile();
+    await testXhrFile();
+    await testRequestNoFile();
+    await testRequestFile();
+    await testRequestOnProgress();
+    await testRequestWithCredentialsNoFile();
+    await testRequestWithCredentialsFile();
+    await testGetStringFile();
+    await testGetStringNoFile();
+    await testRequestResponseTypeArrayBuffer();
+    await testOverrideMimeType();
+    await testXhrUpload();
+    await testXhrPostFormData();
+
+    await testRequestResponseTypeBlob();
+
+    await testResponseTypeJson();
+
+    await testResponseHeaders();
+  });
+}
diff --git a/tests/lib/html/xsltprocessor_test.dart b/tests/lib/html/xsltprocessor_test.dart
new file mode 100644
index 0000000..61cb5a0
--- /dev/null
+++ b/tests/lib/html/xsltprocessor_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.
+
+import 'dart:html';
+
+import 'package:expect/minitest.dart';
+
+main() {
+  group('supported', () {
+    test('supported', () {
+      expect(XsltProcessor.supported, true);
+    });
+  });
+
+  group('functional', () {
+    var isXsltProcessor =
+        predicate((x) => x is XsltProcessor, 'is an XsltProcessor');
+
+    var expectation = XsltProcessor.supported ? returnsNormally : throws;
+
+    test('constructorTest', () {
+      expect(() {
+        var processor = new XsltProcessor();
+        expect(processor, isNotNull);
+        expect(processor, isXsltProcessor);
+      }, expectation);
+    });
+  });
+}
diff --git a/tests/lib/isolate/function_send1_test.dart b/tests/lib/isolate/function_send1_test.dart
index b25042e..1955c96 100644
--- a/tests/lib/isolate/function_send1_test.dart
+++ b/tests/lib/isolate/function_send1_test.dart
@@ -135,12 +135,12 @@
 void testUnsendable(name, func) {
   asyncStart();
   Isolate.spawnUri(Uri.parse("function_send_test.dart"), [], func)
-      .then((v) => throw "allowed spawn direct?", onError: (e, s) {
+      .then<void>((v) => throw "allowed spawn direct?", onError: (e, s) {
     asyncEnd();
   });
   asyncStart();
   Isolate.spawnUri(Uri.parse("function_send_test.dart"), [], [func])
-      .then((v) => throw "allowed spawn wrapped?", onError: (e, s) {
+      .then<void>((v) => throw "allowed spawn wrapped?", onError: (e, s) {
     asyncEnd();
   });
 }
diff --git a/tests/lib/isolate/function_send_test.dart b/tests/lib/isolate/function_send_test.dart
index 24e9d77..4b22fa1 100644
--- a/tests/lib/isolate/function_send_test.dart
+++ b/tests/lib/isolate/function_send_test.dart
@@ -175,12 +175,12 @@
 
 void testUnsendable(name, func) {
   asyncStart();
-  Isolate.spawn(nop, func).then((v) => throw "allowed spawn direct?",
+  Isolate.spawn(nop, func).then<void>((v) => throw "allowed spawn direct?",
       onError: (e, s) {
     asyncEnd();
   });
   asyncStart();
-  Isolate.spawn(nop, [func]).then((v) => throw "allowed spawn wrapped?",
+  Isolate.spawn(nop, [func]).then<void>((v) => throw "allowed spawn wrapped?",
       onError: (e, s) {
     asyncEnd();
   });
@@ -210,7 +210,7 @@
     } finally {
       p.send(0); //   Closes echo port.
     }
-  }).then((p) => throw "unreachable 2", onError: (e, s) {
+  }).then<void>((p) => throw "unreachable 2", onError: (e, s) {
     asyncEnd();
   });
 }
diff --git a/tests/lib/isolate/issue_21398_parent_isolate_test.dart b/tests/lib/isolate/issue_21398_parent_isolate_test.dart
index 34e91de..5264827 100644
--- a/tests/lib/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib/isolate/issue_21398_parent_isolate_test.dart
@@ -29,8 +29,10 @@
   // First spawn an isolate using spawnURI and have it
   // send back a "non-literal" like object.
   asyncStart();
-  Isolate.spawnUri(Uri.parse('issue_21398_child_isolate.dart'), [],
-      [new FromMainIsolate(), receive1.sendPort]).catchError((error) {
+  Future<Isolate?>.value(Isolate.spawnUri(
+      Uri.parse('issue_21398_child_isolate.dart'),
+      [],
+      [new FromMainIsolate(), receive1.sendPort])).catchError((error) {
     Expect.isTrue(error is ArgumentError);
     asyncEnd();
   });
diff --git a/tests/lib/isolate/native_wrapper_message_test.dart b/tests/lib/isolate/native_wrapper_message_test.dart
index 2b663d5..366a84b 100644
--- a/tests/lib/isolate/native_wrapper_message_test.dart
+++ b/tests/lib/isolate/native_wrapper_message_test.dart
@@ -28,7 +28,7 @@
   var snd = Isolate.spawn(echo, msg);
 
   asyncStart();
-  snd.catchError((e) {
+  Future<Isolate?>.value(snd).catchError((e) {
     Expect.isTrue(e is ArgumentError);
     Expect.isTrue("$e".contains("NativeWrapper"));
     port.close();
diff --git a/tests/lib/isolate/stacktrace_message_test.dart b/tests/lib/isolate/stacktrace_message_test.dart
index 41a0820..b8ab5ab 100644
--- a/tests/lib/isolate/stacktrace_message_test.dart
+++ b/tests/lib/isolate/stacktrace_message_test.dart
@@ -14,7 +14,7 @@
   ReceivePort reply = new ReceivePort();
   Isolate.spawn(runTest, reply.sendPort);
   reply.first.then((pair) {
-    StackTrace stack = pair[0];
+    StackTrace? stack = pair[0];
     String stackString = pair[1];
     if (stack == null) {
       print("Failed to send stack-trace");
diff --git a/tests/lib/js/instanceof_test.dart b/tests/lib/js/instanceof_test.dart
new file mode 100644
index 0000000..65bbd21
--- /dev/null
+++ b/tests/lib/js/instanceof_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.
+
+@JS()
+library instanceof_test;
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+import 'dart:js_util';
+
+@JS()
+external void eval(String code);
+
+@JS('Class')
+class Class {
+  external Class();
+  external Constructor get constructor;
+}
+
+@JS()
+class Constructor {}
+
+void main() {
+  eval("self.Class = function Class() {}");
+  var o = new Class();
+  var constructor = o.constructor;
+  Expect.isTrue(instanceof(o, constructor));
+}
diff --git a/tests/lib/lib_vm.status b/tests/lib/lib_vm.status
index c4207d9..92cc427 100644
--- a/tests/lib/lib_vm.status
+++ b/tests/lib/lib_vm.status
@@ -21,9 +21,7 @@
 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.
-js/datetime_roundtrip_test: CompileTimeError
-js/null_test: CompileTimeError
-js/prototype_access_test: CompileTimeError
+js/*: SkipByDesign
 mirrors/deferred_type_test: CompileTimeError
 mirrors/generic_bounded_by_type_parameter_test/02: MissingCompileTimeError
 mirrors/generic_bounded_test/01: MissingCompileTimeError
diff --git a/tests/lib/math/rectangle_test.dart b/tests/lib/math/rectangle_test.dart
index f6b5ed2..f6cf2b2 100644
--- a/tests/lib/math/rectangle_test.dart
+++ b/tests/lib/math/rectangle_test.dart
@@ -68,8 +68,8 @@
     var r1 = createRectangle(test[1]);
     var expected = createRectangle(test[2]);
 
-    Expect.equals(expected, r0.intersection(r1));
-    Expect.equals(expected, r1.intersection(r0));
+    Expect.equals(expected, r0?.intersection(r1!));
+    Expect.equals(expected, r1?.intersection(r0!));
   }
 }
 
@@ -114,8 +114,8 @@
     var r1 = createRectangle(test[1]);
     var expected = createRectangle(test[2]);
 
-    Expect.equals(expected, r0.boundingBox(r1));
-    Expect.equals(expected, r1.boundingBox(r0));
+    Expect.equals(expected, r0?.boundingBox(r1!));
+    Expect.equals(expected, r1?.boundingBox(r0!));
   }
 }
 
diff --git a/tests/lib/mirrors/synthetic_accessor_properties_test.dart b/tests/lib/mirrors/synthetic_accessor_properties_test.dart
index 9d1d6e3..cb32c8a 100644
--- a/tests/lib/mirrors/synthetic_accessor_properties_test.dart
+++ b/tests/lib/mirrors/synthetic_accessor_properties_test.dart
@@ -45,8 +45,7 @@
   Expect.equals(reflectClass(num), mm.returnType);
   Expect.listEquals([], mm.parameters);
 
-  mm = cm.instanceMembers[const Symbol('finalInstanceField=')] as MethodMirror;
-  Expect.isNull(mm);
+  Expect.isNull(cm.instanceMembers[const Symbol('finalInstanceField=')]);
 
   mm = cm.staticMembers[#staticField] as MethodMirror;
   expect('Method(s(staticField) in s(C), synthetic, static, getter)', mm);
@@ -67,6 +66,5 @@
   Expect.equals(reflectClass(int), mm.returnType);
   Expect.listEquals([], mm.parameters);
 
-  mm = cm.staticMembers[const Symbol('finalStaticField=')] as MethodMirror;
-  Expect.isNull(mm);
+  Expect.isNull(cm.staticMembers[const Symbol('finalStaticField=')]);
 }
diff --git a/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart b/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart
index c6aa721..e2899d7 100644
--- a/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart
+++ b/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart
@@ -72,7 +72,6 @@
 Future testWithThreeParams() async {
   setupFunc();
 
-  var playFuture = video.onCanPlay.first;
   video.onError.listen((_) {
     throw ('URL failed to load.');
   });
@@ -86,7 +85,13 @@
     window.console.log('Video is not supported on this system.');
   }
 
-  await playFuture;
+  // Without user interaction, playing the video requires autoplay to be enabled
+  // and autoplay can only be enabled if muted. We loop the video so there is
+  // always an active frame that can be drawn.
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
   context.drawImage(video, 50, 50);
 
   expectPixelFilled(50, 50);
@@ -101,7 +106,6 @@
 Future testWithFiveParams() async {
   setupFunc();
 
-  var playFuture = video.onCanPlay.first;
   video.onError.listen((_) {
     throw ('URL failed to load.');
   });
@@ -117,7 +121,10 @@
     window.console.log('Video is not supported on this system.');
   }
 
-  await playFuture;
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
   context.drawImageToRect(video, new Rectangle(50, 50, 20, 20));
 
   expectPixelFilled(50, 50);
@@ -134,7 +141,6 @@
 Future testWithNineParams() async {
   setupFunc();
 
-  var playFuture = video.onCanPlay.first;
   video.onError.listen((_) {
     throw ('URL failed to load.');
   });
@@ -150,7 +156,10 @@
     window.console.log('Video is not supported on this system.');
   }
 
-  await playFuture;
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
   context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
       sourceRect: new Rectangle(2, 2, 6, 6));
 
@@ -171,7 +180,6 @@
   video = new VideoElement();
   canvas = new CanvasElement();
 
-  var playFuture = video.onCanPlay.first;
   video.onError.listen((_) {
     throw ('URL failed to load.');
   });
@@ -187,7 +195,10 @@
     window.console.log('Video is not supported on this system.');
   }
 
-  await playFuture;
+  video.loop = true;
+  video.muted = true;
+  video.autoplay = true;
+  await video.play();
   context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
       sourceRect: new Rectangle(2, 2, 6, 6));
 
diff --git a/tests/lib_2/html/element_classes_svg_test.dart b/tests/lib_2/html/element_classes_svg_test.dart
index 23a6de0..3beb9d7 100644
--- a/tests/lib_2/html/element_classes_svg_test.dart
+++ b/tests/lib_2/html/element_classes_svg_test.dart
@@ -139,7 +139,7 @@
   test('listAdd', () {
     var elements = elementsSetup();
     var added = elements.classes.add('lassie');
-    expect(added, isNull);
+    expect(added, isFalse);
 
     expect(view(elements.classes), '[classy, foo, lassie, quux, qux, yes]');
     expect(
diff --git a/tests/lib_2/html/js_typed_interop_default_arg_static_test.dart b/tests/lib_2/html/js_typed_interop_default_arg_static_test.dart
new file mode 100644
index 0000000..25adc67
--- /dev/null
+++ b/tests/lib_2/html/js_typed_interop_default_arg_static_test.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.
+
+@JS()
+library js_typed_interop_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+_injectJs() {
+  document.body.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  var Foo = {
+    get42: function(b) { return arguments.length >= 1 ? b : 42; }
+  };
+""");
+}
+
+@JS()
+class Foo {
+  external static num get42([num b = 3
+      // TODO(41375): This should be a static error. It's invalid to have a
+      // default value.
+      ]);
+}
+
+main() {
+  _injectJs();
+
+  test('call tearoff from dart with default', () {
+    var f = Foo.get42;
+    // Note: today both SSA and CPS remove the extra argument on static calls,
+    // but they fail to do so on tearoffs.
+    expect(f(), 3);
+    // TODO(41375): Remove this once the above is resolved. This is temporary
+    // to track this test failure.
+    throw ("This test should not execute. It should fail to compile above.");
+  });
+}
diff --git a/tests/lib_2/html/js_typed_interop_default_arg_test.dart b/tests/lib_2/html/js_typed_interop_default_arg_test.dart
index 5d47a50..b37df7d 100644
--- a/tests/lib_2/html/js_typed_interop_default_arg_test.dart
+++ b/tests/lib_2/html/js_typed_interop_default_arg_test.dart
@@ -15,19 +15,14 @@
     ..type = 'text/javascript'
     ..innerHtml = r"""
   var Foo = {
-    get42: function(b) { return arguments.length >= 1 ? b : 42; },
-    get43: function(b) { return arguments.length >= 1 ? b : 43; }
+    get42: function(b) { return arguments.length >= 1 ? b : 42; }
   };
 """);
 }
 
 @JS()
 class Foo {
-  // Note: it's invalid to provide a default value.
-  external static num get42([num b
-      = 3 // //# default_value: compile-time error
-      ]);
-  external static num get43([num b]);
+  external static num get42([num b]);
 }
 
 main() {
@@ -40,16 +35,11 @@
 
   test('call tearoff from dart with arg', () {
     var f = Foo.get42;
-    expect(f(2), 2); //# explicit_argument: ok
+    expect(f(2), 2);
   });
 
-  test('call tearoff from dart with default', () {
+  test('call tearoff from dart with no arg', () {
     var f = Foo.get42;
-    // Note: today both SSA and CPS remove the extra argument on static calls,
-    // but they fail to do so on tearoffs.
-    expect(f(), 3); //# default_value: continued
-
-    f = Foo.get43;
-    expect(f(), 43);
+    expect(f(), 42);
   });
 }
diff --git a/tests/lib_2/html/js_typed_interop_type1_test.dart b/tests/lib_2/html/js_typed_interop_type1_test.dart
index e10aea3..ca82833 100644
--- a/tests/lib_2/html/js_typed_interop_type1_test.dart
+++ b/tests/lib_2/html/js_typed_interop_type1_test.dart
@@ -45,5 +45,5 @@
   var f = new F(6);
 
   Expect.equals(testA(a), 1);
-  Expect.equals(testF(f), 6); //# 01: ok
+  Expect.equals(testF(f), 6);
 }
diff --git a/tests/lib_2/html/js_typed_interop_type2_test.dart b/tests/lib_2/html/js_typed_interop_type2_test.dart
index aa6f3bf..b9558bb 100644
--- a/tests/lib_2/html/js_typed_interop_type2_test.dart
+++ b/tests/lib_2/html/js_typed_interop_type2_test.dart
@@ -41,5 +41,5 @@
   dynamic d = new D(foo: 4);
   var f = new F(6);
   Expect.equals(testC(d), 4);
-  Expect.equals(testF(f), 6); //# 01: ok
+  Expect.equals(testF(f), 6);
 }
diff --git a/tests/lib_2/js/instanceof_test.dart b/tests/lib_2/js/instanceof_test.dart
new file mode 100644
index 0000000..65bbd21
--- /dev/null
+++ b/tests/lib_2/js/instanceof_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.
+
+@JS()
+library instanceof_test;
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+import 'dart:js_util';
+
+@JS()
+external void eval(String code);
+
+@JS('Class')
+class Class {
+  external Class();
+  external Constructor get constructor;
+}
+
+@JS()
+class Constructor {}
+
+void main() {
+  eval("self.Class = function Class() {}");
+  var o = new Class();
+  var constructor = o.constructor;
+  Expect.isTrue(instanceof(o, constructor));
+}
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index 4fd19d7..78b9986 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -12,9 +12,7 @@
 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.
-js/datetime_roundtrip_test: CompileTimeError
-js/null_test: CompileTimeError
-js/prototype_access_test: CompileTimeError
+js/*: SkipByDesign
 mirrors/deferred_type_test: CompileTimeError
 mirrors/generic_bounded_by_type_parameter_test/02: MissingCompileTimeError
 mirrors/generic_bounded_test/01: MissingCompileTimeError
diff --git a/tests/modular/subclass/f1.dart b/tests/modular/subclass/f1.dart
index 00f7709..2f8ed7a 100644
--- a/tests/modular/subclass/f1.dart
+++ b/tests/modular/subclass/f1.dart
@@ -1,10 +1,11 @@
 // 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 'f0.dart';
 
 class B1 extends A0 {
-  A0 get foo => null;
+  A0 get foo => A0();
 }
 
 A0 createA0() => new A0();
diff --git a/tests/standalone/io/directory_error_test.dart b/tests/standalone/io/directory_error_test.dart
index 892b0a6..159d827 100644
--- a/tests/standalone/io/directory_error_test.dart
+++ b/tests/standalone/io/directory_error_test.dart
@@ -34,7 +34,7 @@
   Expect.throws(() => inNonExistent.createSync(),
       (e) => checkCreateInNonExistentFileSystemException(e));
 
-  inNonExistent.create().catchError((error) {
+  Future<Directory?>.value(inNonExistent.create()).catchError((error) {
     checkCreateInNonExistentFileSystemException(error);
     done();
   });
@@ -59,7 +59,8 @@
   Expect.throws(() => nonExistent.createTempSync('tempdir'),
       (e) => checkCreateTempInNonExistentFileSystemException(e));
 
-  nonExistent.createTemp('tempdir').catchError((error) {
+  Future<Directory?>.value(nonExistent.createTemp('tempdir'))
+      .catchError((error) {
     checkCreateTempInNonExistentFileSystemException(error);
     done();
   });
@@ -79,7 +80,7 @@
   Expect.throws(() => nonExistent.deleteSync(),
       (e) => checkDeleteNonExistentFileSystemException(e));
 
-  nonExistent.delete().catchError((error) {
+  Future<FileSystemEntity?>.value(nonExistent.delete()).catchError((error) {
     checkDeleteNonExistentFileSystemException(error);
     done();
   });
@@ -100,7 +101,8 @@
   Expect.throws(() => nonExistent.deleteSync(recursive: true),
       (e) => checkDeleteRecursivelyNonExistentFileSystemException(e));
 
-  nonExistent.delete(recursive: true).catchError((error) {
+  Future<FileSystemEntity?>.value(nonExistent.delete(recursive: true))
+      .catchError((error) {
     checkDeleteRecursivelyNonExistentFileSystemException(error);
     done();
   });
diff --git a/tests/standalone/io/directory_test.dart b/tests/standalone/io/directory_test.dart
index ddd3760..5c29207 100644
--- a/tests/standalone/io/directory_test.dart
+++ b/tests/standalone/io/directory_test.dart
@@ -196,8 +196,8 @@
           }
         }
 
-        long.delete().catchError(onError);
-        long.delete(recursive: true).catchError(onError);
+        Future<void>.value(long.delete()).catchError(onError);
+        Future<void>.value(long.delete(recursive: true)).catchError(onError);
       });
     });
   }
@@ -453,7 +453,7 @@
 class NestedTempDirectoryTest {
   List<Directory> createdDirectories;
 
-  NestedTempDirectoryTest.run() : createdDirectories = new List<Directory>() {
+  NestedTempDirectoryTest.run() : createdDirectories = <Directory>[] {
     Directory.systemTemp.createTemp('dart_directory').then(createPhaseCallback);
   }
 
@@ -511,7 +511,7 @@
 
   asyncStart();
   var future = new Directory(location).createTemp('dart_tempdir');
-  future.catchError((_) => asyncEnd());
+  Future<Directory?>.value(future).catchError((_) => asyncEnd());
 }
 
 testCreateExistingSync() {
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index 7583b71..1ba41eb 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -74,7 +74,7 @@
     File file = new File(filename);
     Expect.isTrue('$file'.contains(file.path));
     var subscription;
-    List<int> buffer = new List<int>();
+    List<int> buffer = <int>[];
     subscription = file.openRead().listen((d) {
       buffer.addAll(d);
       if (buffer.length >= 12) {
@@ -105,7 +105,7 @@
     int bytesRead;
 
     var file1 = new File(inFilename);
-    List<int> buffer = new List<int>();
+    List<int> buffer = <int>[];
     file1.openRead().listen((d) {
       buffer.addAll(d);
     }, onDone: () {
@@ -118,7 +118,7 @@
       output.flush().then((_) => output.close());
       output.done.then((_) {
         // Now read the contents of the file just written.
-        List<int> buffer2 = new List<int>();
+        List<int> buffer2 = <int>[];
         new File(outFilename).openRead().listen((d) {
           buffer2.addAll(d);
         }, onDone: () {
@@ -819,11 +819,11 @@
     }
 
     read(0, 3, 3, [1, 2, 3]);
-    read(0, 2, 2, [1, 2, null]);
-    read(1, 2, 1, [null, 1, null]);
-    read(1, 3, 2, [null, 1, 2]);
-    read(2, 3, 1, [null, null, 1]);
-    read(0, 0, 0, [null, null, null]);
+    read(0, 2, 2, [1, 2, -1]);
+    read(1, 2, 1, [-1, 1, -1]);
+    read(1, 3, 2, [-1, 1, 2]);
+    read(2, 3, 1, [-1, -1, 1]);
+    read(0, 0, 0, [-1, -1, -1]);
 
     openedFile.closeSync();
   }
@@ -1296,7 +1296,7 @@
     int done = 0;
     bool error = false;
     void getLength() {
-      file.length().catchError((e) {
+      Future<int?>.value(file.length()).catchError((e) {
         error = true;
       }).whenComplete(() {
         if (++done == 2) {
@@ -1564,9 +1564,12 @@
         .then((_) => lift(Expect.isFalse)(newfile.exists()))
         .then((_) {
       if (Platform.operatingSystem != "windows") {
-        new Link(source).create(dest).then((_) => file.rename("xxx")).then((_) {
+        Future<File?>.value(new Link(source)
+            .create(dest)
+            .then((_) => file.rename("xxx"))
+            .then((_) {
           throw "Rename of broken link succeeded";
-        }).catchError((e) {
+        })).catchError((e) {
           Expect.isTrue(e is FileSystemException);
           asyncTestDone("testRename$targetExists");
         });
diff --git a/tests/standalone/io/gzip_format_exception_test.dart b/tests/standalone/io/gzip_format_exception_test.dart
new file mode 100644
index 0000000..2b00af7
--- /dev/null
+++ b/tests/standalone/io/gzip_format_exception_test.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:io';
+
+import 'package:expect/expect.dart';
+
+// This tests whether a FormatException is thrown on bad data.
+main() {
+  Expect.throwsFormatException(() => GZipCodec().decoder.convert([10, 20, 30]));
+}
diff --git a/tests/standalone/io/http_ban_http_embedder_test.dart b/tests/standalone/io/http_ban_http_embedder_test.dart
new file mode 100644
index 0000000..7fd3cb3
--- /dev/null
+++ b/tests/standalone/io/http_ban_http_embedder_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.
+
+// SharedOptions=-Ddart.library.io.allow_http=false
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+
+import 'http_ban_http_normal_test.dart';
+import 'http_bind_test.dart';
+
+Future<void> testWithHostname() async {
+  await testBanHttp(await getLocalHostIP(), (httpClient, httpUri) async {
+    asyncExpectThrows(
+        () async => await httpClient.getUrl(httpUri), (e) => e is StateError);
+    asyncExpectThrows(
+        () async => await runZoned(() => httpClient.getUrl(httpUri),
+            zoneValues: {#dart.library.io.allow_http: 'foo'}),
+        (e) => e is StateError);
+    asyncExpectThrows(
+        () async => await runZoned(() => httpClient.getUrl(httpUri),
+            zoneValues: {#dart.library.io.allow_http: false}),
+        (e) => e is StateError);
+    await asyncTest(() => runZoned(() => httpClient.getUrl(httpUri),
+        zoneValues: {#dart.library.io.allow_http: true}));
+  });
+}
+
+Future<void> testWithLoopback() async {
+  await testBanHttp("127.0.0.1", (httpClient, uri) async {
+    await asyncTest(
+        () => httpClient.getUrl(Uri.parse('http://localhost:${uri.port}')));
+    await asyncTest(
+        () => 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>[
+    testWithHostname(),
+    testWithLoopback(),
+    testWithIPv6(),
+    testWithHTTPS(),
+  ]).then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/http_ban_http_normal_test.dart b/tests/standalone/io/http_ban_http_normal_test.dart
new file mode 100644
index 0000000..118dd4c
--- /dev/null
+++ b/tests/standalone/io/http_ban_http_normal_test.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.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.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();
+  }
+}
+
+main() async {
+  await asyncTest(() async {
+    final host = await getLocalHostIP();
+    // Normal HTTP request succeeds.
+    await testBanHttp(host, (httpClient, uri) async {
+      await asyncTest(() => httpClient.getUrl(uri));
+    });
+    // We can ban HTTP explicitly.
+    await testBanHttp(host, (httpClient, uri) async {
+      asyncExpectThrows(
+          () async => await runZoned(() => httpClient.getUrl(uri),
+              zoneValues: {#dart.library.io.allow_http: false}),
+          (e) => e is StateError);
+    });
+  });
+}
diff --git a/tests/standalone/io/http_client_connect_test.dart b/tests/standalone/io/http_client_connect_test.dart
index 284c441d..79351cd 100644
--- a/tests/standalone/io/http_client_connect_test.dart
+++ b/tests/standalone/io/http_client_connect_test.dart
@@ -55,7 +55,9 @@
 void testGetInvalidHost() {
   asyncStart();
   var client = new HttpClient();
-  client.get("__SOMETHING_INVALID__", 8888, "/").catchError((error) {
+  Future<HttpClientRequest?>.value(
+          client.get("__SOMETHING_INVALID__", 8888, "/"))
+      .catchError((error) {
     client.close();
     asyncEnd();
   });
diff --git a/tests/standalone/io/http_client_request_test.dart b/tests/standalone/io/http_client_request_test.dart
index dae2b2a..43fe994 100644
--- a/tests/standalone/io/http_client_request_test.dart
+++ b/tests/standalone/io/http_client_request_test.dart
@@ -47,7 +47,7 @@
     request.contentLength = 0;
     request.add([0]);
     request.close();
-    request.done.catchError((error) {
+    Future<HttpClientResponse?>.value(request.done).catchError((error) {
       asyncEnd();
     }, test: (e) => e is HttpException);
     return request.done;
@@ -59,7 +59,7 @@
     request.add([0, 0, 0]);
     request.add([0, 0, 0]);
     request.close();
-    request.done.catchError((error) {
+    Future<HttpClientResponse?>.value(request.done).catchError((error) {
       asyncEnd();
     }, test: (e) => e is HttpException);
     return request.done;
@@ -72,7 +72,7 @@
     request.add(new Uint8List(64 * 1024));
     request.add(new Uint8List(64 * 1024));
     request.close();
-    request.done.catchError((error) {
+    Future<HttpClientResponse?>.value(request.done).catchError((error) {
       asyncEnd();
     }, test: (e) => e is HttpException);
     return request.done;
@@ -84,7 +84,7 @@
   testClientRequest((request) {
     request.contentLength = 5;
     request.close();
-    request.done.catchError((error) {
+    Future<HttpClientResponse?>.value(request.done).catchError((error) {
       asyncEnd();
     }, test: (e) => e is HttpException);
     return request.done;
@@ -95,7 +95,7 @@
     request.contentLength = 5;
     request.add([0]);
     request.close();
-    request.done.catchError((error) {
+    Future<HttpClientResponse?>.value(request.done).catchError((error) {
       asyncEnd();
     }, test: (e) => e is HttpException);
     return request.done;
diff --git a/tests/standalone/io/http_close_test.dart b/tests/standalone/io/http_close_test.dart
index d07175f..7de6f94 100644
--- a/tests/standalone/io/http_close_test.dart
+++ b/tests/standalone/io/http_close_test.dart
@@ -132,11 +132,12 @@
     });
     var client = HttpClient();
     for (int i = 0; i < connections; i++) {
-      client.post("127.0.0.1", server.port, "/").then((request) {
+      Future<HttpClientResponse?>.value(
+          client.post("127.0.0.1", server.port, "/").then((request) {
         request.contentLength = 110;
         request.write("0123456789");
         return request.close();
-      }).catchError((_) {
+      })).catchError((_) {
         clientErrors++;
       });
     }
diff --git a/tests/standalone/io/http_cookie_date_test.dart b/tests/standalone/io/http_cookie_date_test.dart
index 6b94254..fd5de9a 100644
--- a/tests/standalone/io/http_cookie_date_test.dart
+++ b/tests/standalone/io/http_cookie_date_test.dart
@@ -16,6 +16,7 @@
 import "package:expect/expect.dart";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index 33c28a3..8d41dd2 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -17,6 +17,7 @@
 import "package:expect/expect.dart";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index 6951916..4f27fcf 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -17,6 +17,7 @@
 import "package:expect/expect.dart";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
index fbdb5ed..58ecb8e 100644
--- a/tests/standalone/io/http_proxy_test.dart
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -274,23 +274,23 @@
   HttpClient client = new HttpClient(context: clientContext);
 
   client.findProxy = (Uri uri) => "";
-  client
-      .getUrl(Uri.parse("http://www.google.com/test"))
+  Future<HttpClientRequest?>.value(
+          client.getUrl(Uri.parse("http://www.google.com/test")))
       .catchError((error) {}, test: (e) => e is HttpException);
 
   client.findProxy = (Uri uri) => "XXX";
-  client
-      .getUrl(Uri.parse("http://www.google.com/test"))
+  Future<HttpClientRequest?>.value(
+          client.getUrl(Uri.parse("http://www.google.com/test")))
       .catchError((error) {}, test: (e) => e is HttpException);
 
   client.findProxy = (Uri uri) => "PROXY www.google.com";
-  client
-      .getUrl(Uri.parse("http://www.google.com/test"))
+  Future<HttpClientRequest?>.value(
+          client.getUrl(Uri.parse("http://www.google.com/test")))
       .catchError((error) {}, test: (e) => e is HttpException);
 
   client.findProxy = (Uri uri) => "PROXY www.google.com:http";
-  client
-      .getUrl(Uri.parse("http://www.google.com/test"))
+  Future<HttpClientRequest?>.value(
+          client.getUrl(Uri.parse("http://www.google.com/test")))
       .catchError((error) {}, test: (e) => e is HttpException);
 }
 
diff --git a/tests/standalone/io/http_read_test.dart b/tests/standalone/io/http_read_test.dart
index 6c6a103..b6f4a7e 100644
--- a/tests/standalone/io/http_read_test.dart
+++ b/tests/standalone/io/http_read_test.dart
@@ -187,7 +187,7 @@
         return request.close();
       }).then((response) {
         Expect.equals(HttpStatus.ok, response.statusCode);
-        List<int> body = new List<int>();
+        List<int> body = <int>[];
         response.listen(body.addAll, onDone: () {
           Expect.equals(data, new String.fromCharCodes(body));
           count++;
diff --git a/tests/standalone/io/http_redirect_test.dart b/tests/standalone/io/http_redirect_test.dart
index 9b19d73..c008a34 100644
--- a/tests/standalone/io/http_redirect_test.dart
+++ b/tests/standalone/io/http_redirect_test.dart
@@ -337,9 +337,9 @@
   setupServer().then((server) {
     HttpClient client = new HttpClient();
 
-    client
-        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/1"))
-        .then((HttpClientRequest request) => request.close())
+    Future<HttpClientResponse?>.value(client
+            .getUrl(Uri.parse("http://127.0.0.1:${server.port}/1"))
+            .then((HttpClientRequest request) => request.close()))
         .catchError((error) {
       Expect.equals(5, error.redirects.length);
       server.close();
@@ -353,9 +353,9 @@
     HttpClient client = new HttpClient();
 
     int redirectCount = 0;
-    client
-        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/A"))
-        .then((HttpClientRequest request) => request.close())
+    Future<HttpClientResponse?>.value(client
+            .getUrl(Uri.parse("http://127.0.0.1:${server.port}/A"))
+            .then((HttpClientRequest request) => request.close()))
         .catchError((error) {
       Expect.equals(2, error.redirects.length);
       server.close();
diff --git a/tests/standalone/io/http_reuse_server_port_test.dart b/tests/standalone/io/http_reuse_server_port_test.dart
index afcaf61..d78e29f 100644
--- a/tests/standalone/io/http_reuse_server_port_test.dart
+++ b/tests/standalone/io/http_reuse_server_port_test.dart
@@ -49,7 +49,7 @@
   asyncStart();
   runServer(0, 10, true).then((int port) {
     // Stress test the port reusing it 10 times.
-    Future.forEach(new List(10), (_) {
+    Future.forEach(List.filled(10, null), (_) {
       return runServer(port, 10, true);
     }).then((_) {
       asyncEnd();
@@ -61,7 +61,7 @@
   asyncStart();
   runServer(0, 10, false).then((int port) {
     // Stress test the port reusing it 10 times.
-    Future.forEach(new List(10), (_) {
+    Future.forEach(List.filled(10, null), (_) {
       return runServer(port, 10, false);
     }).then((_) {
       asyncEnd();
diff --git a/tests/standalone/io/http_server_early_client_close_test.dart b/tests/standalone/io/http_server_early_client_close_test.dart
index 33ab0e1..bc1403a 100644
--- a/tests/standalone/io/http_server_early_client_close_test.dart
+++ b/tests/standalone/io/http_server_early_client_close_test.dart
@@ -75,7 +75,7 @@
 }
 
 void testEarlyClose1() {
-  List<EarlyCloseTest> tests = new List<EarlyCloseTest>();
+  List<EarlyCloseTest> tests = <EarlyCloseTest>[];
   void add(Object data, [String? exception, bool expectRequest = false]) {
     tests.add(new EarlyCloseTest(data, exception, expectRequest));
   }
diff --git a/tests/standalone/io/http_shutdown_test.dart b/tests/standalone/io/http_shutdown_test.dart
index c04a537..68fcbde 100644
--- a/tests/standalone/io/http_shutdown_test.dart
+++ b/tests/standalone/io/http_shutdown_test.dart
@@ -156,7 +156,7 @@
             // TODO(sgjesse): Make this test work with
             //request.response instead of request.close() return
             //return request.response;
-            request.done.catchError((e) {});
+            Future<HttpClientResponse?>.value(request.done).catchError((e) {});
             return request.close();
           })
           .then((response) {})
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
index 87dda6a..a461480 100644
--- a/tests/standalone/io/raw_secure_server_socket_test.dart
+++ b/tests/standalone/io/raw_secure_server_socket_test.dart
@@ -528,8 +528,9 @@
         }
 
         try {
-          RawSecureSocket.secureServer(client, serverContext,
-                  subscription: subscription)
+          Future<RawSecureSocket?>.value(RawSecureSocket.secureServer(
+                  client, serverContext,
+                  subscription: subscription))
               .catchError((_) {})
               .whenComplete(() {
             if (pausedServer) {
@@ -556,7 +557,8 @@
           subscription.pause();
         }
         try {
-          RawSecureSocket.secure(socket, subscription: subscription)
+          Future<RawSecureSocket?>.value(
+                  RawSecureSocket.secure(socket, subscription: subscription))
               .catchError((_) {})
               .whenComplete(() {
             if (pausedClient) {
diff --git a/tests/standalone/io/regress_8828_test.dart b/tests/standalone/io/regress_8828_test.dart
index 22225c8..de9891d 100644
--- a/tests/standalone/io/regress_8828_test.dart
+++ b/tests/standalone/io/regress_8828_test.dart
@@ -24,7 +24,7 @@
     client.get("127.0.0.1", server.port, "/").then((HttpClientRequest request) {
       return request.close();
     }).then((HttpClientResponse response) {
-      List<int> body = new List();
+      List<int> body = [];
       response.listen(body.addAll, onDone: () {
         Expect.equals(
             "first line\nsecond line\n", new String.fromCharCodes(body));
diff --git a/tests/standalone/io/socket_cancel_connect_test.dart b/tests/standalone/io/socket_cancel_connect_test.dart
index 7a2e112..a2c0491 100644
--- a/tests/standalone/io/socket_cancel_connect_test.dart
+++ b/tests/standalone/io/socket_cancel_connect_test.dart
@@ -19,6 +19,7 @@
   Socket.startConnect("8.8.8.7", 80).then((task) {
     task.socket.timeout(timeout, onTimeout: () {
       task.cancel();
+      return task.socket;
     });
     task.socket.then((socket) {
       Expect.fail("Unexpected connection made.");
diff --git a/tests/standalone/io/socket_finalizer_test.dart b/tests/standalone/io/socket_finalizer_test.dart
index 5718559..c82be22 100644
--- a/tests/standalone/io/socket_finalizer_test.dart
+++ b/tests/standalone/io/socket_finalizer_test.dart
@@ -48,6 +48,6 @@
 }
 
 @pragma('vm:never-inline')
-produceGarbage() => all.add(List(1024));
+produceGarbage() => all.add(List.filled(1024, null));
 
 final all = [];
diff --git a/tests/standalone/io/socket_invalid_arguments_test.dart b/tests/standalone/io/socket_invalid_arguments_test.dart
index 3e8b889..8e44afd 100644
--- a/tests/standalone/io/socket_invalid_arguments_test.dart
+++ b/tests/standalone/io/socket_invalid_arguments_test.dart
@@ -28,30 +28,6 @@
   }
 }
 
-testAdd(buffer) {
-  asyncStart();
-  asyncStart();
-  ServerSocket.bind("127.0.0.1", 0).then((server) {
-    server.listen((socket) => socket.destroy());
-    Socket.connect("127.0.0.1", server.port).then((socket) {
-      int errors = 0;
-      socket.done.catchError((e) {
-        errors++;
-      }).then((_) {
-        Expect.equals(1, errors);
-        asyncEnd();
-        server.close();
-      });
-      socket.listen((_) {}, onError: (error) {
-        Expect.fail("Error on stream");
-      }, onDone: () {
-        asyncEnd();
-      });
-      socket.add(buffer);
-    });
-  });
-}
-
 testServerSocketCreation(address, port, backlog) {
   asyncStart();
   var server;
@@ -66,16 +42,8 @@
 
 main() {
   asyncStart();
-  testSocketCreation("string", null);
-  testSocketCreation(null, null);
   testSocketCreation("localhost", -1);
   testSocketCreation("localhost", 65536);
-  testAdd(null);
-  // TODO(8233): Throw ArgumentError from API implementation.
-  // testAdd([-1]);
-  // testAdd([2222222222222222222222222222222]);
-  // testAdd([1, 2, 3, null]);
-  // testAdd([new NotAnInteger()]);
   testServerSocketCreation("string", null, null);
   testServerSocketCreation("string", 123, null);
   testServerSocketCreation("localhost", -1, 123);
diff --git a/tests/standalone/io/socket_upgrade_to_secure_test.dart b/tests/standalone/io/socket_upgrade_to_secure_test.dart
index 116de62..4798d14 100644
--- a/tests/standalone/io/socket_upgrade_to_secure_test.dart
+++ b/tests/standalone/io/socket_upgrade_to_secure_test.dart
@@ -102,8 +102,8 @@
     return completer.future;
   }
 
-  Future<RawSocket> runClient(Socket socket) {
-    Completer<RawSocket> completer = new Completer<RawSocket>();
+  Future<RawSocket?> runClient(Socket socket) {
+    Completer<RawSocket?> completer = new Completer<RawSocket?>();
     var dataReceived = <int>[];
     socket.listen((data) {
       dataReceived.addAll(data);
diff --git a/tests/standalone/io/test_extension.dart b/tests/standalone/io/test_extension.dart
index beed87c..4bd7d8f 100644
--- a/tests/standalone/io/test_extension.dart
+++ b/tests/standalone/io/test_extension.dart
@@ -14,7 +14,7 @@
   String toString() => 'cat $x';
 
   // Implements (a != null) ? a : b using a native C++ function and the API.
-  static int ifNull(a, b) native 'TestExtension_IfNull';
+  static int? ifNull(a, b) native 'TestExtension_IfNull';
 
   static int throwMeTheBall(ball) native 'TestExtension_ThrowMeTheBall';
 }
diff --git a/tests/standalone/io/web_socket_protocol_processor_test.dart b/tests/standalone/io/web_socket_protocol_processor_test.dart
index fc50c61..f7460e2 100644
--- a/tests/standalone/io/web_socket_protocol_processor_test.dart
+++ b/tests/standalone/io/web_socket_protocol_processor_test.dart
@@ -18,6 +18,7 @@
 import "dart:isolate";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
index 45b94e8..9b0e789 100644
--- a/tests/standalone/io/web_socket_test.dart
+++ b/tests/standalone/io/web_socket_test.dart
@@ -289,7 +289,7 @@
         request.response.close();
       });
 
-      createClient(server.port).catchError((error) {
+      Future<WebSocket?>.value(createClient(server.port)).catchError((error) {
         server.close();
       });
     });
diff --git a/tests/standalone/io/web_socket_typed_data_test.dart b/tests/standalone/io/web_socket_typed_data_test.dart
index 595ca60..c05cdb7 100644
--- a/tests/standalone/io/web_socket_typed_data_test.dart
+++ b/tests/standalone/io/web_socket_typed_data_test.dart
@@ -200,7 +200,7 @@
         webSocket.listen((message) => Expect.fail("No message expected"),
             onDone: () => completer.complete(true),
             onError: (e) => completer.completeError(e));
-        webSocket.add(new List()..add(i));
+        webSocket.add([i]);
       });
       return completer.future;
     }
diff --git a/tests/standalone/standalone_kernel.status b/tests/standalone/standalone_kernel.status
index cfbe667..01f6276 100644
--- a/tests/standalone/standalone_kernel.status
+++ b/tests/standalone/standalone_kernel.status
@@ -13,6 +13,8 @@
 
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
+io/http_ban_http_embedder_test: Skip # Requires http server bound to non-loopback; not provided by system.
+io/http_ban_http_normal_test: Skip # Requires http server bound to non-loopback; not provided by system.
 
 [ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
 io/file_lock_test: SkipSlow # Timeout
diff --git a/tests/standalone_2/fragmentation_test.dart b/tests/standalone_2/fragmentation_test.dart
index b083ec1..f24ea09 100644
--- a/tests/standalone_2/fragmentation_test.dart
+++ b/tests/standalone_2/fragmentation_test.dart
@@ -18,6 +18,10 @@
 // VMOptions=--concurrent_mark --concurrent_sweep
 // VMOptions=--concurrent_mark --use_compactor
 // VMOptions=--concurrent_mark --use_compactor --force_evacuation
+// VMOptions=--scavenger_tasks=0
+// VMOptions=--scavenger_tasks=1
+// VMOptions=--scavenger_tasks=2
+// VMOptions=--scavenger_tasks=3
 
 main() {
   final List<List> arrays = [];
diff --git a/tests/standalone_2/io/gzip_format_exception_test.dart b/tests/standalone_2/io/gzip_format_exception_test.dart
new file mode 100644
index 0000000..2b00af7
--- /dev/null
+++ b/tests/standalone_2/io/gzip_format_exception_test.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:io';
+
+import 'package:expect/expect.dart';
+
+// This tests whether a FormatException is thrown on bad data.
+main() {
+  Expect.throwsFormatException(() => GZipCodec().decoder.convert([10, 20, 30]));
+}
diff --git a/tests/standalone_2/io/http_ban_http_embedder_test.dart b/tests/standalone_2/io/http_ban_http_embedder_test.dart
new file mode 100644
index 0000000..7fd3cb3
--- /dev/null
+++ b/tests/standalone_2/io/http_ban_http_embedder_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.
+
+// SharedOptions=-Ddart.library.io.allow_http=false
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+
+import 'http_ban_http_normal_test.dart';
+import 'http_bind_test.dart';
+
+Future<void> testWithHostname() async {
+  await testBanHttp(await getLocalHostIP(), (httpClient, httpUri) async {
+    asyncExpectThrows(
+        () async => await httpClient.getUrl(httpUri), (e) => e is StateError);
+    asyncExpectThrows(
+        () async => await runZoned(() => httpClient.getUrl(httpUri),
+            zoneValues: {#dart.library.io.allow_http: 'foo'}),
+        (e) => e is StateError);
+    asyncExpectThrows(
+        () async => await runZoned(() => httpClient.getUrl(httpUri),
+            zoneValues: {#dart.library.io.allow_http: false}),
+        (e) => e is StateError);
+    await asyncTest(() => runZoned(() => httpClient.getUrl(httpUri),
+        zoneValues: {#dart.library.io.allow_http: true}));
+  });
+}
+
+Future<void> testWithLoopback() async {
+  await testBanHttp("127.0.0.1", (httpClient, uri) async {
+    await asyncTest(
+        () => httpClient.getUrl(Uri.parse('http://localhost:${uri.port}')));
+    await asyncTest(
+        () => 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>[
+    testWithHostname(),
+    testWithLoopback(),
+    testWithIPv6(),
+    testWithHTTPS(),
+  ]).then((_) => asyncEnd());
+}
diff --git a/tests/standalone_2/io/http_ban_http_normal_test.dart b/tests/standalone_2/io/http_ban_http_normal_test.dart
new file mode 100644
index 0000000..118dd4c
--- /dev/null
+++ b/tests/standalone_2/io/http_ban_http_normal_test.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.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.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();
+  }
+}
+
+main() async {
+  await asyncTest(() async {
+    final host = await getLocalHostIP();
+    // Normal HTTP request succeeds.
+    await testBanHttp(host, (httpClient, uri) async {
+      await asyncTest(() => httpClient.getUrl(uri));
+    });
+    // We can ban HTTP explicitly.
+    await testBanHttp(host, (httpClient, uri) async {
+      asyncExpectThrows(
+          () async => await runZoned(() => httpClient.getUrl(uri),
+              zoneValues: {#dart.library.io.allow_http: false}),
+          (e) => e is StateError);
+    });
+  });
+}
diff --git a/tests/standalone_2/io/http_cookie_date_test.dart b/tests/standalone_2/io/http_cookie_date_test.dart
index 6b94254..fd5de9a 100644
--- a/tests/standalone_2/io/http_cookie_date_test.dart
+++ b/tests/standalone_2/io/http_cookie_date_test.dart
@@ -16,6 +16,7 @@
 import "package:expect/expect.dart";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone_2/io/http_headers_test.dart b/tests/standalone_2/io/http_headers_test.dart
index 6e99646..1f8e7e5 100644
--- a/tests/standalone_2/io/http_headers_test.dart
+++ b/tests/standalone_2/io/http_headers_test.dart
@@ -17,6 +17,7 @@
 import "package:expect/expect.dart";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone_2/io/http_parser_test.dart b/tests/standalone_2/io/http_parser_test.dart
index 6951916..4f27fcf 100644
--- a/tests/standalone_2/io/http_parser_test.dart
+++ b/tests/standalone_2/io/http_parser_test.dart
@@ -17,6 +17,7 @@
 import "package:expect/expect.dart";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone_2/io/web_socket_protocol_processor_test.dart b/tests/standalone_2/io/web_socket_protocol_processor_test.dart
index fc50c61..f7460e2 100644
--- a/tests/standalone_2/io/web_socket_protocol_processor_test.dart
+++ b/tests/standalone_2/io/web_socket_protocol_processor_test.dart
@@ -18,6 +18,7 @@
 import "dart:isolate";
 
 part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/embedder_config.dart";
 part "../../../sdk/lib/_http/http_impl.dart";
 part "../../../sdk/lib/_http/http_date.dart";
 part "../../../sdk/lib/_http/http_parser.dart";
diff --git a/tests/standalone_2/regress_41329_helper.dart b/tests/standalone_2/regress_41329_helper.dart
new file mode 100644
index 0000000..f6f82dd
--- /dev/null
+++ b/tests/standalone_2/regress_41329_helper.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.
+
+import 'dart:io';
+
+main() {
+  exitCode = 42;
+}
diff --git a/tests/standalone_2/regress_41329_test.dart b/tests/standalone_2/regress_41329_test.dart
new file mode 100644
index 0000000..3ac957a
--- /dev/null
+++ b/tests/standalone_2/regress_41329_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.
+
+import 'dart:io';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+Future<void> main() async {
+  final origDir = Directory.current;
+  final exePath = Platform.resolvedExecutable;
+  var d = Directory.systemTemp.createTempSync('dart_symlink');
+
+  // Roughly emulate a Brew installation:
+  //   - $BREW/bin/dart -> ../Cellar/dart/2.8.0-dev.20.0/bin/dart
+  //   - $BREW/Cellar/dart/2.8.0-dev.20.0/bin/dart -> $DART_SDK/bin/dart
+  var a = Directory('${d.path}/usr/local/bin');
+  a.createSync(recursive: true);
+
+  // /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 link = Link(linkLocation);
+  link.createSync(exePath, recursive: true);
+
+  // /usr/local/bin/dart -> /usr/local/Cellar/dart/2.8.0-dev.20/bin/dart
+  final link2 = Link('dart')..createSync(linkLocation, recursive: true);
+  final path = link2.absolute.path;
+
+  Directory.current = origDir;
+  final result = await Process.run('${path}',
+      [Platform.script.resolve('regress_41329_helper.dart').toString()]);
+  Expect.equals(result.stdout, '');
+  Expect.equals(result.stderr, '');
+  Expect.equals(result.exitCode, 42);
+}
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index cfbe667..01f6276 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -13,6 +13,8 @@
 
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
+io/http_ban_http_embedder_test: Skip # Requires http server bound to non-loopback; not provided by system.
+io/http_ban_http_normal_test: Skip # Requires http server bound to non-loopback; not provided by system.
 
 [ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
 io/file_lock_test: SkipSlow # Timeout
diff --git a/tools/VERSION b/tools/VERSION
index 41b44a4..ab560b2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -31,9 +31,9 @@
 #
 CHANNEL dev
 MAJOR 2
-MINOR 8
+MINOR 9
 PATCH 0
-PRERELEASE 20
-PRERELEASE_PATCH 0
+PRERELEASE 0
+PRERELEASE_PATCH dev
 ABI_VERSION 32
 OLDEST_SUPPORTED_ABI_VERSION 32
diff --git a/tools/apps/update_homebrew/lib/src/impl.dart b/tools/apps/update_homebrew/lib/src/impl.dart
index 938108b..2a07403 100644
--- a/tools/apps/update_homebrew/lib/src/impl.dart
+++ b/tools/apps/update_homebrew/lib/src/impl.dart
@@ -27,19 +27,28 @@
 
 Future<void> _updateFormula(String channel, File file, String version,
     Map<String, String> hashes) async {
+  var contents = await file.readAsString();
+
+  // Replace the version identifier. Formulas with stable and pre-release
+  // versions have multiple identifiers and only the right one should be
+  // updated.
+  var versionId = channel == 'stable'
+      ? RegExp(r'version \"\d+\.\d+.\d+\"')
+      : RegExp(r'version \"\d+\.\d+.\d+\-.+\"');
+  contents = contents.replaceAll(versionId, 'version "$version"');
+
   // Extract files and hashes that are stored in the formula in this format:
   //  url "<url base>/<channel>/release/<version>/sdk/<artifact>.zip"
   //  sha256 "<hash>"
   var filesAndHashes = RegExp(
-      'channels/$channel/release' +
-          r'/(\d[\w\d\-\.]*)/sdk/([\w\d\-\.]+)\"\n(\s+)sha256 \"[\da-f]+\"',
+      'channels/$channel/release'
+      r'/(\d[\w\d\-\.]*)/sdk/([\w\d\-\.]+)\"\n(\s+)sha256 \"[\da-f]+\"',
       multiLine: true);
-  var contents = await file.readAsString();
   contents = contents.replaceAllMapped(filesAndHashes, (m) {
     var currentVersion = m.group(1);
     if (currentVersion == version) {
       throw new ArgumentError(
-          "Channel $channel is already at version $version in homebrew.");
+          'Channel $channel is already at version $version in homebrew.');
     }
     var artifact = m.group(2);
     var indent = m.group(3);
diff --git a/tools/bots/dart_tests.isolate b/tools/bots/dart_tests.isolate
index 8d72bf3..bb9e7f6 100644
--- a/tools/bots/dart_tests.isolate
+++ b/tools/bots/dart_tests.isolate
@@ -11,7 +11,6 @@
               'third_party/pkg_tested/',
               'third_party/d8/',
               'third_party/firefox_jsshell/',
-              'third_party/observatory_pub_packages/packages/web_components/',
               'tests/angular/',
               'tests/compiler/',
               'tests/corelib_2/',
diff --git a/tools/bots/get_builder_status.dart b/tools/bots/get_builder_status.dart
index cb0d3c4..3612ffa 100755
--- a/tools/bots/get_builder_status.dart
+++ b/tools/bots/get_builder_status.dart
@@ -120,7 +120,6 @@
   if (builder.endsWith('-try')) return;
   configurations = await getConfigurations();
   await printActiveFailures();
-  await printResultsFeedLink();
 }
 
 Future<List<String>> getConfigurations() async {
@@ -198,20 +197,6 @@
   }
 }
 
-void printResultsFeedLink() async {
-  if (builder.endsWith('-try')) return;
-  final groups = {
-    for (final configuration in configurations) configuration.split('-').first
-  };
-  String fragment = [
-    'showLatestFailures=true',
-    'showUnapprovedOnly=true',
-    if (groups.isNotEmpty) 'configurationGroups=${groups.join(',')}'
-  ].join('&');
-  final link = 'https://dart-ci.firebaseapp.com/#$fragment';
-  print('\nFailures link: $link');
-}
-
 Future<http.Response> runFirestoreQuery(String query) {
   final headers = {
     'Authorization': 'Bearer $token',
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 1ab78cd..ec2f704 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -53,7 +53,6 @@
       "tests/ffi_2/",
       "third_party/babel/babel.min.js",
       "third_party/d8/",
-      "third_party/observatory_pub_packages/packages/web_components/",
       "third_party/pkg/",
       "third_party/pkg_tested/",
       "third_party/requirejs/",
@@ -97,7 +96,6 @@
       "tests/ffi_2/",
       "third_party/babel/babel.min.js",
       "third_party/d8/",
-      "third_party/observatory_pub_packages/packages/web_components/",
       "third_party/pkg/",
       "third_party/pkg_tested/",
       "third_party/requirejs/",
@@ -245,7 +243,6 @@
       "out/ReleaseX64/",
       "third_party/pkg/",
       "third_party/pkg_tested/",
-      "third_party/observatory_pub_packages/packages/",
       "tools/sdks/dart-sdk/",
       "pkg/_fe_analyzer_shared/",
       "pkg/async_helper/",
@@ -305,7 +302,6 @@
       "third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip",
       "third_party/pkg/",
       "third_party/pkg_tested/",
-      "third_party/observatory_pub_packages/packages/",
       "tests/.dart_tool/package_config.json",
       "tests/angular/",
       "tests/co19_2/co19_2-analyzer.status",
@@ -391,7 +387,6 @@
       "third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip",
       "third_party/pkg/",
       "third_party/pkg_tested/",
-      "third_party/observatory_pub_packages/packages/",
       "tests/.dart_tool/package_config.json",
       "tests/angular/",
       "tests/co19_2/co19_2-analyzer.status",
@@ -624,7 +619,7 @@
         "host-checked": true
       }
     },
-    "dart2js-hostasserts-weak-(linux|mac|win)-x64-(d8|chrome)": {
+    "dart2js-hostasserts-weak-(linux|win)-x64-(d8|chrome)": {
       "options": {
         "builder-tag": "dart2js-weak",
         "enable-experiment": [
@@ -632,7 +627,50 @@
         ],
         "dart2js-options": [
           "--no-null-safety",
-          "--libraries-spec=sdk_nnbd/lib/libraries.json"
+          "--libraries-spec=sdk_nnbd/lib/libraries.json",
+          "--platform-binaries=out/ReleaseX64NNBD/"
+        ],
+        "host-checked": true
+      }
+    },
+    "dart2js-hostasserts-weak-mac-x64-(d8|chrome)": {
+      "options": {
+        "builder-tag": "dart2js-weak",
+        "enable-experiment": [
+          "non-nullable"
+        ],
+        "dart2js-options": [
+          "--no-null-safety",
+          "--libraries-spec=sdk_nnbd/lib/libraries.json",
+          "--platform-binaries=xcodebuild/ReleaseX64NNBD/"
+        ],
+        "host-checked": true
+      }
+    },
+    "dart2js-hostasserts-strong-(linux|win)-x64-(d8|chrome)": {
+      "options": {
+        "builder-tag": "dart2js-strong",
+        "enable-experiment": [
+          "non-nullable"
+        ],
+        "dart2js-options": [
+          "--null-safety",
+          "--libraries-spec=sdk_nnbd/lib/libraries.json",
+          "--platform-binaries=out/ReleaseX64NNBD/"
+        ],
+        "host-checked": true
+      }
+    },
+    "dart2js-hostasserts-strong-mac-x64-(d8|chrome)": {
+      "options": {
+        "builder-tag": "dart2js-strong",
+        "enable-experiment": [
+          "non-nullable"
+        ],
+        "dart2js-options": [
+          "--null-safety",
+          "--libraries-spec=sdk_nnbd/lib/libraries.json",
+          "--platform-binaries=xcodebuild/ReleaseX64NNBD/"
         ],
         "host-checked": true
       }
@@ -914,6 +952,9 @@
         ]
       }
     },
+    "dartkb-abi-linux-release-x64": {
+      "__comment__": "This configuration is only used for a custom test runner. If it conflicts with a new configuration you are adding, you can make this configuration more specific by adding options."
+    },
     "dartdevk-checked-(linux|mac|win)-(debug|product|release)-(chrome|firefox)": {
       "options": {
         "checked": true,
@@ -1364,7 +1405,7 @@
             "standalone/io"
           ]
         },
-	{
+        {
           "name": "vm nnbd tests in strong mode",
           "arguments": [
             "-ndartkp-strong-${system}-${mode}-${arch}",
@@ -1525,100 +1566,33 @@
     {
       "builders": [
         "vm-kernel-asan-linux-release-ia32",
-        "vm-kernel-asan-linux-release-x64"
-      ],
-      "meta": {
-        "description": "This configuration is used by the vm builders with AddressSanitizer (asan)."
-      },
-      "steps": [
-        {
-          "name": "configure dart",
-          "script": "tools/gn.py",
-          "arguments": [
-            "--mode=${mode}",
-            "--arch=${arch}",
-            "--sanitizer=asan"
-          ]
-        },
-        {
-          "name": "build dart",
-          "script": "tools/build.py",
-          "arguments": [
-            "--sanitizer=asan",
-            "runtime"
-          ]
-        },
-        {
-          "name": "vm tests",
-          "arguments": [
-            "-ndartk-asan-linux-release-${arch}"
-          ]
-        }
-      ]
-    },
-    {
-      "builders": [
+        "vm-kernel-asan-linux-release-x64",
         "vm-kernel-lsan-linux-release-ia32",
-        "vm-kernel-lsan-linux-release-x64"
+        "vm-kernel-lsan-linux-release-x64",        
+        "vm-kernel-msan-linux-release-x64",
+        "vm-kernel-ubsan-linux-release-ia32",
+        "vm-kernel-ubsan-linux-release-x64"
       ],
       "meta": {
-        "description": "This configuration is used by the vm builders with LeakSanitizer (lsan)."
+        "description": "This configuration is used by the VM/JIT builders with sanitizers."
       },
       "steps": [
         {
           "name": "configure dart",
           "script": "tools/gn.py",
-          "arguments": [
-            "--mode=${mode}",
-            "--arch=${arch}",
-            "--sanitizer=lsan"
-          ]
+          "arguments": []
         },
         {
           "name": "build dart",
           "script": "tools/build.py",
           "arguments": [
-            "--sanitizer=lsan",
             "runtime"
           ]
         },
         {
           "name": "vm tests",
           "arguments": [
-            "-ndartk-lsan-linux-release-${arch}"
-          ]
-        }
-      ]
-    },
-    {
-      "builders": [
-        "vm-kernel-msan-linux-release-x64"
-      ],
-      "meta": {
-        "description": "This configuration is used by the vm builders with MemorySanitizer (msan)."
-      },
-      "steps": [
-        {
-          "name": "configure dart",
-          "script": "tools/gn.py",
-          "arguments": [
-            "--mode=${mode}",
-            "--arch=${arch}",
-            "--sanitizer=msan"
-          ]
-        },
-        {
-          "name": "build dart",
-          "script": "tools/build.py",
-          "arguments": [
-            "--sanitizer=msan",
-            "runtime"
-          ]
-        },
-        {
-          "name": "vm tests",
-          "arguments": [
-            "-ndartk-msan-linux-release-${arch}"
+            "-ndartk-${sanitizer}-${system}-${mode}-${arch}"
           ]
         }
       ]
@@ -1628,30 +1602,25 @@
         "vm-kernel-tsan-linux-release-x64"
       ],
       "meta": {
-        "description": "This configuration is used by the vm builders with ThreadSanitizer (tsan)."
+        "description": "This configuration is used by the VM/JIT builders with sanitizers."
       },
       "steps": [
         {
           "name": "configure dart",
           "script": "tools/gn.py",
-          "arguments": [
-            "--mode=${mode}",
-            "--arch=${arch}",
-            "--sanitizer=tsan"
-          ]
+          "arguments": []
         },
         {
           "name": "build dart",
           "script": "tools/build.py",
           "arguments": [
-            "--sanitizer=tsan",
             "runtime"
           ]
         },
         {
           "name": "vm tests",
           "arguments": [
-            "-ndartk-tsan-linux-release-${arch}",
+            "-ndartk-${sanitizer}-${system}-${mode}-${arch}",
             "vm"
           ]
         }
@@ -1659,34 +1628,65 @@
     },
     {
       "builders": [
-        "vm-kernel-ubsan-linux-release-ia32",
-        "vm-kernel-ubsan-linux-release-x64"
+        "vm-kernel-precomp-asan-linux-release-x64",
+        "vm-kernel-precomp-lsan-linux-release-x64",
+        "vm-kernel-precomp-msan-linux-release-x64",
+        "vm-kernel-precomp-ubsan-linux-release-x64"
       ],
       "meta": {
-        "description": "This configuration is used by the vm builders with UndefinedBehaviorSanitizer (ubsan)."
+        "description": "This configuration is used by the VM/AOT builders with sanitizers."
       },
       "steps": [
         {
           "name": "configure dart",
           "script": "tools/gn.py",
-          "arguments": [
-            "--mode=${mode}",
-            "--arch=${arch}",
-            "--sanitizer=ubsan"
-          ]
+          "arguments": []
         },
         {
           "name": "build dart",
           "script": "tools/build.py",
           "arguments": [
-            "--sanitizer=ubsan",
-            "runtime"
+            "runtime",
+            "runtime_precompiled"
           ]
         },
         {
           "name": "vm tests",
           "arguments": [
-            "-ndartk-ubsan-linux-release-${arch}"
+            "-ndartkp-${sanitizer}-${system}-${mode}-${arch}",
+            "vm",
+            "standalone",
+            "standalone_2"
+          ]
+        }
+      ]
+    },
+    {
+      "builders": [
+        "vm-kernel-precomp-tsan-linux-release-x64"
+      ],
+      "meta": {
+        "description": "This configuration is used by the VM/AOT builders with sanitizers."
+      },
+      "steps": [
+        {
+          "name": "configure dart",
+          "script": "tools/gn.py",
+          "arguments": []
+        },
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "runtime",
+            "runtime_precompiled"
+          ]
+        },
+        {
+          "name": "vm tests",
+          "arguments": [
+            "-ndartkp-${sanitizer}-${system}-${mode}-${arch}",
+            "vm"
           ]
         }
       ]
@@ -2046,6 +2046,17 @@
           ]
         },
         {
+          "name": "ddc weak modular tests",
+          "script": "out/ReleaseX64NNBD/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/dev_compiler/test/modular_suite_nnbd.dart",
+            "-ndartdevk-weak-${system}-release-chrome",
+            "--verbose",
+            "--use-sdk"
+          ]
+        },
+        {
           "name": "ddc nnbd weak tests",
           "arguments": [
             "-ndartdevk-weak-linux-release-chrome",
@@ -2625,7 +2636,8 @@
             "language_2",
             "corelib_2",
             "dart2js_extra",
-            "dart2js_native"
+            "dart2js_native",
+            "kernel"
           ],
           "shards": 6,
           "fileset": "dart2js_hostasserts_nnbd"
@@ -2649,6 +2661,40 @@
           ],
           "shards": 6,
           "fileset": "dart2js_hostasserts_nnbd"
+        },
+        {
+          "name": "dart2js nnbd strong tests",
+          "arguments": [
+            "-ndart2js-hostasserts-strong-linux-x64-d8",
+            "--dart2js-batch",
+            "language",
+            "corelib",
+            "dart2js_extra",
+            "dart2js_native",
+            "kernel"
+          ],
+          "shards": 6,
+          "fileset": "dart2js_hostasserts_nnbd"
+        },
+        {
+          "name": "dart2js nnbd strong lib tests",
+          "arguments": [
+            "-ndart2js-hostasserts-strong-linux-x64-chrome",
+            "--dart2js-batch",
+            "lib"
+          ],
+          "shards": 3,
+          "fileset": "dart2js_hostasserts_nnbd"
+        },
+        {
+          "name": "dart2js nnbd strong co19 tests",
+          "arguments": [
+            "-ndart2js-hostasserts-strong-linux-x64-chrome",
+            "--dart2js-batch",
+            "co19/LanguageFeatures/nnbd"
+          ],
+          "shards": 6,
+          "fileset": "dart2js_hostasserts_nnbd"
         }
       ]
     },
@@ -3257,7 +3303,6 @@
           "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
           "arguments": [
             "--fatal-warnings",
-            "--packages=runtime/observatory/.packages",
             "runtime/observatory"
           ]
         },
@@ -3448,41 +3493,6 @@
           "arguments": [
             "clean"
           ]
-        },
-        {
-          "name": "generate ninja for linux-x64-bytecode",
-          "script": "tools/gn.py",
-          "arguments": [
-            "--mode=release",
-            "--arch=x64",
-            "--bytecode"
-          ]
-        },
-        {
-          "name": "build linux-x64-bytecode for benchmarking",
-          "script": "tools/build.py",
-          "arguments": [
-            "--mode=release",
-            "--arch=x64",
-            "create_sdk",
-            "runtime",
-            "gen_snapshot",
-            "dart_precompiled_runtime"
-          ]
-        },
-        {
-          "name": "archive linux-x64-bytecode for benchmarking",
-          "script": "tools/bots/try_benchmarks.sh",
-          "arguments": [
-            "linux-x64-bytecode-archive"
-          ]
-        },
-        {
-          "name": "try linux-x64-bytecode benchmarking",
-          "script": "tools/bots/try_benchmarks.sh",
-          "arguments": [
-            "linux-x64-bytecode-benchmark"
-          ]
         }
       ]
     },
@@ -3609,7 +3619,8 @@
         {
           "name": "run tests",
           "script": "tools/run_abi_tests.py",
-          "testRunner": true
+          "testRunner": true,
+          "arguments": ["-ndartkb-abi-linux-release-x64"]
         }
       ]
     },
@@ -3681,4 +3692,4 @@
     "linux": "buildtools/linux-x64/clang/bin/llvm-symbolizer",
     "macos": "buildtools/mac-x64/clang/bin/llvm-symbolizer"
   }
-}
+}
\ No newline at end of file
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index cd1fbe6..365df82 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -26,9 +26,6 @@
     linux-x64-build - Build linux-x64 for benchmarking.
     linux-x64-archive - Archive linux-x64.
     linux-x64-benchmark - Try linux-x64 benchmarking.
-    linux-x64-bytecode-build - Build linux-x64 with bytecode for benchmarking.
-    linux-x64-bytecode-archive - Archive linux-x64 with bytecode.
-    linux-x64-bytecode-benchmark - Try linux-x64 with bytecode benchmarking.
 EOF
   exit 1
 fi
@@ -191,19 +188,13 @@
     out/ReleaseIA32/dart benchmarks/FfiStruct/dart/FfiStruct.dart
     cd ..
     rm -rf tmp
-  elif [ "$command" = linux-x64-build ] ||
-       [ "$command" = linux-x64-bytecode-build ]; then
+  elif [ "$command" = linux-x64-build ]; then
     # NOTE: These are duplicated in tools/bots/test_matrix.json, keep in sync.
-    if [ "$command" = linux-x64-bytecode-build ]; then
-      # Beware: Don't mix --bytecode with a non-bytecode out/.
-      ./tools/gn.py --mode=release --arch=x64 --bytecode
-    fi
     ./tools/build.py --mode=release --arch=x64 create_sdk
     ./tools/build.py --mode=release --arch=x64 runtime
     ./tools/build.py --mode=release --arch=x64 gen_snapshot
     ./tools/build.py --mode=release --arch=x64 dart_precompiled_runtime
-  elif [ "$command" = linux-x64-archive ] ||
-       [ "$command" = linux-x64-bytecode-archive ]; then
+  elif [ "$command" = linux-x64-archive ]; then
     strip -w \
       -K 'kDartVmSnapshotData' \
       -K 'kDartVmSnapshotInstructions' \
@@ -309,8 +300,7 @@
       runtime/lib \
       benchmarks \
       || (rm -f linux-x64.tar.gz; exit 1)
-  elif [ "$command" = linux-x64-benchmark ] ||
-       [ "$command" = linux-x64-bytecode-benchmark ]; then
+  elif [ "$command" = linux-x64-benchmark ]; then
     rm -rf tmp
     mkdir tmp
     cd tmp
@@ -323,13 +313,7 @@
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages hello.dart
     DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/precompiler2 --packages=.packages hello.dart blob.bin
     DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/dart_precompiled_runtime2 --profile-period=10000 blob.bin
-    DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/precompiler2 --no-gen-bytecode --packages=.packages hello.dart blob.bin
-    DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/dart_precompiled_runtime2 --profile-period=10000 blob.bin
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --optimization-counter-threshold=-1 hello.dart
-    out/ReleaseX64/dart --profile-period=10000 --packages=.packages --enable-interpreter hello.dart
-    out/ReleaseX64/dart --profile-period=10000 --packages=.packages --enable-interpreter --compilation-counter-threshold=-1 hello.dart
-    out/ReleaseX64/dart --profile-period=10000 --packages=.packages --use-bytecode-compiler hello.dart
-    out/ReleaseX64/dart --profile-period=10000 --packages=.packages --use-bytecode-compiler --optimization-counter-threshold=-1 hello.dart
     out/ReleaseX64/dart-sdk/bin/dart2js --packages=.packages --out=out.js -m hello.dart
     third_party/d8/linux/x64/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
     out/ReleaseX64/dart-sdk/bin/dart2js --packages=.packages --out=out.js -m hello.dart
diff --git a/tools/dom/nnbd_src/AttributeMap.dart b/tools/dom/nnbd_src/AttributeMap.dart
index fad3c44..88f3bd4 100644
--- a/tools/dom/nnbd_src/AttributeMap.dart
+++ b/tools/dom/nnbd_src/AttributeMap.dart
@@ -96,7 +96,7 @@
   _ElementAttributeMap(Element element) : super(element);
 
   bool containsKey(Object? key) {
-    return _element._hasAttribute(key as String);
+    return key is String && _element._hasAttribute(key);
   }
 
   String? operator [](Object? key) {
@@ -122,8 +122,8 @@
   // Inline this because almost all call sites of [remove] do not use [value],
   // and the annotations on the `getAttribute` call allow it to be removed.
   @pragma('dart2js:tryInline')
-  static String _remove(Element element, String key) {
-    String value = JS(
+  static String? _remove(Element element, String key) {
+    String? value = JS(
         // throws:null(1) is not accurate since [key] could be malformed, but
         // [key] is checked again by `removeAttributeNS`.
         'returns:String|Null;depends:all;effects:none;throws:null(1)',
@@ -139,12 +139,12 @@
  * Wrapper to expose namespaced attributes as a typed map.
  */
 class _NamespacedAttributeMap extends _AttributeMap {
-  final String _namespace;
+  final String? _namespace;
 
   _NamespacedAttributeMap(Element element, this._namespace) : super(element);
 
   bool containsKey(Object? key) {
-    return _element._hasAttributeNS(_namespace, key as String);
+    return key is String && _element._hasAttributeNS(_namespace, key);
   }
 
   String? operator [](Object? key) {
@@ -172,8 +172,8 @@
   // returned [value], and the annotations on the `getAttributeNS` call allow it
   // to be removed.
   @pragma('dart2js:tryInline')
-  static String _remove(String namespace, Element element, String key) {
-    String value = JS(
+  static String? _remove(String? namespace, Element element, String key) {
+    String? value = JS(
         // throws:null(1) is not accurate since [key] could be malformed, but
         // [key] is checked again by `removeAttributeNS`.
         'returns:String|Null;depends:all;effects:none;throws:null(1)',
diff --git a/tools/dom/nnbd_src/CssClassSet.dart b/tools/dom/nnbd_src/CssClassSet.dart
index 9b38b8d..6a76202 100644
--- a/tools/dom/nnbd_src/CssClassSet.dart
+++ b/tools/dom/nnbd_src/CssClassSet.dart
@@ -17,7 +17,8 @@
    * after the operation, and returns `false` if [value] is absent after the
    * operation.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To toggle multiple classes, use
@@ -51,7 +52,8 @@
    * If this CssClassSet corresponds to one element. Returns true if [value] was
    * added to the set, otherwise false.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To add multiple classes use
diff --git a/tools/dom/nnbd_src/Validators.dart b/tools/dom/nnbd_src/Validators.dart
index 26dac65..a498da9 100644
--- a/tools/dom/nnbd_src/Validators.dart
+++ b/tools/dom/nnbd_src/Validators.dart
@@ -262,7 +262,7 @@
   /// important attributes we want to check, remove it if it's not valid
   /// or not allowed, either as a whole or particular attributes.
   void _sanitizeElement(Element element, Node? parent, bool corrupted,
-      String text, String tag, Map attrs, String isAttr) {
+      String text, String tag, Map attrs, String? isAttr) {
     if (false != corrupted) {
       _removeNode(element, parent);
       window.console
diff --git a/tools/dom/nnbd_src/shared_html.dart b/tools/dom/nnbd_src/shared_html.dart
index 5e7bc8e..f86f288 100644
--- a/tools/dom/nnbd_src/shared_html.dart
+++ b/tools/dom/nnbd_src/shared_html.dart
@@ -4,14 +4,15 @@
 
 part of dart.dom.html;
 
-void Function(T)? _wrapZone<T>(void Function(T) callback) {
+void Function(T)? _wrapZone<T>(void Function(T)? callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.root) return callback;
   if (callback == null) return null;
   return Zone.current.bindUnaryCallbackGuarded(callback);
 }
 
-void Function(T1, T2)? _wrapBinaryZone<T1, T2>(void Function(T1, T2) callback) {
+void Function(T1, T2)? _wrapBinaryZone<T1, T2>(
+    void Function(T1, T2)? callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.root) return callback;
   if (callback == null) return null;
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 3231d7f..44c721e 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -299,7 +299,7 @@
         'ApplicationCache':
         'ApplicationCache,DOMApplicationCache,OfflineResourceList',
         'Event':
-        'Event,InputEvent',
+        'Event,InputEvent,SubmitEvent', # Workaround for issue 40901.
         'HTMLTableCellElement':
         'HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement',
         'GainNode':
@@ -490,7 +490,10 @@
         if len(set(DartType(arg.type.id) for arg in args)) == 1:
             nullable = False
             for arg in args:
-                nullable = nullable or getattr(arg.type, 'nullable', False)
+                # If the 'TreatNullAs' attribute exists, the param technically
+                # is nullable. The conversion happens in the browser.
+                nullable = nullable or getattr(arg.type, 'nullable', False) or \
+                    'TreatNullAs' in arg.ext_attrs
             return (type_ids[0], nullable)
         else:
             return (None, False)
@@ -1271,8 +1274,10 @@
         if self._data.dart_type:
             return self._data.dart_type
         if self.list_item_type() and not self.has_generated_interface():
-            return 'List<%s>' % self._type_registry.TypeInfo(
-                self._data.item_type).dart_type()
+            item_nullable = '?' if self._data.item_type_nullable and \
+                global_options_hack.nnbd else ''
+            return 'List<%s%s>' % (self._type_registry.TypeInfo(
+                self._data.item_type).dart_type(), item_nullable)
         return self._dart_interface_name
 
     def narrow_dart_type(self):
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 68a721f..b017597 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -1413,13 +1413,17 @@
                     self._members_emitter.Emit(
                         '\n'
                         '  // Use implementation from $SUPER.\n'
-                        '  // $TYPE get $NAME native;\n'
-                        '  // void set $NAME($TYPE value) native;\n',
+                        '  // $GET_TYPE get $NAME native;\n'
+                        '  // void set $NAME($SET_TYPE value) native;\n',
                         SUPER=super_attribute_interface,
                         NAME=html_name,
-                        TYPE=self.SecureOutputType(attribute.type.id,
+                        GET_TYPE=self.SecureOutputType(attribute.type.id,
                             can_narrow_type=read_only,
-                            nullable=attribute.type.nullable))
+                            nullable=attribute.type.nullable),
+                        SET_TYPE=self.SecureOutputType(attribute.type.id,
+                            can_narrow_type=read_only,
+                            nullable=attribute.type.nullable or \
+                                'TreatNullAs' in attribute.ext_attrs))
                     return
             self._members_emitter.Emit('\n  // Shadowing definition.')
             self._AddAttributeUsingProperties(attribute, html_name, read_only)
@@ -1548,7 +1552,7 @@
         conversion = self._InputConversion(attr.type.id, attr.id)
         if conversion:
             return self._AddConvertingSetter(attr, html_name, conversion)
-        nullable_type = attr.type.nullable
+        nullable_type = attr.type.nullable or 'TreatNullAs' in attr.ext_attrs
         # If this attr has an output conversion, it is possible that there is a
         # converting getter. We need to make sure the setter type matches the
         # getter type.
@@ -1592,8 +1596,8 @@
 
     def _AddConvertingSetter(self, attr, html_name, conversion):
         # If the attribute is nullable, the setter should be nullable.
-        nullable_in = attr.type.nullable and \
-            not conversion.input_type == 'dynamic'
+        nullable_in = (attr.type.nullable or 'TreatNullAs' in attr.ext_attrs) \
+            and not conversion.input_type == 'dynamic'
         nullable_out = conversion.nullable_output and \
             not conversion.output_type == 'dynamic'
         self._members_emitter.Emit(
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 445dc08..d1507bc 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -17,7 +17,8 @@
    * after the operation, and returns `false` if [value] is absent after the
    * operation.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To toggle multiple classes, use
@@ -51,7 +52,8 @@
    * If this CssClassSet corresponds to one element. Returns true if [value] was
    * added to the set, otherwise false.
    *
-   * If this corresponds to many elements, `null` is always returned.
+   * If this CssClassSet corresponds to many elements, `false` is always
+   * returned.
    *
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.  To add multiple classes use
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 2a270b6..4ad8736 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -120,6 +120,10 @@
     }
   }
 
+  void insertAll(int index, Iterable<Element> iterable) {
+    throw new UnimplementedError();
+  }
+
   void setAll(int index, Iterable<Element> iterable) {
     throw new UnimplementedError();
   }
@@ -130,6 +134,9 @@
 
   Element removeAt(int index) {
     final result = this[index];
+  $if NNBD
+    // TODO(41258): Remove null check after unfork/strong mode.
+  $endif
     if (result != null) {
       _element._removeChild(result);
     }
@@ -138,9 +145,7 @@
 
   Element removeLast() {
     final result = this.last;
-    if (result != null) {
-      _element._removeChild(result);
-    }
+    _element._removeChild(result);
     return result;
   }
 
@@ -566,6 +571,9 @@
 
   @pragma('dart2js:tryInline')
   String$NULLABLE getAttribute(String name) {
+$if NNBD
+    // TODO(41258): Delete this assertion after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     return _getAttribute(name);
@@ -573,6 +581,9 @@
 
   @pragma('dart2js:tryInline')
   String$NULLABLE getAttributeNS(String$NULLABLE namespaceURI, String name) {
+$if NNBD
+    // TODO(41258): Delete this assertion after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     // [namespaceURI] does not need protecting, both `null` and `undefined` map to `null`.
     assert(name != null, 'Attribute name cannot be null');
@@ -581,6 +592,9 @@
 
   @pragma('dart2js:tryInline')
   bool hasAttribute(String name) {
+$if NNBD
+    // TODO(41258): Delete this assertion after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     return _hasAttribute(name);
@@ -588,6 +602,9 @@
 
   @pragma('dart2js:tryInline')
   bool hasAttributeNS(String$NULLABLE namespaceURI, String name) {
+$if NNBD
+    // TODO(41258): Delete this assertion after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     // [namespaceURI] does not need protecting, both `null` and `undefined` map to `null`.
     assert(name != null, 'Attribute name cannot be null');
@@ -596,6 +613,9 @@
 
   @pragma('dart2js:tryInline')
   void removeAttribute(String name) {
+$if NNBD
+    // TODO(41258): Delete this assertion after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     _removeAttribute(name);
@@ -603,6 +623,9 @@
 
   @pragma('dart2js:tryInline')
   void removeAttributeNS(String$NULLABLE namespaceURI, String name) {
+$if NNBD
+    // TODO(41258): Delete this assertion after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     _removeAttributeNS(namespaceURI, name);
@@ -610,6 +633,9 @@
 
   @pragma('dart2js:tryInline')
   void setAttribute(String name, String value) {
+$if NNBD
+    // TODO(41258): Delete these assertions after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     // TODO(sra): assert(value != null, 'Attribute value cannot be null.');
@@ -618,6 +644,9 @@
 
   @pragma('dart2js:tryInline')
   void setAttributeNS(String$NULLABLE namespaceURI, String name, String value) {
+$if NNBD
+    // TODO(41258): Delete these assertions after forcing strong mode.
+$endif
     // Protect [name] against string conversion to "null" or "undefined".
     assert(name != null, 'Attribute name cannot be null');
     // TODO(sra): assert(value != null, 'Attribute value cannot be null.');
@@ -1389,7 +1418,7 @@
    * This uses the default sanitization behavior to sanitize the HTML fragment,
    * use [setInnerHtml] to override the default behavior.
    */
-  set innerHtml(String html) {
+  set innerHtml(String$NULLABLE html) {
     this.setInnerHtml(html);
   }
 
@@ -1414,7 +1443,7 @@
    * * [NodeValidator]
    * * [NodeTreeSanitizer]
    */
-  void setInnerHtml(String html,
+  void setInnerHtml(String$NULLABLE html,
     {NodeValidator$NULLABLE validator,
      NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     text = null;
@@ -1422,7 +1451,7 @@
       _innerHtml = html;
     } else {
       append(createFragment(
-          html, validator: validator, treeSanitizer: treeSanitizer));
+          html$NULLASSERT, validator: validator, treeSanitizer: treeSanitizer));
     }
   }
   String get innerHtml => _innerHtml;
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index 11c04d4..f2005af 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -66,7 +66,7 @@
   set name(String value);
 
   String get value;
-  set value(String value);
+  set value(String$NULLABLE value);
 
   List<Node> get labels;
 
diff --git a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
index ea670cc..7981962 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
@@ -16,13 +16,13 @@
    *
    * * <https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin>
    */
-  void setInnerHtml(String html,
+  void setInnerHtml(String$NULLABLE html,
     {NodeValidator$NULLABLE validator,
      NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     text = null;
     content.nodes.clear();
     var fragment = createFragment(
-        html, validator: validator, treeSanitizer: treeSanitizer);
+        html$NULLASSERT, validator: validator, treeSanitizer: treeSanitizer);
 
     content.append(fragment);
   }
diff --git a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
index 638e458..95da121 100644
--- a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
@@ -141,7 +141,7 @@
     request.onError.listen(controller.addError);
 
     request.onSuccess.listen((e) {
-      T cursor = request.result as dynamic;
+      T$NULLABLE cursor = request.result as dynamic;
       if (cursor == null) {
         controller.close();
       } else {
diff --git a/tools/dom/templates/html/impl/impl_Navigator.darttemplate b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
index 5265a5b..3b2493b 100644
--- a/tools/dom/templates/html/impl/impl_Navigator.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
@@ -6,7 +6,7 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 
-  List<Gamepad> getGamepads() {
+  List<Gamepad$NULLABLE> getGamepads() {
     var gamepadList = _getGamepads();
 
     // If no prototype we need one for the world to hookup to the proper Dart class.
diff --git a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
index 1e66365..a92eb50 100644
--- a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
@@ -82,7 +82,7 @@
     return container.innerHtml;
   }
 
-  set innerHtml(String value) {
+  set innerHtml(String$NULLABLE value) {
     this.setInnerHtml(value);
   }
 
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index a441144..227b2d5 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -77,7 +77,7 @@
 # presumed to be in this version.  Experiment flags will not affect
 # files that specify an earlier version.
 
-current-version: 2.8
+current-version: 2.9
 
 features:
   extension-methods:
diff --git a/tools/migration/bin/migrate.dart b/tools/migration/bin/migrate.dart
index d327040..9edeef7 100644
--- a/tools/migration/bin/migrate.dart
+++ b/tools/migration/bin/migrate.dart
@@ -23,6 +23,10 @@
   var step = arguments[0];
   var testDir = arguments[1];
 
+  // If the test directory is just a single identifier, assume it's a language
+  // test subdirectory.
+  if (!testDir.contains("/")) testDir = "language_2/$testDir";
+
   switch (step) {
     case "branch":
       _createBranch(testDir);
@@ -32,6 +36,10 @@
       _copyFiles(testDir);
       break;
 
+    case "fork":
+      _forkFiles(testDir);
+      break;
+
     case "analyze":
       _analyzeFiles(testDir);
       break;
@@ -44,23 +52,15 @@
 
 /// Creates a Git branch whose name matches [testDir].
 void _createBranch(String testDir) {
-  var dirName = toNnbdPath(testDir)
-      .replaceAll("/", "-")
-      .replaceAll("_", "-")
-      .replaceAll(RegExp("[^a-z0-9-]"), "");
-  var branchName = "migrate-$dirName";
-  if (runProcess("git", ["checkout", "-b", branchName])) {
-    print(green("Created and switched to Git branch '$branchName'."));
+  if (_createGitBranch(testDir)) {
     _showNextStep("Next, copy the migrated files over", "copy", testDir);
-  } else {
-    print(red("Failed to create Git branch '$branchName'."));
   }
 }
 
 /// Copies files from [testDir] to the corresponding NNBD test directory.
 ///
 /// Checks for collisions.
-void _copyFiles(String testDir) {
+void _copyFiles(String testDir, {bool showNextStep = false}) {
   for (var from in listFiles(testDir)) {
     var to = toNnbdPath(from);
     if (fileExists(to)) {
@@ -77,10 +77,36 @@
   }
 
   print(green("Copied files from $testDir -> ${toNnbdPath(testDir)}."));
-  print("Next, commit the new files and upload a new CL with them:");
+  if (showNextStep) {
+    print("Next, commit the new files and upload a new CL with them:");
+    print("");
+    print(bold("  git add ."));
+    print(bold("  git commit -m \"Migrate $testDir to NNBD\"."));
+    print(bold("  git cl upload --bypass-hooks"));
+    _showNextStep("Then use analyzer to migrate the files", "analyze", testDir);
+  }
+}
+
+/// Same as "branch" + "copy" then a commit.
+///
+/// Creates a branch, copies files over, and then commits them.
+void _forkFiles(String testDir) {
+  if (!_createGitBranch(testDir)) return;
+  _copyFiles(testDir, showNextStep: false);
+
+  if (!runProcess("git", ["add", "."])) {
+    print(red("Failed to stage changes."));
+    return;
+  }
+
+  if (!runProcess("git", ["commit", "-m", "Migrate $testDir to NNBD."])) {
+    print(red("Failed to commit changes."));
+    return;
+  }
+
+  print(green("Copied files to a new branch and committed."));
+  print("Next, upload a new CL with them:");
   print("");
-  print(bold("  git add ."));
-  print(bold("  git commit -m \"Migrate $testDir to NNBD\"."));
   print(bold("  git cl upload --bypass-hooks"));
   _showNextStep("Then use analyzer to migrate the files", "analyze", testDir);
 }
@@ -110,3 +136,19 @@
   print(bold("  dart tools/migration/bin/migrate.dart "
       "${dryRun ? '--dry-run ' : ''}$step $testDir"));
 }
+
+bool _createGitBranch(String testDir) {
+  var dirName = toNnbdPath(testDir)
+      .replaceAll("/", "-")
+      .replaceAll("_", "-")
+      .replaceAll(RegExp("[^a-z0-9-]"), "");
+  var branchName = "migrate-$dirName";
+  var success = runProcess("git", ["checkout", "-b", branchName]);
+  if (success) {
+    print(green("Created and switched to Git branch '$branchName'."));
+  } else {
+    print(red("Failed to create Git branch '$branchName'."));
+  }
+
+  return success;
+}
diff --git a/tools/migration/bin/test.dart b/tools/migration/bin/test.dart
new file mode 100644
index 0000000..1f39c51
--- /dev/null
+++ b/tools/migration/bin/test.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.
+
+/// A little utility script to make it easier to run NNBD and legacy tests.
+import 'dart:io';
+
+import 'package:args/args.dart';
+
+import 'package:migration/src/io.dart';
+import 'package:migration/src/test_directories.dart';
+
+/// Maps "normal" names for Dart implementations to their test runner compiler
+/// names.
+const compilerNames = {
+  "analyzer": "dart2analyzer",
+  "cfe": "fasta",
+  "dart2js": "dart2js",
+  "ddc": "dartdevk",
+  "vm": "dartk",
+};
+
+const configurations = {
+  "analyzer": "analyzer-asserts-strong-linux",
+  "cfe": "cfe-strong-linux",
+  "dart2js": "dart2js-weak-linux-x64-d8",
+  "ddc": "dartdevk-strong-linux-release-chrome",
+  "vm": "dartk-strong-linux-release-x64",
+};
+
+void main(List<String> arguments) async {
+  var testDir = "";
+  var isLegacy = false;
+  var compiler = "ddc";
+
+  var argParser = ArgParser();
+  argParser.addFlag("legacy",
+      help: "Run the legacy tests.",
+      negatable: false,
+      callback: (flag) => isLegacy = flag);
+
+  argParser.addOption("configuration",
+      abbr: "c",
+      help: "Which Dart implementation to run the tests on.",
+      allowed: ["analyzer", "cfe", "dart2js", "ddc", "vm"],
+      callback: (option) => compiler = option as String);
+
+  if (arguments.contains("--help")) {
+    showUsage(argParser);
+  }
+
+  try {
+    var argResults = argParser.parse(arguments);
+
+    if (argResults.rest.length != 1) {
+      showUsage(argParser, "Missing test directory.");
+    }
+
+    testDir = argResults.rest[0];
+
+    // If the test directory is just a single identifier, assume it's a language
+    // test subdirectory.
+    if (!testDir.contains("/")) testDir = "language_2/$testDir";
+  } on FormatException catch (exception) {
+    showUsage(argParser, exception.message);
+  }
+
+  if (!isLegacy) testDir = toNnbdPath(testDir);
+
+  // DDC doesn't have a Mac bot so when running DDC tests on a Mac, use a manual
+  // configuration. Otherwise, use the right named configuration.
+  List<String> testArgs;
+  if (Platform.isLinux || compiler != "ddc") {
+    var configuration = configurations[compiler];
+    if (!Platform.isLinux) {
+      // TODO(rnystrom): We'll probably never need to run this script on
+      // Windows, but if we do... do that.
+      configuration = configuration.replaceAll("linux", "mac");
+    }
+
+    testArgs = ["-n$configuration", testDir];
+  } else {
+    testArgs = [
+      "--mode=release",
+      if (!isLegacy) ...[
+        "--enable-experiment=non-nullable",
+        "--nnbd=strong",
+      ],
+      "--compiler=${compilerNames[compiler]}",
+      testDir,
+    ];
+  }
+
+  print("Running tools/test.py ${testArgs.join(' ')}");
+  await runProcessAsync("tools/test.py", testArgs);
+}
+
+void showUsage(ArgParser argParser, [String error]) {
+  if (error != null) {
+    print(error);
+    print("");
+  }
+  print("Usage: dart test.dart <source dir>");
+  print(argParser.usage);
+  exit(error == null ? 0 : 1);
+}
diff --git a/tools/migration/lib/src/io.dart b/tools/migration/lib/src/io.dart
index 638b27b5..faa68cb 100644
--- a/tools/migration/lib/src/io.dart
+++ b/tools/migration/lib/src/io.dart
@@ -131,6 +131,20 @@
   return result.exitCode == 0;
 }
 
+Future<bool> runProcessAsync(String executable, List<String> arguments,
+    {String workingDirectory}) async {
+  if (dryRun) {
+    print("Dry run: run $executable ${arguments.join(' ')}");
+    return true;
+  }
+
+  var process = await Process.start(executable, arguments);
+  process.stdout.listen(stdout.add);
+  process.stderr.listen(stderr.add);
+
+  return (await process.exitCode) == 0;
+}
+
 /// Returns a list of the paths to all files within [dir], which is
 /// assumed to be relative to the SDK's "tests" directory and having file with
 /// an extension in [extensions].
diff --git a/tools/run_abi_tests.py b/tools/run_abi_tests.py
index e32f008..83c26e6 100644
--- a/tools/run_abi_tests.py
+++ b/tools/run_abi_tests.py
@@ -27,7 +27,12 @@
         default=os.path.join(outDir, 'logs'),
         metavar='DIR',
         dest='logDir',
-        help='Directory to output restuls.json and logs.json to.')
+        help='Directory to output results.json and logs.json to.')
+    parser.add_argument(
+        '-n',
+        metavar='NAME',
+        dest='configuration_name',
+        help='Name of the configuration to use in the results.')
     return parser.parse_args()
 
 
@@ -137,10 +142,10 @@
 
 # Diff the results of a test for each version and construct a new test result
 # that reports whether the test results match for each version.
-def diffResults(results):
+def diffResults(results, configuration_name):
     outResult = pickOne(results)
     exp = results[None]['result'] if None in results else None
-    outResult['configuration'] = 'dartkb-abi-linux-release-x64'
+    outResult['configuration'] = configuration_name
     outResult['expected'] = exp
     outResult['result'] = exp
     outResult['matches'] = True
@@ -163,7 +168,7 @@
     logs = ["%s: %s" % (str(v), l['log']) for v, l in logRecords.items()]
     return {
         'name': result['name'],
-        'configuration': 'dartkb-abi-linux-release-x64',
+        'configuration': configuration_name,
         'result': result['result'],
         'log': '\n\n\n'.join([repr(diffs)] + logs),
     }
@@ -179,7 +184,8 @@
     with open(resultFileName, 'w') as resultFile:
         with open(logFileName, 'w') as logFile:
             for name, results in allResults.items():
-                outResult, diffs = diffResults(results)
+                outResult, diffs = diffResults(results,
+                                               flags.configuration_name)
                 resultFile.write(json.dumps(outResult) + '\n')
                 if diffs:
                     logRecords = allLogs[name] if name in allLogs else []
diff --git a/tools/utils.py b/tools/utils.py
index fb26d28..b1084cc 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -379,7 +379,8 @@
     if version.channel == 'be':
         postfix = '-edge' if no_git_hash else '-edge.%s' % GetGitRevision()
     elif version.channel in ('beta', 'dev'):
-        postfix = '-dev.%s.%s' % (version.prerelease, version.prerelease_patch)
+        postfix = '-%s.%s.%s' % (version.prerelease, version.prerelease_patch,
+                                 version.channel)
     else:
         assert version.channel == 'stable'
         postfix = ''
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index 7878730..a374fc2 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -339,7 +339,8 @@
       if (summaryOnly) {
         incrementalComponent.uriToSource.clear();
         incrementalComponent.problemsAsJson = null;
-        incrementalComponent.mainMethod = null;
+        incrementalComponent.setMainMethodAndMode(
+            null, true, incrementalComponent.mode);
         target.performOutlineTransformations(incrementalComponent);
         makeStable(incrementalComponent);
         return Future.value(fe.serializeComponent(incrementalComponent,
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index cfaa8d9..dda6c4e 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -66,12 +66,12 @@
   training_args = [
     "--packages=" + rebase_path("../../.packages"),
     "--libraries-spec=" + rebase_path("../../$libraries_specification_path"),
-  ]
 
-  if (use_nnbd) {
-    training_args += [ "--enable-experiment=non-nullable" ]
-  }
-  training_args += [ rebase_path("$target_gen_dir/dart2js.dart") ]
+    # Specifying the platform explicitly elides running the CFE on the sdk
+    # sources.
+    "--platform-binaries=" + rebase_path("$root_out_dir/"),
+    rebase_path("$target_gen_dir/dart2js.dart"),
+  ]
 }
 
 compile_platform("compile_dart2js_platform") {